Cavemem
Cavemem is local agent memory backed by SQLite. It stores raw memory first, ranks recall with deterministic BM25, and compresses recalled hits only after it already has the original.
Three verbs: remember, recall, forget. Recall only returns hits that clear its threshold. Compressed recall results carry a recovery handle, and reported token costs are inferred.
The order matters
A memory is never lost because the raw text is stored before anything else touches it.
- Write is byte-safe.
rememberwrites the full raw text to SQLite first. The engine is only consulted later, at recall time. If compression were to fail, the memory itself is already safe on disk. - Recall fails toward nothing. A query that scores below the threshold — or that has no term overlap with anything stored — recalls nothing. Cavemem returns an empty result rather than a low-confidence guess. Silence is the honest answer when nothing matches.
- Compression is reversible. Each compressed recall hit carries a CCR
recovery_handle.Recoverreturns the byte-exact original. Compression is transient; the raw memory underneath never changes.
The CLI
Build the binary and drive it directly. Every subcommand prints JSON.
go build -o cavemem ./public/mem/cmd/cavemem
./cavemem remember "the deploy key lives in vault under ops/deploy"
./cavemem recall "where is the deploy key" # { "hits": [...], "basis": "inferred" }
./cavemem forget mem_xxxxxxxxrecall takes an optional limit as a second argument. Recall hits are inferred — the tokens_added, the score, and the basis are all local estimates, never verified.
As an MCP server
Run the binary with no subcommand (or cavemem mcp) and it serves the same three operations as MCP tools over stdio, using the identical framing as caveman-mcp:
cavemem_remember(text: string)
cavemem_recall(query: string, limit?: number)
cavemem_forget(id: string)Point an MCP host at the binary you built:
{
"mcpServers": {
"cavemem": {
"command": "/absolute/path/to/cavemem"
}
}
}The thin clients
The JS and Python clients shell out to the same Go binary. Recall and scoring logic stay in Go. Set CAVEMEM_BIN if the binary is not on your PATH.
import { remember, recall, forget } from "cavemem";
await remember("the deploy key lives in vault under ops/deploy");
await recall("where is the deploy key", 5);import cavemem
cavemem.remember("the deploy key lives in vault under ops/deploy")
cavemem.recall("where is the deploy key", limit=5)A memory is never lost, and recall never bluffs
The raw memory is the source of truth, written before any compression. Recall ranks with deterministic BM25 and only returns hits that clear a conservative threshold — below it, you get nothing rather than a guess. Every figure it reports is inferred, and every compressed hit is recoverable to the byte through its recovery_handle.
Install names aren't live yet
The Go core is BSL; the JS and Python clients are MIT. Today the binary builds from source (go build …) and the clients shell out to it. The registry package names are reserved for launch and are not documented as working until they resolve to this project from a clean machine.