CLAUDE.md: the persistent context file
A markdown file that gives Claude persistent instructions for your project — coding standards, repo structure, do's and don'ts. Loaded automatically every session.
CLAUDE.md is how you give Claude persistent instructions — coding standards, project context, conventions, rules. Claude reads it automatically at the start of every session, so you don’t have to re-explain “we use snake_case for SQL columns” or “always use the Mediator pattern in this repo” every time.
It’s just markdown. There’s no special syntax, no schema. Whatever you write in it becomes part of Claude’s context for that session.
How files stack
Multiple CLAUDE.md files can exist and they stack by scope. Claude loads them in order, with more-specific files layered on top:
| File location | Scope | When it loads |
|---|---|---|
~/.claude/CLAUDE.md | User-wide (all projects) | Every session, regardless of repo |
./CLAUDE.md | Project root | Sessions started inside this project |
./.claude/CLAUDE.md | Project (alternate location) | Same as project root |
./some-dir/CLAUDE.md | Directory-specific | When working inside that subdirectory |
This means user-level CLAUDE.md is for your preferences (e.g., “I prefer tabs,” “default to TypeScript”), and project-level CLAUDE.md is for team conventions (e.g., “use Mediator,” “tests must use FluentAssertions”).
Use /init to generate a starter file interactively, or /memory to open and edit the project’s file directly from a Claude session.
What to put in it
Good content in CLAUDE.md is high-signal: rules and context Claude can’t infer from looking at the code. Examples:
- Conventions that aren’t obvious from the code. “We commit migrations as
YYYYMMDDHHMMSS_descriptive_name.sql” — Claude won’t deduce that from existing files unless there are dozens. - Decisions and their rationale. “We don’t use Entity Framework lazy loading anywhere — we got burned in 2024 by N+1 queries in production.” Telling Claude why prevents it from helpfully suggesting EF lazy loading.
- Tooling preferences. “Use
pnpm, notnpm. Usevitest, notjest.” Saves Claude from guessing wrong. - Repo structure. A short map: “src/api → REST endpoints, src/services → domain logic, src/db → Dapper repos.” Helps Claude navigate without grepping the whole tree.
- Things to never do. “Never edit the generated
*.g.csfiles. Never commit tomasterdirectly.” Prevents whole categories of mistakes.
What NOT to put in it
CLAUDE.md is loaded every session. Bloating it has a cost — Claude has to process it on every turn, and the more it has to consider, the higher the chance it latches onto irrelevant rules.
Avoid:
- Onboarding documentation. “How to get the project running locally” belongs in README.md, not CLAUDE.md. Claude doesn’t run your project locally.
- Detailed domain explanations. A 2,000-word explanation of how your billing system works will dominate the context. Better to have a short pointer (“billing logic lives in src/billing — read the spec at docs/billing.md when needed”) and let Claude pull the detail on demand.
- Outdated rules. A rule that no longer applies actively misleads Claude. Review and prune periodically.
- Things obvious from the code. Claude can read
package.jsonto learn what frameworks you use. It can read existing files to learn naming conventions. CLAUDE.md is for what isn’t in the code.
Keep it lean. A bloated CLAUDE.md reduces effectiveness — Claude has to process all of it every session. Review it periodically and remove anything outdated or unnecessary. The best CLAUDE.md files are short, surgical, and updated as you learn what tripped Claude up most recently.
A reasonable starter shape
Most project CLAUDE.md files end up looking something like this:
# Project context
## Tech stack- .NET 8, C#, Mediator pattern- Postgres + Dapper (no EF)- xUnit + FluentAssertions for tests
## Conventions- snake_case for SQL columns, PascalCase for classes- Migrations: YYYYMMDDHHMMSS_descriptive_name.sql- Never commit to master — always PR
## Repo map- src/api/ REST controllers- src/services/ business logic- src/db/ Dapper repos- tests/ xUnit projects
## Gotchas- Don't use EF lazy loading (N+1 risk — see post-incident doc)- The `worker` project requires Redis on localhost:6379Once you have that, every friction point is a CLAUDE.md update. Claude got the test naming wrong? Add a rule. Claude reached for the wrong logger? Add a rule. The file grows surgically, never with prose.