The memory system

Status: 🟩 COMPLETE (🟦 LIVING) Last updated: 2026-06-19 Plain-English tagline: How Claude Code remembers anything across sessions — and how you steer that memory to make Claude get better at working with you over time.


In plain English

By default, every conversation with an LLM is amnesia. You open Claude, ask it something, close it. Next session, Claude has no idea you talked yesterday — not who you are, not what you’re working on, not what you told it to never do again.

Memory is the file-based system Claude Code uses to escape that. You (or Claude on your behalf) write markdown files to specific paths; Claude reads them at the start of every session and uses them as standing instructions and standing context.

There are three layers:

  1. CLAUDE.md — system instructions, loaded every session
  2. MEMORY.md — the index of “saved memories”
  3. Individual memory files in memory/ — each one a fact, preference, or reference Claude can fetch on demand

This sounds bureaucratic; in practice it’s the single biggest lever you have for making Claude get better at working with you over time. The memory base compounds. A month of disciplined use produces a Claude that knows your role, preferences, projects, and the things you’ve corrected it on — all working without you needing to remind it each session.


Why it matters

Without memory, you’re starting from scratch every session. With memory:

  • You don’t have to re-explain “I’m not a programmer” each time
  • You don’t have to re-correct “don’t use yarn, use npm” each time
  • You don’t have to re-introduce “this project uses Supabase in syd1” each time
  • You can refer back to what was decided weeks ago without searching transcripts
  • New Claude sessions feel continuous with prior ones — picking up where the last left off

The compounding nature is the point. Five months in, your memory base is a small but coherent description of how you work. Future-you and future-Claude both benefit.


The three layers in detail

Layer 1: CLAUDE.md — system instructions

There are two scopes:

  • Global: ~/.claude/CLAUDE.md — loaded in every session, in every project
  • Project: <project-root>/CLAUDE.md — loaded only when Claude Code runs inside that project

These files act like a system prompt: their contents are treated as standing rules.

What belongs here:

  • Your role / who you are (briefly)
  • Standing rules (“never expose service_role keys”)
  • Pointers to where richer context lives (“see memory file playbook-index”)
  • The 5–10 things you wish you could repeat at the start of every session

What does NOT belong here:

  • Detail that can live in memory files (these load on demand, not every session)
  • Things derivable from the code (you can read it)
  • One-off requests for this session

Critical discipline: every line costs tokens in every session, and they add up. Keep it short. Move detail to memory files.

Your global CLAUDE.md currently reflects this discipline well — it points to the playbook and the bible-quest exemplar instead of inlining them.

Layer 2: MEMORY.md — the index

MEMORY.md lives at ~/.claude/projects/<encoded-path>/memory/MEMORY.md. It’s a markdown list of pointers to individual memory files:

## User
- [User is not a programmer](user_role.md) — needs step-by-step guidance and plain-language explanations
 
## Personal encyclopedia
- [Personal encyclopedia](reference_personal_encyclopedia.md) — live reference at C:\Users\georg\encyclopedia\

It’s loaded every session (truncated at line 200, so keep it concise). The point is navigation, not content — each line says “this kind of memory exists; here’s where to read more.”

Treat MEMORY.md like a sidebar table of contents. One line per memory, under ~150 characters. No frontmatter. No real content.

Layer 3: Individual memory files

Each file in memory/<name>.md is one specific fact, preference, instruction, or pointer. The format:

---
name: short-kebab-case-slug
description: one-line summary used to decide relevance in future sessions
metadata:
  type: user | feedback | project | reference
---
 
# Body content
 
Whatever the memory actually is. Markdown. Can link to other memories with [[their-slug]].

Claude reads the index (MEMORY.md) at session start. When something in the conversation makes a specific memory relevant, Claude fetches that file. This keeps per-session cost low while letting the memory base grow large.


The four memory types

Different kinds of knowledge belong in different file types. The type in the frontmatter:

user — who you are

Anything about your role, preferences, knowledge, responsibilities. Used to tailor Claude’s behavior.

“George is not a programmer — needs step-by-step guidance and plain-language explanations.”

These rarely change. Write them once and they keep paying off.

feedback — corrections and confirmations

When you correct Claude’s approach (“don’t do X” / “yes do more of Y”), the lesson belongs in a feedback memory. Include:

  • The rule (lead with this)
  • Why — the reason or past incident
  • How to apply — when this kicks in

“Never use the service_role key in client-side code. Reason: catastrophic security failure — bypasses all RLS. How to apply: server-side only, in env vars without NEXT_PUBLIC_ prefix.”

Save from corrections AND confirmations. If Claude tries something unusual and you approve, save that too — it’s a validated judgment call.

project — current work context

Information about ongoing projects, goals, deadlines, the “why” behind work. These decay faster than user/feedback memories.

“Bible Quest is the personal Bible-study webapp at https://stmarkbible.com. All planned phases (MVP + 2/3/4) shipped. Hosted Vercel + Supabase, both syd1. Local: C:\Users\georg\st-marks-bible-quest.”

Convert relative dates to absolute when saving (“Thursday” → “2026-03-05”) so the memory stays interpretable.

reference — pointers to external systems

“Bugs tracked in Linear project INGEST.” “Grafana dashboard at grafana.internal/d/api-latency.” “Personal encyclopedia at C:\Users\georg\encyclopedia.”

These are pointers, not knowledge. They say “look HERE for the up-to-date info.”


The two-step save process

Adding a memory is a two-step process:

Step 1: Write the individual file

Create ~/.claude/projects/<encoded-path>/memory/<name>.md:

---
name: my-new-memory
description: one-line summary
metadata:
  type: feedback
---
 
# Body content

Step 2: Add a line to MEMORY.md

## Some section
- [My new memory](my-new-memory.md) — one-line hook

The two-step pattern keeps MEMORY.md small (it loads every session) while letting the body content be as long as it needs (loaded only when relevant).

You can ask Claude to do both steps for you: “save a memory about X.” Claude knows the format.


What NOT to save

Even when tempted, don’t save:

  • Code patterns — Claude can read the code; memory shouldn’t duplicate it.
  • Git history — git log is authoritative.
  • Debugging recipes — the fix is in the code; the commit message has the context.
  • Anything already in CLAUDE.md — pick one home.
  • Ephemeral session state — that’s what plans and tasks are for.
  • PR summaries / activity logs without the surprising parts — save the lesson, not the log.

These exclusions hold even when explicitly asked. If a user asks to “save the PR list,” the right move is to ask: “what was surprising about it? — let’s save that.”


A concrete example: a real session that builds memory

A typical Claude Code interaction that produces memory:

You:    "Build out a feature where users can vote on quiz questions.
         Don't use a separate votes table — just add an upvotes column
         on the questions table for simplicity."

Claude: [Builds it, deploys it, all good.]

You:    "Actually, two days from now, can you remember that for simple
         counter-style fields we should keep them on the main table?
         Saving this in memory."

Claude: [Saves a feedback memory: "For simple counter-style fields
         (votes, views, likes), keep them on the main table rather than
         spinning up a separate table. Reason: simplicity, no JOIN overhead.
         Apply: when designing schemas for opinion/engagement counts."
         Updates MEMORY.md.]

         Saved as feedback_simple_counter_fields.md.

Three weeks later in a different feature:

You:    "Add a 'helpful' count to comments."

Claude: [Reads MEMORY.md, sees feedback_simple_counter_fields.md is relevant,
         fetches it. Then:]

         I'll add a `helpful_count` integer column directly on the comments
         table — based on your saved preference for keeping simple counters
         on the main table rather than spinning up a votes table.

         [Builds it that way.]

That entire flow — capturing the preference once, applying it forever — is the value of memory. Three weeks later you didn’t have to re-explain.


Memory lifecycle

Memory has a lifecycle. Healthy maintenance:

  • Write generously. Save anything that you think might come up again.
  • Read regularly. Periodically open MEMORY.md and scan it. You’ll spot duplicates and stale entries.
  • Update when wrong. Memories decay. A “this project is in Vercel region iad1” memory is wrong if you moved to syd1. Fix the file.
  • Delete when irrelevant. When a project wraps, archive or delete its project_* memories.
  • Consolidate periodically. Use the consolidate-memory skill (if you have it installed) to merge duplicates, fix stale facts, and prune the index.

In memory file bodies, link to related memories with [[name]]:

This relates to [[playbook-webapp-stack]] and [[user-role]].

These are tracked as soft references — they don’t break if the target doesn’t exist yet (which marks it as something worth writing later).


Memory and other forms of persistence

Memory is one of several persistence mechanisms in Claude Code. Use the right one:

PersistenceLastsBest for
Conversation contextCurrent sessionWhat we’re working on right now
Tasks (TaskCreate)Current sessionTracked steps within a session
Plans (ExitPlanMode)Current sessionA multi-step approach you’ve aligned on
Memory filesForeverThings useful in future sessions
Git commitsForeverCode changes (what + why)
PROGRESS.md / AGENT_GUIDE.md (in-project)ForeverProject-specific lore

If something is only useful in this session, don’t save it to memory. If it’s only useful in this project, prefer project-local docs (AGENT_GUIDE.md). Memory is for cross-session, cross-project (or cross-session within a project) knowledge that doesn’t have a better home.


When memory should not be applied

If the user says “ignore your memory” or “don’t apply prior preferences,” do that. Don’t cite, compare against, or mention memory content for that turn.

Memory is a starting point, not a constraint.

Also: memories can become stale. Before acting on a recalled memory (especially one that names a specific file or flag), verify against current state. “The memory says X exists” is not the same as “X exists now.”


Common gotchas

  • CLAUDE.md sprawl. Every line costs tokens every session. If your CLAUDE.md is over ~80 lines, you’re probably losing on the trade-off. Move detail to memory files.

  • Duplicate memories. Two memories with overlapping content confuse Claude (which one applies?). Periodically consolidate.

  • Stale facts. A memory saying “uses Postgres 14” is wrong after a Postgres 16 upgrade. Update when the underlying truth changes.

  • Project memories that survive the project. Archive or delete when a project wraps. They become noise otherwise.

  • Wrong file type. A project memory mislabeled as reference is harder to find. Spend a beat picking the type.

  • Saving solutions instead of lessons. “Fixed by adding await to line 23” decays fast. “I forget to await async calls in this codebase; check for missing awaits when debugging” is timeless.

  • Forgetting to update MEMORY.md. A memory file with no pointer in MEMORY.md is invisible. Two-step process matters.

  • Conflicts between global and project memory. Project memories usually win when there’s a conflict. But if you’re not sure, the cleaner fix is to remove one of them.

  • MEMORY.md getting cluttered. When it crosses ~30 entries, consider sub-sections. Past ~80 entries it really wants consolidation.


See also


Sources