DEV Community

brian austin
brian austin

Posted on

Claude Code's CLAUDE.md inheritance: how nested configs actually work

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

/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
Enter fullscreen mode Exit fullscreen mode

/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)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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?"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:

  1. More relevant responses — Claude has the right context for the current task
  2. Fewer tokens used — smaller context = lower cost per operation
  3. 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.

claudecode #ai #productivity #devtools

Top comments (0)