Claude Code CLAUDE.md vs settings.json: which one controls what (and why it matters)
If you've been using Claude Code for more than a week, you've probably edited both CLAUDE.md and .claude/settings.json — and at some point wondered: which file should this go in?
They look similar. They both configure Claude's behavior. But they control completely different things, and mixing them up leads to frustrating results.
Here's the complete breakdown.
The mental model
CLAUDE.md = Claude's brain
settings.json = Claude's permissions
CLAUDE.md is natural language. You write instructions, context, constraints, and preferences. Claude reads it like a colleague reads a briefing doc.
settings.json is machine config. It controls what tools Claude is allowed to use, what commands it can run, what it's blocked from doing.
What CLAUDE.md controls
# Project context
This is a Next.js 14 app using Prisma + PostgreSQL.
# Architecture decisions
- All API routes live in /app/api/
- Database models are in /prisma/schema.prisma
- Never create new /pages/ routes — we're on App Router
# Code style
- TypeScript strict mode always on
- Prefer async/await over .then() chains
- Use Zod for all input validation
# Response format
- Give me code first, explanation after
- Skip obvious comments — I can read the code
- When suggesting a fix, show the before AND after
Things that belong in CLAUDE.md:
- Tech stack and architecture
- Coding conventions and style preferences
- Business domain context (what the app does, who uses it)
- Response format preferences
- Things to always/never do
- Commands to run for common tasks
What settings.json controls
{
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(git add:*)",
"Bash(git commit:*)",
"Bash(cat:*)",
"Bash(grep:*)",
"Bash(find:*)"
],
"deny": [
"Bash(rm -rf *)",
"Bash(git push:*)",
"Bash(curl:*)",
"WebFetch"
]
}
}
Things that belong in settings.json:
- Which bash commands Claude can run without asking
- Which tools are blocked entirely
- Auto-approve settings for trusted operations
- Model preferences (if you're on Pro)
The key difference: CLAUDE.md is read, settings.json is enforced
Claude can choose to ignore something in CLAUDE.md if it thinks it knows better. (It shouldn't, but it can.) Settings.json is a hard fence — Claude literally cannot execute a command that's in the deny list.
This is why:
- Style preferences go in CLAUDE.md — you want Claude to understand and apply them, not be mechanically blocked
- Safety constraints go in settings.json — you want actual enforcement, not suggestions
Real-world example: preventing accidental deploys
Wrong approach — putting it in CLAUDE.md:
# IMPORTANT
Never run `git push` or deployment commands without asking me first.
Claude will try to follow this. But if it's confident a push is needed, it might do it anyway.
Right approach — settings.json:
{
"permissions": {
"deny": [
"Bash(git push:*)",
"Bash(npm run deploy:*)",
"Bash(vercel:*)"
]
}
}
Now it's impossible, not just discouraged.
Real-world example: project conventions
Wrong approach — trying to encode this in settings.json: You can't. Settings.json doesn't support natural language rules.
Right approach — CLAUDE.md:
# Database conventions
- All new tables need a `created_at` and `updated_at` column
- Foreign key names: {table}_{column}_fkey
- Always use UUIDs for primary keys, never auto-increment integers
- Migrations live in /prisma/migrations/ �� never edit them by hand
Claude reads this, understands it, and applies it when writing schema changes.
The inheritance question
Both files support inheritance — but differently.
CLAUDE.md inheritance (directory-based):
~/.claude/CLAUDE.md # global rules for all projects
/project/CLAUDE.md # project rules
/project/src/api/CLAUDE.md # subdirectory rules
All three are read and merged, with deeper files taking precedence.
settings.json inheritance (also directory-based):
~/.claude/settings.json # global permissions
/project/.claude/settings.json # project permissions
Permissions merge — if global denies git push but project allows it, the project setting wins.
My combined setup
Here's what my two files look like on a typical project:
CLAUDE.md:
# Stack
Node.js 20, Express 5, PostgreSQL 16, Redis
# Rules
- Tests live in /test/ mirroring /src/ structure
- All routes must have input validation (Zod)
- Log with winston, never console.log in production code
- Environment variables always via process.env, never hardcoded
# Workflow
- After any schema change, remind me to run migrations
- When creating a new API endpoint, scaffold test file too
- Prefer small focused functions over large ones
# Response style
- Code first, then brief explanation
- If you see a related issue while fixing something, mention it but don't fix it unless I ask
.claude/settings.json:
{
"permissions": {
"allow": [
"Bash(npm run test:*)",
"Bash(npm run lint:*)",
"Bash(npm install:*)",
"Bash(git status:)",
"Bash(git diff:*)",
"Bash(cat:*)",
"Bash(ls:*)",
"Bash(grep:*)"
],
"deny": [
"Bash(git push:*)",
"Bash(rm -rf:*)",
"Bash(DROP TABLE:*)"
]
}
}
Quick reference
| What you want | File |
|---|---|
| Coding style rules | CLAUDE.md |
| Architecture context | CLAUDE.md |
| Domain knowledge | CLAUDE.md |
| Response format preferences | CLAUDE.md |
| Block dangerous commands | settings.json |
| Auto-approve safe commands | settings.json |
| Prevent git push | settings.json |
| Project tech stack info | CLAUDE.md |
| Tool restrictions | settings.json |
One more thing: the API alternative
If you're using Claude Code heavily, you've probably noticed the rate limits. One thing that helps: routing Claude Code through a direct API endpoint instead of Anthropic's consumer tier.
The ANTHROPIC_BASE_URL environment variable lets you point Claude Code at any compatible endpoint:
export ANTHROPIC_BASE_URL=https://simplylouie.com/api
SimplyLouie runs a flat-rate Claude API proxy at $2/month — same claude-3-5-sonnet-20241022 model, no per-token billing, no rate limit anxiety. If you're doing serious Claude Code work, the math tends to favor flat-rate.
The CLAUDE.md vs settings.json confusion trips up a lot of Claude Code users. Once you have the mental model — brain vs fence — the right file for each thing becomes obvious.
What's in your CLAUDE.md that probably shouldn't be? Drop it in the comments.
Top comments (0)