Claude Code's CLAUDE.md inheritance: how nested configs actually work
If you've been using a single CLAUDE.md at your project root, you're missing one of Claude Code's most powerful features: nested CLAUDE.md inheritance.
Here's what's actually happening under the hood — and how to use it to build context-aware agents that behave differently depending on which part of your codebase they're working in.
The inheritance chain
Claude Code reads CLAUDE.md files from multiple locations, merging them in order of specificity:
~/.claude/CLAUDE.md ← global (applies to ALL projects)
/project/CLAUDE.md ← project root
/project/src/CLAUDE.md ← subdirectory
/project/src/api/CLAUDE.md ← deeper subdirectory
Each level adds to (not overwrites) the context from the level above. The most specific file wins on conflicts.
Why this matters
Your frontend and backend have completely different constraints:
- Frontend: "Never use
var, always use TypeScript interfaces, follow Tailwind conventions" - Backend: "Never expose raw errors to clients, always validate with Zod, use parameterized queries"
If you put all of this in one root CLAUDE.md, you get a bloated context that Claude has to parse for every file. Instead:
/project/CLAUDE.md ← shared project conventions
/project/frontend/CLAUDE.md ← React/TypeScript/Tailwind rules
/project/backend/CLAUDE.md ← Node/Zod/SQL security rules
/project/scripts/CLAUDE.md ← "these are throwaway scripts, don't over-engineer"
Real example: a monorepo setup
Here's my actual config for a monorepo with 3 services:
Root /CLAUDE.md:
# Project: MyApp Monorepo
## Shared conventions
- TypeScript everywhere
- Conventional commits (feat/fix/chore)
- No console.log in production code
- Tests required for all business logic
## Services
- /packages/api — Express REST API
- /packages/web — Next.js frontend
- /packages/workers — Background job processors
/packages/api/CLAUDE.md:
# API Service Rules
## Security (CRITICAL)
- Never return raw database errors to clients
- Always use parameterized queries
- Sanitize all user input with Zod before processing
- Auth middleware goes on EVERY route except /health
## Response format
Always return: `{ success: boolean, data?: any, error?: string }`
## DO NOT
- Hardcode credentials
- Use synchronous file operations
- Bypass the rate limiter
/packages/web/CLAUDE.md:
# Web Frontend Rules
## Stack
- Next.js 14 App Router (not Pages)
- Tailwind CSS (not inline styles)
- Zustand for state (not Redux, not Context for global state)
## Component rules
- Server Components by default
- Only use 'use client' when you need interactivity
- All API calls go through /src/lib/api.ts
## DO NOT
- Use `any` type
- Create new state management patterns
- Fetch directly from components (use hooks)
The global ~/.claude/CLAUDE.md
This is applied to every project on your machine. Use it for your personal preferences:
# My personal Claude Code preferences
## Response style
- Be terse. I'm an experienced developer.
- Show code, not explanations (unless I ask)
- One approach, not multiple options
- No "Great question!" or filler phrases
## Code style
- I prefer functional patterns
- Comments only for non-obvious logic
- Explicit over implicit
## What NOT to do
- Don't offer to write tests unless I ask
- Don't suggest refactoring existing code unless asked
- Don't add error handling I didn't request
This alone will save you significant tokens per session — Claude won't pad responses or offer alternatives you'll never use.
Token optimization via inheritance
Here's a counterintuitive insight: more files = fewer tokens used per operation.
When Claude Code is working on /packages/api/routes/users.ts, it loads:
-
~/.claude/CLAUDE.md(personal prefs, ~200 tokens) -
/CLAUDE.md(shared conventions, ~150 tokens) -
/packages/api/CLAUDE.md(API rules, ~200 tokens)
Total: ~550 tokens of highly relevant context.
If you had one root CLAUDE.md with everything: easily 1,200+ tokens, most of which is irrelevant to the current task.
Debugging inheritance
Not sure what Claude is reading? Run:
# See which CLAUDE.md files are in scope
find . -name "CLAUDE.md" | sort
# Or ask Claude directly in your session:
# "What CLAUDE.md files are you currently reading?"
Claude Code will list the files and their contents in order of inheritance.
The @import trick
You can reference other files from CLAUDE.md:
# Backend Rules
@import ./docs/api-conventions.md
@import ./docs/security-checklist.md
This keeps CLAUDE.md files small while pulling in detailed documentation only when Claude is working in that directory.
Practical takeaway
If your project has distinct domains (frontend/backend, services, scripts), add a CLAUDE.md to each one. The overhead is minimal (one file per directory) and the payoff is significant:
- More relevant responses — Claude has the right context for the current task
- Fewer tokens used — smaller context = lower cost per operation
- More consistent output — rules apply exactly where needed
If you're running Claude API calls directly (not via Claude Code), a flat-rate proxy like SimplyLouie lets you experiment with context sizes without worrying about per-token costs — useful when you're tuning your CLAUDE.md setup.
Top comments (0)