Blog
ENPL

Memory in Claude Code — what it actually remembers and how to steer it

Memory is a Claude Code mechanism that persists facts about you, the project and preferences across sessions. Showing how it works under the hood, when to use it, and when CLAUDE.md is better.

·4 min read
Memory in Claude Code — what it actually remembers and how to steer it

Claude Code greets you with a fresh session every time. Without memory it would forget who you are, your stack, why you asked for something specific recently. Memory is a file system in ~/.claude/projects/{slug}/memory/ that preserves this between sessions.

After 4 months with active memory I have ~30 stored facts. Showing how it works.

4 memory types

The system distinguishes 4 types:

TypeWhat goes inExample
userWho the user is, their preferences"kkaletka prefers terse responses"
feedbackRules and corrections from the user"Always commit immediately, no asking"
projectProject state, decisions, deadlines"Auth refactor due 2026-04-15"
referencePointers to external resources"Linear project INGEST tracks pipeline bugs"

Every fact is its own markdown file with frontmatter. Plus MEMORY.md as an index.

How the agent decides what to save

The system rule: save when a fact is non-obvious from the code. That is:

✅ Save: "User prefers PR-per-feature, not bundled refactors"
✅ Save: "Background agent jobs use Telegram chat 5094102576"
✅ Save: "Bath thermostat reports temp ×10 (parse / 10)"

❌ Don't save: "Project uses Next.js 16", visible in package.json
❌ Don't save: "src/auth/ contains login flow", visible from a grep
❌ Don't save: "Last commit was about...", git log has it

When memory > CLAUDE.md

CLAUDE.md is global instructions, loaded into every session. Memory is facts, available on demand.

CLAUDE.md for things that ALWAYS matter:

  • Identity ("I'm Claw, kkaletka's agent")
  • Safety rules ("Never send emails without confirmation")
  • Global preferences ("Reply concisely, no fluff")

Memory for CONTEXTUAL things:

  • State of a specific project
  • Rules for a specific workflow
  • Facts about external systems

When CLAUDE.md hits 200+ lines, time to move some to memory. Memory doesn't load "by force", the agent reads when needed.

Anti-patterns

1. Saving session summaries. "Today we refactored X, added Y", that's git log, not memory. Memory is for PERSISTENT facts, not a chronicle.

2. Duplicating CLAUDE.md. If CLAUDE.md says "user prefers terse" and memory says the same, you have two sources of truth. Update only one → drift.

3. Saving temporary state. "User is testing feature flag X", ephemeral, not memory. Tasks or plan.

4. Memory as TODO list. Memory is "what you already know". TaskCreate is "what you have to do". Don't mix.

My workflow

What I save: facts in the "agent should know this in a future session" category. After 4 months that's:

  • 4 files user_*.md (who I am, phone, email, style preferences)
  • 7 files feedback_*.md (commit policy, rebuild policy, how to parse the HA thermostat)
  • 15 files project_*.md (state of each active project, devops gotchas)
  • 3 files reference_*.md (pointers to BetterUptime, Vikunja, Gmail attachments workaround)

What I delete: when a fact goes stale (project closed, preference changed), the agent should erase memory. I have a rule: if the agent tells me something "from memory" and I know it's stale, I ask it to update.

Example: how a fact becomes memory

Session:

> Claude, freaky-trade-alert.sh didn't fire, check what's wrong
 
[agent debugs]
 
Agent: The script is at /home/kkaletka/docker/scripts/freaky-trade-alert.sh.
       The profile list in SQL and the local ACTIVE table must match.
       Adding a new profile requires updating BOTH. Save to memory?
 
> Yes, save it

Memory entry (project_freaky_trade_alert.md):

---
name: Freakyprofit Report
description: Freaky trade alert pipeline on mini PC
type: project
---
 
`/home/kkaletka/docker/scripts/freaky-trade-alert.sh` on mini PC. Add new profiles to SQL + active list (both places, otherwise no alerts).

Next session, 2 weeks later: I ask about adding a new profile, the agent immediately knows where and how.

Worth knowing

1. Memory is project-specific. Each project (working dir) has its own memory store. Cross-project doesn't work unless you copy.

2. It can be large. The MEMORY.md index is loaded into context every time. Individual files, on demand. Don't be afraid to keep many, but the index should have one-line pointers.

3. Version it. Memory is also code. I keep ~/.claude/projects/ in git. If the agent saves something weird, git diff shows.


Memory isn't magic or true memory. It's a file system with a convention. But used well it makes the agent feel like someone who actually knows you, instead of Stack Overflow with a better prompt.