The CLAUDE.md File: Your AI's Persistent Memory
- Understand the four CLAUDE.md scopes and how they layer together
- Write an effective CLAUDE.md with the correct sections for a real project
- Know what to include and what to exclude to keep the file lean and useful
The Problem: Claude Starts Fresh Every Time
Every Claude Code session begins with zero memory of the last one. You explained your tech stack last Tuesday — Claude does not remember. You corrected a mistake on Wednesday — it will make the same mistake on Thursday. You told it to always use async/await — next session it is back to Promise chains.
This is not a bug. AI models do not retain information between separate sessions by design. But it creates a real problem: you end up repeating yourself constantly, and every session requires a warm-up period where Claude re-learns your project.
CLAUDE.md solves this. It is a markdown file that Claude Code reads automatically at the start of every session. Whatever you put in it, Claude knows before you type your first prompt.
The Four Scopes
CLAUDE.md exists at four different levels, and all four are loaded and merged together every session:
1. Managed (org-wide)
/Library/Application Support/ClaudeCode/CLAUDE.md ← macOS
/etc/claude-code/CLAUDE.md ← Linux
C:Program FilesClaudeCodeCLAUDE.md ← Windows
Set by IT/DevOps. Cannot be overridden by users.
2. Project (team-shared)
./CLAUDE.md or ./.claude/CLAUDE.md
Commit this to git. Everyone on the team uses it.
3. Local (personal, gitignored)
./CLAUDE.local.md
Your personal overrides for this project.
Add to .gitignore — do not commit.
4. User (all your projects)
~/.claude/CLAUDE.md
Applies to every project you open. Good for personal style preferences.
All four files are concatenated in this order: managed → user → project → local. Later files take precedence over earlier ones. The /init command creates the project-level file.
What Belongs in CLAUDE.md
Think of CLAUDE.md as the onboarding document you would give a new developer joining your team — but written for Claude specifically. Here is what to include:
Tech stack
Be specific. Not "we use Node" but "Node.js 18 LTS, Express 4.x, PostgreSQL 14, TypeScript, npm 9+." Claude uses this to make correct assumptions about syntax, available APIs, and package managers.
Build and test commands
The exact commands — not descriptions of them. Claude will run these without asking every time.
## Commands
- Dev server: `npm run dev`
- Tests: `npm test`
- Lint: `npm run lint`
- Build: `npm run build`
- Database: `npm run migrate`
Project structure
Where things live. Claude searches for files, but knowing the layout upfront makes it faster and more accurate.
## Structure
- `src/routes/` — API endpoint handlers
- `src/models/` — Database models and queries
- `src/middleware/` — Auth, validation, error handling
- `tests/` — Jest test suites (mirrors src/ structure)
Code conventions
Indentation, naming, error formats, async patterns. The things that differ between projects and would not be obvious from reading one file.
## Conventions
- 2-space indentation, no tabs
- camelCase for variables and functions, PascalCase for classes
- All errors are thrown, not returned
- Always use async/await, never .then() chains
- API errors return `{ error: string, code: number }`
Critical patterns — the most important section
These are the things that are true about your project but not obvious. The things a new developer would get wrong on their first day. Real examples from real projects:
## Critical Patterns
- Payment amounts are stored in CENTS, not dollars. Always multiply by 100 before storing.
- The `user_id` field is a STRING UUID, not an integer. Never cast to int.
- Stripe webhooks must respond with HTTP 200 immediately, then process async.
- All API routes require `Authorization: Bearer <token>` except /login and /register.
- Database queries go through the ORM in src/db.ts — never use the raw pg client directly.
Things Claude often gets wrong
This section evolves as you use Claude Code. Every time Claude makes the same mistake twice, add it here. This turns a correction into permanent institutional knowledge.
## Things Claude Often Gets Wrong
1. Do not use `res.json()` — use our `sendResponse()` helper in src/utils/response.ts
2. Never import directly from packages — check src/lib/ for our wrapped versions first
3. Test files use `describe/it`, not `test()` blocks
4. The staging API is at staging.example.com, not staging-api.example.com
What Does Not Belong in CLAUDE.md
Three categories of content actively hurt rather than help:
- Secrets and credentials — API keys, passwords, tokens. Never put these here. Use environment variables. CLAUDE.md goes in git, and secrets in git is a serious security incident waiting to happen.
- Long step-by-step procedures — If you need Claude to follow a multi-step workflow, create a custom slash command (covered in Lesson 5). Long procedures in CLAUDE.md are hard to maintain and consume context budget.
- Bloat — Keep CLAUDE.md under 200 lines. Every line you add consumes part of the context window that could go toward your actual task. Prioritise the conventions Claude gets wrong, not every detail about your project.
The @import Syntax
Instead of copying content into CLAUDE.md, reference external files with @:
See @README.md for the project overview and architecture diagram.
See @package.json for all available npm scripts.
See @.claude/rules/api-design.md for our API design standards.
Claude reads those files on-demand when they become relevant, rather than loading everything upfront. This keeps your main CLAUDE.md lean while still making all the information available.
Scoped Rules for Large Projects
On larger projects, a single CLAUDE.md can get unwieldy. Use the .claude/rules/ directory to create rules that only apply to specific file patterns:
.claude/rules/
├── api-design.md # Rules for src/api/** files
├── frontend.md # Rules for src/components/** files
├── testing.md # Rules for tests/** files
└── security.md # Security requirements for all files
Each rules file can include frontmatter to scope it:
---
paths:
- "src/api/**/*.ts"
---
# API Design Rules
- All endpoints must validate input with Joi before processing
- Return 422 for validation errors, 400 for malformed requests
- Every endpoint must be documented with a JSDoc @route comment
A Complete CLAUDE.md Example
Here is what a well-structured CLAUDE.md looks like for a real project. This is the kind of file you would aim to have after your first two weeks with Claude Code on a project:
# Payment Processing API
## Tech Stack
- **Runtime**: Node.js 18 LTS
- **Framework**: Express.js 4.x
- **Database**: PostgreSQL 14 (see DATABASE_URL in environment)
- **Language**: TypeScript (strict mode)
- **Package manager**: npm 9+
## Commands
- Dev: `npm run dev` (nodemon + ts-node)
- Tests: `npm test` (Jest, runs against test DB)
- Lint: `npm run lint` (ESLint + Prettier)
- Build: `npm run build` (compiles to dist/)
- Migrate: `npm run migrate`
## Structure
- `src/routes/` — Express route handlers
- `src/models/` — Database models (thin wrappers over queries)
- `src/middleware/` — Auth, validation, error handling
- `src/utils/` — Shared helpers
- `src/lib/` — Wrapped third-party clients (Stripe, SendGrid, etc.)
- `tests/` — Jest suites, mirrors src/ structure
## Conventions
- 2-space indentation, no tabs
- camelCase variables/functions, PascalCase classes/interfaces
- All errors thrown, never returned
- async/await only — no .then() chains
- API error format: `{ error: string, code: string }`
## Critical Patterns
- Amounts are in CENTS. Multiply by 100 before storing.
- user_id is a UUID string — never cast to integer
- All auth routes need Bearer token in Authorization header
- Use our ORM helpers in src/models/ — never raw SQL
- Stripe webhooks: respond 200 immediately, then process
## Things Claude Often Gets Wrong
1. Use sendSuccess()/sendError() from src/utils/response.ts — not res.json()
2. Check src/lib/ before importing packages directly
3. Tests use describe/it blocks, not test()
4. Never commit directly to main — always use feature branches
The Iteration Loop
Your CLAUDE.md on day one will be thin. That is fine. The real workflow is this:
- Run
/initto get a first draft - Start using Claude Code for real tasks
- When Claude gets something wrong, correct it in the chat
- After correcting it, ask: "Should we add this to CLAUDE.md?" If yes, add it
- After a few weeks, your CLAUDE.md is a genuinely useful document that prevents whole categories of mistakes
The goal is to stop correcting the same thing twice. Every correction you make in a chat session that you do not also put in CLAUDE.md is a correction you will have to make again next session.
CLAUDE.md for Teams
When multiple developers use Claude Code on the same project, CLAUDE.md becomes a shared asset:
- Commit your project CLAUDE.md to git. It should be reviewed like any other important configuration file. When a new convention is established, update CLAUDE.md in the same PR.
- Use CLAUDE.local.md for personal preferences. Your local database connection string, your personal debugging workflow, your preferred editor settings — these go in CLAUDE.local.md (gitignored) so they do not affect teammates.
- Use ~/.claude/CLAUDE.md for cross-project habits. If you always want Claude to use a specific commit message format, always prefer async/await, or always check for test coverage, put that in your user-level CLAUDE.md.
The result is a layered system: team conventions in the project file, personal preferences in the local file, universal habits in the user file. Claude Code reads all three every time.
- CLAUDE.md is auto-loaded every session — it is the only way to give Claude persistent memory about your project
- Four scopes: managed (org), project (git-committed), local (gitignored), user (all projects)
- Include: tech stack, build commands, project structure, coding conventions, critical patterns, and things Claude gets wrong
- Exclude: secrets, long procedures, bloat — keep it under 200 lines
- The iteration loop: correct Claude in chat, then add the correction to CLAUDE.md so you never repeat it