CLAUDE.md and Memory Files
Project-scoped instructions, auto-loaded memory, and the per-user memory system. The highest-leverage customization point.
What it is#
CLAUDE.md is a plain-text instruction file that Claude Code automatically loads into context whenever a session opens in a directory containing it. It is the project’s persistent briefing to every future session — a file that tells the model the conventions of the codebase, the rules it must follow, the commands it should run, and the things it must not do.
Memory files are the same idea applied to user-scoped knowledge: a per-user directory of small markdown files that Claude Code can read and write to carry information across sessions. They live under ~/.claude/projects/<project>/memory/ and persist between conversations.
Together they are the most useful customization mechanism Claude Code offers. Most other features (slash commands, hooks, sub-agents) are valuable; these two are necessary.
When to use it#
CLAUDE.md is for anything that is true of the project:
- Conventions the team has agreed on (naming, formatting, file layout).
- Commands the model should run (
pnpm test,cargo build,make lint). - Constraints that aren’t obvious from the code (which branch is
main, what the deployment flow is, which APIs are vendored vs external). - Gotchas a new contributor would learn the hard way (we removed feature X because of incident Y; never modify file Z directly).
- A short style guide for prose (tone, voice, what we call things).
Memory files are for anything that is true of the user:
- Role and seniority context (
user is a senior backend engineer focused on data pipelines). - Preferences for collaboration (
prefers terse responses; skip trailing summaries). - Feedback the user has given on past sessions (
don't mock the database in tests — Q3 incident with mocked migrations). - References to external systems the user uses (
bugs are tracked in Linear project INGEST).
The split is deliberate: project files are shared with everyone who works on the repo; memory files travel with you. Don’t put user-specific preferences in CLAUDE.md, and don’t put project conventions in memory.
How it works#
Loading order and scope#
When a Claude Code session starts in ~/repos/my-app/, the loader looks for CLAUDE.md files at:
- Project root —
~/repos/my-app/CLAUDE.md. Loaded for any session under this tree. - Subdirectory — e.g.
~/repos/my-app/backend/CLAUDE.md. Loaded only when sessions open inside that subtree. Useful for monorepos where each package has its own conventions. - User-global —
~/.claude/CLAUDE.md. Loaded for every Claude Code session you run, regardless of project. Reserve for things that are true of you across every codebase you touch.
All three are concatenated into the system prompt. The model treats them as instructions: high-leverage, but not infinite — every line in CLAUDE.md is a line that costs tokens on every session.
Memory: the auto-memory system#
Under your user-config directory (typically ~/.claude/projects/-<encoded-project-path>/memory/), Claude Code maintains a small file-based memory:
MEMORY.md— an index file that lists pointers to all memory entries. Always loaded into the session’s context.- Individual memory files — markdown files with YAML frontmatter (
name,description,metadata.type). Linked fromMEMORY.md. Loaded on demand when relevant.
The model writes to these files when you tell it something worth remembering. The four memory types it tracks are user (role, preferences), feedback (corrections and confirmations), project (in-flight initiatives, dates, decisions), and reference (pointers to external systems).
The index is always present; the bodies are loaded only when needed. This is what makes the system scale beyond a few entries without burning context.
Configuration#
File location#
| Layer | Path | Loaded for |
|---|---|---|
| User-global | ~/.claude/CLAUDE.md | Every session, every project |
| Project root | <repo>/CLAUDE.md | Any session under the repo |
| Subdirectory | <repo>/<subdir>/CLAUDE.md | Sessions opening inside that subtree |
| Memory index | ~/.claude/projects/<encoded>/memory/MEMORY.md | Every session for that project |
| Memory entries | ~/.claude/projects/<encoded>/memory/*.md | On demand when relevant |
Structure#
CLAUDE.md is plain Markdown with no required frontmatter. Common sections:
## Commands- `pnpm dev` — start dev server- `pnpm test` — run vitest- `pnpm lint` — biome check (run before committing)
## ArchitectureKey things that aren't obvious from the file tree…
## Conventions- Prefer Edit over Write for existing files- No emojis in commits or docs unless explicitly asked- Force-pushing main is acceptable; the history has been squashed before
## Gotchas- Vercel build needs the `d2` CLI bootstrapped by scripts/build.sh- Pagefind requires `script-src 'wasm-unsafe-eval'` in CSPMemory files use a stricter frontmatter:
---name: prefers-terse-responsesdescription: Terse, no-summary response stylemetadata: type: feedback---
Skip trailing summaries; the user reads the diff.
**Why:** explicitly requested after the third long-summary turn.**How to apply:** any response that would end with "I changed X to Y" should just end after the change is made.Examples#
Minimal project CLAUDE.md#
This is an Astro 5 + Tailwind v4 site.
## Commands- `pnpm dev` — http://localhost:4321- `pnpm build` — sh scripts/build.sh- `pnpm test` — vitest run
## Conventions- Edit existing files; don't create new ones unless asked- No comments unless the WHY is non-obvious- Force-pushing main is acceptableSubdirectory CLAUDE.md in a monorepo#
# CLAUDE.md (backend/)
Python 3.12 service. Postgres 15 + Redis. uv-managed deps.
## Commands- `uv run pytest`- `uv run ruff check`
## Things not to do- Never modify migrations/ once committed — write a new migration insteadA feedback memory entry#
---name: no-polling-background-tasksdescription: Wait for notifications, don't chain polling Bashmetadata: type: feedback---
When a Bash command runs with `run_in_background: true`, do notchain a polling Bash after it. The system notifies when complete.
**Why:** the user pointed this out after a polling loop slowedthe conversation down twice in the same session.**How to apply:** any time you'd be tempted to `sleep N; check`,just stop and wait for the notification instead.Gotchas#
- Token cost is real. Every line of
CLAUDE.mdis in the system prompt of every session. A 500-lineCLAUDE.mdis fine; a 5000-line one starts to eat materially into the working context window. Prune aggressively. MEMORY.mdis the index, not a memory itself. Don’t put memory bodies in it — bodies go in separate files, pointers go inMEMORY.md. Past ~200 lines the index gets truncated.- Memory files can grow stale. A project-type memory about “the auth migration deadline of 2026-03-05” is wrong by April. The model should re-check before acting on a memory; treat memory as context, not as ground truth.
- User-global
CLAUDE.mdfollows you across repos. Keep it small and truly cross-cutting. Anything project-specific belongs in the project’sCLAUDE.md, not the user-global one. - No secrets.
CLAUDE.mdis committed to the repo; memory files live on disk in your user dir. Neither is the right place for tokens, keys, or credentials. - Subdirectory files don’t override the root — they concatenate. If you want to override a project-root rule for a subdirectory, write the override explicitly (“In this directory only, prefer X over Y”).
- The model can write to memory but the index update is two steps. When asking it to remember something, it writes the entry and updates
MEMORY.md. If you ever see an orphaned memory file with no pointer in the index, the second step failed — the entry is essentially invisible to future sessions.
Related features#
- Settings and Configuration
- Context Window and Token Budget
- The Conversation Loop
- Permission Rules and Allowlists
A short test for whether something belongs in CLAUDE.md
Ask: “Would a competent new contributor learn this from reading the code?” If yes, leave it out — it’s redundant. If no, and they’d waste an hour figuring it out, put it in. The best CLAUDE.md lines are the ones that prevent an hour of confusion at the cost of fifteen seconds of reading.