work-memory is a local-first CLI for durable work state. It stores concise facts, decisions, evidence, open questions, and next actions. It can also show a compact queue for active work.
It is not a transcript archive, task runner, cloud service, daemon, web UI, embedding store, or automatic GitHub or Slack importer. It uses one local SQLite database, FTS5 search, typed links, and deterministic ranking. It makes no network requests at runtime.
Go 1.25+ is required. SQLite is compiled into the binary through the pure-Go modernc.org/sqlite driver.
go install ./cmd/memory
export PATH="$(go env GOPATH)/bin:$PATH" # if needed
memory init
memory # open the interactive work queueFor a repository-local binary:
go build -o ./bin/memory ./cmd/memory
./bin/memory initThe default database is ~/Library/Application Support/work-memory/memory.db on macOS and $XDG_DATA_HOME/work-memory/memory.db (or ~/.local/share/...) elsewhere. Override it with WORK_MEMORY_DB or memory --db ./work-memory.db ....
Run memory in a terminal for a read-only, keyboard-first view of open work.
The TUI shows the active, waiting, and blocked queue with the selected item's
next action and durable context. Use Tab or the left/right arrows to switch
between the queue and its scrollable detail pane, j/k or the up/down
arrows to move or scroll, f to filter by status, area, or repository, and
/ to search. Use y to copy the record ID, r to reload, ? for help, and
q to quit. Set NO_COLOR to disable terminal styling.
Explicit commands remain the stable surface for agents, scripts, and lifecycle
updates. Bare memory only launches the TUI when both input and output are
terminals; pipes and non-interactive runs keep the normal command behavior.
Use the durable record surface for a standalone decision, review, incident analysis, or completed outcome:
recordcreates one record.updatechanges that same record without changing its ID.contextreturns a bounded, scoped brief before related work.list,show, andlinkinspect or connect records.
Use the workflow surface for work that is active, waiting, blocked, closed, or parked:
begincreates or resumes the one durable record for a work item.nowis the compact live queue.checkpoint,wait,handoff,close, andparkupdate the same work item at meaningful state changes.
Do not create a second record for a tracked work item at handoff.
memory record \
--title "Choose retrieval limits" \
--status completed \
--repo example/repository --branch feature/retrieval \
--summary "Bounded retrieval returns useful recent decisions." \
--decision "Use explicit byte and token limits." \
--evidence "Focused storage tests pass." \
--next-action "Review the public contract." \
--owner owner --tag retrieval \
--link issue=example/repository#12 --source terminal --json
memory update RECORD_ID --status completed --next-action "" --jsonrecord and update also accept a JSON object with --input PATH or --input -.
Retrieve a narrow brief with every known scope field:
memory context "retrieval limits" \
--repo example/repository --branch feature/retrieval \
--link issue=example/repository#12 \
--max-tokens 600 --max-bytes 4000 --jsonScope fields are conjunctive. Use --json for a compact bounded envelope. Use --json-full only for human diagnostics.
Records accept title, status, repository location, summary, decision, evidence, questions, next action, owners, tags, links, and source. Record status is active, blocked, completed, abandoned, or superseded.
Retrieve scoped context first. Then begin or resume one work item and keep the returned record ID.
memory begin \
--title "Add retrieval limits" \
--status active --class build --area search \
--owner owner --needs-next-action \
--repo example/repository --branch feature/retrieval \
--worktree /path/to/repository \
--link issue=example/repository#12 \
--next-action "Add focused limit tests." --jsonWorkflow status is active, waiting, blocked, closed, or parked. now contains active, waiting, and blocked work only.
memory now --repo example/repository --priority-owner owner --json--priority-owner OWNER places that owner's needed actions first. It is explicit; the generic CLI has no priority-owner default. Use --repo, --owner, --area, and --limit to narrow the queue.
Update the same ID only at meaningful state changes:
memory checkpoint RECORD_ID --status blocked \
--evidence "The fixture cannot represent the edge case." \
--next-action "Wait for fixture support." --json
memory wait RECORD_ID --next-action "Wait for the maintainer decision." --json
memory handoff RECORD_ID --summary "Ready for the next tool." \
--evidence "Focused tests pass." \
--next-action "Resume after review." --json
memory close RECORD_ID --summary "Shipped and verified." --json
memory park RECORD_ID --summary "Deferred until the next release." \
--next-action "Resume after release planning." --jsonLifecycle updates are transactional. Invalid record fields or workflow status leave the record and workflow overlay unchanged. handoff requires --evidence. close clears a stale next_action unless you explicitly replace it. park preserves an intentional resume action.
begin, each lifecycle command, and now support compact JSON with --json. now returns an items array and count; workflow items contain operational state, location, next action, links, source, and update time rather than full evidence.
For a task runner:
- Retrieve scoped context.
- Run
beginonce and pass its record ID to the task. - Add a task link when one exists:
memory link RECORD_ID --type thread --target TASK_ID. - Require the task to use
checkpoint,wait,handoff,close, orparkon that ID.
The task must not call begin again or edit SQLite directly.
For a non-threaded tool, add --tool-ref TOOL:RUN to begin:
memory begin --title "Terminal validation" --class build \
--tool-ref terminal:run-42 --source terminal --jsonA later begin with the same tool reference resumes the same item. A thread ID is optional metadata; the record ID or typed tool link provides continuity.
Use --json for scripts and harnesses. Do not scrape human output.
memory list --repo example/repository
memory show RECORD_ID --json
memory link RECORD_ID --target https://github.com/example/repository/pull/12 --type pr
memory link RECORD_ID --record OTHER_RECORD_ID --relation informs
memory export --output work-memory.json
memory import work-memory.json
memory import work-memory.json --on-conflict skipExports use {"format":"work-memory","version":1}. Import is transactional. The SQLite schema is v2; opening a v1 database adds the local workflow overlay in place. The workflow overlay is not part of the v1 export format.
- The binary performs no network requests and has no telemetry.
- Records, links, and FTS data remain in the selected SQLite database.
- Database directories are owner-only where supported. Databases and exports use mode
0600. - Full-text search duplicates searchable text inside the same SQLite file. Deleting the database and its
-waland-shmsidecars deletes local state. - Exports are plaintext. Protect them like the database.
- Never store secrets, credentials, API keys, personal data, full tool output, full transcripts, or model reasoning. Link source artifacts instead.
go test ./...
go run ./cmd/memory --db /tmp/work-memory-demo.db init