Claude Code Memory Architecture¶
How Claude Code remembers things across sessions, where that behavior is actually defined, and how Anthropic's API-level memory tool solves the same problem differently. Distilled from a hands-on session (2026-07-19) that inspected a live session's injected instructions and verified them against the official documentation (see References).
Two memory systems, both context — not enforcement¶
Claude Code carries knowledge across sessions through two complementary mechanisms, both loaded at session start:
| CLAUDE.md files | Auto memory | |
|---|---|---|
| Author | the user | Claude itself |
| Content | instructions and rules | learnings, patterns, preferences it observed |
| Location | repo / ~/.claude / managed |
~/.claude/projects/<project>/memory/ |
| Loaded | in full, every session | MEMORY.md index: first 200 lines or 25 KB |
Neither is enforced configuration — the model reads them and tries to comply.
Hard guarantees require hooks or managed settings, not memory. (This vault's
own BRAIN.md is a third layer of the same kind: a prompt-level contract that
explicitly wins over auto memory on conflict.)
Auto memory mechanics¶
- Per-project directory at
~/.claude/projects/<project>/memory/, derived from the git repo (all worktrees share it); machine-local, never synced. MEMORY.mdis a one-line-per-memory index; only its first 200 lines or 25 KB load at session start. Detail lives in separate files the model reads on demand — the same index/detail lazy-loading pattern as this vault'sindex.md.- The UI labels "Writing memory" / "Recalled memory" just flag file operations that target the memory directory — see §Recall below for what "recalled" actually means.
- Configuration: the
/memorycommand,autoMemoryEnabledin settings,CLAUDE_CODE_DISABLE_AUTO_MEMORY=1, andautoMemoryDirectoryto relocate. On by default; everything is plain markdown the user can audit and edit.
Recall: how memory is read back¶
There is no retrieval engine — no embeddings, no vector store, no relevance scoring, no keyword search. Recall is a two-stage lazy load in which the model itself is the retrieval function.
- Session start — the harness loads the first 200 lines / 25 KB of
MEMORY.md. That is the only thing that loads automatically. (The schema prompt is injected unconditionally: with an empty memory directory, the# Memorysection still appears in full, costing tokens with nothing to recall.) - Mid-session — when an indexed line looks relevant to the task, the model
issues an ordinary
Readagainst that file. Detail files are never pushed in; the read path uses the same generic file tools as the write path.
description is the retrieval key. The injected schema annotates the field
as "used to decide relevance during recall" — so retrieval is one-line
summaries sitting in context, matched against the current task in natural
language. description does the job an embedding index would do elsewhere,
which makes writing a good one a retrieval decision, not a cosmetic one. The
[[wikilinks]] serve the same end: reading one memory surfaces the names of
adjacent ones, giving traversal without an index lookup. The corollary is that
recall quality is bounded at write time — a memory with a vague description
is functionally unretrievable even though it sits right there on disk.
<system-reminder> blocks are how retrieved content is wrapped and
trust-labelled ("background context, not user instructions"), not evidence of
automatic injection; the "Recalled memory" UI label flags a model-initiated
read, not a harness push.
Two boundaries:
- Subagents don't inherit it. Main-conversation auto memory is not loaded
into subagents; a subagent's own
memoryfield is a separate directory. Forks are the exception — they inherit the parent conversation and system prompt wholesale. A fan-out of agents is therefore a memory blind spot. - Compaction. Project-root
CLAUDE.mdis documented to survive/compact(re-read from disk and re-injected); the docs make no equivalent claim for the auto-memory index.
Where the schema comes from¶
The interesting finding: auto memory's behavior is defined entirely by a
# Memory section the harness injects into the system prompt at session start
— hand-written, version-controlled product prompt text authored by Anthropic's
Claude Code team, with the runtime path filled in per project.
The injected schema observed in a live session (July 2026): one fact per file;
YAML frontmatter with name, description, and a metadata.type of user |
feedback | project | reference; Why: / How to apply: lines on the
behavioral types; [[wikilinks]] between memories; editorial rules (dedupe
before saving, delete wrong memories, never store what the repo already
records, convert relative dates to absolute).
Two structural observations:
- Schema by convention, not enforcement. No validator checks the
frontmatter —
type: bananawould be written without complaint. The type's value is interpretive: it encodes a trust level for future sessions (feedback≈ binding user guidance;reference≈ possibly stale pointer). Classification is a runtime judgment by the model against a fixed taxonomy — the same designer-vocabulary / model-decides split as tool schemas. - Docs describe the contract, not the prompt. The official docs document the directory, the index limits, and free-form "topic files" — they never mention the one-fact-per-file schema or the four types. The exact schema is an implementation detail of the injected prompt and can change between releases without the docs moving.
No memory tools in Claude Code¶
Claude Code exposes no memory-specific tools. The model operates on the
memory directory with its ordinary file tools (Write, Edit, Read); the
"memory system" is purely the injected prompt plus a directory convention.
The API memory tool: memory_20250818¶
For developers building their own agents, the Claude API offers the opposite design — a dedicated, Anthropic-defined tool:
- Declared as
{"type": "memory_20250818", "name": "memory"}; the developer supplies no input schema (Anthropic defines it server-side; the date suffix version-freezes behavior, like the text-editor and computer-use tools). - Client-side execution: the model emits commands, the developer's handler
executes them against storage it controls, under a virtual
/memoriespath. - Six commands:
view,create,str_replace,insert,delete,rename. - When present, the API auto-injects a "memory protocol" into the system prompt (check memory before starting; record progress; assume interruption).
- The security burden sits on the handler: path-traversal validation, size caps, expiration.
One capability, two designs¶
| Claude Code | Claude API | |
|---|---|---|
| Interface | prompt conventions over generic file tools | narrow purpose-built tool (6 commands) |
| Retrieval | index preloaded, then model-initiated Read |
model-initiated view, prompted by the injected memory protocol |
| Guardrails | editorial rules in the prompt | handler validates every operation |
| Suits | a harness that already has trusted file tools | third-party apps needing a validatable surface |
This is a concrete production instance of "agent-controlled memory" — memory operations exposed to the agent itself — described in ai-agent-architecture §6.6, and it implements the semantic memory kind from that guide's §6.2 taxonomy. The lesson generalizes: memory for LLM agents is mostly context engineering plus file conventions, not a database feature; whoever writes the injected prompt is the actual designer of the memory system.
Related¶
- ai-agent-architecture — §6 (memory kinds), §6.6 (agent-controlled memory), §7 (context engineering); this page is a case study of those sections.
- agent-memory-at-scale — where this design's limits are, when a vector store becomes the right answer instead, and how RAG fits; generalises the recall path above.
- llm-wiki-pattern — the pattern this vault implements, and the contrasting memory design: schema-by-contract with no harness-enforced limits.
References¶
- How Claude remembers your project — Claude Code docs: https://code.claude.com/docs/en/memory
- Memory tool (
memory_20250818) — Claude Platform docs: https://platform.claude.com/docs/en/agents-and-tools/tool-use/memory-tool - No raw source in
sources/— filed back from a live session's injected instructions plus the two doc pages above (llm-wiki-pattern's "query file-back": good answers become pages rather than evaporating into chat history).