Proactive, local-first memory for AI coding agents - it acts before your agent repeats a mistake. Formerly Anamnesis.
Project description
🧠 Nevertwice
Proactive, local-first memory for AI coding agents - it acts before your agent repeats a mistake.
Your coding agent forgets everything when a session ends. Nevertwice remembers: the bug you hit last week, the pattern that worked, the reason you picked Postgres over Mongo. Then it does what other memory tools don't. Instead of padding every prompt with recalled text, it stays quiet until it has something useful, then acts by catching the mistake before your agent repeats it - measured live, a fired guard cut a real model's repeat-error rate by 86% (the harness is in the repo). Memory that earns its tokens.
No database. No server. No account. No telemetry. Zero pip dependencies.
The core is stdlib-only and recall works fully offline (lexical fallback, no model). Lesson
extraction wants a local Ollama or one optional cloud key. Claude Code
is wired natively by install.py; Cursor, Codex, Zed and the rest connect via MCP or the watch
daemon (details).
Formerly Anamnesis - renamed 2026-07 (same project, same store, old env vars still work).
$ # days ago, a different session, your agent hit a CUDA OOM and Nevertwice recorded the lesson.
$ # now, a fresh agent, a new prompt:
$ python nevertwice/memory_search.py "training crashes out of gpu memory" myproject
⚠ 1 relevant lesson recalled (confidence 0.68):
• [mistake] CUDA OOM at batch=64 on this GPU
→ lower batch size or enable gradient checkpointing; it recurred twice.
▶ See a guard fire: python examples/guard_demo.py · the whole machine on one project: python examples/scenario_demo.py · the 25-second recall demo: python examples/demo.py (any OS). All use a throwaway store; your real vault is untouched. Recording the GIF: docs/DEMO.md
Overview
Every morning your agent starts from zero. It re-reads the same files, rediscovers the same gotchas, and now and then repeats the exact mistake it made on Tuesday. You are paying tokens to re-teach it your own project on a loop.
Nevertwice gives it a memory. It watches each session, distils the durable lessons into short Markdown notes, commits them to git, and feeds the relevant ones back at the start of the next session and again as you type each prompt. The agent stops re-learning and starts recollecting.
The part most memory tools get wrong is the store itself. Here it is just files: your agent's
memory is a folder of Markdown notes in a git repo (a vault), and you own every byte of it. You
can open it in Obsidian, grep it, diff it, git pull it to another machine, or delete a note you
disagree with. There is no vector database to run and no service to trust. That is the part no
cloud competitor can copy without giving up their business model. Embeddings run locally on Ollama
by default, or on a single cloud key if you would rather not run a local model.
And it is not a toy. On the public LongMemEval benchmark, with the same local embedder for every system, Nevertwice out-retrieves the funded hosted leaders (Mem0, LangMem, A-MEM) on every metric, and you can reproduce that in one command. The numbers, and an honest account of what we tried and cut to get there, are below.
Want more than coding memory? Flip on the opt-in Brain layer and the same captured sessions self-wire into a knowledge graph of papers, methods, and datasets, tracking how your thinking on each one evolved. It is pull-only, read on demand, so your token budget never notices it is there.
git clone https://github.com/DonPlaton/nevertwice && cd nevertwice
python install.py
install.py detects your backend, prints what it chose, and wires Claude Code (Anthropic's
terminal coding agent). Using something else? Cursor, Cline, Codex, and Zed connect through the
MCP server or the watch daemon instead (INTEGRATIONS.md). Your next session
starts with its memory already loaded. The five-minute walkthrough is in QUICKSTART.md.
Why not Mem0, Zep, or Letta? Those are a hosted service plus a vector database you ship your data to. Nevertwice is plain files on your disk that you can read, grep, and diff, and nothing leaves the machine by default. The honest, benchmarked comparison is further down.
Memory that acts
Every other memory system is a better library. It retrieves text and injects it into the prompt, taxing every single turn. We measured that axis to its end and found it is reader-bound and commoditizing: the LLM, not the memory, is the variable. So Nevertwice does something no other memory does. It treats memory as a set of token-budgeted interventions that stay silent until they have something worth saying.
- Guards. A guard is a tiny pattern distilled from a past mistake, stored as one line in
a JSON ledger (not your prompt). Before your agent writes code, the pattern is checked against
the edit; on a match, a one-line warning fires, at zero context tokens until it does. Concrete:
the mistake
cursor.execute(f"SELECT ... '{name}'")becomes the guardexecute\(\s*f["'], and the next time the agent reaches for an f-string SQL query it sees "past mistake: build SQL with query parameters, never an f-string." The design is Popperian: a guard is advisory until corroborated across sessions, retires itself after false positives, and is always overridable. Memory proposes, reality disposes, and the agent is never boxed in. - Anticipation. Predicts the failure your current plan is heading toward by resemblance to past ones, and surfaces one precise warning. Spend is proportional to risk, not paid per turn.
- Counterfactual. "What breaks if I change X?" answered from an induced causal graph in a few lines rather than an episode dump, at about 7× fewer tokens than recalling every related note.
Every intervention is explainable (it cites the note it was born from), overridable in one line, and off by default where it could be noisy. A memory that acts must earn the right to.
These are measured on real tasks, with the harness to reproduce each one. The samples are small and run by one person; the point is that the harness is in the repo and the numbers are checkable, not that they are the last word.
| claim | result | evidence |
|---|---|---|
| a fired guard changes a real model's output | real error rate 0.36 → 0.05 (−86%) on DeepSeek (12 tasks × 8 trials) | LIVE_VALIDATION.md |
| memory that acts vs always-injecting recalled text | same error-prevention for ~31× fewer tokens | ACTIVE_MEMORY.md |
| answer-accuracy on the standard benchmark | 0.788 LongMemEval-oracle (open reasoner) | QA_ACCURACY.md |
| retrieval vs the funded leaders | R@5 0.80 › Mem0 0.76, one shared embedder | COMPARISON.md |
One honest caveat we measured rather than hid: the payoff scales with the agent's own capability. A strong model applies a delivered lesson and captures most of the benefit; a small 3B model captures about half. Memory removes the knowledge bottleneck, not the reasoning one (LIVE_VALIDATION.md).
All three interventions are on the Python API and the MCP server (Model Context Protocol, the open standard agents use to call tools), so this works on every agent: Claude Code, Cursor, Cline, Codex, Zed, and anything else that speaks MCP or writes session logs to disk (INTEGRATIONS.md).1 The moat isn't a better database. It's plain files you own, plus a memory that acts and costs almost nothing until it does.
Why Nevertwice
| Nevertwice | Mem0 / Zep / Letta / Cognee / memanto / Hindsight | |
|---|---|---|
| Acts before the mistake | ✅ guards + anticipation + counterfactual, 0 tokens until they fire | ✗ retrieve-and-inject only (taxes every turn) |
| Runs | your machine, local files | a service, vector DB, or cloud (memanto: closed engine) |
| Store format | human-readable Markdown + Git | opaque DB rows and embeddings |
| Dependencies | 0 Python packages (stdlib core), local Ollama for embeddings (or an optional cloud embedder) | many, usually a server plus a DB |
| Your data leaves the machine? | never by default (local embeddings; cloud embedder is opt-in) | usually, via cloud APIs |
| Auto-capture | ✅ native for Claude Code, always-on daemon for the rest | manual API calls |
| Knowledge graph | ✅ entity + typed-relation graph over the Markdown, traversable, no DB | a separate graph database (Neo4j / FalkorDB) |
| Open in Obsidian | ✅ it is your vault | ✗ |
| Honest about what works | ✅ we publish the negative results | rarely |
You own every byte of your agent's memory, and you can read it.
See it work
Recorded from the real system (examples/guard_demo.py + examples/scenario_demo.py, throwaway vault) - every number on screen is measured live, nothing is mocked. The 5.9x recall saving shown is for this small demo project; it grows with the store (9.1x on the default, 44x at ~220 notes).
$ # session 1: you hit a CUDA OOM, Nevertwice quietly records the lesson
$ # ...days later, session 2, a fresh agent, new prompt:
$ python nevertwice/memory_search.py "training crashes out of gpu memory" myproject
⚠ 1 relevant lesson recalled (confidence 0.68):
• [mistake] CUDA OOM at batch=64 on this GPU
→ lower batch size or enable gradient checkpointing; it recurred twice.
In Claude Code this happens automatically at session start and on each prompt. The agent simply already knows.
Review what it knows
Two read-only commands surface the store for a human or an agent, with no embedder, no LLM, and no network:
$ python -m nevertwice.digest --days 7 # what was added / revised this week, per project & type
$ python -m nevertwice.digest --conflicts # the supersession ledger: every fact the memory revised
digest is the daily/weekly "what's new"; conflicts is the audit trail behind "contradictions
don't pile up", pairing each retired note with the one that superseded it. Both are also
nevertwice.api.digest() / nevertwice.api.conflicts() and MCP tools (memory_digest,
memory_conflicts), so an agent can ask too.
Prefer a visual? One command writes a single self-contained HTML file (no server, no account, no external asset) that you open in a browser:
$ python -m nevertwice.dashboard --days 30 # → memory_dashboard.html, then opens it
It is a snapshot of the whole store (stats, per-project, recent, the contradiction ledger,
top entities) that you can mail, commit, or read offline. The file is the UI, the same way
the notes are the database, with no serve process to run. (For live editing, the vault opens
in Obsidian as-is.)
How it works
your session (any agent)
│ Claude Code hook · MCP call · ingest.py · watch daemon
▼
extract → mistakes · patterns · decisions (local Ollama, or one cloud key; secrets redacted)
│ + a per-project "card" (status · stack · open gotchas · decisions)
│ + local embeddings (bge-m3, multilingual) + git auto-commit
▼
Markdown + Git store (open in Obsidian if you like)
│ SessionStart → inject the project card and the relevant lessons
│ UserPromptSubmit → task-aware recall by the prompt text
│ anytime → memory_search "<query>" · MCP · CLI
▼
the agent recollects
Retrieval is hybrid: semantic search over local embeddings, fused with lexical search, behind a
calibrated abstention gate. A nonsense query gets back "no confident match" instead of a
confident wrong answer, which matters more for a memory than chasing one extra point of recall.
When a newer lesson contradicts an older one, supersession retires the old note (it moves to a
Superseded/ folder, kept for history but out of the recall pool) so the agent only ever sees the
current truth, and a fix links back to the bug it resolved.
Memory for any agent
Claude Code is the zero-config case. install.py wires five hooks (four for capture and recall,
plus a PreToolUse guard that fires before a repeat mistake) and capture is automatic from then on,
with nothing to configure.
Every other agent that writes its sessions to disk (Codex, Cline, Roo, Aider, Gemini CLI) is
covered by nevertwice watch, a small stdlib polling daemon that finds the known log folders on
your machine and mines finished sessions as they land. Start it once at login and forget it. The
same engine also runs as a one-shot sweep if you prefer cron over a resident process.
If you call models from Python, wrap the client in one line with auto_capture(client) or decorate
a chat function with @capture_chat. Any MCP client such as Cursor, Claude Desktop, or Zed can
talk to nevertwice/mcp_server.py for search, remember, and ingest. LangChain and LlamaIndex get
drop-in retriever and memory adapters. The agent can even write its own lessons through
remember_lessons with no separate extraction model at all. Copy-paste recipes for each live in
INTEGRATIONS.md. One honest caveat: Cursor and Windsurf keep their chat in a
SQLite blob rather than plain files, so they need an export step before the watcher can read them.
Benchmarks
External and reproducible, on LongMemEval-oracle (940 sessions in one shared store, 500
human-annotated questions, local bge-m3). Nevertwice's own numbers reproduce with the zero-dep
core; the head-to-head against Mem0 / LangMem / A-MEM installs those competitors' own packages to
run them on the same stand (their deps, not ours), and the dataset is fetched separately
(research/data/README.md):
| method | R@1 | R@5 | R@10 | MRR |
|---|---|---|---|---|
| semantic | 0.42 | 0.65 | 0.73 | 0.53 |
| lexical (BM25) | 0.52 | 0.75 | 0.83 | 0.62 |
| calibrated fusion (shipped default, 0 deps) | 0.55 | 0.80 | 0.86 | 0.66 |
| + trained cross-encoder (opt-in) | 0.61 | 0.83 | 0.86 | 0.71 |
The shipped ranker fuses the semantic and lexical signals with calibrated score fusion, which lifts
R@5 from 0.66 under the rank fusion most systems ship to 0.80. The optional cross-encoder
(bge-reranker-v2-m3, NEVERTWICE_XRERANK=1, [reranker] extra) then takes top-1 to 0.61. Reproduce
with python research/longmem_eval.py [--xrerank] (the dataset is fetched separately).
The head-to-head, run locally and reported straight. On the same stand with the same local embedder for everyone, we ran Mem0, LangMem, and A-MEM end to end on Ollama, no paid key. Nevertwice leads every metric: R@5 0.80 against Mem0's 0.758, LangMem and A-MEM at 0.692, and top-1 0.55 (0.61 with the reranker) against Mem0's 0.478. The win is the fusion, not the embedder, which is identical for all four. We are careful about what is a moat: calibrated score fusion is classic retrieval, so the durable edge is the substrate (plain files, $0, local, no server), and we publish the full table plus what we tried and cut in COMPARISON.md and research/RETRIEVAL_FUSION.md.
Compare methodology, not headlines. Vendor posts quote LongMemEval scores from other protocols: answer accuracy with an LLM judge, oracle context handed to a reader, closed embedders, different question subsets. The tables above are retrieval R@k on one open stand with every variable pinned except the memory pipeline itself, and one command reruns the whole thing on the competitors' own packages (which records the exact versions it compared against). When a bigger number appears somewhere, first ask what it measures.
After retrieval: the axis that actually separates memory
Here is the uncomfortable truth about memory benchmarks in 2026: retrieval R@k has stopped discriminating. Independent analysis finds that across LongMemEval, LoCoMo and peers, retrieval-miss dominates the error budget while retrieval-hit-but-wrong-answer is rare, so the headline scores mostly measure "did the right note come back" - and every serious system now scores high there. The gap that shows up in production (Mem0's own 91.6 on LoCoMo drops to ~49% effective at 50k sessions once stale data and contradictions enter) lives after retrieval: does the memory resolve contradictions, resist poisoning, and forget the right things?
That is the axis Nevertwice is built for, and every number is measured with a harness in research/:
- Contradictions resolve at write time. A newer fact retires the older one to
Superseded/, so recall only ever returns the current truth and theconflictsledger keeps the audit trail. Most competitors are add-only or leave deletion to you (COMPARISON.md). - Poisoning defence, measured. 88% of memory-poisoning acceptance attacks blocked (precision 0.91), prompt-injection caught 100%, and - stated plainly because honesty is the point - only ~50% of plausible-false facts (research/POISONING.md).
- Forgetting is a policy, not neglect. A submodular coreset keeps +0.14 more topic coverage than recency-sorting at a tight 20% retention budget, with less redundancy (research/FORGETTING.md).
- We publish the negative results. Consolidating episodes by replacement halved downstream recall in our own test, so it is not shipped (research/CONSOLIDATION_EVAL.md).
Retrieval is table stakes; this is the moat, and it is the part a competitor cannot copy by swapping in a better embedder.
What we measured, and what we cut
Most memory projects pile on clever ranking and assume it helps. We built the clever parts, measured them on real data, and deleted the ones that lost, because a memory you cannot trust is worse than none.
A promptable LLM reranker actually lowered top-1 precision against the plain bi-encoder, so it is gone. We A/B tested four "stronger" local embedders and none beat bge-m3 at top-1, so the default is unchanged. Abstractive consolidation, the trick of summarising many notes into one principle, dropped real recall@3 from 0.82 to 0.35, because a general principle embeds away from the specific question that needs it, so it never shipped. The recurrence prior is a sound mechanism that stays dormant on a young single-user store, so it sits off the hot path. The one idea that earned its place was the trained cross-encoder, and we only learned which was which by measuring. The write-ups live in the research directory.
What is in the box
Everything here ships today, not on a roadmap:
- Ask "what did we believe on March 3?" and bi-temporal queries answer from that day's truth.
- A new fact that contradicts an old one retires it at write time; recall never serves both.
- Recall walks
[[wikilinks]]for multi-hop answers, abstains instead of guessing, and carries lessons across projects. - Secrets are redacted before anything is written. A poisoning guard caught every injection, exfiltration, and destruction attempt in the study; across the full acceptance-attack set it blocks 88% at precision 0.91 (details in research/POISONING.md).
- A SQLite index keeps per-query cost flat into tens of thousands of notes; a submodular forgetting cap stops unbounded growth.
- Sync between machines is
git pull. Concurrent edits to the same note auto-merge field-by-field (recurrence takes the max, a retirement wins, tags union). - The project card travels: it exports to and imports from AGENTS.md and the Open Knowledge Format (OKF, the draft Google/Anthropic interchange spec), so other tools can read what yours knows.
An opt-in Brain layer turns the same captured sessions into a self-wiring knowledge graph for
research or personal knowledge: typed entities (paper, method, dataset, benchmark, …), per-entity
cards that roll up everything known about each across projects, a timeline of how your take on it
evolved, and a graph-centrality salience signal. It is pull-only, read on demand and never
injected, so the lean, token-bounded hot path is byte-for-byte unchanged when it is off (the
default). Turn it on with NEVERTWICE_PROFILE=research (or general); see
docs/BRAIN_LAYER_DESIGN.md.
Privacy
Embeddings run locally on Ollama by default, so nothing leaves the machine. If you would rather not
run a local model, point NEVERTWICE_EMBED_PROVIDER at openai, voyage, cohere, or gemini with one
key and recall goes through that instead. With no embedder at all, recall falls back to lexical
full-text search rather than going dark. Extraction is local-first, and an optional cloud key
(Cerebras, Groq, DeepSeek, or Gemini, all zero-retention) only ever speeds it up. Secrets are
redacted before anything is written or sent. The store is yours, on your disk, under your git.
And there is no telemetry: no account, no usage pings, no phone-home. The only network calls
are the ones you configured yourself (your Ollama endpoint, or your own cloud key), and
NEVERTWICE_LOCAL_ONLY pins named projects to local-only for good.
Install
git clone https://github.com/DonPlaton/nevertwice && cd nevertwice
python install.py # idempotent; backs up ~/.claude/settings.json before wiring hooks
python install.py --ollama # also pull the local models (bge-m3 embedder + an extraction model)
python install.py --profile research # turn on the opt-in Brain layer (research/general)
python install.py --print # dry run, shows what it would do and writes nothing
The installer ends by printing your options: which profile is active and how to switch the Brain
layer on (coding is the default; research/general add the knowledge graph), so a first run is
self-explanatory.
For cloud extraction, copy .env.example to .env and add one key. With no key it uses local
Ollama. To skip a local model for recall too, set NEVERTWICE_EMBED_PROVIDER with the matching key
and run embed_index.py --rebuild once. With no backend at all, extraction pauses loudly (sessions
are kept and retried, never dropped) and recall runs on lexical full-text search until an embedder
shows up.
Projects you already have. Once the hooks are wired, every new session is captured automatically,
and past Claude Code sessions backfill on the catch-up sweep with no action needed. To seed a rich
context card for a large existing project right away instead of waiting for sessions to accumulate,
point the bootstrapper at it: python -m nevertwice.bootstrap_contexts /path/to/project.
Tests
Thirty-seven suites, standard library only, LLM and embedder fully mocked. No network, no GPU:
for t in tests/_test_*.py tests/research/_test_*.py; do python "$t" || break; done
CI runs them on Linux, Windows, and macOS across Python 3.10, 3.12, and 3.13.
Docs
Quickstart · Architecture · Brain layer (opt-in) · Integrations · Configuration · Benchmarks · Comparison vs Mem0/Zep/Letta/A-MEM · Research, the honest eval lab · Security policy
Author and citation
Built by Platon Chernov. If Nevertwice helps your work or your research, a ⭐ is genuinely
appreciated, and a citation is welcome; a CITATION.cff ships with the repo.
License
MIT, see LICENSE. Use it, fork it, build on it.
-
Cursor and Windsurf keep their chat in a local SQLite blob rather than plain log files, so they need a one-time export step before the watch daemon can read them; the MCP path works for them with no export. Details in INTEGRATIONS.md. ↩
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nevertwice-2.1.0.tar.gz.
File metadata
- Download URL: nevertwice-2.1.0.tar.gz
- Upload date:
- Size: 235.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cb1eff16c6c68057949afd351f2385f49a6e10ddcc7bff51fc877ee00dea333a
|
|
| MD5 |
7e65da0e4a14700093a1c548011a7dfc
|
|
| BLAKE2b-256 |
4faeab4f0ada72ca6aeac64b23a1be56f6a2f9e99b2bf6842f444b15d392bafe
|
File details
Details for the file nevertwice-2.1.0-py3-none-any.whl.
File metadata
- Download URL: nevertwice-2.1.0-py3-none-any.whl
- Upload date:
- Size: 244.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
38489c1e2ab8c75e8cd3b912fb3858494cf6ed8f4eff42941e9a120b000953ca
|
|
| MD5 |
fa6f753a3347aad1696efefb66db8e51
|
|
| BLAKE2b-256 |
100140e50fc118abaa8e23670e268a2244da8877ccd147ced78473ed5a009021
|