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.