workmem
v0.4.0
Published
Recheck-backed working memory CLI for AI coding workflows
Maintainers
Readme
workmem
Working memory for AI coding agents.
Compresses diffs, remembers findings between runs, and rechecks what changed — so you stop resending the same context every prompt.
The loop. Run
workmem initonce per repo. Before prompting your agent, runworkmem build-contextto produce a compact packet of just the diffs, findings, and rules that actually changed since last time. After the agent replies,workmem save-runremembers what it found. Next time,workmem rechecktells you which findings are still relevant.
Why this exists
You're using Claude Code / Codex / Cursor on the same branch for hours. By the third prompt you've already paid for:
- the same repo-level instructions, three times
- the full diff against
main, four times - the previous run's findings, by hand-copying
- the model re-discovering "fix the auth handler in
src/auth/login.ts" for the third time in a row
workmem is a local, agent-agnostic layer that sits in front of the agent
and removes that waste. Zero runtime dependencies. Pure Node ≥ 18.
Install
npm install -g workmemor run without installing:
npx workmem --helpQuick start
# verify your environment
workmem doctor
# inside any git repo
workmem init # creates .workmem/
# before prompting your agent
workmem build-context --task "investigate retry handler"
# after the agent's reply
workmem save-run --input agent-reply.json
# next iteration
workmem recheck # which findings are still relevant?Three ways to use it
1. As a CLI (the canonical way)
workmem init
workmem build-context [--task <text>] [--mode balanced|aggressive|terse]
[--target generic|codex|claude|cursor]
[--base <ref>] [--head <ref>] [--staged]
[--files a,b,c] [--max-files 12]
[--use-mincut] [--mincut-budget 4000]
workmem save-run [--input file.json] [--kind review|fix|investigation]
workmem recheck [--against <run-id>]
workmem status
workmem list-runs
workmem show-run --run-id <id>
workmem compress [--input file] [--max-tokens 4000] [--mode balanced|aggressive|terse]
workmem prune [--keep 20] [--days 30] [--dry-run]
workmem clear [--yes]
workmem config
workmem doctor2. Piped — for shell / CI workflows
# emit JSON, pipe to your agent
workmem build-context --format json | claude
# pre-PR review workflow
workmem build-context --staged --format markdown > /tmp/packet.md
your-agent --context /tmp/packet.md3. Programmatic — as a Node library
const { runCli, parseArgs } = require('workmem');
const opts = parseArgs(['build-context', '--task', 'fix bug', '--format', 'json']);
const packet = JSON.parse(runCli(opts, process.cwd()));
console.log(packet.metrics.reductionPercent, '%');Honest, measured numbers
npm run eval reproduces these locally. Three hand-labeled fixtures (a rules
doc, a build log, an investigation note) under eval/fixtures/ plus a
must_retain list of phrases the compressor should keep regardless of mode.
| mode | avg reduction | avg signal retention | |---|---:|---:| | balanced | 40.0% | 86.6% | | aggressive | 46.9% | 82.1% | | terse | 51.4% | 82.1% |
Retention is the share of hand-labeled must_retain phrases that survive the
compression. Reduction alone can be gamed by dropping everything; retention
measures whether the bits that matter survive. Per-fixture breakdown lives
in eval/results.md.
The old README claimed "99%+ reduction" — that was a single contrived input. These are the numbers on real, varied inputs.
Algorithm note — log compression preserves errors verbatim
A surprise the eval suite caught on v0.3: the original compressLogs ranked
lines by frequency and kept the top-K. Error lines are unique (they appear
once), so they sorted to the bottom and got dropped — exactly the information
a log compressor exists to preserve.
The current implementation:
- Partition lines into important (errors, warnings, stack frames, exit
codes,
TypeError,TS####, PythonFile "...", line Nframes) and noise candidates. - Keep all important lines verbatim in source order.
- Frequency-group only the noise.
- Budget the noise summary against
(maxLines − important.count).
Eval delta: log retention went from 40% → 100% with the same compression
budget. See lib/compressor.js compressLogs for the
implementation and test/unit/compressor.test.js
for regression coverage.
Composes with mincut-context
workmem and mincut-context are designed to compose:
mincut-contextpicks which files matter for a task (symbol-graph aware, runs personalized PageRank from your task description).workmemcompresses, remembers, and rechecks those files across runs.
Use them together with --use-mincut:
npm install -g mincut-context # one-time
workmem build-context --task "fix login bug" --use-mincutWhen the mcx binary is on PATH, workmem will ask it for the most relevant
file set first and use that instead of "every file in the diff". Falls back to
git-diff selection if mcx is missing or errors. Each packet stamps
selectionStrategy: "mincut" | "git-diff" so you can tell which path produced
the output.
Storage
Everything stays local — no cloud, no telemetry.
~/.codex/memories/workmem/ global per-user store
.workmem/config.json per-repo settings
.workmem/snapshots/ local-only snapshots
.workmem/ignore paths workmem won't touchOverride the global store: WORKMEM_HOME=/custom/path workmem status
The .workmem/ directory is added to .git/info/exclude automatically by
workmem init, so memory never lands in commits.
Agent-specific renderers
workmem build-context --target <name> produces a packet shaped for the
agent's native input format:
| Target | Shape |
|---|---|
| generic (default) | Markdown sections — works everywhere |
| codex | Markdown with codex-style <task> / <context> blocks |
| claude | Claude Code-friendly XML tags |
| cursor | Markdown with @file mentions for Cursor's context UI |
Honest tradeoffs
| What's not optimal | What we do |
|---|---|
| Runs locally only — no cross-machine sync | By design. Memory is per-developer per-branch. |
| Compression is heuristic, not lossless | Modes (balanced / aggressive / terse) let you trade detail for tokens |
| No semantic search inside saved runs | list-runs + show-run + recheck are the indexing surface today |
| CommonJS, not ESM | Package is small; ESM port is a future minor bump |
| File selection without --use-mincut is git-diff-based | Pair with mincut-context for task-aware symbol-graph selection |
Contributing
git clone https://github.com/dhrupo/workmem.git
cd workmem
npm test # 81 unit + smoke
node eval/runner.js # compression eval suite
node bin/workmem.js --helpPRs especially welcome for:
- New
--targetrenderers (Aider, Continue, Cline) - Additional eval fixtures (rules / logs / notes from your own codebases)
- New "important line" patterns for
compressLogs - Semantic search across saved runs
CI runs on Ubuntu + macOS × Node 18 / 20 / 22 on every push.
License
MIT
