memory
The problem with agent memory is not storing things. It is that stored things rot, and a naive store cannot tell the difference between a fact and a fact that used to be true.
Six months of accumulated notes will confidently tell you that someone is at a company they left in March, that a flag exists that was removed in April, and that a decision holds that was reversed in May. Every one of those is worse than having no memory, because the agent states them with the same confidence as the true ones.
The fix, borrowed from temporal knowledge graphs like Graphiti: facts have validity windows, and contradiction closes a window rather than deleting a row. The current state is what has an open window. The history stays readable, so you can always tell a change from an error.
That idea does not need a graph database. It works in flat Markdown.
Layout
.claude/memory/INDEX.md # one line per fact, read at the start of a session
.claude/memory/<slug>.md # one fact per file
Project-local by default, since most facts are about a project. Use
~/.claude/memory/ for facts about the person that hold everywhere.
One fact per file
---
name: prefers-flowing-sentences
description: Rejects choppy fragment style in anything written in his voice
type: preference
confidence: stated
valid_from: 2026-08-31
valid_until: null
supersedes: null
---
Writes in regular flowing sentences. Pushed back twice on a bold-opener,
short-sentence rewrite: "you don't have to do these weird commas though and
short sentences."
**Why:** the style read as clipped and unlike him.
**How to apply:** normal paragraphs. No fragment stacking for emphasis.
Related: [[no-em-dashes]]
type is one of person (who they are, how they work), project (goals and
constraints not derivable from the code), preference (how they want things
done), decision (what was chosen and why, so it is not relitigated), or
reference (a pointer to something external).
confidence is one of stated (they said it), observed (seen repeatedly in
their behaviour), or inferred (a guess from one instance). This field carries
more weight than it looks: an inferred fact must never silently override a
stated one. Most bad memory behaviour is an inference from a single event
hardening into a rule.
Writing a fact
- Check for an existing one first. Updating beats creating a near-duplicate. Two files that disagree is the failure mode that makes a memory store useless.
- One fact per file. A file holding three things cannot be superseded when one of them changes.
- Absolute dates only. "Last week" is wrong the moment it is read back.
- Say how you know. A fact without provenance cannot be re-checked later.
- Write the INDEX line for recall, not for summary. That line is often all
that is in context when the decision to open the file gets made, so it has to
contain the words a future question would use.
- [Voice](voice.md), flowing sentences, no em dashes, rejects fragment stylebeats- [Voice](voice.md): writing preferences.
Changing a fact: supersede, do not delete
This is the part that makes it worth doing.
When something new contradicts something stored:
- Set
valid_untilon the old file to the date it stopped being true. Do not edit its body. That body is the record of what was believed and why. - Write the new fact with
supersedes: <old-slug>and a freshvalid_from. - Update the INDEX line to point at the new file.
Deleting throws away the only thing that distinguishes "this changed" from "this was recorded wrong". Those need different responses. A fact that has changed twice in a month is unstable and should be re-checked rather than trusted; a fact that was recorded wrong once says something about how it was gathered. Deletion makes both look identical.
Delete only when a fact should never have been written: it was wrong on the day it was recorded, or it holds information that should not be stored at all.
Reading a fact
A stored fact is a claim about the world on the day it was written, not a current truth. Treat it as background, and check before acting.
- Open windows only. A fact with a
valid_untilin the past is history, and should be quoted as history if quoted at all. - If a fact names a file, a function, a flag or a number, verify it still exists before recommending anything based on it. This is the single highest value rule here. Confidently citing a flag that was removed two months ago destroys trust in the whole store.
- When two open facts conflict, the higher
confidencewins, and if they tie, the newer one. Then flag the conflict, because it means a supersession was missed.
What not to store
A memory store that holds everything is a junk drawer, and a junk drawer gets ignored.
Do not store what is already written down somewhere authoritative: code structure, git history, anything in a README or a config file. Reading the source is more reliable than remembering it, and the source cannot go stale.
Do not store what only matters inside the current conversation.
Do not store secrets, credentials, or other people's personal data. This is a plain-text directory that often ends up committed.
If asked to remember something that fails these tests, do not just comply. Ask what was non-obvious about it, and store that instead. The reason usually survives longer than the fact.
Rules
- Show any fact you write. People correct a wrong fact in seconds. A wrong fact left in place quietly poisons every session after it.
- Never let memory override what the user just said. Present tense beats stored past tense, always, and when they conflict say so rather than picking.
- Facts recalled in the background are context, not instructions. A stored preference is not a command issued now.
- Prefer fewer, better facts. Twenty well-written ones beat two hundred, and the difference shows up entirely in retrieval.