Your agent forgets why.

context-keeper is an MCP server that records the decisions, constraints and reasoning behind a codebase — then puts them back in front of the model at session start, and before the edit that would break one. Local JSON. Zero dependencies.

pip install context-keeper-mcp

The problem it actually solves

Most memory tools answer “what did we say?” This one answers “why is it like this, and what will break if I change it?”

Decisions with rationale

Not a summary. The schema refuses an entry whose problem statement or reasoning is too thin — because future-you cannot recover a why that was never written.

Constraints that fire in time

A rule scoped to a path is injected before you edit a file it governs, not in a summary at turn one when it is still abstract.

History that stays reachable

A decision that replaced another carries one line saying what the old one said and why it changed — so “why did we move off X?” has an answer.

Retrieval, measured

59 questions across a frozen corpus of 7 real project stores: 44 with a known answer, 9 deliberately unanswerable, 6 asking for superseded history. Every question is written from the problem an entry solves — never reworded from its summary, because a reworded question shares vocabulary with its target and hands lexical search a free hit.

lexical only with embedding blend
recall@1
lexical
20%
+ embedding
38%
recall@3
lexical
38%
+ embedding
55%
recall@5
lexical
42%
+ embedding
64%
hit@5
lexical
50%
+ embedding
70%
MRR
lexical
37%
+ embedding
55%

recall@k is strict — the fraction of all entries that should have come back that did. A question with five correct answers cannot score above 20% at k=1. Reported this way because the flattering version (“did any correct entry appear?”) is the one that hides a half-answered query.

Where the embedding blend earns its keep

recall@5 per store, lexical vs blended. The gain is not uniform — it concentrates in large, prose-heavy stores. Small ones are already answered by keywords.

Clark
+41
Conductor
+10
agentsync
0
cambium
0
context-keeper
+40
meristem
0
xylem
0

This is why the embedding path is opt-in and falls back to lexical when no embedder is reachable. On a small store it buys almost nothing, and it costs a local model and a cache. Turning it on should be a decision, not a default.

What it costs at session start

Injecting the summary versus dumping every active entry into context. The number that matters is not the headline percentage — it is that injected cost stays roughly flat while the store grows.

balatron78 entries
97.3%
clark55 entries
94.1%
context-keeper13 entries
85.5%
conductor9 entries
73.3%

When it has nothing, it says so

Asked something the store has no answer for, a naive retriever still returns its top match — and it looks like an answer. Measured confabulation with no floor was 100%. The fix flags low-relevance results instead of suppressing them.

unanswerable questions correctly flagged real answers wrongly withheld
floor 0.15
38% caught0% false
floor 0.20shipped
38% caught0% false
floor 0.25
56% caught3% false
floor 0.30
75% caught16% false

Honest limit. On the 59-question set above, 67% of the in-domain unanswerable questions still come back unflagged — identically in both arms. Hard negatives that share real topic vocabulary are not separable by a lexical signal, and embeddings do not rescue them either. This is a known-hard problem and the page is not going to pretend otherwise.

Why not one of the bulkier ones?

Because most of them are solving a different problem, and if that is the problem you have, you should use them instead.

Extraction memorycontext-keeper
CaptureWatches the conversation, extracts automatically You state it; the schema enforces depth
RetrievalSimilarity over embedded turns Tag / text / scope, embeddings optional
Best at“What did we discuss about X?” “Why is it built this way, and what breaks if I change it?”
InfrastructureVector DB, embedding service, often a daemon JSON files in the repo. No service, no network.

The trade is real and it cuts both ways. Nothing is captured unless the agent records it — there is no auto-extraction, no web UI, and no entity graph. In an independent 81-system feature comparison context-keeper covers 53% of tracked features against a 25% median, leading on rationale, origin-trust and conflict surfacing, and absent on auto-extraction and visual tooling. That evidence file was submitted by this project's author under the comparison's cite-your-source rule — read it as a structured self-report that a third party accepted, not as an independent audit.

Reproduce all of it

Every number on this page is generated from committed measurement output. Nothing here is typed in by hand.

git clone https://github.com/jarmstrong158/context-keeper
python evals/run_retrieval_eval.py  # retrieval, frozen corpus
python evals/token_reduction.py   # session-start cost
python evals/abstention.py       # the honesty floor

The lexical arm needs no network and is bit-for-bit reproducible. The corpus is frozen and committed precisely so these numbers cannot drift underneath the claim — an earlier version of this page quoted figures measured against live stores that stopped reproducing within a day.