Skip to content

CLI Reference ​

The stepbook command is the headless interface to a stepbook project — used by both humans and agents. Every command runs against the project discovered from the current directory (see Config).

Global ​

stepbook <command> [options]
  • Version: -v, --version
  • Help: stepbook --help, or stepbook <command> --help

Output modes ​

Most commands accept two mutually exclusive output flags:

  • --json — a machine-readable versioned envelope on stdout.
  • --md — write a Markdown report to state/reports/ and print its path.

With no flag, output is human-readable and colored. In --json/--md mode, info-level chatter is redirected to stderr so stdout stays clean.

Exit codes ​

CodeMeaning
0Success.
1Runtime failure — a step threw, a check failed, output unreadable.
2Config / usage error — bad flag combination, missing config, unknown step.

Addressing a unit in a run ​

A run's trajectory nodes are keyed by unit name when a unit runs once, or <unit>#<index> when it repeats (e.g. one node per agent turn). Commands that take a unit name — q <unit>, variance <unit>, snapshot-diff <unit> — resolve it by name against the trajectory.


init ​

Scaffold a new stepbook project (config + sample step + sample input).

sh
stepbook init
stepbook init --dir my-pipeline --name my-pipeline
OptionDescription
-d, --dir <path>Target directory (default .).
-n, --name <name>Pipeline name (default: directory name).
--forceOverwrite existing files.
--jsonMachine-readable output.

add-step alias: add ​

Generate a new step skeleton. Placed anywhere matching your steps glob.

sh
stepbook add-step extract --type llm
stepbook add-step summarize -t derive -d steps/stage-2
Argument / OptionDescription
<name> (required)Step key — becomes the file basename and the defineStep name.
-t, --type <type>input | parse | llm | derive | eval (default parse).
-d, --dir <path>Destination dir relative to project root (default steps).
--forceOverwrite an existing file.
--jsonMachine-readable output.

run ​

Execute the pipeline entrypoint once and persist a run blob. Prints the trajectory tree — the units the entrypoint composed, in call order.

sh
stepbook run                            # canonical input
stepbook run inputs/hello.json          # specific input
stepbook run --just analyze --case Empty  # one unit against a named case, isolated
stepbook run --no-cache --json
Argument / OptionDescription
[input]Input file (relative to inputs/ or absolute). Optional.
-j, --just <step>Run one unit in isolation (pair with --case).
--case <name>With --just, run that unit against a named case only.
-f, --from <step>Force re-execution starting at this step.
-t, --to <step>Stop execution after this step.
--till <step>Shorthand for --from <first> --to <step>.
--no-cacheBypass the snapshot cache (re-execute everything).
--jsonMachine-readable envelope.
--mdWrite a Markdown report to state/reports/.

--just <step> --case <name> runs a single unit against one case — no cache, no persisted blob — for tight iteration on one unit.

In --json mode the data payload is { pipeline, ts, git_sha, blob, totals, root }, where root is the run's TrajectoryNode tree. See The Cache for how --from and --no-cache interact with replay.


check ​

CI-friendly: run the pipeline and exit non-zero if any check fails.

sh
stepbook check
stepbook check --cases            # run every unit's cases in isolation
stepbook check --step analyze     # only this step, with cached upstream
stepbook check --json | jq '.data.totals.fail'
Argument / OptionDescription
[input]Input file (relative to inputs/ or absolute).
-s, --step <key>Check only this step (with cached upstream).
--casesRun every unit's cases in isolation, not the pipeline.
--jsonMachine-readable envelope.
--mdWrite a Markdown report.

Exits 1 if any assertion fails — this is what makes check the CI verb. In --json mode the data payload carries totals, failed, and the run's trajectory root tree.


diff ​

Compare two whole runs — assertion flips plus a drift summary.

sh
stepbook diff                              # previous vs latest
stepbook diff --from latest-3 --to latest
OptionDescription
--from <selector>Older run selector (default previous).
--to <selector>Newer run selector (default latest).
--jsonMachine-readable envelope.
--mdWrite a Markdown report.

Run selectors: latest, previous, latest-N (e.g. latest-3), all, or a timestamp/SHA substring.


snapshot-diff alias: sdiff ​

Compare a single step's output between two run blobs.

sh
stepbook snapshot-diff analyze
stepbook snapshot-diff analyze --fields
stepbook snapshot-diff analyze --open
stepbook snapshot-diff analyze --across-last 5
Argument / OptionDescription
<step> (required)Step key to diff.
--from <selector>Older run selector (default previous).
--to <selector>Newer run selector (default latest).
--fieldsShow per-field drift breakdown.
--openOpen both snapshots in $STEPBOOK_DIFF_CMD (default code --diff).
--across-last <N>Diff every adjacent pair across the last N runs (overrides --from/--to).
--jsonMachine-readable envelope.
--mdWrite a Markdown report.

variance alias: var ​

Measure run-to-run variance for a step. See Drift & Stability.

sh
stepbook variance classify -n 10
stepbook variance classify --across-last 5 --show-clusters
stepbook variance classify -n 10 --embed 0.9
Argument / OptionDescription
<step> (required)Step key to measure.
-n, --runs <N>Fresh sampling: re-execute the step N times.
--across-last <N>Historical: use the last N persisted runs (default 5).
--show-clustersList identical-output clusters with representatives.
--embed [threshold]Cluster via pipeline.ts's exported embed (default threshold 0.85).
--jsonMachine-readable envelope.
--mdWrite a Markdown report.

q alias: query ​

Run a query against a step's output. Queries are a structured YAML surface that compiles to JSONata; pass --jsonata to write a raw JSONata expression instead. See StepQL.

sh
stepbook q analyze "select: longWords"             # YAML query (default)
stepbook q analyze query.yaml                       # multi-line query from a file
stepbook q analyze "$.longWords[$length($) > 8]" --jsonata --json
stepbook q analyze "select: longWords" --explain    # show the compiled JSONata
stepbook q analyze --saved my-query
stepbook q analyze "select: density" --save density-check
Argument / OptionDescription
<step> (required)Step key whose output to query.
[query]A YAML query, or a path to a .yaml/.yml file (omit with --saved).
--jsonataTreat <query> as a raw JSONata expression instead of YAML.
--explainPrint the compiled JSONata and exit (don't run).
-r, --run <selector>Run selector (default latest).
-f, --format <fmt>Human-mode output: table | json | raw (default table).
--save <name>Save this query under <name> for the step.
--saved <name>Recall a previously saved query (omit the positional query).
--jsonMachine-readable envelope (overrides --format).
--mdWrite a Markdown report.

--save and --saved are mutually exclusive.


list alias: ls ​

List persisted runs, newest first.

sh
stepbook list
stepbook list --limit 50 --json
OptionDescription
-n, --limit <N>Max runs to show (default 20).
--jsonMachine-readable envelope.
--mdWrite a Markdown report.

list-steps alias: steps ​

List discovered units. Columns: KEY, TYPE (and SOURCE with -v).

sh
stepbook list-steps
stepbook list-steps --verbose      # include each unit's source file path
OptionDescription
-v, --verboseInclude each unit's source file path.
--jsonMachine-readable envelope.

cases alias: cs ​

List a unit's named cases (its fixtures / "stories"), or all units' cases.

sh
stepbook cases
stepbook cases analyze
Argument / OptionDescription
[step]Only show cases for this unit (default: all).
--jsonMachine-readable envelope.

save-case ​

Snapshot a unit's recorded input from a run into cases/<step>/<name>.json, so you can replay it with run --just <step> --case <name>.

sh
stepbook save-case analyze regression
stepbook save-case analyze regression --from-run 2026-06-30T12:00:00.000Z
Argument / OptionDescription
<step> (required)Unit whose recorded input to snapshot.
<name> (required)Case name — becomes cases/<step>/<name>.json.
--from-run <ts>Run timestamp to read from (default: last run).
--jsonMachine-readable envelope.

The input is read from the unit's trajectory node in the chosen run, so the unit must have been invoked in that run.


prune ​

Delete old run blobs. Requires at least one of --keep-last or --older-than.

sh
stepbook prune --keep-last 20
stepbook prune --older-than 30d --dry-run
OptionDescription
--keep-last <N>Keep the N newest runs, prune the rest.
--older-than <duration>Prune runs older than e.g. 30d, 2w, 12h.
--dry-runPreview the prune set; don't delete.
--jsonMachine-readable envelope.
--mdWrite a Markdown report.

Pruning removes run blobs from state/runs/; it does not touch the snapshot cache.


dashboard ​

Launch the stepbook UI (a Vite dev server).

sh
stepbook dashboard
stepbook dashboard -p 7000 --no-open
stepbook dashboard --host 127.0.0.1 --workspace ..
OptionDescription
-p, --port <n>Port (default 6125). Strict — refuses to fall back if taken.
--no-openDon't auto-open the browser.
-w, --workspace <path>Workspace root for project discovery (default: parent of config dir).
--host <addr>Bind address (default 127.0.0.1; LAN access needs an explicit IP, not 0.0.0.0).

Port behavior

stepbook dashboard -p <n> is strict: if the port is taken it errors, because you asked for a specific port. By contrast, npm run dev (the contributor entry point) falls through to the next free port.

Released under the MIT License.