In my recent piece about skills audits, I wrote that a death certificate needs a second witness. That audit found telemetry somehow blind to skills I use. Capture is hard.
This is a possible version of that second witness.
Every Claude Code session I’ve run for the past ten days or so has left a record of what it decided. And it has a log of its provenance - the receipts.
It’s called rutter. The name is from the age of sail - a rutter was the logbook of the routes actually sailed, as opposed to the map. The map tells you what’s known. The rutter is what you did about it.
I think the argument behind it is as interesting as the code.
A store of knowledge is not the same as remembering how you used it
Like a lot of people, I keep a knowledge vault. About 2,400 markdown notes right now - product strategy, research briefs, my Static Drift setting’s global bible, decisions.
But if you give that same folder to two different people, they’ll take different things away from it. Open different notes. Reach different conclusions. Find the answer to which question.
None of that is in the folders. It never has been.
AI memory products tend to treat knowledge and how it’s used as one thing.
That’s usually consolidation. The assistant summarizes its learnings. Combines that with what it already believed. Keeps one current answer. That’s how Claude Code keeps a session summary in window in my chat.
It’s a very reasonable default. It also has one, irreversible, loss.
If you merge entries, you don’t have a record of what you thought before. You only have a record of what the merge decides you think now.
In a lot of cases, for convenience, that’s fine. But it’s not a memory of your own reasoning.
My principle of design
A summary is not a record - it’s an assertion. If I add a versioned state of its provenance, it becomes a record, because I can check it.
Everything in rutter follows.
During my work - when a decision is made - the session writes one plain-English line about what was decided. And it references the notes it touched. The reference carries the content hash of the note as it was when it was read. The server computes the hash, not the client.
Nothing gets rewritten. That memory record is append-only. When I change my mind, the new position will be next to the old one. In order, and keeping my old, wrong, answers.
And if a note that’s referred to in the records is changed - which happens, all the time - the drift is shown, but not resolved. Some tools will make judgments on what’s stale. Instead, I want to see the reference whose target note changed, and what that drift was. I’m a better person to make the decision on what it all means, not the tool itself.
No model inside
There’s no LLM in this. It’s in the project’s constitution.
rutter is code plus storage: TypeScript, SQLite full-text search, markdown files sitting beside the notes they describe.
The reasoning stays in the client, where the context is.
That’s deliberate. The server can’t judge the prose. So it can’t consolidate it, decide it’s stale, reach its own conclusions. Every judgment call comes back to me - I’m the only person qualified to make it.
And the capture is free. The client writes the summary while its context is loaded. No extra inference. The capture hook is a tiny shell script.
After ten days’ use: 193 session entries, 106 different notes referenced. 4.6% of my vault - which doesn’t sound much. That’s the point though - memory of use is sparse because the use itself might be sparse.
Kill criteria
In my piece last week I said we need to write kill criteria before we get emotionally attached. I’ve tried to take that to heart.
The stateful features of rutter are behind a gate. Do I use this memory, at least three times a week, for two weeks? Every recall gets logged. If the count doesn’t go up, the feature doesn’t move forward.
I tried to draft a kill condition that distinguished between human use and agent use. If only the model ever consulted the memory, that’s infrastructure and not a librarian. But that’s not how I use it.
If I ask “what have I been working on recently?”, the assistant makes the call. The call is model-executed, and that’s just what I intended (consciously or not).
Memory reached through conversation is still memory reached.
So the kill condition today is different. Does the recall ever change what I do next? If I just make a recall and nothing happens, then it’s become a write-only log. That’s the opposite of what I’m trying for.
It’s published with an MIT license, spec and receipts, at github.com/shinytoyrobots/rutter. I’ll keep working on it for myself. But there’s no promise of support.
Doctor Emanuel Lagos
The Librarian in Neal Stephenson’s Snow Crash is the inspiration for this. A helper that remembers and thinks alongside you. That’s something a stateless assistant can’t be, and which consolidation destroys by accident.
That Librarian was discursive. You talked, it talked back - to a daemon written by its in-fiction creator, Doctor Emanuel Lagos.
That’s the direction I’m toying with for what comes next. A librarian you talk to, not an index to query. The no-model rule should survive - the personality doesn’t live in the server. The server is shipping instructions to every client it connects to. The voice is just more instruction. So that character will perform in the client.
The record underneath will still be inert. Append-only, and checkable.
We’ll see if it clears its own gates. That possibility is in the spec.
Even if you never run the code, I think the argument stands. A store records what is known. The record of use is what you did about it.
Further reading:
rutter - Your notes are the store. This is your memory of using them.
“You’re lost, unless you have a rutter.” - on the value of going there yourself and taking notes.
Stryker, C. What is AI agent memory? IBM Think.
Article photo by stephan hinni on Unsplash.
