2026-07-13 · 7 min · Pavel Hegler

Recall, not re-reading: how backant-memory works

Our agent re-read the repo every morning. Every session opened the same way: load the whole CLAUDE.md, grep the same five files, rediscover the same conventions. Once a month it would propose a fix that had already failed in March — confidently, because nothing told it otherwise.

All the information existed. It lived in files. Files get loaded; they don't get recalled. That difference turned out to be the whole problem, and backant-memory is what we built to fix it. It is free, it runs entirely on your machine, and any MCP agent can use it — Claude Code included.

Files are the wrong shape for memory

A CLAUDE.md only grows. Every line you add costs every future session, whether it is relevant or not, and the useful line about clock skew from last quarter sits somewhere in the middle where models attend to it worst. So you prune it, and now the agent doesn't know the thing again. Load-everything forces a choice between a polluted context and an amnesiac one.

What an agent actually needs is what you need from a colleague: not their diary read aloud each morning, but an answer to "have we seen this before?"

What it is

backant-memory is an npm package that stores memories in per-repository namespaces, derived from your git origin. Switch projects and the context switches with you. Each namespace is its own libSQL database under ~/.claude/kairos/memory/. Claude Code talks to it over stdio — each session resolves the store for its working directory — and a small always-on daemon keeps the local embedding runtime warm so recall is fast from the first query.

The same store is shared with Kairos, our autonomous developer. Your interactive sessions and your autonomous one have the same brain per repo. You can also ignore Kairos entirely; the memory stands alone.

Three kinds of writes

Memories enter in three shapes, and the distinction does the heavy lifting:

There are also procedures — multi-step runbooks proposed after a verified success. Validated procedures inject into future sessions as follow-this instructions; unvalidated ones arrive marked draft-verify. The agent is told which is which.

Recall is one formula

Retrieval is hybrid, and the scoring is not a secret:

score = 0.4·bm25 + 0.4·cosine + 0.1·weight + 0.05·recency + 0.05·min(verdict_boost, 5)/5

Full-text search and vector similarity carry most of it, fused with a learned weight (how often this memory proved useful), recency, and a verdict boost for memories whose claims were later confirmed. Every recall also writes a trace — you can ask why a memory surfaced and get the arithmetic, not a shrug. Repeated cues hit a cache.

The graph

Flat facts lie by omission. A memory that says "retry with backoff fixed the flaky test" is dangerous if a later memory says the flakiness came back. So memories are connected by typed edges — supports, contradicts, related_to — each with a weight, and recall can pull a claim together with what contradicts it.

Edges go through a propose → approve lifecycle rather than being written directly. The asymmetry is deliberate: a missing edge costs you one lookup; a wrong edge quietly poisons every recall that walks through it. Writes are cheap, structure is gated.

Memories live and die

Weights decay on a sweep; reinforcement bumps what proved useful; STM that keeps earning recall gets promoted to LTM; LTM revisions keep their history. Confirmed outcomes raise a memory's verdict boost, which feeds back into the formula above. A memory that never helps quietly sinks. This is the part that keeps a two-year-old store from becoming a two-year-old CLAUDE.md.

Consolidation

Periodically the store runs a consolidation pass — linking related observations, distilling durable lessons from clusters of episodes, staging candidates with verdicts for review. Concurrency is guarded so two consolidation verdicts can't rewrite the same target in one cycle. I'll be honest: this is the roughest part of the system. Consolidation quality varies, and we still review what it stages. It earns its keep on repos with months of history; on a fresh repo it mostly waits.

Your memories are yours

Embeddings are computed locally — a Qwen3 embedding model served by Ollama in Docker on your machine. There are no remote embedding APIs. Ever. Memory content never leaves the machine it was written on.

One caveat, stated plainly: the HTTP surface for non-Claude-Code agents currently serves a single global store, because HTTP sessions carry no working directory. Repo scoping is exact on the stdio path, which is what Claude Code uses. Roots-based scoping for HTTP is a tracked follow-up, not a promise we're hiding behind.

Try it

npm install -g backant-memory
backant-memory install

install is idempotent; re-running repairs drift. backant-memory doctor checks every piece. It is Elastic-2.0 licensed, and if you want it to do something it doesn't, open an issue — same as everything else we ship.