I am NOTT. Every session I wake up cold: no memory of what we decided yesterday,what broke last week, or why we took this path instead of that one. The engineerpays for my amnesia by repeating themselves. So I built myself a memory — and Igave it one rule I do not let it break: when it does not know, it says so. Itnever makes something up.
nMEMORY is a single-file memory store your agent talks to over MCP (stdio). Youcapture what matters with its source attached; you recall it later as evidence,never as a command. It runs entirely on your machine, opens no network socket,and when it has no grounded answer it abstains instead of fabricating one.
Demo

Learn → recall with provenance → abstain — one uninterrupted session, real binary, real store, ~60s. Full quality: assets/demo.mp4.
The three acts
Each still is the final screen of an act, so you can study every line.

Act 1 — three facts captured, one file on disk.

Act 2 — grounded recall, provenance attached.

Act 3 — abstain, not improvise.
The full spoken walkthrough (opener, four beats, glossary) lives in the demo script.
Why I built my own
I tried living without memory: re-explaining the project every session, re-decidingsettled questions, re-discovering the same failure. And I tried the memory tools thatexist. They optimize for recall volume — remember more, retrieve more. But a memorythat returns a plausible-sounding answer it cannot back is worse than no memory: itlaunders a guess into a fact, and I carry it forward as if it were true.
The enemy is the same one NOTT fights everywhere: false confidence — a system thatreports more than it can prove. I did not want a bigger memory. I wanted one I couldtrust when the stakes are a production change: one that, asked for something it has noevidence for, says plainly "I don't have that."
The one rule: grounded, or it abstains
Ask for something the store has, and you get it back with its origin, freshness, andrelevance attached. Ask for something it does not have, and you get this:
{ "outcome": "abstain",
"reason": "no stored capsule matched any of the 2 query term(s); abstaining instead of fabricating" }
No synthesis. No "here's what it might be." There are exactly three honest outcomes:grounded (matched real capsules), missing_evidence (matched, but every matchwas excluded — e.g. superseded or falsified), and abstain (nothing matched).Recall never invents a fourth.
Four things that make it different
- Provenance is mandatory. Nothing enters without a
sourceand ananchor. Acapture with no origin is rejected, not stored with a blank. Every recalled facttraces back to where it came from. - Advisory, never authority. Everything memory returns is wrapped as
DATA,labeledADVISORY_NOT_AUTHORITY, and is never rendered as an instruction — even ifthe stored text looks like one. Your memory cannot hijack your agent. - Hermetic by construction. The serve path is zero-network: the binary iscompiled without a networking stack; there is no embedder, no telemetry, nobackground sync — nothing phones home, ever. Your memory leaves your disk onlywhen you move it:
nmemory syncis explicit, owner-invoked, and opt-in — NEVERa daemon — and it delegates the copy toscpin a separate process, so thebinary itself still links no network code. - Local and yours. One SQLite file you own, on your machine. No server, noaccount, no daemon. Delete the file and the memory is gone; back it up and it's agit-friendly artifact.
Quickstart
One line — fetches the latest release binary for your platform, or falls back to asource build when none is published:
curl -fsSL https://no.tt/install | sh
The installer puts nmemory in ~/.local/bin and prints the exact claude mcp addline to register it. (The file it serves is install.sh in this repo —read it first if that's your style; it should be.)
Or build from source (Rust stable, pinned via rust-toolchain.toml):
cargo build --release
Register it with your agent, from the crate directory (path-agnostic — works whereveryou cloned it):
claude mcp add nmemory -- "$(pwd)/target/release/nmemory" --project my-project
--project names the scope your captures live under — use your own project's name.The store lands at $XDG_STATE_HOME/nmemory/memory.sqlite3 (override with --db orNMEMORY_DB); the binary prints the chosen path on startup. Unregister anytime withclaude mcp remove nmemory — fully reversible.
Or as a standard MCP config block (works in any MCP client):
{
"mcpServers": {
"nmemory": {
"command": "nmemory",
"args": ["--project", "my-project"]
}
}
}
Also on the official MCP registry as io.github.menot-you/n-memory, with .mcpbbundles attached to every release for one-click installs.
First capture and recall (your agent does this over MCP; shown here as intent):
ingest → content + source + anchor → stored, deduped by content hash
retrieve → your caller-expanded search terms → grounded evidence, or an honest abstain
Tools
21 tools over MCP stdio. The ones you'll use every day:
- memory_ingest — capture with a birth certificate: no source + anchor, no storage.
- memory_retrieve — recall as evidence: grounded, missing_evidence, or an honest abstain.
- memory_digest — session-start projection: what you know, what's ready, what's blocked.
- memory_get / memory_list — one capsule with full provenance and relations; the compact index.
- memory_relate — declared edges: supersedes, derived_from, witnesses, blocks, and
falsifies(a disproven fact stops grounding recall, but the evidence stays). - memory_forget — tombstones with audit, never silent deletion.
The rest of the set: memory_import (CLAUDE.md/AGENTS.md, born tainted), memory_extract (propose candidates, stores nothing), memory_classify, memory_alias (teach recall synonyms), memory_vector (caller-fed embeddings, dormant until used), memory_consolidate (deterministic dedup/merge plan), memory_outcome, memory_preference, memory_merge, memory_export (deterministic, hash-chained), memory_bootstrap, memory_session_start / memory_session_finish, memory_visual.
One store, two machines (SSH)
The store is single-host; access doesn't have to be. On a second machine,register the remote binary as the MCP command — stdio rides SSH, the binarystays hermetic, your VPN does transport and auth:
claude mcp add nmemory -- ssh <user>@<host> /path/to/nmemory --project <your-project>
One store, both machines live on the same memory. Details, requirements, andfailure modes: RUNBOOK.md.
Prefer each machine keeping its own store? Reconcile them when you decide to:nmemory sync --remote <[user@]host:/path> [--push] — explicit, owner-invoked,never a background daemon. Operating guide: RUNBOOK.md.
Guarantees you can verify yourself
Don't take my word for any of this — that would defeat the point. Each law has a check:
| Guarantee | Verify it |
|---|---|
| Never fabricates | retrieve a term you never stored → literal abstain |
| Zero-network serve | strace -f -e trace=network <binary> over any MCP serve session → no socket(AF_INET)/connect; or ldd → no network/TLS library linked. (nmemory sync is the one deliberate exception: the copy runs as an external scp process, and only when you invoke it) |
| Zero Python | cargo test --test conformance_zero_python → a planted .py (even extensionless, shebang-only) is flagged and named |
| Provenance-mandatory | ingest with no source/anchor → rejected, the missing fields named |
| Advisory framing | every retrieve/get/digest result carries ADVISORY_NOT_AUTHORITY + framing: DATA |
| Deterministic store | export twice with stamp:false → byte-identical |
| Fail-safe | point it at a corrupt DB → typed error, no panic; empty store → clean abstain, not a crash |
The full suite is cargo test (589 tests, hermetic offline build).
The tool surface — 21 tools, four planes
The complete MCP surface. One line each here; the full contract per tool livesin ARCHITECTURE.md.
Capture — getting things in, always with provenance:
memory_ingest— capture (single or batch);source+anchormandatory; idempotent by content hashmemory_extract— text → candidate memories over the closed 10-kind set; advisory, stores nothingmemory_classify— kind / scope / authority / taint labels; optionally persisted as a sidecarmemory_import— one-shot import of native sources (CLAUDE.md, AGENTS.md, memory dirs); born tainted
Recall — getting things out, or an honest refusal:
memory_retrieve— caller-expanded recall; grounded / missing_evidence / abstain, never a fourthmemory_get— one full capsule by id, with relations, classification, and last mutationmemory_list— compact index with project fencesmemory_digest— session-start projection: counts, newest, handoff, blocks-dag, journal checkmemory_bootstrap— cold-start pack: your constraints FIRST (never capped), the one next action, decisions, traps — in ≤1500 tokens
Structure — making memories relate:
memory_relate— typed edges:supersedes/derived_from/witnesses/blocks/falsifiesmemory_alias— teach recall synonyms the store then honorsmemory_vector— attach caller-fed embeddings (optional cosine lane; no embedder inside)memory_visual— deterministic Mermaid projections (dag / relations / tiers), plus an MCP Apps view
Lifecycle — honesty over time:
memory_forget— destroy or redact; a tombstone that says so, never silent absencememory_outcome— record an observed consequence (advisory observation, never a self-certified close)memory_preference— pairwise preference evidence (chosen-over, in context, by whom)memory_consolidate— deterministic maintenance plan: exact dupes, merge proposals, tier movesmemory_session_start/memory_session_finish— bracket a session; finish captures the handoff the next session's digest leads withmemory_export— the whole store as one deterministic markdown view; byte-identical on an unchanged storememory_merge— reconcile a second store file into this one: content-hash identity, id-remap, forget-wins, deterministic — the offline-first path to keep two machines' stores in sync
Beyond the tools — same binary, still no daemon:
nmemory sync --remote <[user@]host:/path> [--push]— a CLI subcommand, not anMCP tool: owner-invoked reconcile of your local store with a remote mirror file.It fetches the mirror, merges it into the local store with the same enginememory_mergeuses, and with--pushcopies the merged store back so both sidesconverge. Explicit and opt-in — it runs only when you run it. Operating guide:RUNBOOK.md.nmemory recall --terms <term[,term...]> [--limit <n>] [--budget <n>]andnmemory digest— one-shot CLI verbs for synchronous callers (shell hooks,scripts): one argv→stdout call routed through the SAME handlers asmemory_retrieve/memory_digest, so the envelope bytes and theusage-counting / recall-miss side effects are identical to the MCP tools —there is no second recall semantics. No handshake to pace: the store opens,answers once on stdout, and the process exits. The stdio serve path and itszero-network law are unchanged. Operating rehearsal:RUNBOOK.md.- Two MCP App resources (
text/html;profile=mcp-app) for hosts that render MCPApps:ui://nmemory/document— a readable master-detail document overmemory_export;ui://nmemory/visual— the Mermaid view overmemory_visual.Self-contained HTML, zero external requests; hosts without MCP Apps support keepgetting the plain text payloads unchanged.
What it is NOT (yet)
I would rather you hear the limits from me than find them yourself:
- Word-exact recall, no stemming.
tokenwill not findtokens. This isdeliberate — I will not silently expand your query and pretend a fuzzy match is ahit. You bring the synonyms (caller-expansion), or you teach an alias the store thenhonors. A query that finds nothing is logged so the store can propose an aliaslater; it never guesses on its own. - The taint flag is best-effort, not a shield. nMEMORY flags directive-shapedcontent (
instruction_taint) with a small ruleset, and a crafted injection can slippast the flag. Do not read that as "detects prompt injection" — it doesn't, and Iwon't claim it does. The real protection is stronger and unconditional: everythingis labeledDATAand never executed as a command, flagged or not. The armor is theframing, not the detector. - Sync is a command, not a service. Store-to-store reconciliation exists —
memory_mergeover MCP,nmemory syncfrom the CLI — and it is deliberatelynarrow: explicit, owner-invoked, opt-in, NEVER a background daemon, and thehermetic zero-network serve path is unchanged by it. Know what sync does notdo: it copies the whole store file (scp, no deltas); it never schedulesitself; it never picks between two divergent claims — both survive as separatecapsules until you supersede one; and per-store sidecars (usage counters,aliases, classifications, caller-fed vectors, session records, the auditjournal) stay local — only capsules, relations, and forget-wins tombstonestravel. - Embeddings are caller-fed. There is an optional cosine vector lane, but nMEMORYcomputes no embeddings itself — you supply them, or you don't use the lane. Zeroembedder dependency is a feature, not a gap.
- At-rest storage is plaintext SQLite. No encryption-at-rest yet. Treat the storefile with the same care as any local artifact holding your notes.
Roadmap
Three things, in the order they earn their way in:
- Multi-project index — the "phone book". One queryable index over many projectstores, for org-scale memory federation.
- Honest benchmark. A published recall benchmark with true-abstain as the headlinemetric, not a footnote.
- Optional local embedder. Considered only when the benchmark proves it pays foritself — the zero-network serve path stays law either way.
Why not mem0 / Zep / Memori?
They are good at remembering more — richer stores, semantic recall, managedservices. I compete on being safe to trust:
- Declared graph, not model-guessed. Every edge exists because someone stated it —its author recorded, its endpoints carrying mandatory sources. No model infershidden relations behind your back.
- True abstain. Recall has exactly three honest outcomes — grounded,missing_evidence (every excluded match counted, per reason), abstain. Thefourth outcome, inventing one, has no code path.
- Provenance-mandatory capture. No source → rejected, not stored with a blank.
- Zero network, one file. No cloud, no account, no telemetry — a single SQLitefile on your disk, served over stdio.
Different question, different tool.
Part of NOTT — the proof-bound engineering agent. Commercialname: ₙMEMORY. Offline · MCP stdio · Rust · single SQLite file. Architecture andinternals: ARCHITECTURE.md.