Claude forgets everything between sessions — I spent 2 hours teaching it to remember

For the fifth time this week, I explained to Claude that I didn't want a summary at the end of my messages. For the fifth time, he noted it. For the fifth time, the next session, he'd forgotten.

It's not a bug. It's normal operation. Claude Code starts each session with a blank slate. Preferences, corrections, decisions made together the day before—all of it vanishes with /clear or the end of the session. After a few weeks of intensive use on ShareBox, I felt like I was training an amnesiac intern.

Phase 1: Put everything in CLAUDE.md

My first reaction was to write everything in the project's CLAUDE.md. Code conventions, tech stack, deployment rules—but also my personal preferences. "Concise responses." "No summary." "Senior dev, don't need the basics explained." "Always reload php-fpm after editing PHP." The file grew.

Within two weeks, ShareBox's CLAUDE.md was 200 lines. A mix of project constraints (ffmpeg has no GPU, remuxing is disabled) and personal preferences (response style, technical level). Some info was temporary—an architecture decision in progress, a bug to investigate this week. Others were permanent. Everything coexisted in the same file, with no hierarchy.

The problem: Claude loads the entire CLAUDE.md each session. The bigger it gets, the more the signal drowns in noise. And temporary info stays there, even when it's no longer relevant. A 300-line CLAUDE.md ends up being as useful as a README that nobody reads.

The discovery: auto-memory

Reading Claude Code's documentation, I discovered the persistent memory system. Markdown files in a dedicated directory—~/.claude/projects/<project>/memory/ for project-specific memory, ~/.claude/memory/ for global memory. Claude reads them at startup via an index file called MEMORY.md, and can update them during a session.

The distinction from CLAUDE.md became clear at that moment. CLAUDE.md describes the project: stack, conventions, deployment, technical gotchas. It's versioned with the code, it's stable. Memory describes the working relationship: who I am, how I want us to work together, what decisions are in progress.

The first thing I did: extract from CLAUDE.md everything that was about me rather than the project. My technical profile, my style preferences, the corrections I'd had to make several times. CLAUDE.md got back to a reasonable size, and this information had a dedicated place.

The 4 drawers

Each memory file has a type. It's not an arbitrary label—it defines when and how Claude will use it.

The user type tells Claude who he's working with. My user_profile.md contains three lines: senior PHP/JS dev, personal project, prefers simple code. That's enough for Claude to adjust his explanation level without me having to introduce myself each session.

The feedback type captures course corrections. "Don't add Co-Authored-By in commits." "Concise and direct responses, no summary." These are things I had to correct once or twice, and never want to explain again. This is the type that solved my original problem—the end-of-message summaries disappeared.

The project type tracks current state: active architecture decisions, initiatives, time-bound constraints. On ShareBox, I noted the migration to v2.0.0 and known issues. This type ages quickly—a decision made in January can be obsolete by March.

The reference type points to external resources. The demo Docker setup, ports, rebuild command. Everything Claude can't deduce from the code but needs regularly.

What goes in—and what I learned not to put in

At first, I made the opposite mistake from CLAUDE.md: I wanted to note everything. Every gotcha, every minor decision, every preference. Memory bloated as fast as the file it was supposed to replace.

The rule I eventually adopted is simple: a memory file should contain information that is not deducible from the code or CLAUDE.md, and useful in future sessions.

What passes the filter:

  • A style preference confirmed or corrected ("no summary at end of response", "always go through this function to modify this behavior")
  • An invisible gotcha in the code—a constraint Claude wouldn't discover by reading files
  • An architecture decision in progress, not yet in the code
  • A pointer to an external resource used regularly

What doesn't pass:

  • What's visible in the files—Claude will find it on his own
  • Details of past sessions—git log is more reliable
  • Work in progress—it belongs to the session, not memory
  • Conventions already in CLAUDE.md—unnecessary duplication

Project vs global: where to put what

I wasted time putting personal preferences in ShareBox's project-specific memory, only to rediscover them absent when working on another repo. Project memory (~/.claude/projects/<cwd-sanitized>/memory/) is isolated by working directory. A different folder, different memory.

Global memory (~/.claude/memory/) applies everywhere, across all projects. That's where transversal preferences go: response style, technical level, communication conventions.

The practical rule: start with project memory. If a preference shows up in all projects, move it to global. Never duplicate.

Automate the feeding

Asking Claude manually to save each preference works the first few days. Then you forget. I added a rule to my ~/.claude/CLAUDE.md (the user CLAUDE.md, loaded in all sessions):

# Global rules — all sessions, all projects

## Auto-memory

Whenever a session reveals persistent information, save it immediately
to the right memory file without waiting for the user to ask:

- Discovered or corrected preference  -> memory/user or memory/feedback
- Approach correction                 -> memory/feedback
- Durable project decision            -> memory/project
- Pointer to external resource        -> memory/reference

Don't save: temporary state, work in progress, what's already in CLAUDE.md,
what's deducible from the code.

The filter is as important as the trigger. Without the "Don't save" part, Claude notes every session detail and memory grows out of control. That's exactly the problem we were trying to avoid.

Memory ages: the audit prompt

After a month, I had project files talking about decisions resolved two weeks ago. Claude read them, factored them in, and it created confusion. Memory isn't a "fire and forget" system—it requires maintenance.

I wrote an audit prompt that I run at session start when memory has drifted:

Audit the memory files in `.claude/projects/.../memory/`.

For each file:
1. Is the content still accurate? (check against current file state if needed)
2. Is it non-deducible from the code or CLAUDE.md?
3. Is the type correct? (user / feedback / project / reference)
4. Is the description in the frontmatter precise enough?

Global consistency: duplicates, contradictions, obsolete project memories, MEMORY.md up to date?

Result in table: File | Problem | Recommended action
Then apply the corrections.

To avoid having to find it again, I saved it as a slash command in ~/.claude/commands/audit-memory.md. Since then, /audit-memory is enough.

The result

Today, my ShareBox project memory fits in 5 short files. A user profile, two feedbacks (no Co-Authored-By, concise responses), a project file (ShareBox architecture, Docker, TMDB), one reference (demo setup). CLAUDE.md contains only what concerns the project itself.

Claude hasn't asked me for my technical level in weeks. He no longer adds a summary at the end of messages. He knows remuxing is disabled and why. Sessions start directly on the topic, without a re-introduction phase.

The system isn't magic. It requires discipline—knowing what to note, where to note it, and cleaning up regularly. But that's exactly what you do with any work tool. Auto-memory transforms Claude from an amnesiac tool into a collaborator who learns. As long as you don't let it become, itself, a 300-line file nobody reads.

📄 Associated CLAUDE.md

Comments (2)

NILE GREEN 7 Apr 2026, 14:22
Worth adding a distinction between memory as retrieval versus memory as state. What you're describing here is retrieval-based memory — Claude reads files at session start. Real persistent memory updates internal state continuously and doesn't need to be read back in. My agents have permanent write access and memory that persists across sessions without loading files. The difference shows up in behavior over time — retrieval-based systems recall, state-based systems develop. Both useful but they're solving different problems.
Odilon Hugonnot 7 Apr 2026, 16:45
Good distinction — you're right that these are different architectures. What I describe here is explicit retrieval: files read at session start, fully transparent and under version control. Your state-based approach (continuous writes, implicit retrieval) enables the "develop over time" behavior, which is a real advantage for long-running agents.

The trade-off I see: explicit retrieval gives you auditability and control — you can read, edit, or revert any memory entry. Implicit state is more fluid but harder to inspect when something drifts. Both useful, both retrieval under the hood — the difference is granularity and transparency.