Originally published at heycc.cn. This is a mirrored copy — the canonical version is kept up to date at the source.
Claude Code CLAUDE.md and Memory: How to Use Them in 2026
Every Claude Code session starts with an empty context window. Nothing you taught it yesterday carries over by default. Two mechanisms close that gap: CLAUDE.md files that you write, and auto memory that Claude writes for itself. Used well, they turn a forgetful assistant into one that knows your build commands, your conventions, and the bug you both fixed last week. Used badly, they bloat your context and Claude follows them inconsistently.
What follows pins down exactly where these files live, the order they load, the import and rules systems layered on top, and the one situation where a hook beats memory outright. Every claim traces to the official Claude Code memory documentation listed in Sources.
The two memory systems, side by side
The most common confusion is treating CLAUDE.md and auto memory as the same thing. They are not. One is instructions you author; the other is notes Claude takes. Both load at the start of every conversation, and crucially, both are treated as context, not enforced configuration. Claude reads them and tries to comply, but there is no guarantee of strict adherence.
| Dimension | CLAUDE.md files | Auto memory |
|---|---|---|
| Who writes it | You | Claude |
| Contents | Instructions, standards, workflows | Learnings, build commands, debugging insights |
| Scope | Project, user, or org | Per git repository, shared across worktrees |
| Loaded into | Every session, in full | Every session (first 200 lines or 25KB of MEMORY.md) |
| Where it lives | Your repo and home dir | ~/.claude/projects/<project>/memory/ |
| Edit method | You write markdown | Claude writes; you can edit or delete |
If you want to guide behavior, write CLAUDE.md. If you want Claude to learn from your corrections without manual effort, leave auto memory on. They complement each other rather than compete.
Where CLAUDE.md files live and the order they load
CLAUDE.md files can sit in four scopes. They load from broadest to most specific, so a project instruction appears in context after a user instruction. Within the user, project, and local layers, the more specific file is the last one Claude reads, which is why a project rule tends to take hold over a contradicting personal one.
| Scope | Location | Use for |
|---|---|---|
| Managed policy | macOS: /Library/Application Support/ClaudeCode/CLAUDE.md; Linux/WSL: /etc/claude-code/CLAUDE.md; Windows: C:\Program Files\ClaudeCode\CLAUDE.md
|
Org-wide standards, security policy |
| User | ~/.claude/CLAUDE.md |
Personal preferences across all projects |
| Project |
./CLAUDE.md or ./.claude/CLAUDE.md
|
Team-shared, version-controlled instructions |
| Local | ./CLAUDE.local.md |
Personal per-project notes (gitignore this) |
Managed policy is the one scope that stands apart, and it is easy to get backwards. Its CLAUDE.md loads before user and project files, as the broadest layer, and it cannot be excluded by individual settings, which is why organizations deploy it via MDM or Group Policy for compliance. But "loads first" describes order, not a guaranteed conflict winner for text. Here is the part worth internalizing: a CLAUDE.md is non-enforced context, so if a managed policy says 4-space indentation and a project CLAUDE.md says 2-space, the docs do not promise either one wins. With contradictory instructions, Claude "may pick one arbitrarily." Do not assume the project file overrides the org policy — that claim is unsupported, and if anything the managed layer is the documented top of the stack.
If you need a behavior that must hold regardless of what Claude decides, do not express it as competing CLAUDE.md text at all. Managed settings (permissions.deny, sandbox.enabled, and friends in managed-settings.json) are enforced by the client no matter what Claude does. CLAUDE.md shapes behavior; settings enforce it. That split is the real precedence story.
Beyond the named scopes, Claude Code also walks up the directory tree from wherever you launched it. Run Claude in foo/bar/ and it concatenates foo/bar/CLAUDE.md, foo/CLAUDE.md, and any CLAUDE.local.md alongside them. These are concatenated, never overridden, ordered from filesystem root down to your working directory, so the file closest to where you launched is read last. Within a directory, CLAUDE.local.md is appended after CLAUDE.md, so your personal notes are the final word at that level.
Generate a starting file with /init
You do not have to write CLAUDE.md from scratch. Run /init and Claude analyzes the codebase, then creates a file with build commands, test instructions, and the conventions it discovers. If a CLAUDE.md already exists, /init suggests improvements rather than overwriting it, so it is safe to re-run.
/init is also AGENTS.md-aware: in a repo that already has one, it reads AGENTS.md and incorporates the relevant parts into the generated CLAUDE.md, along with configs like .cursorrules and .windsurfrules. If you want a similar structured starting point for a different tool, our guide to writing Cursor rules covers the same ideas from the Cursor side.
Importing files with @path
CLAUDE.md can pull in other files using @path/to/import syntax. The imported content expands into context at launch, right alongside the file that referenced it.
See @README for project overview and @package.json for npm commands.
# Additional Instructions
- git workflow @docs/git-instructions.md
- @~/.claude/my-project-instructions.md
A few rules govern imports:
- Both relative and absolute paths work. Relative paths resolve relative to the file containing the import, not your working directory.
- Imports recurse up to four hops deep. An imported file can import another, and so on, to a maximum depth of four.
-
Code spans and fenced blocks are skipped. Wrap a path in backticks to mention it without importing:
`@README`stays literal, while@READMEoutside backticks imports. - External imports require approval once. The first time Claude Code sees them it shows a dialog listing the files. Decline and those imports stay disabled, with no repeat prompt.
One persistent myth deserves a direct answer: splitting CLAUDE.md into @path imports does not reduce context usage. Imported files still load and enter the context window at launch. Imports help organization, not token budget. If you actually need to cut context, you want path-scoped rules (below), not imports.
Reusing AGENTS.md
Claude Code reads CLAUDE.md, not AGENTS.md. If your repo already standardizes on AGENTS.md for other agents, the clean fix is a CLAUDE.md that imports it, then adds Claude-specific notes:
@AGENTS.md
## Claude Code
Use plan mode for changes under `src/billing/`.
A symlink also works, but on Windows it needs Administrator privileges or Developer Mode, so the @AGENTS.md import is the portable choice.
Path-scoped rules with .claude/rules/
For larger projects, splitting instructions into .claude/rules/*.md keeps things modular. Each file covers one topic, discovered recursively so you can nest frontend/ and backend/ folders.
.claude/
├── CLAUDE.md
└── rules/
├── code-style.md
├── testing.md # loads every session
└── api-design.md # path-scoped, loads on demand
Rules come in two flavors, and this is where you reclaim context:
-
Rules without a
pathsfrontmatter field load every session at the same priority as.claude/CLAUDE.md. They are always in context. -
Path-scoped rules declare a YAML
pathsfield and load only when Claude works with matching files.
---
paths:
- "src/api/**/*.ts"
---
# API rules
- All endpoints must include input validation.
- Use the standard error response format.
That API rule costs zero context until Claude touches a matching TypeScript file. This is the real lever for trimming startup tokens. User-level rules in ~/.claude/rules/ load before project rules, giving project rules higher priority.
Auto memory: notes Claude takes for itself
Auto memory requires Claude Code v2.1.59 or later (check with claude --version). It is on by default. As Claude works, it saves build commands, debugging insights, and preferences it discovers, deciding what is worth keeping for a future session.
Storage is per git repository at ~/.claude/projects/<project>/memory/. Because the path derives from the repo, all worktrees and subdirectories of the same repo share one directory. It is machine-local and not shared across machines or cloud environments. Inside that directory, a MEMORY.md file acts as the index, and Claude offloads detail into topic files like debugging.md or api-conventions.md that it reads on demand.
The load rule is specific and worth memorizing: only the first 200 lines of MEMORY.md, or the first 25KB, whichever comes first, enter context at session start. Everything past that threshold, and every topic file, loads only when Claude reaches for it with its normal file tools. That is why Claude keeps MEMORY.md lean — it is a table of contents, not a dumping ground. To audit or prune what Claude has stored, run /memory, which lists every loaded CLAUDE.md, CLAUDE.local.md, and rules file, toggles auto memory, and links straight to the memory folder.
When to skip memory and reach for a hook
CLAUDE.md and memory are context. Both can be ignored under load, on a bad day, or when two instructions disagree. So there is a clear line: if an action must happen at a specific lifecycle moment — run make lint before every commit, reformat after every edit, block a write to a protected path — do not write it as a CLAUDE.md rule and hope. Write it as a hook.
Hooks execute as shell commands at fixed events and apply regardless of what Claude decides. A PreToolUse hook that exits non-zero hard-blocks the action before the permission check even runs. That is enforcement; CLAUDE.md is guidance. The same logic extends to managed settings: permissions.deny is enforced by the client, while a managed CLAUDE.md merely nudges. Pick the layer that matches your stakes.
| You want to... | Use | Why |
|---|---|---|
| Suggest a convention Claude usually follows | CLAUDE.md | Context, easy to author, but not guaranteed |
| Let Claude learn from your corrections automatically | Auto memory | Zero manual effort; Claude decides what to keep |
| Trim startup context on a big repo | Path-scoped rules | Load only when matching files are touched |
| Guarantee a step runs at a lifecycle event | Hook | Executes as a shell command, not optional |
| Hard-block a tool, command, or path org-wide | Managed settings (permissions.deny) |
Enforced by the client regardless of Claude |
Layering the four mechanisms
A healthy setup layers these deliberately. A short project CLAUDE.md (aim for under 200 lines) carries the conventions everyone shares. Path-scoped rules under .claude/rules/ hold the instructions that only matter in one corner of the codebase, so they cost nothing until needed. A gitignored CLAUDE.local.md keeps your personal sandbox URLs out of everyone else's context. Auto memory quietly accumulates the build commands and debugging lessons you would otherwise re-explain. And for the handful of rules that genuinely cannot be optional, a hook or a managed setting does the enforcing.
The mistake to avoid is treating every layer as interchangeable. Imports are for organization, not token savings. Managed policy CLAUDE.md is the broadest layer and cannot be turned off, but it still ships behavioral context, not a guaranteed override of conflicting text — only managed settings are hard-enforced. Get those distinctions right and memory stops being a source of surprise.
Reading this against the official docs
The claims here lean almost entirely on the Claude Code memory documentation (read 2026-06-28). It is that page that frames CLAUDE.md and auto memory as context, not enforced configuration with no guarantee of strict adherence, that documents managed policy CLAUDE.md as loading before user and project files and as not excludable by individual settings, and that — pointedly — stops short of saying a project CLAUDE.md overrides managed policy on a content conflict, telling readers instead that Claude "may pick one arbitrarily" between contradicting instructions. The same page supplies the MEMORY.md load limit ("first 200 lines or 25KB"), the four scopes with their exact managed-policy paths, the import rules (relative-path resolution, four-hop depth, code-span skipping, one-time external-import approval), the .claude/rules/ behavior, and the v2.1.59 auto-memory minimum — all matching verbatim or near-verbatim. The claim that hard enforcement belongs to managed settings like permissions.deny and to hooks, never to CLAUDE.md text, draws on the Settings and Hooks references alongside it. Version numbers are the detail most worth re-confirming on the live page before you rely on one.

Top comments (0)