I Gave Claude Code Long-Term Memory

AI coding assistants forget everything between sessions. Here's the persistent-memory system I built so mine finally remembers my projects, my decisions, and my mistakes.

Every time I started a new Claude Code session, I was pairing with a brilliant collaborator who had total amnesia.

It knew how to write code, but it knew nothing about my code — which architecture decisions I had already made and rejected, why a particular module was shaped the way it was, the bug we fixed last Tuesday, or even that a given project existed at all. Every session opened with the same tax: re-explaining context I had already explained a dozen times.

So I built it a memory. Not the kind that lives inside one conversation and evaporates when the window closes — a genuinely persistent one that survives across sessions, across projects, and across weeks. Here is how it works, what was hard, and what I would tell you before you build your own.

Statelessness is both the feature and the curse

Large language models are stateless. Each session, the context window is the short-term memory — and when the session ends, that memory is gone. This is great for privacy and simplicity, and it is exactly why your AI assistant feels like it has early-onset amnesia. The model's weights know how to program; they do not know anything durable about your particular world.

The context window is a whiteboard, not a notebook. What I wanted was a notebook: a place facts accumulate and get pulled back in when they are relevant, without me copy-pasting a project brief into every new chat.

The shape of the solution

Three pieces, and the third is the one that makes it actually stick:

  1. A memory store — atomic facts, each one a small "card," tagged with concepts and linked to other cards by typed relations.
  2. A daemon that exposes recall and store as callable tools, so the assistant can query and write memory in the middle of a task.
  3. Hooks that make memory automatic — one injects relevant memories at the start of a session, another harvests new ones at the end.

Let me take them one at a time, because each taught me something.

1. Atomic cards, not transcripts

My first instinct was to just save whole conversations and search them later. Terrible idea. Transcripts are ninety-five percent throat-clearing and five percent signal, and retrieval over that ratio gives you mush.

The unit that works is the atomic fact: one card holds one durable thing worth remembering — a decision and its rationale, a constraint, a gotcha, a dead end I should not walk down twice. Each card carries a few concepts (for retrieval) and, crucially, typed relations to other cards: supersedes, contradicts, elaborates, caused-by. The relations are what turn a pile of notes into something with a spine.

A good litmus test for what deserves to be a card: could I reconstruct this from the code or the git history? If yes, do not store it — the repo already remembers. Store the things the repo cannot tell you: why you chose X over Y, the customer constraint that is not written down anywhere, the thing that looked like a bug but was not.

2. A daemon the assistant can actually call

A memory the assistant cannot reach is just a diary. The bridge is the Model Context Protocol — a standard way to expose tools to an AI client. I run a small background service (managed by launchd on macOS so it comes back after reboots) that offers two primitives: recall(query) and store(fact). Now, before starting real work, the assistant can call recall with the files and concepts involved and get back the relevant history — unprompted.

The lesson here was operational, not clever: treat the memory service like production infrastructure. When it silently died, every session quietly got dumber and I did not notice for a day. Health checks and a heartbeat matter more than any fancy retrieval trick.

3. Hooks: making memory automatic

Here is the failure mode of every personal-knowledge system ever built: it depends on you remembering to use it. If recalling and saving are manual steps, you will skip them exactly when you are busy — which is always.

So I made both ends automatic with lifecycle hooks:

  • A session-start hook semantically searches the store for memories relevant to the project and files I am opening, and injects the top matches into the very first prompt. The session begins already oriented.
  • A session-end hook scans the transcript for inline "observation" tags the assistant emitted while working — little in-the-moment flags that say "this decision is worth keeping" — and persists them as cards. Capture happens as a side effect of doing the work, not as a chore afterward.

That second hook is the whole ballgame. The assistant is best positioned to know what mattered at the moment it mattered; harvesting those flags later means I never have to sit down and "write up my notes."

The three hard problems

Recall drift: semantic search never says "I don't know"

This one bit me last week. I asked the system about a project it had genuinely never stored. It did not say "no match." It confidently handed back my other projects — the nearest neighbors in embedding space — at around fifty percent similarity, formatted exactly like real hits.

That is the trap of vector search: it always returns the closest vectors, so the absence of a fact looks identical to a weak match. The partial fix is a similarity threshold. The real fix is a mindset: treat recall as a lead, not a verdict, and verify. The tell that saved me was dead simple — none of the "matches" literally contained the thing I had searched for. When your retrieval is confident but wrong, check whether the result actually mentions the query.

Signal versus noise: the store wants to rot toward trivia

Store too much and recall drowns in low-value cards; store too little and the whole thing is decorative. There is no clever algorithm for this — it is a taste problem, enforced by the "could the repo tell me this?" rule above, plus periodic pruning. A memory system's quality is set less by what it remembers than by what it refuses to.

Staleness: yesterday's truth, stated with confidence

Facts expire. "We deploy through service X" becomes actively harmful the day you switch to Y — and a naive store will keep asserting the old thing forever, with total confidence. This is what the supersedes and contradicts relations are for: a newer card can override an older one, and recall surfaces the winner instead of both. Without that, your memory does not just get stale, it lies to you.

Does it actually work?

Yes — and the moment that sold me was mundane, which is how you know it is real. I opened a fresh session on a project I had not touched in weeks, and the assistant already knew the deploy setup, the one deploy script that was broken, and the decision we had made about not looking something up by name. I had typed nothing but "let's continue."

It is not magic. It is a retrieval system with good hygiene, wired into the moments where remembering and recording naturally happen. But the gap between an assistant that re-learns your project every session and one that remembers is the gap between a contractor and a colleague.

Should you build one?

You do not need a daemon, semantic search, or auto-capture to start — those are refinements. The minimum viable memory is a single markdown file of atomic facts plus a session-start hook that pastes it into context. That alone will change how your AI assistant feels, immediately.

Add the pieces as the pain demands them: semantic recall when the file gets too big to inject wholesale, typed relations when stale facts start biting, auto-capture when you notice you are not writing things down. Build it in that order and each step pays for itself before you take the next.

The headline is not "I built an elaborate system." It is that a stateless tool became a persistent collaborator by adding the one thing it structurally lacks — and that most of the work was not in the storage, but in the hygiene around it.


Related reading