TL;DR
CLAUDE.md is a plain-Markdown instruction file that Claude Code loads at the start of every session and re-reads after /compact. Put a project file at ./CLAUDE.md (or ./.claude/CLAUDE.md), commit it, and keep it under 200 lines. Cover five things: build/test/lint commands, conventions, forbidden paths, project layout, and “always do X” rules. Generate a first draft with /init, then refine. As of June 2026, Claude Code also keeps auto memory (notes it writes itself), so you no longer hand-write everything — and the old # “add to memory” shortcut is gone.
What CLAUDE.md actually is
It is not a README for humans. According to the official Claude Code memory docs, CLAUDE.md content is delivered as a user message right after the system prompt, then loaded into the context window at the start of every session. So it is durable context, not enforced configuration: Claude reads it and tries to follow it, but there is no hard guarantee. The more specific and concise the instructions, the more reliably they stick.
That single fact drives every rule below. Because it competes for tokens with your actual conversation, and because vague lines get skimmed, the goal is a short file of concrete, verifiable rules — not a wiki.
This guide is for engineers running Claude Code on a real project who keep hitting the same friction: it ignores your import order, edits files you said to leave alone, runs the wrong test command, or rewrites idioms it should have followed.
Two memory systems, June 2026
Claude Code has shipped two complementary memory mechanisms, and they are both loaded at the start of every conversation. Knowing which is which decides what you should write by hand.
| CLAUDE.md files | Auto memory | |
|---|---|---|
| Who writes it | You | Claude |
| Contains | Instructions and rules | Learnings Claude discovered |
| Scope | Project, user, or org | Per git repository |
| Loaded | In full, every session | First 200 lines / 25 KB of MEMORY.md, every session |
| Best for | Standards, workflows, architecture | Build commands, debug insights, preferences it picks up |
Auto memory requires Claude Code v2.1.59 or later (check with claude --version) and is on by default. It lives at ~/.claude/projects/<project>/memory/, keyed off the git repo, so all worktrees in the same repo share it. When you see “Writing memory” or “Recalled memory” in the UI, that is auto memory, not your CLAUDE.md. Browse or disable it with /memory, or set CLAUDE_CODE_DISABLE_AUTO_MEMORY=1.
Practical upshot: do not spend CLAUDE.md lines on things Claude reliably learns after one session. Reserve the file for what it would otherwise re-derive or get wrong every time.
Where the file goes (and the load order)
CLAUDE.md can live at several scopes. They are concatenated, not overridden, in this load order — broadest first, so the most specific instruction is read last and wins ties:
| Scope | Location | Committed? |
|---|---|---|
| Managed policy (org) | macOS /Library/Application Support/ClaudeCode/CLAUDE.md; Linux/WSL /etc/claude-code/CLAUDE.md; Windows C:\Program Files\ClaudeCode\CLAUDE.md | Pushed by IT/MDM |
| User (personal) | ~/.claude/CLAUDE.md | No (your machine) |
| Project (team) | ./CLAUDE.md or ./.claude/CLAUDE.md | Yes, via source control |
| Local (private) | ./CLAUDE.local.md | No — add to .gitignore |
Claude walks up the directory tree from your working directory and loads every CLAUDE.md and CLAUDE.local.md it finds along the way, in full, at launch. Files in subdirectories below you are loaded on demand, only when Claude reads a file in that subdirectory. Within a directory, CLAUDE.local.md is appended after CLAUDE.md, so your personal notes are read last at that level.
For a monorepo, that means a root CLAUDE.md with global rules plus a per-package frontend/CLAUDE.md or services/api/CLAUDE.md for stack-specific rules. If an ancestor file from another team leaks in, exclude it with claudeMdExcludes in .claude/settings.local.json (glob patterns against absolute paths).
Generate the first draft with /init
Do not start from a blank file. Run /init in the repo: Claude analyzes the codebase and writes a starting CLAUDE.md with the build commands, test instructions, and conventions it can detect. If a CLAUDE.md already exists, /init suggests improvements instead of overwriting. It also reads existing AGENTS.md, .cursorrules, .devin/rules/, and .windsurfrules and folds the relevant parts in. Setting CLAUDE_CODE_NEW_INIT=1 enables an interactive multi-phase flow that asks follow-up questions and shows a reviewable proposal before writing.
Treat the generated file as a draft. The high-value content is what /init cannot discover: your unwritten conventions, forbidden paths, and the mistakes you are tired of correcting.
What to actually put in it
Five sections carry almost all the value. Keep each rule concrete enough to verify, with a tiny example.
- Project summary — 3 to 5 sentences: what it is, primary entry points. Example:
Next.js 15 app, App Router, deployed via Vercel. Entry: app/page.tsx. Background jobs: lib/jobs/*.ts. - Build / test / lint commands — the single most valuable section. Without it, Claude tries
npm testwhen you usepnpm test --runand burns turns debugging. Be exact:Test: pnpm test --run. Lint: pnpm lint. Type: pnpm typecheck. Run all three before declaring a task done. - Conventions, each with an example — “Use named exports, no default exports” beats “write clean code.” The docs’ own benchmark: “Use 2-space indentation” works; “format code properly” does not.
- Forbidden paths — be explicit:
Do not edit src/generated/*, prisma/migrations/*, or any file matching *.gen.ts.Claude honors this well. - Per-task hints — a short “When asked to add a route” block naming the files to touch and the order. Same for components, migrations, and tests.
Keep a small “Corrections” section at the bottom and add a line whenever you catch the agent drifting. Block-level HTML comments (<!-- maintainer note -->) are stripped before the content reaches Claude, so use them for human-only notes without spending context tokens.
Stay under 200 lines
The docs target under 200 lines per CLAUDE.md file. Longer files consume more context and measurably reduce adherence — rules at the bottom get skimmed. When it grows, you have three options that beat a giant file:
- Path-scoped rules. Put topic files in
.claude/rules/(for exampletesting.md,security.md). Add apaths:frontmatter glob like"src/api/**/*.ts"and the rule only loads when Claude touches matching files, saving context the rest of the time. Rules withoutpathsload every session at the same priority as.claude/CLAUDE.md. - Imports. Reference other files with
@path/to/filesyntax anywhere in CLAUDE.md. Relative paths resolve against the importing file; recursion is capped at four hops. Note: imports help organization but not context size, since imported files still load at launch. - Skills. Move multi-step procedures into a skill, which only loads when invoked or judged relevant — not on every session.
Reuse AGENTS.md instead of duplicating
Claude Code reads CLAUDE.md, not AGENTS.md. If your repo already keeps an AGENTS.md for other agents, do not copy it. Create a one-line CLAUDE.md that imports it, then add Claude-specific lines below:
@AGENTS.md
## Claude Code
Use plan mode for changes under `src/billing/`.
A symlink (ln -s AGENTS.md CLAUDE.md) also works when you have nothing Claude-specific to add; on Windows use the @AGENTS.md import since symlinks need Administrator rights.
Editing memory mid-session
The old # prefix that prepended a line to memory was removed. As of June 2026 you have two clean paths: run /memory to list every loaded CLAUDE.md, CLAUDE.local.md, and rules file and open any of them in your editor, or just tell Claude “add this to CLAUDE.md” in chat. Asking Claude to “remember” something without naming the file routes it to auto memory instead.
When CLAUDE.md is not the right tool
CLAUDE.md shapes behavior; it does not enforce it. If a rule must run at a fixed point — before every commit, after every edit — write a hook instead. Hooks execute as shell commands at lifecycle events regardless of what Claude decides, so “block edits to migrations/” or “run make lint before commit” belong there, not in prose. To force an instruction into the system prompt itself, pass --append-system-prompt (better for scripts than interactive use).
First-run exercise
- Skim a recent PR you reviewed in this repo. Write down your top 3 nitpicks.
- Convert each into a one-sentence rule in CLAUDE.md, with a tiny example.
- Run a small Claude Code task that touches similar code. Confirm it follows the rules.
- If it ignored one, sharpen the wording (concrete example beats abstract principle) and re-run.
Quality check before you commit
- Run
/memoryand confirm the file is actually listed as loaded. If it is not there, Claude cannot see it. - Is it under 200 lines and roughly one to two screens?
- Are commands copy-pasteable exactly as written? “run tests” confuses;
pnpm test --rundoes not. - Does each rule carry a concrete example? Abstract rules regress.
- Scan for contradictions across your root, nested, and
.claude/rules/files — conflicting guidance gets resolved arbitrarily.
FAQ
- How long should CLAUDE.md be? Target under 200 lines. The file loads in full regardless of length, but longer files consume more context and reduce adherence; rules at the bottom get skimmed.
- Why isn’t Claude following my CLAUDE.md? Most often the file is not loaded (check with
/memory), the rule is too vague, or two files conflict. CLAUDE.md is context, not enforcement — for must-run rules use a hook. - Should secrets go in CLAUDE.md? No. It is committed source. Reference env var names, not values. Put personal, gitignored bits in
CLAUDE.local.md. - What’s the difference between CLAUDE.md and auto memory? You write CLAUDE.md (standards, rules). Claude writes auto memory (build commands, debug insights it discovers). Both load every session; auto memory needs v2.1.59+ and is on by default.
- Do nested CLAUDE.md files survive
/compact? The project-root file is re-read from disk after compaction. Nested subdirectory files are not re-injected automatically — they reload the next time Claude reads a file in that subdirectory. - Do I need one for a solo project? Even a 15-line file helps. Without it, Claude re-derives your conventions every session.
Common mistakes
- Writing it once and never updating — agent behavior shifts and the file goes stale. Add a line each time you correct the same thing twice.
- Vague constraints (“write clean code”) instead of verifiable ones (“named exports, no default exports”).
- Letting it grow past 200 lines instead of moving topics into
.claude/rules/or skills. - Mixing human-onboarding content with agent rules — keep README.md and CLAUDE.md separate.
- Omitting forbidden paths — the agent will eventually edit generated code if you do not say not to.
- Skipping the exact test/lint/build commands — the agent guesses, often wrongly.
- Hand-writing things auto memory already learned — wasted lines. Run
/memoryto see what it figured out on its own.
Related
- Claude Code does not understand project
- Claude Code beginner guide
- Claude Code project setup
- AI coding context management
- Claude Code slash commands
- Claude Code vs Cursor
Tags: #AI coding #Tutorial #Claude Code