You just spent twenty minutes writing the perfect system prompt in your CLAUDE.md file. You fire up Claude Code, ask it to scaffold a new module, and... it completely ignores your coding conventions. Again.
I've been there. After using Claude Code across multiple projects for the past few months, I've learned that most "Claude isn't listening" problems come down to one thing: not understanding how the .claude/ folder actually works.
Let me walk you through the anatomy of this folder, because once you get it right, Claude Code goes from a generic assistant to something that genuinely understands your project.
The Problem: Configuration That Never Sticks
Here's the scenario that trips most people up. You create a CLAUDE.md in your project root, add your preferences, and things work — sometimes. Other times Claude Code seems to forget everything. Or worse, your teammate clones the repo and gets completely different behavior.
The root cause is almost always one of these:
- You're putting config in the wrong file or the wrong location
- You don't understand the precedence chain
- You're mixing project-level and user-level settings
Let's fix all of that.
Step 1: Understand the Folder Structure
The .claude/ folder lives in your project root (and also in your home directory at ~/.claude/). Here's what a well-configured project-level .claude/ folder looks like:
.claude/
├── settings.json # Tool permissions and behavioral config
├── settings.local.json # Your personal overrides (gitignored)
└── CLAUDE.md # Project-level instructions (but often lives at repo root)
There's also a top-level CLAUDE.md that can sit right in your repo root — and this is actually the one most people should start with. The key insight is that Claude Code reads instructions from multiple locations and merges them together.
The Precedence Chain
This is where things get interesting. Claude Code loads context from several CLAUDE.md files in a specific order:
# Loaded from broadest to most specific:
~/.claude/CLAUDE.md # User-level (your personal preferences)
./CLAUDE.md # Project root (team conventions)
./.claude/CLAUDE.md # Project .claude folder
./src/CLAUDE.md # Subdirectory-specific (if you're working there)
More specific files take priority. So if your user-level CLAUDE.md says "use tabs" but your project CLAUDE.md says "use spaces," you'll get spaces when working in that project. This is the right behavior, but it confuses people who don't realize the chain exists.
Step 2: Write a CLAUDE.md That Actually Works
The biggest mistake I see is treating CLAUDE.md like a casual README. Claude Code parses this as direct instructions, so you need to be specific and imperative.
Here's a bad example:
# About This Project
This is a Next.js app. We like clean code and good testing.
That tells Claude almost nothing actionable. Here's what actually works:
# Project Conventions
- This is a Next.js 15 app using the App Router with TypeScript strict mode
- Use named exports, never default exports
- All components go in src/components/ with a barrel index.ts
- Tests use Vitest, not Jest. Test files live next to source files as *.test.ts
- Use server components by default. Only add "use client" when you need interactivity
- Error handling: use Result types from src/lib/result.ts, never throw in business logic
- Database queries go through the repository pattern in src/repositories/
# Commands
- Build: `npm run build`
- Test: `npm run test`
- Lint: `npm run lint:fix`
Notice the pattern: each instruction is a concrete, actionable rule. Tell Claude Code what to do, not what your project is about in the abstract.
Step 3: Configure settings.json Properly
The settings.json file controls tool permissions — which commands Claude Code can run without asking you every single time. This is the file that stops the constant "Can I run npm test?" prompts.
{
"permissions": {
"allow": [
"Bash(npm run test)",
"Bash(npm run lint:fix)",
"Bash(npm run build)",
"Bash(npx tsc --noEmit)"
],
"deny": [
"Bash(rm -rf *)",
"Bash(git push --force)"
]
}
}
The critical distinction: settings.json gets committed to your repo (shared team config), while settings.local.json is for your personal overrides and should be in .gitignore.
If you've ever been frustrated that Claude keeps asking for permission to run your test suite, this is the fix. Add your safe commands to the allow list and you'll stop the interruption loop.
Step 4: Use settings.local.json for Personal Preferences
This is the file most people don't know about. It follows the same schema as settings.json but is meant for individual developer overrides.
{
"permissions": {
"allow": [
"Bash(docker compose up -d)",
"Bash(psql -h localhost)"
]
}
}
Maybe you run your database locally in Docker but your teammate uses a cloud instance. Your settings.local.json lets you pre-approve your local workflow commands without affecting the team config.
Don't forget to gitignore it:
# Add to .gitignore
.claude/settings.local.json
Step 5: Subdirectory CLAUDE.md Files for Monorepos
This one's a game-changer if you work in a monorepo. You can place CLAUDE.md files in subdirectories, and Claude Code picks them up when working in that context.
my-monorepo/
├── CLAUDE.md # Shared conventions
├── packages/
│ ├── api/
│ │ └── CLAUDE.md # API-specific: "use Hono, not Express"
│ └── web/
│ └── CLAUDE.md # Frontend-specific: "use Tailwind v4 syntax"
This means your API package can have completely different conventions from your frontend package, and Claude Code respects the boundaries. I started using this pattern after getting frustrated with Claude applying React patterns to my backend code in a monorepo.
Common Gotchas and How to Avoid Them
Claude ignores your CLAUDE.md changes mid-session. Claude Code reads CLAUDE.md at the start of a conversation. If you edit it while a session is active, you may need to start a fresh session with /clear for the changes to take effect.
Conflicting instructions across files. If your root CLAUDE.md says "use Prettier" and a subdirectory CLAUDE.md says "use Biome," you'll get inconsistent behavior. Audit your chain. Keep shared rules at the root and only put genuine overrides in subdirectories.
Overly long CLAUDE.md files. I've seen people dump entire style guides into CLAUDE.md. Remember, this consumes context window. Keep it focused on the rules that Claude Code actually gets wrong without guidance. If Claude already writes decent TypeScript, you don't need to tell it how to write TypeScript.
Not committing settings.json. If your team doesn't share the base settings.json, everyone wastes time individually approving the same commands. Commit it. Use settings.local.json for personal stuff.
Prevention: A Quick Setup Checklist
When I start a new project now, here's my checklist before writing any code with Claude Code:
- Create
CLAUDE.mdat project root with concrete conventions - Create
.claude/settings.jsonwith pre-approved safe commands - Add
.claude/settings.local.jsonto.gitignore - If it's a monorepo, add subdirectory
CLAUDE.mdfiles per package - Keep instructions short, specific, and imperative
- Review and trim
CLAUDE.mdevery few weeks as the project evolves
The .claude/ folder isn't complicated, but it's one of those things where getting the details right makes a huge difference in your day-to-day experience. Set it up once, set it up right, and Claude Code stops feeling like a generic tool and starts feeling like a teammate who actually read the contributing guide.
Top comments (0)