Every run can leave a replayable record: one NDJSON file that proves what ran, in what order, at what cost.
You ran a workflow an hour ago. It worked (or it didn’t), and now someone
asks: what exactly happened? With most AI tooling the answer scrolled
away. With Nika the run itself is a file: every event the engine emitted,
one JSON line each, in order, with timestamps. Save it, share it, replay
it. The run is evidence, not a memory.A real run, replayed: the plan lights task by task exactly as the
recorded event stream says it happened.
nika run renders a live storyboard for humans. Add --json and the
same run streams machine events instead, one NDJSON line per event:
nika run review.nika.yaml --json > .nika/traces/review.ndjson
That single redirect is the whole recorder. The stream is designed for
CI and agents (stdout stays pure NDJSON; nothing else is printed there),
so capturing it live costs nothing. By convention, project traces live
under .nika/traces/ next to the workflows they record; the CLI reads a
trace from any path you give it.Since 0.94 the redirect is optional: every run writes its own journal
to .nika/traces/<timestamp>-<id>.ndjson by default, and the verdict
line prints the path. --resume, nika trace show|replay and the editor
read it directly. Opt out per run with --no-trace-file, or globally
with NIKA_NO_TRACE_FILE (nika try never journals — the mock
rehearsal is not a workspace run).
A trace is the run’s lifecycle spine. Each line is one event with a
unique id, a nanosecond timestamp, a kind, and typed fields:
workflow_started, then one task_scheduled per task
task_started when a task’s dependencies clear
task_completed (with duration_ms), or task_failed, or
task_skipped (a when: gate said no), or task_cache_hit
(a resumed run reused this task’s recorded work)
workflow_completed, or workflow_failed, or workflow_paused
(a human gate is waiting — the trace carries the prompt payload)
Here is a real capture, verbatim, from a two-task exec workflow:
{"id":{"uuid":"019f23fb-af22-76b0-a124-4fc91d3166e9"},"timestamp":1783015124770000000,"kind":"workflow_started","run":null,"correlation":null,"fields":[{"key":"workflow","value":"version-stamp"},{"key":"permits","value":"engine floor (no boundary declared)"}]}{"id":{"uuid":"019f23fb-af22-76b0-a124-4fd5aa792ff9"},"timestamp":1783015124770000000,"kind":"task_scheduled","run":null,"correlation":null,"fields":[{"key":"task","value":"stamp"}]}{"id":{"uuid":"019f23fb-af3d-7331-807d-3ec787e872c3"},"timestamp":1783015124797000000,"kind":"task_started","run":null,"correlation":null,"fields":[{"key":"task","value":"stamp"},{"key":"note","value":"exec · date"}]}{"id":{"uuid":"019f23fb-af3d-7331-807d-3ed6051694b4"},"timestamp":1783015124797000000,"kind":"task_completed","run":null,"correlation":null,"fields":[{"key":"task","value":"stamp"},{"key":"note","value":"exec · date"},{"key":"duration_ms","value":26}]}{"id":{"uuid":"019f23fb-af5a-70d3-a7e2-1cfd58fbaed3"},"timestamp":1783015124826000000,"kind":"workflow_completed","run":null,"correlation":null,"fields":[{"key":"workflow","value":"version-stamp"}]}
The spine is not the whole vocabulary. Deeper kinds record retries
(task_retrying), cancellation (task_cancelled,
workflow_cancelled), money (cost_incurred), security checks
(permit_checked), streaming (infer_chunk) and the agent loop
(agent_tools_selected, agent_budget_checkpoint, and friends). The
full event system, including the durability checkpoints that make runs
resumable, is documented in Concepts · Events.Real spend also rides the spine: a priced task_completed carries a
cost_usd field next to its tokens — absent for mock and local
runs (unpriced is honestly absent, never a fake 0). Agent loops
report the loop’s accumulated tool spend as tools_cost_usd.
nika trace replay .nika/traces/review.ndjson # re-render the run, livenika trace show .nika/traces/review.ndjson # print the final card only
replay plays the recorded events through the same renderer that drew
the original run: same storyboard, same timing, same verdict card.
show skips the animation and prints the summary.
Replay = re-render, never re-execute. Replaying a trace calls no
model, runs no command, touches no file. Zero tokens, zero effects.
It is a projection of what already happened, safe to run on any
machine, any number of times.
The trace is not just a log — it is a hash chain. Every event the
engine emits carries a link over the one before it: task boundaries,
each permit check, every tool call an agent: loop makes, the run seal
at the end. Nothing the engine did is off the chain, and nothing can be
edited, reordered, or dropped from the middle without breaking it.
nika trace verify .nika/traces/review.ndjson
verify walks the chain and then climbs a proof ladder, reporting the
highest tier honestly attained:
CHAINED — the links hold; the sequence is intact.
SEALED — a signature over the whole chain verifies against a
custody key (the run was signed).
ANCHORED — a detached sidecar verifies fully offline against a
public transparency log entry + an RFC 3161 timestamp (nika trace anchor is the opt-in network act that mints it).
REPLAYED — a fresh run reproduces the recorded one.
Three refusals name themselves rather than hide in a tier: a broken
chain is TAMPERED, lines appended after the seal are SEAL BURIED
(forgery, never a crash), a sidecar that vouches for nothing is ANCHOR FORGED. This is the property no scrollback and no vendor dashboard
gives you: the evidence proves itself, on your machine, without
trusting the tool that wrote it.
The run is auditable. Which tasks ran, in what order, how long
each took, what it cost, which permits were checked: it is all in the
file, not in someone’s scrollback.
The run is verifiable. Every event is hash-chained and the whole
chain verifies offline (nika trace verify) — tamper-evident by
construction, not by trust.
The run is shareable. Attach the .ndjson to a PR or an issue.
A reviewer replays it locally and sees exactly what you saw, without
credentials and without re-running anything.
The demos are honest. The replays on nika.sh
(“Press play. It really ran.”) are exactly these files: recorded runs
played back through the same renderer, not screenshots and not
mockups.
The run is resumable. The same file doubles as the checkpoint:
nika run --resume <trace> skips completed work with visible cache
hits and re-arms a paused human gate. See Resume a run.
Reference · CLI: every nika run and nika trace
flag, including --json and --output json (the typed outputs:
export, a different surface from the event stream).
Concepts · Events: the full event vocabulary and
the durability model behind it.