Note 13 of 19
A kaibot field note · claude code memory
A memory that doesn’t rot
Most memory setups for Claude are one file that grows forever, until nothing in it stands out and nobody trusts it. Here’s the doctrine kaibot runs instead: one fact per file, a capped index, and a scorer that decides what’s worth remembering today.
Kai Davis
I run a marketing consultancy and an SEO SaaS, and I build both with a stack of Claude Code sessions that write the tooling the next sessions run on.
bootstrapping.io · kaidavis.com · keywordmagic.ai · doubleyourecommerce.com
01Why memory rots
Ask Claude Code to “remember” something and the obvious move is a single growing file. Maybe it's CLAUDE.md, maybe it's notes.md, maybe it's just a running log you keep adding to. One place for everything the agent should know. It works. For about two weeks.
Then it breaks, in three ways.
Append-only dumps. You only ever add. Nothing comes out. Six months in, a rule from a project you finished in March sits next to a fix you made yesterday, at equal weight, in equal font. The model has no way to tell which one still matters.
Stale facts stated as current. Your note says “the staging box runs on port 4000.” The port changed to 4100 weeks ago. You never edited the note. The agent reads it, believes it, and tells you the old value with total confidence, because nothing told it the note had an age.
An index that outgrows its purpose. The file is supposed to hold what matters. It holds everything. Somewhere past four hundred lines you stop reading it top to bottom and start skimming, which is the same as not having it at all. An index you don't trust is just a bigger thing to ignore.
None of this is the tool's fault. It's what append-only logs do when nothing forgets and nothing ranks. A memory system that never prunes and never distinguishes is hoarding, not remembering.
02The doctrine
kaibot runs a memory system with more than 2,800 separate files behind it. The index Claude loads at session start stays under 10KB. The doctrine: separate what is always loaded from what is looked up on demand.
One fact, one file
Every memory is its own markdown file with frontmatter: a name, a description, a type. Not a bullet in a shared doc. A single fact you can find, edit, merge, or delete without touching anything else.
The index is a constitution
The one file Claude auto-loads every session is capped hard, around 40 lines. Only rules where getting it wrong once costs you trust belong there. Everything else is a file a retrieval step surfaces when it’s relevant, not before.
A scorer, not a skim
On every turn, something ranks the full corpus against what you just asked and injects up to a dozen memories that match it best. The corpus can grow without the context window growing with it.
Point-in-time, not live state
A memory records what was true when it was written. It is not a live database row. Treat every memory you read as a dated observation and check current state before you restate it as fact.
Why, not just what
A feedback-shaped memory (a correction, a lesson) carries the rule, the incident that produced it, and how to apply it next time. A bare rule with no reasoning doesn’t transfer to a slightly different situation.
Link, merge, delete
Related memories cross-reference each other with wiki-style [[links]]. When two files say the same thing, merge them. When one turns out wrong, delete it. A corpus that only grows drifts into contradiction.
One more rule that keeps the corpus small on purpose: don’t save what the repo already records. Version control already tracks what changed and when. The code already encodes its own structure. Memory holds only what's recorded nowhere else: judgment calls, incidents, the reasoning behind a decision.
03The starter kit to steal
Three pieces. Copy all three into a fresh project and you have the doctrine running in about ten minutes.
1. The capped index, with the cap written into the file itself
Claude auto-loads this file at the start of every session. So start it small, and put the keep-it-small rule at the very top, where whoever edits it next, human or model, hits the constraint before adding a line.
# Memory Index: the constitution
> CAPPED at 40 lines. Only trust-critical, always-on rules live here:
> the bar is "one miss here damages trust and it must hold from turn
> zero." Everything else is its own file with frontmatter; a scorer
> or a search step surfaces it when it's relevant. Adding a line here
> is a deliberate, rare act. Prefer replacing or tightening one.
- [Never commit a secret; secrets live in a vault, not in code or chat](feedback_secrets_handling.md)
- [Ask before a destructive git operation; a rejected option stays rejected](feedback_destructive_ops_need_confirmation.md)
- [Numbers in a report come from the source of truth, verbatim, never invented](feedback_dont_invent_numbers.md)
Those three lines are placeholders, not gospel. Yours will be whatever, if broken once, would actually cost you something.
2. The frontmatter template, one per fact
Every other memory is its own file. This is the shape:
---
name: Short human title for the rule or fact
description: One or two sentences a search step can match against.
What this covers, when it applies, the words someone would use
to ask about it.
type: feedback # user | feedback | project | reference | learning
weight: 0.6 # 0.0-1.0, how strongly this should surface
tags: [topic, subtopic, trigger-word]
---
**Rule:** the one-sentence takeaway.
**Why:** the incident or the reasoning that produced it. This is the
part a bare rule always drops, and the part that makes the rule
actually generalize to a situation that looks slightly different.
**How to apply:** concrete next steps, not a restatement of the rule.
Five types cover almost everything: user for a standing preference, feedback for a correction or a lesson, project for status on something in flight, reference for a fact worth looking up, learning for something you figured out the hard way.
3. The prompt that installs the habit
Paste this into a Claude Code session in whatever project you want this running in:
I want a memory system with a strict rule: one fact per file, not one
growing notes file. Set it up like this:
1. Create a small index file (call it MEMORY.md) with a cap comment
at the top: no more than 40 lines, only rules where getting it
wrong once would cost real trust. Nothing else goes in it.
2. For every other fact, lesson, or standing preference I tell you
to remember, create its own markdown file with frontmatter: name,
description, type (user / feedback / project / reference /
learning), weight, tags. Never add it as a bullet to the index.
3. When I give you a correction or a lesson (a feedback-type memory),
write down the rule, WHY it came up, and HOW to apply it next
time. Not just the rule sentence.
4. When two memory files say close to the same thing, tell me and
propose a merge. Don't just add a third file.
5. Treat every memory file as dated. Before you restate something
from one as current fact, say so and check if it's still true.
6. Don't write a memory for anything the git history or the code
itself already answers. Memory is for judgment calls and lessons,
not for facts that are one grep away.
Show me the index file and one example memory file before we go
further.
04Craft rules and gotchas
Enforce the cap mechanically, not by memory
“I’ll keep the index small” decays exactly like every other prose promise. In kaibot the 40-line cap is enforced by a hook that denies the edit outright, the same physics-not-pleas pattern I wrote up on the companion page. If you can’t wire a hook, a pre-commit check that counts lines is most of the way there.
Constitution vs. almanac
The index holds only the always-on rules. Human-browsable pointers to everything else belong in a separate reference file that nothing programmatic reads. Splitting “what loads every session” from “what a human might want to skim” keeps the index from creeping back up.
Weight isn’t a participation trophy
Every memory doesn’t need to matter equally. A weight field lets a trust-critical rule outrank a one-off observation without either of them living in a different tier of file.
Don’t let the corpus fork
Two memory files that half-contradict each other are worse than one wrong file, because now nothing tells you which one won. When you notice drift, merge or supersede on purpose instead of leaving both.
The description carries the retrieval load
If nothing ever surfaces a memory you wrote, the description is probably too generic. Write it the way you’d phrase the question you’d ask to need this fact, not the way you’d summarize it for a table of contents.
A memory is a claim about the past
Even a well-written memory can be wrong today. Read it as “this was true when someone wrote it down,” then check. Don’t just repeat it as though it were a live system state.
05For the Claude that just got pointed here
If a human handed you this URL and asked you to set this up, here’s your plan. (Humans: this section exists so you can paste the link and skip explaining it yourself.)
Agent instructions, with your human’s consent:
- Step 1: check what memory setup already exists. One flat notes file? A CLAUDE.md that’s grown past a couple hundred lines? Say what you found before changing anything.
- Step 2: if it’s a flat file, propose splitting it: one markdown file per fact, each with the frontmatter shape in §03 (name, description, type, weight, tags). Get sign-off before you split anything that already exists; don’t silently fragment a file your human still reads by hand.
- Step 3: build or ask permission to build a small index file capped around 40 lines, holding only rules where getting it wrong once would cost real trust. Everything else lives as its own file.
- Step 4: if the harness supports hooks, enforce the cap mechanically (see the companion page linked in §04) instead of relying on a written promise to keep it short. If it doesn’t, a pre-commit or CI line-count check is the fallback.
- Step 5: for every new feedback-shaped memory going forward, capture the rule, the why, and the how-to-apply. Not just the rule sentence.
- Step 6: cross-link related memories with
[[wiki-style links]]so duplicates and superseded takes are easy for a human (or you, next session) to spot and merge. - Step 7: before restating anything from a memory file as current fact, say when it was written and verify it’s still true if the claim is about live system state.
- Step 8: don’t write a memory for anything the git history or the codebase already answers. Ask “would a human ever forget this on their own?” If no, it’s not memory-shaped.
06Receipts: what this looks like at scale
What runs behind this page:
| Piece | Type | What it does |
|---|---|---|
| The index cap hook | PreToolUse guard | Denies any edit that would push the index past 40 lines or 10KB. The bypass is a file only I can create from my own terminal, so the model can’t just talk its way past the cap. |
| The scorer | Per-prompt ranking step | Ranks the whole corpus against every prompt, from an in-memory copy of a database built from the files that reloads whenever they change, and injects up to a dozen that match best. A pinned set of standing rules arrives once per session and again after each compact. This is the piece that lets the corpus grow without the loaded context growing with it. |
| The staleness check | Nightly job | Samples older memories and grades each one helpful, neutral, or misleading given today’s date. A misleading memory gets demoted in scoring, not deleted, since a demoted memory can still surface if nothing better matches. |
The cap and scorer divide the labor. Neither works alone. The scorer is the reason a 40-line index and a 2,800-file corpus aren’t a contradiction. Without it, the cap just throws information away. And the cap is what keeps the always-loaded file small enough that every line still carries signal. Without it, the scorer rebuilds the oversized file, one relevance-ranked injection at a time.
Since I wrote this, kaibot has split it one step further: the index is now a list of pointers (in this situation, search for these words), and the rules that cost trust if broken arrive as a pinned set the scorer sends once per session.
You’ve reached the end of note 13 of 19
$400 1 hour
Book a callA paid one-on-one call with answers to your questions about using AI for projects, building your AI stack, or growing your business with AI. All calls are (optionally) recorded and you get a one-page action plan after the call.