DEV Community

brian austin
brian austin

Posted on

Claude Code project memory: how CLAUDE.md files work across nested directories

Claude Code project memory: how CLAUDE.md files work across nested directories

If you've been using a single CLAUDE.md at your project root, you're missing half of how Claude Code's memory system works.

Claude Code reads multiple CLAUDE.md files in a hierarchy. Understanding this unlocks a completely different way to organize instructions for complex projects.

The CLAUDE.md hierarchy

When you run Claude Code in a directory, it reads:

  1. ~/.claude/CLAUDE.md — your global instructions (applies everywhere)
  2. {project-root}/CLAUDE.md — project-wide instructions
  3. {current-subdirectory}/CLAUDE.md — directory-specific instructions
  4. Any CLAUDE.md in intermediate directories

All of these get merged together. More specific files override more general ones.

your-project/
├── CLAUDE.md              # "This is a Node.js API, use async/await"
├── src/
│   ├── CLAUDE.md          # "These are route handlers, always validate input"
│   ├── routes/
│   └── models/
│       └── CLAUDE.md      # "These are Mongoose models, always add timestamps"
└── tests/
    └── CLAUDE.md          # "Use Jest, describe/it format, 90% coverage minimum"
Enter fullscreen mode Exit fullscreen mode

Global CLAUDE.md: your personal AI preferences

This one is underused by most developers.

Create ~/.claude/CLAUDE.md to set preferences that apply across every project:

# Global Claude preferences

## Communication style
- Be concise. Skip the preamble.
- When suggesting changes, show diffs not full files
- If something is ambiguous, ask ONE clarifying question before proceeding

## Code style (my defaults)
- TypeScript over JavaScript when possible
- Functional patterns preferred over OOP
- Named exports, not default exports
- Always handle errors explicitly

## Things I never want
- No inline comments explaining what the code does (I can read code)
- No TODO comments — either do it or don't
- No `any` types in TypeScript
Enter fullscreen mode Exit fullscreen mode

Every project you open will inherit these preferences automatically.

Project CLAUDE.md: team-shared context

The root CLAUDE.md should contain context that every developer on your team needs:

# Project: Payment API

## Architecture
- Express + TypeScript + Prisma
- PostgreSQL on RDS
- Deployed to AWS ECS via GitHub Actions

## Critical rules
- NEVER log payment card data, even partially
- All financial calculations use decimal.js (not floating point)
- Database migrations go in /migrations, never modify existing ones

## Test database
- Local: postgresql://localhost/payments_test
- Seed: `npm run db:seed`

## Common commands
- `npm run dev` — start with hot reload
- `npm run test:watch` — jest in watch mode
- `npm run prisma:studio` — browse database
Enter fullscreen mode Exit fullscreen mode

Subdirectory CLAUDE.md: specialist context

This is where the hierarchy gets powerful. Give Claude different instructions depending on where it's working:

# /src/routes/CLAUDE.md

## Route handler conventions
- Input validation with zod before any business logic
- All handlers are async, return void, use res.json()
- Error handling: throw ApiError, middleware catches it
- Rate limiting is applied at the router level, not handler level

## Authentication
- req.user is always populated by auth middleware
- Never trust req.body.userId — always use req.user.id

## Response format
{
  success: boolean,
  data: T | null,
  error: string | null
}
Enter fullscreen mode Exit fullscreen mode
# /src/workers/CLAUDE.md

## Background job context
- Workers run in separate processes, no access to request context
- Use job-scoped logger: getLogger(job.id)
- Always handle job failure explicitly — BullMQ won't retry by default
- Max execution time: 5 minutes. Long jobs must checkpoint progress.

## Database in workers
- Create a fresh Prisma client per worker process
- Close it in the finally block
Enter fullscreen mode Exit fullscreen mode

Now when Claude is editing a route handler, it knows the route conventions. When it's editing a worker, it knows the job constraints. Without you having to explain it every time.

The ~/.claude/settings.json complement

CLAUDE.md is for what Claude should know. settings.json is for what Claude is allowed to do.

{
  "permissions": {
    "allow": [
      "Bash(npm run test:*)",
      "Bash(npm run lint)",
      "Bash(git diff:*)",
      "Bash(git log:*)"
    ],
    "deny": [
      "Bash(rm -rf:*)",
      "Bash(git push:*)",
      "Bash(npm publish:*)"
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

Brain (CLAUDE.md) + Guardrails (settings.json) = a Claude that knows your codebase and can't accidentally nuke production.

The rate limit problem

As your CLAUDE.md files get richer — global preferences, project context, subdirectory specializations — your token usage goes up. Every conversation starts by loading all relevant CLAUDE.md files into context.

If you're hitting rate limits mid-session, there are two solutions:

Option 1: Keep CLAUDE.md files lean. Use bullet points, not prose. Reference don't explain.

Option 2: Route through a proxy that removes rate limits entirely.

export ANTHROPIC_BASE_URL=https://api.simplylouie.com
export ANTHROPIC_API_KEY=your-key
Enter fullscreen mode Exit fullscreen mode

SimplyLouie is ✌️$2/month and removes the overloaded errors so your CLAUDE.md-heavy sessions don't get interrupted.

Quick reference: what goes where

Content Where
Personal code style preferences ~/.claude/CLAUDE.md
My preferred communication style ~/.claude/CLAUDE.md
Project architecture overview {root}/CLAUDE.md
Team conventions & critical rules {root}/CLAUDE.md
Route/module specific patterns {subdir}/CLAUDE.md
Tool permissions ~/.claude/settings.json
Project-specific tool overrides {root}/.claude/settings.json

Setting this up in your project

# Create global preferences
mkdir -p ~/.claude
touch ~/.claude/CLAUDE.md

# Create project-level memory
touch ./CLAUDE.md

# Create subdirectory specializations
touch ./src/routes/CLAUDE.md
touch ./src/workers/CLAUDE.md
touch ./tests/CLAUDE.md

# Tell Claude about its own memory system
claude "Read all CLAUDE.md files in this project and summarize what you know about the codebase"
Enter fullscreen mode Exit fullscreen mode

That last command is useful to verify Claude is reading everything correctly — it will tell you exactly what context it loaded.


The hierarchy is one of Claude Code's most powerful features, and most people only use 20% of it by having a single root CLAUDE.md. Subdirectory specialization is what makes Claude genuinely feel like a team member who knows the codebase.

Running Claude Code sessions that get interrupted by rate limits? Set ANTHROPIC_BASE_URL=https://api.simplylouie.com and ANTHROPIC_API_KEY=your-keySimplyLouie is ✌️$2/month.

Top comments (0)