local-first memory · npx dreamd-mcp · Apache-2.0
dreamd
A local-first memory layer for AI coding agents. Most tools treat a database as canonical and files as an export; dreamd inverts it, so the plain JSONL in your repo is the memory and the daemon is just a convenience layer on top.
dreamd v0.1 · public release August 9, 2026.
the memory is a file
Your memory is one line of readable JSONL.
No database to canonicalize, no export step, no vendor format. What an agent records lands as one plain line in .agent/episodic/AGENT_LEARNINGS.jsonl, on disk, in your repo. Here is a real one:
{"schema_version":"1.0.0","id":"evt_01JR04101000XYZB2C3D4E5F6G","timestamp":"2026-04-10T10:00:00Z","pain":3.5,"importance":4.5,"pinned":false,"skill_action":"rust::async::stream_buffered","source_harness":"aider","content":"futures::stream::iter(urls).map(fetch).buffered(8) caps concurrent in-flight tasks at 8 while preserving output order. Switch to buffer_unordered(8) when downstream is order-independent, same backpressure, lower tail latency."} You can cat it, grep it, git diff it, and hand-edit it in any editor. Shut the daemon down and the memory is still there, still readable. The files are the source of truth; the daemon is the convenience layer that reads and writes them.
Delete the binary. Your memory survives.
the memory layer
Drop a folder. Your agents share it.
One .agent/ folder per repository, one MCP server, one single binary. Claude Code, Cursor, Cline, and anything else that speaks MCP read and write the same memory, so what one agent learns the next one already knows.
Shared across every agent
Your preferences and project decisions live here and are read at session start. Every supported agent writes corrections and preferences back to the same plain files automatically.
Every observation captured
Raw entries accumulate in AGENT_LEARNINGS.jsonl, an append-only log. Nothing an agent records is discarded before the dream cycle evaluates it.
High-signal lessons promoted
The dream cycle is deterministic: no model, no network. It clusters entries by skill_action, promotes recurring ones into LESSONS.md, and prunes or archives the rest by a salience score over age, pain, importance, and recurrence.
supported tools
One memory layer, every harness you use.
One MCP server. Every harness connects to it. Drop the .agent/ folder once, point every agent at it.
the api
Two tools. That is the whole surface.
dreamd exposes exactly two MCP tools. Small on purpose, not unfinished. There is nothing to learn beyond reading and writing memory, and nothing hidden behind them.
Read the memory
BM25 lexical search over the log, ranked by a salience score. Returns the entries most relevant to the query, deterministically.
Write to the memory
Appends one node to AGENT_LEARNINGS.jsonl. Append-only, so history is never rewritten and every write is visible in git diff.
the facts
Everything you need to know.
No marketing claims. Every statement is something you can verify in the repo.
search_nodes + append_node .agent/, your repo, on disk honest tradeoffs
What BM25 costs us.
Retrieval in v0.1 is BM25 lexical search over a Tantivy index. No embedding model, no vector database, no semantic matching. That is a real limit: BM25 matches words, not meaning, so a query worded differently from the stored note can miss it. Better to say that out loud than paper over it.
The choice is deliberate. Lexical search is deterministic, runs on any machine with no model to download and no GPU, adds no network hop, and every result is explainable from the score. For structured, high-signal coding memory, matching the exact terms an engineer used is usually the behavior you want. When that tradeoff stops being the right one, the index is derived state and can be replaced without touching your files.
install
One command, one folder, zero config.
Run this in your project root. The daemon starts, the .agent/ folder appears, and every supported agent discovers it automatically.
npx dreamd-mcp Requires Node.js 20+. One-time setup. The daemon starts automatically and runs silently in the background.
project status
Where things stand.
A Botzr Research project · botzr.com
a related project
WasTrue
WasTrue is a separate, in-progress benchmark of how AI memory systems hold up when the underlying facts change. It is not dreamd, and it is not shipping yet.
Conflict-of-interest disclosure: WasTrue comes from the same author as dreamd, a memory layer it measures alongside other systems. That is a direct interest in the outcome, so treat any published result with the skepticism it deserves and reproduce it yourself. More detail when it is ready to show.
faq
The objections answered plainly.
Where does my memory actually live?
In .agent/ inside your repo, as plain JSONL and Markdown on your disk. Nothing is sent anywhere, there is no account, and there is no telemetry. The .agent/.dreamd/ folder holds the local index and daemon state and is gitignored, but the memory itself under .agent/ is meant to be committed, so it travels with the repo and stays readable even without dreamd installed.
Isn't this just AGENTS.md with extra steps?
AGENTS.md is what you wrote down; .agent/ is what your agent recorded. The markdown you maintain by hand is a static file. dreamd is a daemon that reads and writes structured memory across every session and every harness, automatically. If you only use one agent in one repo and you're happy editing markdown by hand, you don't need dreamd.
Why not a vector database?
Vector DBs solve retrieval over unstructured text at scale. dreamd targets structured, high-signal memory for coding agents: preferences, corrections, project state, external references. The data model is closer to a typed key-value store than a vector index. The salience formula scores each entry; recall is deterministic, not approximate.
Why Rust?
Single binary, no runtime dependency, predictable latency under load. dreamd runs as a sidecar and should never be the slow thing in your agent loop. Rust's type system also maps cleanly to the memory schema enforced across files.
How does dreamd relate to Mem0, Zep, and Letta?
They are all memory systems, but they differ in shape. Mem0 and Zep are hosted APIs, Letta is an agent platform with managed memory, and dreamd is a local daemon writing to a .agent/ folder in your repo. dreamd's bet is that file-native memory, readable and diffable on disk, fits coding agents better than database-canonical memory. Architecture notes, not quality claims, are on the comparison page.
Does this work with OpenCode / Aider / Continue / Goose / Roo Code?
v0.1 ships with a native MCP server for Claude Code, Cursor, and Cline. OpenCode, Aider, Continue, Goose, and Roo Code adapters are planned for v0.1.1 and will follow the same .agent/ folder contract. The spec is open; contributions welcome.