Source-code-verified internals of Claude Code's memory system.
| Property | CLAUDE.md | Auto Memory (MEMORY.md) |
|---|---|---|
| Author | You | Claude |
| Contains | Instructions and rules | Learnings and patterns |
| Scope | Project, user, or org | Per working tree / git repo |
| Loaded | Every session, in full | First 200 lines or 25KB |
| Injection point | System prompt context section | System prompt + per-query attachments |
Files load from broadest to most specific scope (source: src/utils/claudemd.ts). The harness walks up the directory tree from cwd to root, then processes root-to-cwd for precedence:
/etc/claude-code/CLAUDE.md (Linux) — cannot be excluded~/.claude/CLAUDE.md — personal, all projects~/.claude/rules/*.md — loaded before project rules./CLAUDE.md or ./.claude/CLAUDE.md — shared via git./.claude/rules/*.md — can have paths: frontmatter for conditional loading./CLAUDE.local.md — personal, gitignoredCLAUDE.md content is injected as a system prompt context section (not a user message). It fully survives compaction — re-read from disk after /compact.
@path/to/file syntax imports additional files. Resolves relative to the importing file. Max recursion depth: 5. HTML comments stripped before injection. Imports do NOT work inside code blocks.
There is no enforced size limit on CLAUDE.md. A 40KB flag exists but only triggers a warning in the /doctor command. Files of any size are loaded in full. That said, adherence degrades beyond ~200 lines — this is a practical recommendation, not a hard limit.
Stored in ~/.claude/projects/<project-slug>/memory/. All worktrees within the same repo share one memory directory.
Dual caps applied (source: src/memdir/memdir.ts:35-103):
| Cap | Value | Purpose |
|---|---|---|
| Line cap | 200 lines | Catches index sprawl |
| Byte cap | 25,000 bytes | Catches long-line indexes |
When truncated, a WARNING is appended explaining which cap fired. Topic files (individual memory files) are NOT loaded at startup.
When topic files are surfaced by the selection agent:
| Limit | Value |
|---|---|
| Per-file lines | 200 |
| Per-file bytes | 4,096 (~4KB) |
| Session total | 61,440 (60KB) |
| Max files scanned | 200 |
Truncated files get a note: "Use FileRead to view the complete file at: [path]"
Claude Code uses Claude Sonnet as a dedicated sub-agent for deciding which memory files to attach (source: src/memdir/findRelevantMemories.ts).
| Aspect | Details |
|---|---|
| Input | User query + list of memory file headers (filename, description, type, mtime) |
| Output | Up to 5 filenames (hard-coded max) |
| De-duplication | Files shown in prior turns are excluded from re-selection |
| Tool awareness | If a tool is in recentTools, usage docs deprioritized, but warnings/gotchas kept |
| Injected as | <system-reminder> attachments |
type field does NOT influence selection
The frontmatter type (user/feedback/project/reference) is used for display only in the memory manifest. It does NOT filter or influence the Sonnet selector's decision. Only filename and description matter for routing.
Runs as a forked agent (shares prompt cache with main agent) at end of each query loop. Has restricted tool permissions: Read/Grep/Glob, read-only Bash, and FileEdit/FileWrite only within the memory directory. Skipped if the main agent already wrote to memory that turn.
Background agent that synthesizes daily logs/transcripts into durable memories. Four phases: Orient → Gather → Consolidate → Prune.
Gates (cheapest checked first):
Feature-gated. User override: autoDreamEnabled in settings.json.
Distinct from auto-memory. A periodic background sub-agent extracts key session info into .session/memory.md. Triggered by token thresholds (~30K init, ~20K between updates). Does not interrupt the main conversation. This is for within-session continuity, not cross-session persistence.
SYSTEM_PROMPT_DYNAMIC_BOUNDARY — cache scope split pointTriggers when token usage ≥ (effective context window - 13,000 tokens). Circuit breaker stops after 3 consecutive failures. CLAUDE.md and MEMORY.md survive compaction (re-read from disk).