Skip to main content
A run answers three questions at three different times: what will happen? (before), what is happening? (during), what happened? (after). One command each, all offline-friendly โ€” every frame below is real output from this workflow:
standup-digest.nika.yaml
nika: v1
workflow: standup-digest
description: "Pull commits and tickets in parallel, then digest."

model: mock/echo                       # swap for ollama/llama3.2:3b or any provider

tasks:
  - id: commits
    exec:
      command: "sleep 0.4 && git log --oneline -5 2>/dev/null || printf 'feat: resume'"

  - id: tickets
    exec:
      command: "sleep 0.3 && printf 'NIKA-42 open'"

  - id: digest
    depends_on: [commits, tickets]
    infer:
      prompt: "Digest commits ${{ tasks.commits.output }} and tickets ${{ tasks.tickets.output }}"
      max_tokens: 400

outputs:
  digest: "${{ tasks.digest.output }}"

Before ยท nika inspect

Static anatomy: the DAGโ€™s wave groups (what runs in parallel), plus three planning lines โ€” the parallelism width, the pinch points, and each taskโ€™s blast radius. Zero execution, zero tokens:
$ nika inspect standup-digest.nika.yaml
standup-digest ยท 3 tasks ยท 2 waves ยท โ‰ฅ $0.0000 (floor โ€” unbounded tasks)
  โ•ญ wave 1 โ”€โ”€ 2 in parallel โ”€โ•ฎ
  โ”‚ โ—† commits  exec          โ”‚
  โ”‚ โ—† tickets  exec          โ”‚
  โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
    โ†“
  โ—† digest   infer ยท mock/echo
  (no orphans ยท DAG check NIKA-DAG-001 clean)

parallelism  width 2 ยท can run together: commits ยท tickets
pinch        digest ยท nothing else runs while these run
blast        commits blocks 1 ยท tickets blocks 1
Read it before a long run the way you read a query plan before an expensive query.

During ยท the live render

In an interactive terminal, nika run animates a storyboard: tasks light up as their dependencies clear, in the wave order inspect predicted. Piped (CI logs, tee), the same run prints one plain, deterministic frame instead โ€” โˆฅ marks tasks that ran in parallel:
$ nika run standup-digest.nika.yaml
  ๐Ÿฆ‹ nika ยท standup-digest ยท 3 tasks
     permits โœ“ engine floor (no boundary declared)

  โœ”  commits  exec ยท sleep       416ms โˆฅ
  โœ”  tickets  exec ยท sleep       312ms โˆฅ
  โœ”  digest   infer ยท mock/echo    0ms
  โ”€โ”€ 3/3 done ยท $0.000 ยท elapsed 0.4s โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Four render modes, one per audience:
FlagSurface
(none, terminal)Live animated storyboard, then waterfall + verdict card
--no-progressOne plain final frame (the CI-stable surface ยท default when piped)
--quietThe final verdict line only โ€” โœ” standup-digest ยท 3 tasks ยท 0.4s ยท $0.000
--jsonPure NDJSON events on stdout, progress to stderr (the machine lane ยท see Traces)

After ยท the waterfall and the verdict card

An interactive run ends with two frames. The waterfall shows where the wall-clock went โ€” overlapping bars are the parallelism you actually got. The verdict card compresses the run into one box: the wave shape (โ—†โ—† โ‡‰ โ—† โ€” two in parallel, then one), tasks, waves, retries, duration, cost, model, and the typed outputs it produced:
  commits  โ–•โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–  416ms
  tickets  โ–•         โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–  305ms
  digest   โ–•                                 โ–ˆโ–    0ms
  0s ยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยทยท 417ms
  โ•ญโ”€ nika โœ“ standup-digest โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
  โ”‚  โ—†โ—† โ‡‰ โ—†    3 tasks ยท 2 waves ยท 0 retries  โ”‚
  โ”‚  418ms ยท $0.0000 ยท mock/echo              โ”‚
  โ”‚  outputs โ†’ digest (string)                โ”‚
  โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
The same frames are recoverable from any recorded trace, hours or machines later:
nika run standup-digest.nika.yaml --json > .nika/traces/standup.ndjson

nika trace show   .nika/traces/standup.ndjson   # storyboard + waterfall + verdict card
nika trace replay .nika/traces/standup.ndjson   # re-render the run live ยท never re-execute
trace show prints the final frames; trace replay plays the recorded events through the same renderer that drew the original run. Replay calls no model and runs no command โ€” it is a projection of what already happened (Traces & replay).

Terminals & CI

The live surfaces are TTY-only by design. Piped or NO_COLOR output is the sober register (plain per-line events โ€” what CI logs want). Two render themes ship: unicode (default) and --ascii (every glyph has an ASCII twin โ€” use it on terminals without good box-drawing fonts, including older Windows setups; Windows Terminal renders the default theme fine). --no-color, NO_COLOR, and CLICOLOR_FORCE follow the standard resolution order.