README
¶
durable-inspect
Read-only CLI for a durable-go journal. Lists tasks and steps; it does not start, cancel, or complete runs.
Opens the journal with NewReadOnlyEngine. --dir / -d wins over DURABLE_DIR. Put DURABLE_PAYLOAD_KEY and DURABLE_JOURNAL_MAC_KEY in the environment (flags put secrets on the command line). Hex is tried first for both keys; otherwise the string is raw bytes. --redact hides INPUT and RESULT. One -d and one key pair per command — plaintext and AES (or CRC and HMAC) journals belong in separate directories (second NewEngine on a new dataDir; do not mix in one tree). If a writer still holds the exclusive lock, the command fails — stop that process or inspect a copy of the directory.
Payloads, file modes, and tokens: README — Data privacy.
Install
go install github.com/agenticenv/durable-go/cmd/durable-inspect@latest
durable-inspect -h
Puts the binary on $(go env GOPATH)/bin (keep that on your PATH).
From a checkout (repo root):
go build -o bin/durable-inspect ./cmd/durable-inspect
# or: task build
./bin/durable-inspect -h
go run ./cmd/durable-inspect -- -h
go run needs -- before flags so they are not eaten by go run.
Point at a journal
The path is the engine dataDir (the folder that contains .lock and tasks/), not the repo root.
| Source | When it is used |
|---|---|
--dir / -d |
If passed — always wins |
DURABLE_DIR |
If --dir / -d is omitted |
| neither | Error: directory required |
export DURABLE_DIR=./data
./bin/durable-inspect task list
./bin/durable-inspect -d ./data task list
./bin/durable-inspect --dir=./data task list
Example journals after cd examples && go run ./<name>/ live under examples/<name>/.data/<journal>/ (gitignored).
cd examples && go run ./yaml-task/
./bin/durable-inspect -d examples/yaml-task/.data/yaml-journal task list
cd examples && go run ./payload-codec/
export DURABLE_PAYLOAD_KEY="$KEY"
export DURABLE_JOURNAL_MAC_KEY="$MAC"
./bin/durable-inspect -d examples/payload-codec/.data/aes --redact task get echo run-1
./bin/durable-inspect -d examples/payload-codec/.data/journal-mac step get echo run-1 echo
Decrypt and redact
Prefer env vars. --payload-key and --journal-mac-key appear in ps. Use DURABLE_PAYLOAD_KEY and DURABLE_JOURNAL_MAC_KEY. Flags override env when you pass them.
DURABLE_PAYLOAD_KEY supplies the AES-GCM key so task get / step get / step list can decode encrypted INPUT and RESULT. Hex (32/48/64 chars) is tried first; otherwise the string must be 16, 24, or 32 raw bytes. Omit it to print stored bytes (quoted ciphertext if the writer used NewAESGCMCodec). A wrong key fails closed.
DURABLE_JOURNAL_MAC_KEY is required to read a journal written with WithJournalMACKey. Hex is tried first; otherwise the string is raw key bytes.
--redact is display-only — it does not change the journal or replace PayloadCodec. It replaces non-empty task/step INPUT and RESULT with [redacted], including after a successful decrypt. Status, IDs, timestamps, ERROR, and PANIC are still shown.
| Source | When it is used |
|---|---|
--payload-key |
If passed — always wins |
DURABLE_PAYLOAD_KEY |
If --payload-key is omitted |
| neither | Stored bytes (plaintext JSON, or ciphertext) |
--journal-mac-key |
If passed — always wins |
DURABLE_JOURNAL_MAC_KEY |
If --journal-mac-key is omitted |
| neither (MAC journal) | HMAC frames look empty / not found |
export DURABLE_PAYLOAD_KEY="$KEY"
export DURABLE_JOURNAL_MAC_KEY="$MAC"
./bin/durable-inspect -d ./data task get echo run-1
./bin/durable-inspect -d ./data --redact step get echo run-1 say
Commands
durable-inspect [flags] task list [--status STATUS]
durable-inspect [flags] task get <taskID|runID|name> [runID]
durable-inspect [flags] step list <taskID> <runID>
durable-inspect [flags] step get <taskID> <runID> <stepID>
Flags can appear anywhere (-d after list is fine). --status is valid only on task list.
task list
All runs in the journal, newest first.
./bin/durable-inspect -d ./data task list
./bin/durable-inspect -d ./data task list --status running
--status is one of: running, waiting, completed, failed.
Columns: TASK_ID, RUN_ID, NAME, STATUS, CREATED.
NAME is the optional WithName label, not the task ID.
task get
One run: metadata, task input (input.json — one JSON value for I; {} when the task used struct{}), then its steps. Step input and version are stored on each step record when set.
# task ID — if several runs share it, the table is printed and the command exits 1
./bin/durable-inspect -d ./data task get echo
# run ID
./bin/durable-inspect -d ./data task get run-1
# WithName label
./bin/durable-inspect -d ./data task get "Echo Task"
# exact run
./bin/durable-inspect -d ./data task get echo run-1
With one argument, the value is matched against task ID, run ID, or name. Two arguments are always taskID then runID.
step list
Steps for one run (STEP_ID, STATUS, VERSION, INPUT, STARTED, COMPLETED).
./bin/durable-inspect -d ./data step list echo run-1
step get
One step, including VERSION / INPUT / RESULT / ERROR when present.
./bin/durable-inspect -d ./data step get echo run-1 say
Typical flow
- Set
DURABLE_DIRor pass-dat the journal root. task listto findTASK_ID/RUN_ID.task get <taskID> <runID>for status and every step. SetDURABLE_PAYLOAD_KEYif the writer used AES-GCM; setDURABLE_JOURNAL_MAC_KEYif it usedWithJournalMACKey; add--redactbefore pasting output.step get …if you need a step result.
Lock / “journal is locked by a writer”
A live NewEngine on the same directory takes an exclusive flock. Inspect cannot open that dir until the writer Closes (process exit after defer e.Close(), or a copy of the folder). Multiple inspect processes can share a journal when no writer is present.
Help
./bin/durable-inspect -h
./bin/durable-inspect --help
Documentation
¶
Overview ¶
Command durable-inspect is a read-only viewer for a durable-go journal.
durable-inspect -d ./data task list durable-inspect -d ./data task get <taskID|runID|name> [runID] durable-inspect -d ./data step list <taskID> <runID> durable-inspect -d ./data step get <taskID> <runID> <stepID>
--dir / -d wins over DURABLE_DIR. The journal must not be held by a writer.