AI Agents
How Claude Code remembers a project across sessions: where CLAUDE.md files load from, @imports, path-scoped rules, auto memory, and what to keep out of each.
You explain the test command to Claude Code on Monday, again on Tuesday, and on Wednesday it runs npm test in a pnpm monorepo. Every session starts with a fresh context window, so anything not written down is gone. Claude Code memory solves this in three places: CLAUDE.md files you write, rules scoped to parts of the codebase, and auto memory Claude writes itself. Here is where each loads from and what belongs in it.
Claude Code carries knowledge across sessions in two ways. CLAUDE.md files hold instructions you write: build commands, conventions, architecture. Auto memory holds notes Claude writes from your corrections and preferences. Both load at the start of every session as context, not as enforced configuration, so specific and concise instructions are followed far more reliably than long, vague ones.
CLAUDE.md files can live at four scopes. They load from the broadest to the most specific, so a project instruction appears in context after a user instruction:
| Scope | Location | Shared with |
|---|---|---|
| Managed policy | /Library/Application Support/ClaudeCode/CLAUDE.md (macOS), /etc/claude-code/CLAUDE.md (Linux and WSL), C:\Program Files\ClaudeCode\CLAUDE.md (Windows) | Everyone on the machine |
| User | ~/.claude/CLAUDE.md | Just you, all projects |
| Project | ./CLAUDE.md or ./.claude/CLAUDE.md | The team, through git |
| Local | ./CLAUDE.local.md (add it to .gitignore) | Just you, this project |
A few loading rules explain most surprises:
foo/bar/ and it loads foo/bar/CLAUDE.md and foo/CLAUDE.md, ordered from the filesystem root down, so the file closest to where you launched is read last.CLAUDE.md inside packages/api/ is included only when Claude reads files in that directory.<!-- notes --> are removed before injection, so you can leave notes for human maintainers at no token cost.Run /context in a session to see which memory files actually loaded, and /init to generate a starting CLAUDE.md from your codebase. The full reference is in the Claude Code memory documentation.
The official guidance is to keep each CLAUDE.md under 200 lines, and the reasoning is simple: every line costs context in every session, and adherence drops as files grow. Write instructions concrete enough to verify: "Run pnpm tsc --noEmit before committing" rather than "make sure types are right". A compact project file looks like this:
<!-- Maintainer note: keep this under 200 lines. Procedures go in skills. -->
# Orders service
## Commands
- Install: `pnpm install`
- Test one file: `pnpm vitest run path/to/file.test.ts`
- Typecheck before committing: `pnpm tsc --noEmit`
## Conventions
- API handlers live in `src/api/handlers/`, one file per route
- Money is stored as integer cents, never floats
- Log with `logger` from `src/lib/log.ts`, never `console.log`
## Gotchas
- Integration tests need a local Redis on port 6379
- `src/generated/` is produced by `pnpm codegen`; never edit it by hand
Service layout: @docs/architecture.md
Rules shared with other coding agents: @AGENTS.md
The @path lines are imports. Imported files are expanded into context at launch alongside the file that references them, relative paths resolve from the importing file, and imports can nest up to four hops deep. Imports help organization but do not save context, because imported files still load at startup. Wrap a path in backticks to mention it without importing it. If your repository already has an AGENTS.md for other tools, importing it from CLAUDE.md is the documented way to share one set of instructions, since Claude Code reads CLAUDE.md, not AGENTS.md.
Instructions that only matter for part of the codebase should not load for every task. Put them in .claude/rules/, one topic per file, and scope them with a paths field in YAML frontmatter:
---
paths:
- "src/api/**/*.ts"
---
# API handler rules
- Validate every request body with the Zod schema in the same folder
- Return errors with `problem()` from `src/api/errors.ts`
- Every new route needs an entry in `docs/api.md`
A path-scoped rule loads when Claude reads a file that matches one of its glob patterns. Rules without a paths field load at launch with the same priority as .claude/CLAUDE.md. Personal rules in ~/.claude/rules/ apply to every project on your machine and load before project rules, so the project wins when they overlap.
Browse ready-made Claude Code subagents for testing, security, MCP, performance and more, each downloadable as a Markdown file.
Browse the agent libraryAuto memory is on by default. As Claude works, it saves notes of four kinds, recorded as a type field in each file's frontmatter: user (your role and preferences), feedback (corrections and confirmed approaches), project (ongoing work and decisions the code does not show) and reference (where to find things outside the repository). It deliberately skips anything it can derive from the code or that your CLAUDE.md already says.
~/.claude/projects/<project>/memory/
├── MEMORY.md index: one line per memory, loaded every session
├── user_role.md one memory per file, read on demand
└── feedback_testing.md
The details that matter in practice:
MEMORY.md, whichever comes first. Topic files are read on demand with normal file tools.memory setting; the main conversation's memory is not loaded into subagents, except forks./memory lists every memory file, toggles auto memory, and opens the folder. The files are plain markdown you can edit or delete.To turn auto memory off for one project, set it in that project's settings:
{
"autoMemoryEnabled": false,
"claudeMdExcludes": ["**/other-team/CLAUDE.md"]
}
claudeMdExcludes is the monorepo companion setting: it skips CLAUDE.md files from other teams that the directory walk would otherwise pick up. You can also disable auto memory with the CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 environment variable.
| Put it in | When the content is | Example |
|---|---|---|
| Project CLAUDE.md | A fact every session needs | Test command, money stored as cents |
| .claude/rules/ with paths | Only relevant to certain files | API handler conventions |
| A skill | A multi-step procedure used sometimes | Release checklist |
| A hook | Something that must always happen | Block edits to generated files |
| Auto memory | A preference or correction Claude learned | "Prefers small commits" |
The hook row is the one teams skip most often. CLAUDE.md is delivered as context after the system prompt, so it shapes behaviour but cannot guarantee it. If an action must be blocked regardless of what Claude decides, write a PreToolUse hook; Claude Code hooks explained shows how. Procedures that do not need to sit in context every session belong in skills, covered in advanced Claude Code skills.
/doctor check that proposes trims for content Claude can derive from the codebase./compact, Claude re-reads the project-root CLAUDE.md from disk, but something you only said in conversation may be lost. If it matters, write it down./memory occasionally and delete what is no longer true.The best first step is small: run /init, cut the result to the 30 lines you would tell a new teammate on their first day, and add a line each time you catch yourself correcting Claude twice. For how memory interacts with delegated work, see the Claude Code subagents guide, and for memory in agents you build yourself, agent memory and context persistence.
Instructions you write live in CLAUDE.md files: ./CLAUDE.md or ./.claude/CLAUDE.md for the project, ~/.claude/CLAUDE.md for you personally, and CLAUDE.local.md for private project notes. Notes Claude writes itself, called auto memory, live in ~/.claude/projects/<project>/memory/ with a MEMORY.md index.
Aim for under 200 lines per file. Every line loads into context at the start of every session, and longer files reduce how reliably instructions are followed. Move procedures into skills, file-type rules into .claude/rules/ with a paths field, and detailed references into files Claude reads on demand.
You write CLAUDE.md, and it holds instructions: build commands, conventions, architecture. Claude writes auto memory, and it holds learnings: your corrections, preferences and project context it could not derive from the code. Both load at the start of each session; auto memory loads only the first 200 lines or 25KB of MEMORY.md.
Run /context to confirm the file actually loaded. If it did, the instruction is probably vague, contradicted by another memory file, or buried in a long file. CLAUDE.md is context, not enforcement, so anything that must always happen, such as running a linter before a commit, belongs in a hook.