Local-first conversational memory for AI coding agents. Your agent answers "what were we talking about last week?" by navigating a time-hierarchical index — not by replaying your whole history into its context window.
Everything runs on your machine: an append-only RocksDB event log, a local BM25 index (Tantivy), a local vector index (HNSW + Candle embeddings), and a gRPC daemon your agent talks to. Capture is passive — CLI hooks pipe events in, so the agent spends zero tokens recording what it did.
Three things are structurally different, not just tuned differently:
- Passive, zero-token capture. Events arrive from CLI hooks. The agent is not asked to "decide what to remember", so remembering costs no tokens and cannot be skipped when the context is full.
- Local-first. The event log, the indexes, and the embeddings live in
~/.local/share/agent-memory. Nothing leaves the machine unless you turn on an LLM summarizer or LLM reranking and give it an API key. - Cross-CLI. Memory is a layer beside the CLI, not inside one, so the same store is reachable from more than one agent runtime.
The long-form comparison against Mem0, Zep, MemMachine, and Letta — including the "won't the vendors just build this in?" question — is in docs/positioning/agent-memory-vs-competition.md.
Instead of scanning everything, the agent drills down a Table of Contents built over time, reading a summary at each level and deciding whether to go deeper:
Year ──▶ Month ──▶ Week ──▶ Day ──▶ Segment ──▶ Grip ──▶ raw events
│
summary + keywords ─────┘ excerpt + provenance
Three independent retrieval layers feed a single fused ranking:
┌──────────────────────────────┐
hooks ──▶ ingest ──▶│ RocksDB append-only log │
(passive) └───────────────┬──────────────┘
│ outbox
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
BM25 (Tantivy) HNSW vectors TOC + topics
└─────────────────────┼─────────────────────┘
▼
MemoryOrchestrator
(fuse ─▶ rerank ─▶ explain)
▼
gRPC ──▶ memory search
MemoryOrchestrator is reachable from the shipped binaries: the daemon's
RouteQuery RPC calls it, and memory search is a client of that RPC.
Prerequisites: macOS or Linux, protoc, and Rust (the repo pins the
toolchain in rust-toolchain.toml, so rustup picks the right one).
# Ubuntu/Debian: sudo apt-get install -y protobuf-compiler libclang-dev
# macOS: brew install protobuf llvmgit clone https://github.com/SpillwaveSolutions/agent-memory.git
cd agent-memory
cargo build --release -p memory-daemon -p memory-ingest -p memory-cli
export PATH="$PWD/target/release:$PATH"Prefer not to compile? Each release ships one archive per platform containing all four binaries — see docs/setup/quickstart.md.
The daemon runs in the foreground. There is no built-in background mode — use
systemd, launchd, or your terminal multiplexer.
memory-daemon start --foreground &
memory-daemon statusFirst start creates the store and its index directories under
~/.local/share/agent-memory/ and downloads the embedding model for vector
search. With no network it logs a warning and runs BM25-only — the daemon still
starts.
In real use, CLI hooks do this for you (see step 6). To prove the path works:
memory add --content "We chose RS256 over HS256 for the auth service JWTs" --agent claude
memory add --content "Rate limiting lives in the gateway, not the auth service" --agent claudeIndexing is not synchronous with ingest. Events land in the event log
immediately and an outbox drain indexes them on a one-minute schedule, so a
query issued straight after memory add legitimately returns nothing.
sleep 70memory search "which JWT signing algorithm did we pick" --top 5
memory search "rate limiting gateway" --format json | jq '.results[0].text_preview'BM25 matches tokens as written — it does not stem, so jwt will not find
JWTs. Paraphrase matching is the vector layer's job, and that needs the
embedding model from step 2.
memory recall is the same search with LLM reranking; it needs an API key and
falls back to the heuristic ranker (and says so in its explainability
payload) when the model is unavailable.
cargo build --release -p memory-installer
target/release/memory-installer install --agent claude --projectInstalls hooks, commands, and skills into ./.claude/. Use --global for
~/.claude/, and --dry-run to see the file list first. Run
memory-installer install --help for the runtimes on offer.
This table is the point of the v3.1 milestone. If a row says experimental, it is experimental.
| Area | Status | Notes |
|---|---|---|
| Append-only event log (RocksDB) | Solid | Immutable, durable, the source of truth |
Passive hook capture → memory-ingest |
Solid | Covered by the bats CLI suites on Linux + macOS |
| TOC build and drill-down navigation | Solid | Year → Month → Week → Day → Segment → Grip |
| Grips / provenance | Solid | Excerpts link back to the events they came from |
| BM25 keyword search (Tantivy) | Solid | Exact tokens, no stemming (jwt does not match JWTs). Events indexed before v3.1 have empty text_preview and there is no backfill command — see UPGRADING and #41 |
| Vector search (HNSW + Candle) | Solid | Mechanism is wired; retrieval quality is not yet measured (#40). First daemon start downloads the embedding model; with no network the daemon warns and runs BM25-only |
| Topic graph | Works | Clustering quality is not benchmarked (#40) |
Hybrid fusion + RouteQuery orchestration |
Works | Wired end-to-end in Phase 54; explainability reports what actually ran |
| LLM summarization / LLM rerank | Experimental | Needs an API key; fails open to the heuristic ranker and reports rerank=heuristic when it does |
| Cross-project federated query | Experimental | Implemented; not performance-characterised |
| Cross-encoder rerank | Not implemented | The extension point exists and returns an explicit error — it is not silently degraded. Build only if #39 says retrieval is the bottleneck (#44) |
| Ingest → searchable latency | ~1 minute | The outbox drains on a schedule; ingest is deliberately not blocked on indexing |
Offline TOC rebuild (admin rebuild-toc) |
Not implemented | Exits non-zero with guidance. TOC nodes come from the daemon's scheduled rollup jobs (#43) |
| Background daemonization | Not implemented | --background exits non-zero with guidance rather than pretending. v3.2 will ship install-service unit files (#42) |
docs/benchmarks.md explains what the harness measures and, specifically, why
the old "65 second TOC" number was a harness defect (it timed ingest-time
rollup and labelled it navigation).
Committed results live in benchmarks/results/. Today both are mock-backend
runs — a mock retrieval backend and a mock judge — so they demonstrate the
harness, not competitive quality. There is deliberately no comparison
marketing in this repo, and there will not be until a real-backend,
real-judge run is committed next to the claim
(#39).
Maintaining six runtime converters and five CLI test suites as first-class promises is not sustainable for this project's size, so the promise is tiered rather than uniform.
| Tier | Runtimes | What it means |
|---|---|---|
| Tier 1 — supported | Claude Code, Codex CLI | Converters are exercised on every PR (bats suites on Linux + macOS). Bugs here are release blockers |
| Tier 2 — best effort | Gemini CLI, Copilot CLI | Converters are implemented and tested; their bats suites run on a weekly schedule, not the PR gate. Fixes are welcome, response is not guaranteed |
| Not supported | OpenCode | The converter was an empty stub that reported success and wrote nothing. It was removed in Phase 57 rather than shipped. --agent opencode is now rejected |
Any runtime can still feed the store directly by piping events to
memory-ingest with --agent <name> — that path is runtime-agnostic and is
unaffected by tiering.
| Doc | What's in it |
|---|---|
| docs/README.md | Concepts: progressive disclosure, TOC navigation, grips |
| docs/setup/quickstart.md | Longer install path, including prebuilt binaries |
| docs/setup/agent-setup.md | Per-runtime hook wiring |
| docs/ARCHITECTURE.md | Crate layout and data flow |
| docs/API.md | gRPC surface |
| docs/benchmarks.md | What the perf harness measures, and what it does not |
| docs/verification/57-quickstart-transcript.md | The transcript of this quickstart being run on a clean machine, defects and all |
| docs/positioning/agent-memory-vs-competition.md | Head-to-head vs Mem0 / Zep / MemMachine / Letta |
| docs/UPGRADING.md | Version-to-version migration notes |
| docs/RELEASING.md | How to cut a tag so the pipeline cannot repeat the v3.1.0 stale-ref incident |
| CHANGELOG.md | What changed per release, including retractions |
task pr-precheck before every PR — it runs the same format, clippy, test, and
doc gates CI does. See CLAUDE.md for repository conventions.
MIT — see LICENSE.