Findings from a whole-repo cross-platform audit. Data loss: - evals/llm_run.py wrote the snapshot with write_text(ensure_ascii=False) and no encoding: on Windows that truncates results.json to 0 bytes, then raises at the first non-cp1252 char. Destroyed the committed snapshot and the run. - compress.py read the user's target with errors="ignore", silently dropping undecodable bytes, backing up the mangled text, passing its own readback check, then overwriting the original. Now decodes strictly and refuses. Broken on Windows: - benchmarks/ and evals/ read SKILL.md, README.md and results.json without an encoding; all three raise on a cp1252 decode. - cavemem's Python client used text=True with no encoding, so a non-ASCII memory failed to store and any recall came back mojibake. - native-hook-fast spawned a second full Node process from inside a hook with no timeout at all. Also fixed: - Backported the pnpm cross-drive shim fix to the five copies that never got it; hoisted two inline parsers so all of them are unit-testable. - portable-command now resolves through PATH/PATHEXT instead of silently no-op'ing on a bare command name. - uninstall.ps1 writes a temp .js instead of node -e (matches install.ps1). - Real backoff on the flag rename retry; EPERM/EBUSY retry when replacing a running binary. - Hooks act on the first complete JSON payload instead of blocking on EOF; the stats child timeout drops below the host's hook budget. - Statusline tests run the .ps1 on Windows instead of skipping. - Added the macOS CI job the repo never had. Left unfixed and annotated in place: the win32 hookCommand emits PowerShell call-operator syntax while #835 describes the runner as git-bash /bin/sh. Needs a real Windows host to settle; guessing would break whichever works. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NveRZs9mV97iX7HSgq3BYF
cavemem
Durable, compression-native agent memory: remember, recall, supersede,
history, forget.
Memories live in a local SQLite store; recall ranks them with BM25 behind a
conservative threshold and compresses each hit through the
Caveman engine, so the inferred token cost is honest and the dropped
detail stays recoverable. Counts are inferred; component never claims verified
savings.
Go core and binary ship under BSL 1.1. Thin JS/Python clients remain MIT.
BSL runtime is source-available, not OSI Open Source before Change Date. See
LICENSE and ../LICENSING.md.
CLI
go build -o cavemem ./mem/cmd/cavemem
./cavemem remember "the deploy key lives in vault under ops/deploy"
./cavemem recall "where is the deploy key" # JSON: { hits: [...], basis: "inferred" }
./cavemem recall "full migration context" 5 0 # explicit 0 token budget = unlimited
./cavemem supersede mem_xxxxxxxx "deploy key moved to vault ops/deploy-v2"
./cavemem history mem_yyyyyyyy # oldest → current
./cavemem forget mem_xxxxxxxx
./cavemem # runs the MCP server over stdio
MCP
{ "mcpServers": { "cavemem": { "command": "cavemem" } } }
Libraries
Thin clients shell text to the binary over stdin (avoiding OS argument-size limits;
set CAVEMEM_BIN if it is not on PATH):
an oversized remember exits with code 65; both clients export
MEMORY_TOO_LARGE_EXIT_CODE so callers can branch without parsing stderr.
import { remember, recall, supersede, history, forget } from "cavemem"; // js/index.mjs
await remember("…"); await recall("…", 5, 2000); await recall("…", 5, 0); // unlimited
import cavemem # py/cavemem.py
cavemem.remember("…"); cavemem.recall("…", limit=5, token_budget=2000)
Guarantees
- Byte-safe write: raw text is stored before anything else, so a memory is never lost.
- Off-topic query recalls nothing rather than guessing.
- Recall packs at most 2000 inferred tokens by default. CLI, MCP,
JS, and Python callers may explicitly request
token_budget: 0for unlimited recall; omitting it never disables the cap. - Recall excludes superseded facts by default; history stays local and auditable.
- Every compressed recall hit carries a
recovery_handle.