Local-first memory for AI agents
Most agent memory makes a database the source of truth. We made it your files.
agentcairn inverts the stack: human-readable Markdown with [[wikilinks]] is the truth, and a rebuildable DuckDB index gives your agent fast hybrid retrieval. Hand-edit a fact in Obsidian and the agent picks it up.
By Charles C. Figueiredo · Apache-2.0 · 06.10.26
Vault · source of truth
--- tags: [auth, fix] --- Fixed login by rotating [[jwt-secret]] during [[deploy]].
Index · disposable cache
MCP · recall
cairn recall "how did we fix login?"
Rotated the jwt-secret during deploy.
↳ auth-fix.md
The inversion
Most systems make the database the truth. We made it your files.
Mem0 and Zep keep your memory in a cloud database. Letta and agentmemory keep it in a database too, and treat files — if any — as a one-way export. agentcairn is the only one where the Markdown vault is the source of truth.
So your memory survives a model upgrade, a corrupted index, a schema change — even uninstalling the tool. There is nothing to lose, because the truth was never trapped in the database.
Six differentiators
Vault is the source of truth
Human-readable Markdown with frontmatter and [[wikilinks]]. Edit it by hand; the index honors your edits.
The index is disposable
DuckDB is a rebuildable cache. cairn reindex restores everything — zero data loss.
Non-lossy by construction
The full note is always retained. Distillation only adds derived notes that link back.
Redaction before every write
Secrets scrubbed (regex + entropy + URL-cred) before body, title, or tags reach the vault.
A free, deterministic graph
Your [[wikilinks]] are the graph — no LLM extraction, no hallucinated entities.
Daemonless, zero external DB
One embedded DuckDB does vector + BM25 + graph. No server, no Neo4j/Postgres/Qdrant.
How it works
Capture reads your agent's session transcripts out-of-band, then redacts → dedups → importance-gates → distills into the vault. Retrieval fuses BM25 + vectors with RRF, with an optional cross-encoder reranker. The vault and the index reconcile on spawn; the MCP server exposes remember · recall · search · build_context · recent.
Survives uninstall
Delete the index. Reindex. Everything's back.
The index is a cache. The proof is destructive: remove it, rebuild it, lose nothing — because the truth was never in the database.
Honestly measured
| arm | r@5 | r@10 | MRR |
|---|---|---|---|
| BM25 only | 0.527 | 0.604 | 0.459 |
| vector only | 0.536 | 0.637 | 0.433 |
| hybrid (RRF) | 0.562 | 0.648 | 0.477 |
| hybrid + reranker | 0.662 | 0.735 | 0.608 |
LoCoMo retrieval, turn-level macro-avg, FastEmbed nomic-embed-text-v1.5 (the default).
Context efficiency. On LongMemEval-S (~136k-token sessions), agentcairn answers from ~2,500 tokens of recalled context per query — a ~55× reduction in what the model has to read. Estimate; 20-query sample.
- No single headline number — these are relative ablation signals.
- graph-boost is inert on chat corpora (no native wikilink graph); it's for real vaults.
- QA-accuracy numbers use an Anthropic judge, not GPT-4o — not comparable to published leaderboards.
Quickstart
uvx agentcairn # on-demand MCP server cairn ingest --vault ~/vault # distill recent sessions cairn sweep --vault ~/vault # ingest + reindex cairn recall "how did we fix auth?" # hybrid recall cairn reindex ~/vault # rebuild from Markdown cairn doctor # health-check the index
Trust & security
Redaction before write
regex + entropy + URL-credential
Localhost-only MCP
READ_ONLY queries, no exposed ports
No telemetry
nothing phones home
Index outside the vault
the .duckdb cache is never synced