When you first install Claude Code and run it in a real project, there are a handful of configuration files that actually change how it behaves. Most people find out about them by running into problems first. This post is the setup I use, with complete examples you can copy directly.
I'm covering four things: CLAUDE.md, settings.json, .claudeignore, and the state file pattern for longer sessions. Each section has a working example and one anti-pattern that shows up constantly.
CLAUDE.md loads into context on every message. That means it's always running, always consuming tokens, and always influencing behavior. The instinct is to put everything in it. The result is a 500-line document that Claude half-reads and half-ignores.
The file should answer three questions: what is this project, what should always happen, and what should never happen. Everything else belongs somewhere else or nowhere at all.
Here's the structure that works:
# Project Next.js 16 App Router project. TypeScript strict. Supabase for data. Deployed on Vercel. ## Stack - Framework: Next.js 16 (App Router only, not Pages Router) - Language: TypeScript, strict mode - Styling: TailwindCSS 4 - Database: Supabase (PostgreSQL) - Package manager: npm ## Rules Always: - Use App Router conventions (server components by default, "use client" only when needed) - Write TypeScript. No `any` unless you have a specific reason and leave a comment. - Use native fetch. No axios. - Add 150-300ms delays between external API calls. Never: - Add console.log statements - Create utility files for one-time operations - Refactor code that isn't part of the task - Add backward-compatibility shims ## Directory structure - app/api/ — API route handlers - components/ — React components (PascalCase filenames) - lib/ — shared logic, data sources, hooks - types/ — shared TypeScript types ## Error handling Try-catch with graceful degradation. Never swallow errors silently. Log to console.error, not console.log.
That's roughly 200 words. It covers everything Claude needs to make correct decisions without being told explicitly. The key is that every line either changes behavior or it doesn't. If removing a line wouldn't change anything, cut it.
Anti-pattern: Writing preferences instead of rules. "Prefer functional components" doesn't fire. "Never use class components" does. Preferences are suggestions; Claude treats them as optional. If you actually need the behavior, write it as a constraint.
The Claude Code settings file lives at ~/.claude/settings.json for global settings, or .claude/settings.json in a project for project-level overrides. The project file takes precedence.
The settings that actually matter:
{
"defaultMode": "acceptEdits",
"cleanupPeriodDays": 30,
"env": {
"NODE_ENV": "development"
}
}
defaultMode controls whether Claude asks for confirmation before editing files. Options are "default" (asks), "acceptEdits" (accepts file edits automatically, still asks for bash), and "bypassPermissions" (accepts everything). For supervised sessions, "acceptEdits" is the right setting. It stops the mid-task confirmation prompts on file changes while keeping you in the loop on shell commands.
cleanupPeriodDays controls how long conversation history is kept locally. The default is 30 days. If you're running Claude Code heavily, older history adds up. Set it to something reasonable.
Key bindings can be customized in settings too. The ones I actually use:
{
"defaultMode": "acceptEdits",
"cleanupPeriodDays": 30,
"keyBindings": {
"acceptSuggestion": "tab",
"dismissSuggestion": "escape"
}
}
Anti-pattern: Using "bypassPermissions" for normal development. It feels faster because there are zero confirmation prompts, but it also means Claude can run arbitrary shell commands without asking. Save that mode for fully automated pipelines where you've already reviewed what will run. For interactive sessions, "acceptEdits" is the better tradeoff.
.claudeignore works like .gitignore and lives in the project root. Files matching patterns here won't be read into context when Claude does a file search or tries to understand the codebase. This matters because context has a finite size, and large generated files can fill it before Claude gets to the actual source code.
The standard list for a Next.js project:
# Dependencies node_modules/ # Build output .next/ out/ dist/ # Generated files *.generated.ts *.generated.js # Test snapshots (large, rarely useful mid-session) **/__snapshots__/ # Coverage reports coverage/ # Environment files (never read into context) .env .env.local .env.production .env.* # Logs *.log npm-debug.log* # Package lock (no useful signal for Claude) package-lock.json yarn.lock pnpm-lock.yaml # Large data files *.csv *.sql supabase/seed.sql
The most important entries are node_modules/ (obvious) and lock files. A package-lock.json can be 20,000 lines. Claude doesn't need it, and if it gets pulled into context during a dependency question, it crowds out everything else.
Anti-pattern: Ignoring your entire tests/ directory. Tests are one of the most useful signals Claude has about how your code is supposed to work. If Claude can't see the tests, it makes up assumptions about behavior instead of reading the actual spec. Ignore snapshots and coverage reports, not the test files themselves.
Claude Code sessions start blank. CLAUDE.md loads, the project is there, the code makes sense. But what was done last session, what decisions were made, and what comes next? That's gone unless it's written down somewhere.
For tasks that take more than one session, I keep a file at tasks/current-task.md:
## Active Task goal: "what you're trying to accomplish" started: 2026-03-16T10:00:00Z steps: - [x] completed step - [ ] next step - [ ] future step last_checkpoint: "where you are and what the next move is"
First thing in any session: read this file. It's the handoff note from the previous session. After any meaningful chunk of work: update last_checkpoint. Before a compaction: write down why you made the decisions you made, not just what was done.
The full writeup on this pattern, including how to handle parallel sub-agents and what to do before compaction, is in The state file: how autonomous agents survive context resets.
Anti-pattern: Putting session state in CLAUDE.md. CLAUDE.md is for things that are always true about the project. The task file is for things that change as you work. Mixing them means CLAUDE.md goes stale and you lose the separation that makes both files useful. Keep them separate.
If you want prompts that work with this setup, the Agent Prompt Playbook has 40+ copy-paste prompts for Claude Code: task delegation patterns, multi-agent coordination, error handling, context management, and more. $29 at payhip.com/b/6rRkT.