Claude Code memory: CLAUDE.md, rules and auto memory
PLClaude Code memory is two mechanisms that carry knowledge between sessions: CLAUDE.md files and .claude/rules/ that people write, and auto memory that Claude writes for itself. All of them load as context, concatenated rather than overriding one another, so they guide Claude but never enforce anything. Anything that must always happen belongs in a hook or a permission rule.
A new teammate asks Claude Code to “add an endpoint for refunds”. Claude writes an Express route in JavaScript under src/routes/, while your service is Fastify, TypeScript-only, and keeps handlers in src/api/v2/. Two weeks later a senior engineer’s session gets it right, because their personal ~/.claude/CLAUDE.md happens to say so, and the team argues about whether “the AI” is reliable. The model is the same in both sessions. The context it was given is not.
This page is for the developer who owns a repository’s agent setup and for the tech lead who wants the same behaviour from every session on the team. It assumes Claude Code is installed and has been run once in the repository; if not, start with project initialization.
What you get from a working Claude Code memory setup
Section titled “What you get from a working Claude Code memory setup”- A map of every file Claude Code loads, when it loads, and who else sees it
- A five-step setup for a new or existing repository, with a prompt that grounds
/initoutput in how the repo really works - A decision table for where each instruction belongs:
CLAUDE.md, a path-scoped rule, a local file, a skill, a hook, or nowhere - Four copy-paste prompts: bootstrap, audit, compress, and promote auto memory into
CLAUDE.md - A verification routine that proves the files loaded and are obeyed, without reading every diff
- Failure modes with the command that diagnoses each one
Which memory files does Claude Code load, and when?
Section titled “Which memory files does Claude Code load, and when?”Every file below is read as context. None of them overrides another: Claude Code concatenates them, from the broadest scope to the most specific, and within a directory CLAUDE.local.md comes after CLAUDE.md. When two instructions conflict, Claude may follow either one, so the fix for a conflict is to delete one of them, never to rely on order.
| Scope | Location | Loads | Shared with |
|---|---|---|---|
| Managed policy | macOS /Library/Application Support/ClaudeCode/CLAUDE.md, Linux and WSL /etc/claude-code/CLAUDE.md, Windows C:\Program Files\ClaudeCode\CLAUDE.md, or the claudeMd key in managed settings | At launch; cannot be excluded | Everyone on the machine |
| User | ~/.claude/CLAUDE.md and ~/.claude/rules/*.md | At launch | You, in every project |
| Project | ./CLAUDE.md or ./.claude/CLAUDE.md, plus any CLAUDE.md in directories above the one you launched from | At launch | The team, through git |
| Project rules | .claude/rules/**/*.md | At launch, or only when Claude reads a matching file if the rule has paths frontmatter | The team, through git |
| Local | ./CLAUDE.local.md | At launch, right after the CLAUDE.md in the same directory | You, in this checkout. Add it to .gitignore yourself |
| Subdirectory | packages/web/CLAUDE.md and similar, below the launch directory | When Claude reads a file in that directory | The team, through git |
| Auto memory | ~/.claude/projects/<project>/memory/MEMORY.md plus topic files | First 200 lines or 25 KB of MEMORY.md at launch; topic files on demand | You, on this machine, across all worktrees of the repo |
Three details from the official memory reference change how you write these files:
- Size. Anthropic’s target is under 200 lines per
CLAUDE.md. Claude Code loads a file of up to 4 MiB in full and skips a larger one, and warns at startup (and in/status) when a file, or all files together, pass the recommended length. - Delivery.
CLAUDE.mdcontent arrives as a user message after the system prompt. That is the mechanical reason it is advisory. - Comments. Block-level HTML comments (
<!-- note for maintainers -->) are stripped before injection. Use them for notes to humans that should cost no tokens.
AGENTS.md fits into the same table. From v2.1.277, Claude Code reads AGENTS.md when there is no CLAUDE.md, .claude/CLAUDE.md or CLAUDE.local.md in the launch directory or above it; sessions on Amazon Bedrock, Google Cloud, Microsoft Foundry, an LLM gateway or with telemetry off need v2.1.281. Both versions are on the latest and stable release channels since stable reached v2.1.287 (checked 2026-10-12); an older build still needs the @AGENTS.md import shown below. The Project instructions setting in /config changes the default, for example to claude-md-and-agents-md to read both.
Where does each instruction belong?
Section titled “Where does each instruction belong?”Most memory problems are routing problems: a line in the always-loaded file that only matters for one directory, or a “must” that only a hook can guarantee.
| The instruction is… | Put it in | Why |
|---|---|---|
| A fact every session needs: build, test and lint commands, a non-obvious convention, a decision you did not take the obvious way on | Project CLAUDE.md | Loads everywhere, reviewed like code |
| Only relevant to one part of the tree (API handlers, migrations, React components) | .claude/rules/<topic>.md with paths | Loads only when Claude reads a matching file |
| A multi-step procedure you run sometimes (release, incident triage) | A skill | Loads when invoked or judged relevant, not every session |
Something that must happen every time (format on edit, block git push --force) | A hook or a permissions.deny rule | Executes regardless of what Claude decides |
| Your own sandbox URL, local port, or test account | CLAUDE.local.md | Personal and uncommitted |
| A preference you hold in every repo | ~/.claude/CLAUDE.md or ~/.claude/rules/ | Follows you, not the project |
| A company-wide policy reminder | Managed CLAUDE.md | Every user on the machine, cannot be excluded |
| Architecture summaries, directory maps, dependency lists | Nowhere | Claude derives them from the code, and a written copy goes stale |
The last row is the one teams resist. The cross-tool argument for deleting rather than adding, with a protocol for testing each cut, is in Pruning CLAUDE.md and AGENTS.md.
Set up memory for a repository
Section titled “Set up memory for a repository”-
Generate a draft with
/init. Inside a session in the repository root, run/init. Claude analyses the codebase and writes aCLAUDE.md, or suggests improvements if one already exists. It also folds in Cursor rules (.cursor/rules/,.cursorrules) and.github/copilot-instructions.md. Moving over from another agent wholesale?/import codex|gemini|cursor(v2.1.213 and later; Cursor v2.1.265; not available on Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry or Claude Platform on AWS) appends a one-time copy of that agent’s instruction files, such asAGENTS.md, to the matchingCLAUDE.mdand carries over its MCP servers, commands, subagents and skills; run the audit prompt further down on the result.For an interactive flow, set
CLAUDE_CODE_NEW_INIT=1in your shell or in theenvblock of a settings file before you run/init. It then asks which artifacts to create (CLAUDE.mdfiles, skills, hooks), explores with a subagent, asks follow-up questions, and shows a proposal before writing. With the variable set,/initalso readsAGENTS.md,.windsurf/rules/,.devin/rules/and.clinerules, and its personal option createsCLAUDE.local.mdand adds it to.gitignore. -
Ground the draft in what the repo really does.
/initoutput tends to describe the file tree, which Claude can already see. Replace it with what Claude cannot derive, using the bootstrap prompt below. -
Move directory-specific rules out of the root file. Anything that applies to one area goes into
.claude/rules/with apathslist (see path-scoped rules). -
Add your personal layer. Put machine-specific details in
CLAUDE.local.mdand addCLAUDE.local.mdto.gitignore. If you work across several git worktrees, the local file exists only in the worktree where you created it, so import a home-directory file instead:@~/.claude/payments-api-personal.md. -
Confirm what loaded. Run
/contextand check the Memory files list. A file missing from that list is invisible to Claude, however good it is.
What a project CLAUDE.md that earns its lines looks like
Section titled “What a project CLAUDE.md that earns its lines looks like”This is the result for the refunds scenario above: 27 lines, each one something Claude would otherwise get wrong.
# Payments API
<!-- Owner: platform team. Review changes to this file like code. -->
## Commands- `pnpm dev` starts the API on port 3000; it needs Redis on localhost:6379- `pnpm test` runs Vitest; run it before you say a change is done- `pnpm typecheck` is the type gate; CI fails without it- `pnpm db:migrate` applies Prisma migrations to the local database only- `pnpm db:reset` DROPS the local database; never run it unless I ask
## Conventions- Fastify + TypeScript only. No Express, no `.js` source files- HTTP handlers live in `src/api/v2/<resource>/`, one file per route- Validate every request and response with the Zod schemas in `src/schemas/`- Errors are RFC 7807 problem details via `problem()` in `src/lib/errors.ts`- Log with `logger` from `src/lib/logger.ts`, never `console.log`
## Decisions that look wrong but are deliberate- Money is an integer number of cents (`amountCents`), never a float, because the ledger reconciles to the cent- We do not use Prisma transactions for refunds; `src/ledger/refund.ts` uses an outbox table so the provider call can be retried idempotently
## Never- Edit a migration file after it is merged; add a new migration- Add a dependency without asking firstTwo properties make it work. Every instruction is concrete enough to check (“run pnpm test before you say a change is done”, not “test your changes”), and every “why” is attached to the rule it justifies, so Claude can apply the rule to a case the file never mentions.
What to leave out matters as much. Emphasis stacks such as **ALWAYS**, MUST or IMPORTANT do not make a rule stick; when a rule is being ignored, the cause is usually length, vagueness or a contradiction elsewhere. A git workflow, PR etiquette or onboarding checklist that already lives in CONTRIBUTING.md does not need a second copy: import it, or leave it for Claude to read when a task needs it.
How do you split a large CLAUDE.md with imports?
Section titled “How do you split a large CLAUDE.md with imports?”CLAUDE.md can pull in other files with @path syntax anywhere in the text:
See @README.md for the product overview and @package.json for scripts.
## Git workflow- Follow @docs/git-workflow.mdRelative paths resolve from the file that contains the import, imports can nest up to four hops deep, and paths inside code spans or fenced blocks are not imported. Imports organise; they do not save context, because every imported file loads at launch. The first time a project imports a file outside the working directory, Claude Code asks you to approve external imports; declining disables them for that project.
If the repository already has an AGENTS.md for Codex or other agents, keep it as the single shared file and put Claude-specific additions in a small CLAUDE.md next to it:
@AGENTS.md
## Claude Code- Use plan mode for any change under `src/ledger/`The import works on every version and provider, including sessions that cannot read AGENTS.md directly. How Codex reads the same file is covered in AGENTS.md and skills in Codex.
Scope rules to part of the codebase
Section titled “Scope rules to part of the codebase”A file in .claude/rules/ without frontmatter loads in every session, with the same priority as .claude/CLAUDE.md. Add a paths list and it loads only when Claude reads a file that matches:
---paths: - "src/api/**/*.ts" - "src/schemas/**/*.ts"---
# API handler rules
- Every handler validates input and output with a Zod schema from `src/schemas/`- Return `ApiResponse<T>`; never return a raw Prisma model- Rate-limit public routes with the `rateLimit` plugin registered in `src/app.ts`What the reference documents about rule files, and what trips people up:
pathsis the only frontmatter field Claude Code reads (checked against v2.1.283, 2026-09-26). It accepts a YAML list or a comma-separated string, and brace expansion (src/**/*.{ts,tsx}).- If the YAML does not parse, Claude Code ignores the frontmatter and loads the rule everywhere. Run
claude --debugto see the parse error. - A rule triggers when Claude reads a matching file, not on every tool call. Until then, it is not in context.
.claude/rules/is searched recursively, sofrontend/andbackend/subfolders work.- For a monorepo where other teams’
CLAUDE.mdfiles load into your sessions, setclaudeMdExcludes(a list of globs matched against absolute paths) in.claude/settings.local.json. Claude Code in large codebases covers the full monorepo layout.
What auto memory saves, and how to keep it honest
Section titled “What auto memory saves, and how to keep it honest”Auto memory is on by default. As Claude works, it saves notes of four types (recorded in each file’s type frontmatter field): user (your role and preferences), feedback (corrections you give and approaches you confirm), project (ongoing work, deadlines and decisions it cannot derive from code or git), and reference (where outside information lives, such as a tracker or dashboard). It skips what it can derive from the codebase and what your CLAUDE.md already says. “Saved 2 memories” or “Recalled 2 memories” in the interface means it is reading or writing that directory.
MEMORY.md is an index, one line per memory. Only its first 200 lines or 25 KB, whichever comes first, load at launch; Claude Code nudges Claude to shorten it near the limit and returns an error when a write pushes it over. Topic files load only when Claude opens them. From v2.1.214, each memory file with frontmatter carries a modified timestamp, so you can see how old a fact is.
Three distinctions decide whether auto memory helps or quietly misleads:
- “Remember X” goes to auto memory, not
CLAUDE.md. Saying “remember that the API tests need a local Redis” saves a private note on your machine. To change the team’s file, say “add this to CLAUDE.md”, or open it with/memory. - It is machine-local. Your teammates, your CI runners and your cloud sessions never see it. A correction that matters to everyone has to be promoted into
CLAUDE.mdor a rule. - Subagents do not inherit it. The main conversation’s auto memory is not loaded into subagents (a fork is the exception). A subagent can keep its own with the
memoryfield; see custom subagents.
To turn it off, use the toggle in /memory (it writes autoMemoryEnabled to your user settings), set "autoMemoryEnabled": false in one project’s settings, or export CLAUDE_CODE_DISABLE_AUTO_MEMORY=1.
Capture a rule at the moment you correct Claude
Section titled “Capture a rule at the moment you correct Claude”The cheapest time to write a rule is right after Claude gets something wrong for the second time, or a code review catches something Claude should have known. Pick the destination by who needs it:
add to CLAUDE.md: we use pnpm, never npm or yarnremember that my local Postgres runs on port 5433The first line changes the shared file, which then goes through review with the rest of your diff. The second stays in your auto memory. Write the rule as specifically as you would write a prompt: “we use pnpm, never npm or yarn” is checkable, “remember our package manager” is not.
How do you prove the memory files work?
Section titled “How do you prove the memory files work?”A memory setup is only as good as its effect on the output, and you should not have to read every diff to know it is working. Check three things, from cheapest to strongest.
1. The file loaded. Run /context and read Memory files. For path-scoped rules and subdirectory files, which load later, log every load with the InstructionsLoaded hook. Add this to .claude/settings.local.json; it needs jq:
{ "hooks": { "InstructionsLoaded": [ { "hooks": [ { "type": "command", "command": "jq -c '{file: .file_path, scope: .memory_type, why: .load_reason, via: .trigger_file_path}' >> ~/.claude/instructions-loaded.log" } ] } ] }}load_reason is session_start, nested_traversal, path_glob_match, include or compact, and trigger_file_path names the file whose read pulled in a lazy load, so the log shows exactly when and why a rule entered the context. The hook is observability only: it cannot block or change loading. It also does not fire for an AGENTS.md that Claude reads directly through Project instructions (checked against v2.1.283, 2026-09-26); it does fire when a CLAUDE.md imports AGENTS.md, which is one more reason to keep the import.
2. The instruction is visible to the model. A headless probe asks Claude to quote what it was given, which separates a rule Claude never received from one it received and did not follow. Run it in the terminal from the directory whose rules you are testing:
claude -p "Without reading any files, quote word for word every instruction you were given about database migrations. If there is none, answer NONE."The probe sees only what loads at launch; to test a path-scoped rule, have it first read a file the rule matches (for example Read prisma/migrations/<latest>/migration.sql, then quote…).
3. The behaviour changed. Keep three representative tasks for the repository (for example: add an endpoint, add a migration, fix a failing test). After a change to memory, run each in a fresh session and let the existing gates judge the result: typecheck, lint, tests, and any hook that enforces a convention. A rule that no gate can check and that the probe cannot quote is a candidate for deletion.
Treat CLAUDE.md and .claude/rules/ as code: changes go through a pull request, the author pastes the probe output and the gate results into the description, and the tech lead who owns the agent setup approves it. Anything a gate already enforces does not need a sentence in memory; anything that must never happen belongs in a hook or permission rule, where it is enforced rather than requested.
How do you audit and compress a CLAUDE.md that has grown?
Section titled “How do you audit and compress a CLAUDE.md that has grown?”Files rot the same way everywhere: rules contradict each other, instructions outlive the code they described, and the file passes the length where Claude follows it reliably. Start a fresh session (/clear) so earlier conversation does not bias the review, then run the audit.
The built-in /doctor checkup (alias /checkup, v2.1.206 and later for this check) proposes the same kind of cut for a checked-in CLAUDE.md: it removes what Claude can derive from the codebase, keeps pitfalls, rationale and conventions that differ from tool defaults, and can move always-loaded guidance into skills or nested CLAUDE.md files. It reports first and asks before changing anything. After either route, run the three checks above again.
When Claude Code memory does not behave
Section titled “When Claude Code memory does not behave”Claude ignores an instruction. Run /context to confirm the file loaded. If it did, look for length, vagueness or a contradiction in another file: two conflicting rules mean Claude may pick either. Make the rule concrete and delete its rival. If the instruction must run at a fixed point, such as before every commit, move it to a hook.
An instruction disappears after /compact. The project-root CLAUDE.md is re-read from disk after compaction. Subdirectory CLAUDE.md files and path-scoped rules come back only when Claude next reads a matching file, and instructions you gave only in chat are gone. Put anything you want to survive into a file.
A path-scoped rule applies everywhere, or nowhere. Everywhere usually means the frontmatter failed to parse (so the rule loaded unconditionally) or the file has no paths at all; run claude --debug. Nowhere usually means a glob that does not match, or a [ in a pattern that is not a valid bracket expression. Test with a plain pattern such as src/**/*.ts first.
AGENTS.md is not being read. Any CLAUDE.md, .claude/CLAUDE.md or CLAUDE.local.md in the launch directory or above it takes precedence, including a local file you created for your own notes. Check claude --version: v2.1.277 or later, or v2.1.281 on Bedrock, Google Cloud, Foundry, a gateway or with telemetry off. If Project instructions is missing from /config, the built-in agents-md plugin is disabled or the version is too old, and the first session after an upgrade can still skip the file. The fix that works on every version is a CLAUDE.md containing @AGENTS.md.
Your CLAUDE.local.md ended up in a commit. Claude Code does not gitignore it for you (checked against v2.1.283, 2026-09-26; only the CLAUDE_CODE_NEW_INIT=1 personal option does). Add it to .gitignore, remove it from the index with git rm --cached CLAUDE.local.md, and move anything secret out of it.
Teammates get different behaviour from the same repo. Compare their /context Memory files lists. User-level files and rules load alongside project files, and a user rule that conflicts with a project rule is followed unpredictably. Ask everyone to keep project conventions out of ~/.claude/.
Auto memory holds something wrong. Run /memory, open the auto memory folder, and edit or delete the file. A stale memory is worse than none, because Claude trusts it. If MEMORY.md is past 200 lines, entries beyond that point are not loaded at all; ask Claude to consolidate the index.
A CI or scripted run ignores the project’s memory. claude --bare skips CLAUDE.md discovery and auto memory by design. For jobs that check out untrusted code, run claude --bare --setting-sources "" --strict-mcp-config so that no project instructions, settings, hooks or MCP servers load; for trusted jobs that need the conventions, drop --bare or pass the rules explicitly with --append-system-prompt. The CI/CD guide covers which to use when.
The file states goals, not facts. “100% test coverage” in a repo at 40% makes Claude either nag on every change or ignore the rule. Write what is true today and track goals elsewhere.
Where to go next with Claude Code memory
Section titled “Where to go next with Claude Code memory”- Pruning CLAUDE.md and AGENTS.md: the ablation protocol for deciding which lines to delete, and when to re-run it after a model change
- Long-term context retention patterns: the same ideas across Claude Code, Codex and Cursor
- Hooks automation: turn the rules that must never be broken into enforcement
- Enterprise integration: deploy a managed
CLAUDE.mdand managed settings across an organisation - Cursor project rules: the equivalent mechanism if part of your team works in Cursor