Every Claude Code session starts fresh. No memory of yesterday’s debugging session. No recollection of the architectural decision you explained three times last week. Unless you set up memory deliberately — and set it up well.
Claude Code has two memory mechanisms that work in fundamentally different ways. Understanding both, and knowing when each is the right tool, is the difference between a session that picks up exactly where you left off and one where you’re re-explaining the same constraints from scratch.
The Two-Layer Memory System
Claude Code carries knowledge across sessions through two complementary systems:
CLAUDE.md files are instructions you write explicitly. Team coding standards, architectural constraints, “always run tests before committing” — anything you want Claude to hold in context every session.
Auto memory is notes Claude writes itself. When Claude discovers your build command, corrects a mistake you’ve made before, or learns a debugging pattern that consistently works in your codebase, it saves that to ~/.claude/projects/<project>/memory/MEMORY.md.
Both load at session start. Neither is enforced configuration — Claude reads them as context, then acts. If you need something to actually be enforced regardless of what Claude decides, write it as a PreToolUse hook that blocks the action. The more specific and concise your instructions, the more consistently Claude follows them.
| CLAUDE.md files | Auto memory | |
|---|---|---|
| Who writes it | You | Claude |
| Contents | Instructions, rules, conventions | Build commands, debugging insights, preferences |
| Scope | Project, user, or org | Per repository, shared across worktrees |
| Loaded | Every session, in full | First 200 lines or 25KB of MEMORY.md at start; topic files on demand |
| Best for | Coding standards, workflow rules, architecture | Accumulated learnings from corrections |
CLAUDE.md Files: Scope and Load Order
CLAUDE.md files exist at four scope levels. They load in this order, from broadest to most specific:
1. Managed Policy (Organization-wide)
macOS: /Library/Application Support/ClaudeCode/CLAUDE.md
Linux: /etc/claude-code/CLAUDE.md
Windows: C:\Program Files\ClaudeCode\CLAUDE.md
Deployed via MDM or configuration management. Applies to every Claude Code session on the machine. Cannot be excluded by individual users. Cannot be overridden. Use it for company-wide coding standards and compliance requirements.
Organizations can also embed CLAUDE.md content directly in managed-settings.json:
{
"claudeMd": "Always run `make lint` before committing.\nNever push directly to main."
}
2. User Instructions
~/.claude/CLAUDE.md
Personal preferences that apply across all projects — your preferred coding style, shortcuts you use, tools you always want available. Private to your account.
3. Project Instructions
./CLAUDE.md
./.claude/CLAUDE.md (equivalent)
Team-shared instructions for this specific project. Commit this to version control. Focus on project-level facts: architecture, build commands, conventions, the services this codebase integrates with.
4. Local Instructions
./CLAUDE.local.md
Personal project-specific preferences that shouldn’t be committed. Your sandbox URLs, local database credentials, test data patterns. Add CLAUDE.local.md to .gitignore — running /init and choosing the personal option does this automatically.
How Load Order Works
When you run Claude Code from project/src/, it loads:
- Managed policy CLAUDE.md
~/.claude/CLAUDE.mdproject/CLAUDE.mdproject/src/CLAUDE.md- All
CLAUDE.local.mdfiles at each level
Files are concatenated in this order, so instructions closer to your working directory appear last — and last-read instructions generally carry more weight in context. Subdirectory CLAUDE.md files (below your working directory) load lazily when Claude reads files in those directories, not at session start.
Writing Effective CLAUDE.md Instructions
The 200-Line Budget
Target under 200 lines per CLAUDE.md. This is not a hard limit, but a practical one: longer files consume more of your context window and reduce adherence. Every line in CLAUDE.md is a line not available for your actual task.
When you find yourself writing a 400-line CLAUDE.md, that’s a signal to restructure. Move topic-specific instructions to .claude/rules/ with path scoping so they only load when relevant.
Specificity Over Generality
Vague instructions get ignored. Specific instructions get followed.
<!-- Weak — Claude will interpret "properly" in its own way -->
Format code properly.
<!-- Strong — verifiable, actionable -->
Use 2-space indentation. Run `npm run lint` before committing. Never use `var`.
<!-- Weak -->
Keep the codebase organized.
<!-- Strong -->
API handlers live in src/api/handlers/. Database models in src/db/models/.
Don't put business logic in route handlers.
When to Add to CLAUDE.md
The trigger for updating CLAUDE.md is almost always a repetition:
- Claude made the same mistake twice
- You typed the same correction you typed last session
- A code review caught something Claude should have known about your codebase
- A new contributor would need this context on day one
If it’s a piece of information that should persist across every session for everyone working on this project, it belongs in CLAUDE.md. If it’s a procedure that only matters sometimes, it probably belongs in a skill.
HTML Comments for Maintainers
Block-level HTML comments in CLAUDE.md are stripped before loading into Claude’s context:
<!--
Maintainer note: This rule exists because of the 2026 Q2 migration.
Remove after all services move to the v2 API.
See: internal/docs/api-v2-migration.md
-->
Always use the v2 API client from src/clients/api-v2.ts. Never import from src/clients/api-v1.ts.
The maintainer note doesn’t consume context. Claude only sees the rule.
Importing External Files
CLAUDE.md supports @path/to/file imports:
# Project Overview
See @README.md for project architecture.
Check @package.json for available npm commands.
# Git Workflow
@docs/git-workflow.md
Imports load at session start alongside the CLAUDE.md file. They can recurse up to 4 levels deep. Important: imports do not reduce context usage — everything loads regardless.
To share personal instructions across git worktrees, import from home:
@~/.claude/my-project-preferences.md
The .claude/rules/ System
For large codebases, .claude/rules/ is how you scale CLAUDE.md without bloat.
Directory Structure
your-project/
├── CLAUDE.md # Core instructions (keep under 200 lines)
└── .claude/
├── CLAUDE.md # Alternative location for project instructions
└── rules/
├── testing.md # Testing conventions
├── api-design.md # API design standards
├── security.md # Security requirements
├── frontend/
│ └── react-patterns.md
└── backend/
└── database.md
Rules without paths frontmatter load unconditionally at session start, equivalent to CLAUDE.md. Rules with paths frontmatter load only when Claude reads matching files.
Path-Scoped Rules
---
paths:
- "src/api/**/*.ts"
- "tests/api/**/*.test.ts"
---
# API Development Rules
All API endpoints require input validation using Zod schemas.
Use the standard error response format from src/utils/errors.ts.
Every endpoint needs an OpenAPI doc comment.
This TypeScript API rule only loads when Claude is working with TypeScript files in src/api/ or the corresponding test directory. It doesn’t consume context during frontend work, database migrations, or documentation tasks.
Common Glob Patterns
| Pattern | Loads when Claude works with |
|---|---|
**/*.ts | Any TypeScript file |
src/**/* | Any file under src/ |
*.md | Markdown in project root |
src/{api,db}/**/*.ts | TypeScript in api/ or db/ |
**/*.test.{ts,js} | Any test file |
Sharing Rules Across Projects with Symlinks
.claude/rules/ supports symlinks:
# Link a shared directory
ln -s ~/company-claude-rules .claude/rules/company
# Link a specific file
ln -s ~/security-standards/owasp-rules.md .claude/rules/security.md
Circular symlinks are detected and handled gracefully.
Auto Memory: How Claude Learns
What Gets Saved
Auto memory captures what Claude learns through your corrections and discoveries:
- Build commands and test invocations
- Project-specific debugging patterns
- Code style preferences you’ve enforced
- Architectural insights Claude discovers from reading the codebase
- Workflow habits that consistently work for this project
Claude doesn’t write to auto memory every session. It decides based on whether the information would be valuable in a future conversation. The auto memory save behavior is intentionally conservative — you won’t find it cluttered with trivia.
Storage Layout
~/.claude/projects/<project-hash>/memory/
├── MEMORY.md # Index, loaded at every session start (first 200 lines / 25KB)
├── debugging.md # Debugging patterns specific to this project
├── api-conventions.md # API design patterns Claude has learned
└── build-system.md # Build commands and configuration notes
The <project-hash> derives from the git repository root, so all worktrees in the same repo share one auto memory directory. This is intentional: knowledge about a codebase applies across branches.
The 200-Line / 25KB Threshold
Only the first 200 lines or 25KB of MEMORY.md load at session start. Content beyond this threshold is ignored at startup. Claude keeps MEMORY.md concise by moving detailed information into topic files (debugging.md, api-conventions.md, etc.), which it reads on demand using standard file tools.
This is different from CLAUDE.md files, which load in full regardless of length.
Configuring Auto Memory
Auto memory is on by default. Toggle it within a session:
/memory
Or set it in project settings:
{
"autoMemoryEnabled": false
}
Or via environment variable:
CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 claude
To store auto memory in a custom location (useful for shared team memory across projects):
{
"autoMemoryDirectory": "~/team-shared-memory/backend-services"
}
The path must be absolute or start with ~/.
Auditing and Editing Auto Memory
Everything auto memory saves is plain markdown you can read, edit, or delete:
/memory
This command lists all loaded CLAUDE.md and CLAUDE.local.md files, lets you toggle auto memory, and links to the auto memory folder. Select any file to open it in your editor.
When you explicitly ask Claude to remember something — “always use pnpm, not npm” — it saves to auto memory. To add to CLAUDE.md instead, say “add this to CLAUDE.md” or edit the file directly through /memory.
Debugging Memory Issues
Verify Which Files Are Loading
The first step when Claude isn’t following your instructions:
/memory
This lists every CLAUDE.md and rules file loaded in the current session. If a file isn’t listed, Claude can’t see it.
Common reasons a file doesn’t load:
- Wrong location (check the scope hierarchy)
- Path-scoped rule with a glob that doesn’t match your current files
- File is in a subdirectory below your working directory and hasn’t triggered yet
InstructionsLoaded Hook for Detailed Debugging
For complex setups with path-scoped rules or deep subdirectory CLAUDE.md files, the InstructionsLoaded hook gives you a precise audit trail:
{
"hooks": {
"InstructionsLoaded": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "bash -c 'echo \"[$(date +%H:%M:%S)] InstructionsLoaded: reason=$(echo $CLAUDE_HOOK_DATA | jq -r .reason) path=$(echo $CLAUDE_HOOK_DATA | jq -r .path)\" >> /tmp/instructions-audit.log'"
}
]
}
]
}
}
This writes a timestamped entry for every instruction file load — at session start, when a subdirectory file triggers, or after /compact. Watch the log to confirm your path-scoped rules are activating when expected.
Instructions Lost After /compact
After compaction, Claude re-reads and re-injects project-root CLAUDE.md automatically. Nested CLAUDE.md files in subdirectories do not re-inject — they reload the next time Claude reads a file in that subdirectory.
If an instruction disappeared after /compact, it was either:
- Given only in conversation (not saved to any file)
- In a nested CLAUDE.md that hasn’t re-triggered yet
Fix: add conversation-only instructions to your project CLAUDE.md, or re-open a file in the relevant subdirectory.
CLAUDE.md Too Large
If your file exceeds 200 lines and adherence is degrading:
- Identify which rules are actually needed every session vs. only for specific file types
- Move file-type-specific rules to
.claude/rules/withpathsfrontmatter - Move multi-step procedures to skills
- Remove instructions that aren’t necessary anymore
Excluding Files in Monorepos
In large monorepos, CLAUDE.md files from other teams’ directories load when you run Claude from the repo root. The claudeMdExcludes setting lets you skip them:
{
"claudeMdExcludes": [
"**/packages/legacy-app/CLAUDE.md",
"/home/user/monorepo/platform-team/.claude/rules/**"
]
}
Add this to .claude/settings.local.json to keep it private. Patterns use glob syntax matched against absolute file paths.
Managed policy CLAUDE.md files cannot be excluded — they always apply.
Integrating AGENTS.md and CLAUDE.md
If your repository already uses AGENTS.md for OpenAI Codex or other agents, don’t duplicate the content:
# CLAUDE.md
@AGENTS.md
## Claude Code Specifics
Use plan mode for changes to src/billing/.
Run `npm run test:integration` (not just unit tests) before committing payment flows.
Claude loads the import at session start, then appends the Claude-specific section. A symlink also works if no Claude-specific additions are needed:
ln -s AGENTS.md CLAUDE.md
When you run /init in a repo with an existing AGENTS.md, Claude reads it and incorporates the relevant parts into the generated CLAUDE.md. It also reads .cursorrules and .windsurfrules.
User-Level Rules for Personal Preferences
Rules in ~/.claude/rules/ apply to every project on your machine. They load before project rules, giving project rules higher priority when there’s a conflict.
~/.claude/rules/
├── preferences.md # "I prefer explicit return types in TypeScript"
├── git-workflow.md # "Always write descriptive commit messages, not 'fix bug'"
└── testing.md # "I prefer integration tests over excessive mocking"
Use user-level rules for preferences that aren’t project-specific: personal coding style, workflow habits, things you’d want in every project regardless of team conventions.
The Memory Decision Tree
When you have a piece of information that Claude should know, here’s how to decide where it goes:
Does Claude need this in every session?
├── Yes → Does it apply to everyone on the team?
│ ├── Yes → Project CLAUDE.md (commit it)
│ └── No → CLAUDE.local.md (gitignore it)
└── No → Does it apply only to specific file types?
├── Yes → .claude/rules/ with paths frontmatter
└── No → Is it a multi-step procedure?
├── Yes → Write a skill
└── No → Add it to conversation context as needed
Auto memory fills in the gaps: things Claude discovers that are worth knowing but you didn’t explicitly write down.
Common CLAUDE.md Template for a TypeScript API Project
# Project: Payment Service API
## Build and Test
- Install: `npm install`
- Dev server: `npm run dev`
- Run tests: `npm run test:unit && npm run test:integration`
- Lint: `npm run lint`
- Build: `npm run build`
## Architecture
- API handlers: `src/api/handlers/`
- Database models: `src/db/models/`
- Business logic: `src/services/`
- Shared types: `src/types/`
- No business logic in route handlers. No direct DB queries in handlers.
## Conventions
- TypeScript strict mode. Explicit return types on public functions.
- Zod schemas for all external input validation.
- All database operations go through the service layer, never direct Prisma calls in handlers.
- Use the logger from `src/utils/logger.ts`, not console.log.
## Testing
- Integration tests required for all API endpoints.
- Unit tests for services and utilities.
- Test data factories in `tests/factories/`.
- Run `npm run test:unit` before PRs, full suite before merging.
## Dependencies
- Add new packages through PRs, not direct installs during sessions.
- Check if a utility already exists in `src/utils/` before adding a dependency.
## Git
- Never commit directly to main.
- Branch naming: `feat/description`, `fix/description`, `chore/description`.
This is under 200 lines, covers build/test/architecture/conventions/git, and avoids the common antipatterns (vague instructions, redundant rules, information Claude can read from the codebase itself).
What Survives Compaction
When you run /compact, Claude summarizes the conversation to reduce context size. Here’s what carries forward:
- Project-root CLAUDE.md is re-read from disk and re-injected
- User CLAUDE.md re-injects
- Auto memory (MEMORY.md) re-injects
- Managed policy CLAUDE.md re-injects
What does not automatically re-inject after compaction:
- Nested CLAUDE.md files from subdirectories (re-trigger when Claude reads files there)
- Path-scoped rules (re-trigger when Claude works with matching files)
- Context you gave only in conversation
The safe pattern: anything Claude needs to know consistently should be in a CLAUDE.md file, not just mentioned in chat.
Internal Links
- Claude Code Hooks Complete Reference — PreToolUse hooks for enforcing rules beyond CLAUDE.md’s reach
- Best Claude Code Skills 2026 — Skills for procedures that don’t belong in CLAUDE.md
- Claude Code Permissions and Trust Levels — Settings files and where they live alongside CLAUDE.md
- Writing Effective CLAUDE.md — Focused deep dive on CLAUDE.md authoring
- AGENTS.md vs CLAUDE.md — When to use each format and how to run both