Skip to main content
Always invoke as bunx smithers-orchestrator <command> (see Installation for why). Use --help on any command for the canonical option list.

Conventions

  • Run control is workspace-scoped. The workspace Gateway is the default control plane for controllers, Bun cron jobs, monitors, bots, and custom clients; use smithers-orchestrator/gateway-client or Gateway RPC/REST rather than opening SQLite/PGlite/Postgres or querying _smithers_* tables. One-shot CLI commands are also a supported abstraction boundary. Direct stores are runtime/migration/maintainer-diagnostic internals.
  • smithers gateway status --format json discovers the verified singleton URL for the current workspace. Do not parse its runtime state file, assume port 7331, or pass --backend to ps/inspect/other control commands to search another store. --backend is for Gateway/workflow bootstrap and explicit migration diagnostics only.
  • Task root: tools run from the project root (the nearest directory containing a .smithers/, walking up from the working directory). up, workflow run, graph, and eval all resolve the root this way, so the launch form never changes where tasks run. Override with --root; a resume without --root reuses the root the run was originally launched with.
  • Boolean flags accept either bare form (--watch) or explicit --watch true|false.
  • Global options: --format toon|json|yaml|md|jsonl, --filter-output <key.path>, --full-output, --token-count, --token-limit N, --token-offset N, --schema, --llms, --llms-full, --mcp, --help, --version.
  • MCP stdio mode: pass --mcp to start Smithers as an MCP server. Add --surface semantic|raw|both to choose the exposed tool surface. Add --allowed-tools name,name and/or --read-only to scope the semantic toolset exposed to outbound MCP clients.
  • Workflow resolution: revert, replay, fork, retry-task, and timetravel take a workflow file path. up, graph, eval, and optimize accept either a workflow path or a discovered workflow ID (an existing file is used as-is; otherwise the argument is resolved as an ID, the same way workflow run does). workflow run <name> resolves IDs from the nearest local .smithers/workflows/<name>.tsx (walking up from the working directory) and from the global ~/.smithers/workflows/ pack. Local workflows take precedence: on an id collision the local file wins. The global pack honors SMITHERS_HOME. So global workflows run from any directory, while a repo’s own pack can override them by name.
  • Rewrites: bunx smithers-orchestrator workflow WORKFLOW_ID runs a discovered workflow when <id> resolves; bunx smithers-orchestrator workflow.tsx behaves like bunx smithers-orchestrator up workflow.tsx; bunx smithers-orchestrator chat create behaves like bunx smithers-orchestrator chat-create.
  • JSON arguments are preflighted before workflow modules load. --input and --annotations accept an inline JSON value or - to read JSON from stdin, capped at 1 MiB.

Exit codes

0   success
1   execution failure
2   run cancelled / cancel succeeded
3   `up` ended in waiting-approval, waiting-event, or waiting-timer
4   invalid arguments / user-correctable input error
130 SIGINT
143 SIGTERM

Output envelope and next-step CTAs

On a TTY the CLI prints human-formatted text. When output is piped or captured (any non-TTY consumer, such as an AI agent), each command instead emits a single TOON envelope: the command’s data, plus a “Next steps” cta block that suggests follow-up commands. The cta renders as a TOON table:
commands[2]{command,description}:
  bunx smithers-orchestrator logs run-abc123,Tail active run
  bunx smithers-orchestrator inspect run-abc123,Inspect most recent run
Read each row as two comma-separated fields declared by the {command,description} header. The runnable shell command is the first field, up to the comma; the text after the comma is a human description, not part of the command. So the first row’s command is bunx smithers-orchestrator logs run-abc123, and Tail active run is prose. Never copy-paste a whole row into a shell. Field values are unquoted unless they themselves contain a comma or a quote, in which case TOON quotes and escapes them (a --prompt "..." value comes out as "... --prompt \"<describe>\""); strip that TOON quoting before running. On a TTY the same CTA renders as aligned command # description lines, so this parsing only matters for piped or agent output. Pass --format json to get the same cta as a nested object with explicit command and description keys and skip parsing the table.

Pauses, resume, and detached runs

bunx smithers-orchestrator up exits when a run reaches a durable wait state (waiting-approval, waiting-event, or waiting-timer), even in foreground mode. bunx smithers-orchestrator up --detach starts a background owner and returns its runId, but that owner also exits when the run pauses. This is expected: the persisted run is waiting for an external decision, signal, or timer rather than burning a process. To drive a run to completion across pauses, use the Gateway (getRun, streamRunEventsResilient, submitApproval, submitSignal, and resumeRun) for an automated keeper. For ad-hoc operation, the equivalent public CLI commands are ps, why RUN_ID, inspect RUN_ID, logs RUN_ID -f, approve/deny, signal, and up <workflow.tsx> --resume RUN_ID. Use --force only after confirming the previous owner is gone or intentionally replacing it. Never implement the keeper by querying the run store. If resume fails with RESUME_METADATA_MISMATCH, the workflow file changed after the run started. Resume validates the original workflow metadata and source hash; it is not a hot-reload mechanism for stopped runs. Start a fresh run instead, for example with a new --run-id, or overwrite an existing planned id with --force when that command supports it. When iterating on a workflow definition, expect each edit to require a fresh run rather than --resume.

Interactive mode and the full-screen TUI monitor

bunx smithers-orchestrator up --interactive (or just bunx smithers-orchestrator up / bunx smithers-orchestrator workflow run from an interactive TTY without a positional argument) opens a terminal UI that guides you through three steps:
  1. Workflow picker - fuzzy-search your installed workflows and select one.
  2. Input prompts - fill required fields for the chosen workflow.
  3. Full-screen monitor - the run starts in a detached background process and the terminal switches into a full-screen view that tracks it live.
The monitor connects to a local Gateway on port 7331, starting one automatically if none is running. It exits when you press q. Agents: hand humans interactive commands. When you (an AI agent) give a human a command to run themselves, include the --interactive flag whenever the command supports it (bunx smithers-orchestrator up --interactive, bunx smithers-orchestrator workflow run WORKFLOW_ID --interactive), so the human lands in this full-screen monitor instead of a detached log tail. Reserve the non-interactive forms for CI, scripts, and the commands you execute yourself with your shell tool. Never pass --interactive to a command you run programmatically, since it opens a full-screen TUI your harness cannot drive.

Monitor modes and keybindings

The monitor opens in Tree mode. Switch modes with the letter aliases below. From any non-Tree mode the number keys 15 also jump straight to a mode (and 1 returns to Tree).
ModeReach it withWhat you see
Tree1 (from another mode)Node tree with per-node output, logs, diffs, and props; inline approval banner when waiting
Graphg (toggles Tree ↔ Graph), or 2Directed dependency graph; j/k navigate, inspects a node in Tree
Logsl, or 3Filtered event stream (up to 2 000 events); [/] filter by attempt, f toggles follow
Timelinet, or 4Horizontal tick strip you scrub with j/k to inspect node state at past frames; L jumps back to live (inspect-only; rewind with bunx smithers-orchestrator rewind)
Hijackh, or 5Hand off to bunx smithers-orchestrator hijack for an active node
Quitq (or Ctrl-C)(quit)
Inside Tree mode the number keys are inspector tabs, not mode switches: 1 output, 2 logs, 3 diff, 4 props (/ also walk the tabs). Use the g/l/t/h aliases to leave Tree. The status header shrinks to a compact one-liner on terminals narrower than 100 columns; the keybar adapts the same way.

Monitoring a background run

A detached run (up --detach / run --detach) and an MCP run_workflow background launch both execute where the user has no live view of progress. To close that gap, the CLI returns a monitoring block with the run and prints agent-directed guidance in the “Next steps” CTA: offer the user one of these ways to watch the run, then set up whichever they pick.
  1. Smithers Monitor (live, zero setup): run bunx smithers-orchestrator monitor RUN_ID to open the gateway’s live web UI over every run in the workspace, focused on this one (status, execution tree, events, approvals), no code required. See the Smithers Monitor.
  2. Status-report cron (hands-off): a Bun job that every 5 minutes calls Gateway getRun and reports the status; use streamRunEventsResilient while the process is awake.
  3. Live custom UI (richest, most work): run bunx smithers-orchestrator ui RUN_ID when the workflow declares a .smithers/ui/<workflow>.tsx UI with <UI entry="../ui/<workflow>.tsx" />, otherwise author the UI source and declaration first. See custom workflow UIs.
  4. Quick HTML page (fastest): write a static status page from Gateway getRun / getDevToolsSnapshot, open it, and refresh it about every 5 minutes.
The same monitoring object (its text plus structured options) is in the run_workflow MCP result for background launches, and is null when waitForTerminal is set (the run already finished).

Workflow UIs

Open a run’s custom browser UI with:
bunx smithers-orchestrator ui RUN_ID
bunx smithers-orchestrator ui discovers the workspace singleton, verifies that the answering process serves this workspace, and uses its advertised URL. Discovery refuses gateways that advertise another workspace; use --gateway <url> or --no-autostart when you need to be explicit. When none is running it starts smithers gateway automatically (one per workspace: concurrent autostarts race on a lock and share the winner) and then opens the UI. smithers gateway serves workspace run state and workflow-owned <UI> declarations, with entry files resolved relative to the workflow that declared them. A workspace with no local .smithers pack and no prior run store still boots and serves the global pack alone. That is the headless sandbox shape: provision a VM with bunx smithers-orchestrator init --global --yes --no-skill (the default bun install inside ~/.smithers is required for pack workflows to import) and smithers gateway serves the full pack, UIs included, from any bare cloned repo. Manage the daemon with smithers gateway status and smithers gateway stop. Use bunx smithers-orchestrator ui RUN_ID --no-autostart to fail fast when no Gateway is already running, or --gateway <url> for a remote Gateway.

Troubleshooting

  • RESUME_METADATA_MISMATCH: the workflow source or metadata changed since the run began. Start a fresh run instead of resuming across the edit.
  • Bundled jj exits with EACCES: the optional @smithers-orchestrator/jj-<platform> binary is present but not executable. Run chmod +x node_modules/@smithers-orchestrator/jj-*/bin/jj, reinstall Smithers, or set SMITHERS_JJ_PATH to a working jj binary. Confirm resolution with bunx smithers-orchestrator workflow doctor.

Command catalog (TOON)

Commands listed by dotted name. human and alerts use an action positional instead of nested subcommands.
commands[89]:
  - name: init
    purpose: Install the local Smithers workflow pack into .smithers/. In an interactive terminal init asks one question (your preferred coding agent), installs the pack with defaults plus that agent's plugin (or skill if no plugin), then opens a hijacked tutorial session hosted by that agent; piped/agent/CI runs (or --yes) install defaults. Pass an optional prompt to also launch the create-workflow builder after init.
    args[1]{name,type,required,desc}:
      prompt,string,false,Optional plain-English task: after init, launch the create-workflow builder with this prompt pre-filled
    flags[12]{name,short,type,default,desc}:
      agent,,string,,Preferred coding agent id (e.g. claude, codex, pi); skips the interactive agent question
      tutorial,,boolean,true,After install, open a hijacked tutorial session hosted by your preferred agent (interactive init only); --no-tutorial skips
      force,,boolean,false,Overwrite existing scaffold files
      agents-only,,boolean,false,Only create .smithers/agents/ and leave workflow pack untouched
      install,,boolean,true,Run bun install inside the pack after scaffolding
      add-agents,,boolean,false,Launch the account registration wizard after scaffolding
      skill,,boolean,true,Install the curated smithers skill into detected coding agents and append workflow guidance to existing CLAUDE.md/AGENTS.md files
      global,,boolean,false,Scaffold the global pack in ~/.smithers (honors SMITHERS_HOME) instead of ./.smithers
      update-prompt,,boolean,true,In an interactive terminal, ask which drifted shipped pack files to update (warns on shared components); --no-update-prompt skips
      template,,string,,Show next steps for a canonical starter template ID after init
      yes,,boolean,false,Non-interactive: skip prompts and use defaults; alias for --non-interactive
      non-interactive,,boolean,false,Non-interactive: skip prompts and use defaults; alias for --yes
  - name: make-workflow
    purpose: Build a new Smithers workflow from a plain-English description. Dispatches to the create-workflow builder.
    args[1]{name,type,required,desc}:
      task,string,false,Plain-English description of the workflow to build (forwarded as the builder prompt)
    flags[35]{name,short,type,default,desc}:
      detach,d,boolean,false,Background mode; print runId/pid/logFile and exit
      run-id,r,string,,Explicit run ID
      max-concurrency,c,number,4,Maximum parallel tasks
      root,,string,,Tool sandbox root directory
      log,,boolean,true,Enable NDJSON event log file output
      log-dir,,string,,NDJSON event logs directory
      allow-network,,boolean,false,Allow bash tool network requests
      max-output-bytes,,number,,Max bytes a single tool call can return
      tool-timeout-ms,,number,,Max wall-clock time per tool call in ms
      hot,,boolean,false,Hot reload for .tsx workflows
      input,i,string,,Input data as JSON string or '-' to read JSON from stdin
      annotations,,string,,Run annotations as flat JSON string/number/boolean object or '-' to read JSON from stdin
      resume,,boolean|string,false,Resume an existing run; may be true or a run ID
      force,,boolean,false,Resume even if still marked running
      resume-claim-owner,,string,,Internal durable resume claim owner
      resume-claim-heartbeat,,number,,Internal durable resume claim heartbeat
      resume-restore-owner,,string,,Internal durable resume restore owner
      resume-restore-heartbeat,,number,,Internal durable resume restore heartbeat
      serve,,boolean,false,Start an HTTP server alongside the workflow
      supervise,,boolean,false,Run stale-run supervisor loop with --serve
      supervise-dry-run,,boolean,false,With --supervise; detect without resuming
      supervise-interval,,string,10s,Supervisor poll interval
      supervise-stale-threshold,,string,30s,Heartbeat staleness threshold
      supervise-max-concurrent,,number,3,Max runs resumed per poll
      port,,number,7331,HTTP server port when --serve
      host,,string,127.0.0.1,HTTP bind address when --serve
      auth-token,,string,,Bearer token for HTTP auth or SMITHERS_API_KEY env
      insecure,,boolean,false,Allow unauthenticated non-loopback HTTP binding; dangerous
      metrics,,boolean,true,Expose /metrics endpoint when --serve
      backend,,enum,,Bootstrap storage selection for a workflow owner or workspace Gateway; not a run-discovery/control flag (sqlite|pglite|postgres)
      post-failure,,boolean,true,Auto-launch the post-failure autopsy workflow when this run fails (disable with --no-post-failure or SMITHERS_POST_FAILURE=0)
      verbose,,boolean,false,Show engine info logs (run lifecycle, agent sessions) on interactive runs
      report,,boolean,true,Narrate the result with a cheap agent and open an HTML summary on interactive runs (disable with --no-report or SMITHERS_NO_REPORT=1)
      prompt,p,string,,Prompt text mapped to input.prompt when --input is omitted
      interactive,,boolean,false,Pick inputs through interactive terminal prompts and live-render the run
  - name: starters
    purpose: Show plain-English starter workflows with copy-paste commands
    args[1]{name,type,required,desc}:
      id,string,false,Starter ID or alias
    flags[4]{name,short,type,default,desc}:
      audience,,string,,Filter by audience such as product, support, or founder
      goal,,string,,Filter by goal such as plan, build, debug, or quality
      workflow,,string,,Filter by seeded workflow ID
      tag,,string,,Filter by starter tag
  - name: hermes
    purpose: Add Smithers to a local Hermes agent (register the MCP server and install the native Hermes plugin); alias for mcp add --agent hermes
  - name: up
    purpose: Start or resume a workflow execution from a discovered workflow ID or a .tsx workflow file path
    args[1]{name,type,required,desc}:
      workflow,string,false,Workflow ID or file path (omit with --interactive to pick one)
    flags[34]{name,short,type,default,desc}:
      detach,d,boolean,false,Background mode; print runId/pid/logFile and exit
      run-id,r,string,,Explicit run ID
      max-concurrency,c,number,4,Maximum parallel tasks
      root,,string,,Tool sandbox root directory
      log,,boolean,true,Enable NDJSON event log file output
      log-dir,,string,,NDJSON event logs directory
      allow-network,,boolean,false,Allow bash tool network requests
      max-output-bytes,,number,,Max bytes a single tool call can return
      tool-timeout-ms,,number,,Max wall-clock time per tool call in ms
      hot,,boolean,false,Hot reload for .tsx workflows
      input,i,string,,Input data as JSON string or '-' to read JSON from stdin
      annotations,,string,,Run annotations as flat JSON string/number/boolean object or '-' to read JSON from stdin
      resume,,boolean|string,false,Resume an existing run; may be true or a run ID
      force,,boolean,false,Resume even if still marked running
      resume-claim-owner,,string,,Internal durable resume claim owner
      resume-claim-heartbeat,,number,,Internal durable resume claim heartbeat
      resume-restore-owner,,string,,Internal durable resume restore owner
      resume-restore-heartbeat,,number,,Internal durable resume restore heartbeat
      serve,,boolean,false,Start an HTTP server alongside the workflow
      supervise,,boolean,false,Run stale-run supervisor loop with --serve
      supervise-dry-run,,boolean,false,With --supervise; detect without resuming
      supervise-interval,,string,10s,Supervisor poll interval
      supervise-stale-threshold,,string,30s,Heartbeat staleness threshold
      supervise-max-concurrent,,number,3,Max runs resumed per poll
      port,,number,7331,HTTP server port when --serve
      host,,string,127.0.0.1,HTTP bind address when --serve
      auth-token,,string,,Bearer token for HTTP auth or SMITHERS_API_KEY env
      insecure,,boolean,false,Allow binding a non-loopback --host with NO auth (exposes unauthenticated approve/deny/cancel control of the run; dangerous)
      metrics,,boolean,true,Expose /metrics Prometheus endpoint when --serve
      interactive,,boolean,false,Pick a workflow and inputs interactively then open the full-screen run monitor (no silent fallback: fails with TUI_MONITOR_UNAVAILABLE if the tui package is missing, leaving the detached run running)
      backend,,enum,,Bootstrap storage selection for a workflow owner or workspace Gateway; not a run-discovery/control flag (sqlite|pglite|postgres)
      post-failure,,boolean,true,Auto-launch the post-failure autopsy workflow when this run fails (disable with --no-post-failure or SMITHERS_POST_FAILURE=0)
      verbose,,boolean,false,Show engine info logs (run lifecycle, agent sessions) on interactive runs
      report,,boolean,true,Narrate the result with a cheap agent and open an HTML summary on interactive runs (disable with --no-report or SMITHERS_NO_REPORT=1)
  - name: migrate
    purpose: Copy the legacy bun:sqlite smithers.db into PGlite or Postgres and write the migrated.json marker
    flags[3]{name,short,type,default,desc}:
      to,,enum,pglite,Target backend (pglite|postgres)
      url,,string,,Postgres connection URL when --to postgres
      keep-sqlite,,boolean,true,Keep the legacy SQLite database after a successful copy
  - name: eval
    purpose: Run a workflow over JSON/JSONL cases and write a regression report
    args[1]{name,type,required,desc}:
      workflow,string,true,Workflow file path or discovered workflow ID
    flags[16]{name,short,type,default,desc}:
      cases,c,string,,JSON array, { cases: [...] }, or JSONL case file
      suite,s,string,,Stable suite ID used in run IDs and report paths
      run-label,,string,current UTC timestamp + nonce,Label appended to eval run IDs
      dry-run,n,boolean,false,Plan run IDs without launching workflows
      concurrency,j,number,1,Number of eval cases to run at once
      max-cases,,number,,Run only the first N cases
      report,r,string,.smithers/evals/<suite>.json,Report path
      force,,boolean,false,Overwrite an existing report
      include-output,,boolean,true,Include workflow outputs in the report
      max-concurrency,,number,,Per-workflow task concurrency
      root,,string,,Tool sandbox root directory
      log,,boolean,true,Enable NDJSON event log file output
      log-dir,,string,,NDJSON event logs directory
      allow-network,,boolean,false,Allow bash tool network requests
      max-output-bytes,,number,,Max bytes a single tool call can return
      tool-timeout-ms,,number,,Max wall-clock time per tool call in ms
      optimization,,string,,Apply a Smithers optimization artifact while running the eval suite
  - name: optimize
    purpose: Run GEPA prompt optimization over a workflow eval suite and write an optimized prompt artifact
    args[1]{name,type,required,desc}:
      workflow,string,true,Workflow file path or discovered workflow ID
    flags[16]{name,short,type,default,desc}:
      cases,c,string,,JSON array, { cases: [...] }, or JSONL case file
      suite,s,string,,Stable suite ID used in run IDs and report paths
      provider,p,enum,openai-api,GEPA patch generator provider
      model,m,string,,Optimizer model for provider-backed GEPA
      artifact,a,string,,Write the optimized prompt artifact to this path
      report-dir,,string,,Directory for baseline and optimized eval reports
      min-improvement,,number,0.000001,Minimum required absolute score improvement
      max-cases,,number,,Run only the first N cases
      concurrency,j,number,1,Number of eval cases to run at once
      max-concurrency,,number,,Per-workflow task concurrency
      root,,string,,Tool sandbox root directory
      log,,boolean,true,Enable NDJSON event log file output
      log-dir,,string,,NDJSON event logs directory
      allow-network,,boolean,false,Allow bash tool network requests
      max-output-bytes,,number,,Max bytes a single tool call can return
      tool-timeout-ms,,number,,Max wall-clock time per tool call in ms
  - name: supervise
    purpose: Watch for stale running runs and auto-resume them
    flags[4]{name,short,type,default,desc}:
      dry-run,n,boolean,false,Detect stale runs without resuming
      interval,i,string,10s,Poll interval
      stale-threshold,t,string,30s,Heartbeat staleness threshold before resume
      max-concurrent,c,number,3,Max runs resumed per poll
  - name: gateway
    purpose: Serve the multi-run Gateway RPC/WS control plane for workspace run state (one singleton per workspace; a second start refuses); unlike up --serve, this is not tied to one run
    args[1]{name,type,required,desc}:
      action,enum,false,Manage the running singleton instead of serving: status | stop
    flags[7]{name,short,type,default,desc}:
      host,H,string,127.0.0.1,Gateway bind address
      port,p,number,7331,Preferred port (falls back to an ephemeral port when taken; clients discover the verified URL with gateway status)
      backend,,enum,,Storage behind this workspace Gateway; a boot/deployment choice, not a client run-lookup flag (sqlite|pglite|postgres)
      auth-token,,string,,Bearer token for HTTP/WS auth (or SMITHERS_API_KEY); required for a non-loopback host
      mint-token,,boolean,false,Mint a random bearer; require it on every request and record it only in the 0600 runtime state file
      insecure,,boolean,false,Allow a non-loopback host with NO auth (dangerous)
      idle-timeout,,number,,Exit after this many ms with no clients, in-flight runs, or registered schedules (0 = stay up; autostarted daemons set this automatically); overridable via SMITHERS_GATEWAY_IDLE_MS
  - name: monitor
    purpose: Open the Smithers Monitor, the gateway's live web UI over every run in the workspace (served at /monitor, no .smithers pack required). Pure observation; launches no run, no workflow, no agents. Resolves the workspace's singleton gateway (--gateway probe, then runtime-state discovery, then legacy port probe, then autostart) and opens the browser
    args[1]{name,type,required,desc}:
      runId,string,false,Focus this run when the monitor opens (deep-linked as ?runId=)
    flags[5]{name,short,type,default,desc}:
      gateway,g,string,,Gateway base URL (default http://127.0.0.1:<port>)
      port,,number,7331,Gateway port when --gateway is not set
      open,,boolean,true,Open a browser; use --no-open to just print the URL
      autostart,,boolean,true,Start a local Gateway automatically when no Gateway is reachable; --no-autostart fails fast instead
      daemon,,boolean,true,Autostart the Gateway as a background daemon; --no-daemon (or SMITHERS_NO_DAEMON=1) disables daemonized autostart
  - name: bug
    purpose: File a smithers bug report to bug.smithers.sh; with --run it attaches the run's workflow, status, error, and last ~50 events with secrets scrubbed
    flags[4]{name,short,type,default,desc}:
      run,,string,,Attach this run's workflow name, status, error, and recent events to the report
      title,,string,,Bug title (derived from the run's error when omitted)
      body,,string,,Bug description body
      endpoint,,string,https://bug.smithers.sh/api/bugs,Bug endpoint URL; the SMITHERS_BUG_ENDPOINT env var takes precedence
  - name: review
    purpose: Run code review plus story-form HTML walkthrough generation for a repo or PR
    args[1]{name,type,required,desc}:
      repo,string,false,Repository path; defaults to the current directory
    flags[17]{name,short,type,default,desc}:
      from,,string,,Base ref for a merge-base diff
      to,,string,,Head ref for a merge-base diff
      commit,,string,,Review one commit
      pr,,string,,Review a GitHub PR and post the review onto it
      background,,string,,Requirement background for review and narration
      no-review,,boolean,false,Skip review agents
      no-narrate,,boolean,false,Skip the narrator agent
      no-verify,,boolean,false,Skip verification over findings
      quiz,,enum,auto,off|auto|on
      concurrency,,number,8,Parallel file reviews
      timeout,,number,10,Per-agent-task timeout in minutes
      out,,string,,Output HTML path
      title,,string,,Walkthrough title (default: narrator headline)
      db,,string,,Smithers db path
      split,,boolean,false,Side-by-side diffs instead of unified
      publish,,boolean,false,Upload to the share service and print the share URL
      open,,boolean,false,Open the walkthrough in the default browser
  - name: ps
    purpose: List active, paused, and recently completed runs
    flags[5]{name,short,type,default,desc}:
      status,s,string,,"Filter: running|waiting-approval|waiting-event|waiting-timer|paused|continued|finished|failed|cancelled"
      limit,l,number,20,Max rows
      all,a,boolean,false,Include all statuses
      watch,w,boolean,false,Refresh continuously
      interval,i,number,2,Watch refresh seconds
  - name: logs
    purpose: Tail lifecycle events for a run
    args[1]{name,type,required,desc}:
      runId,string,true,Run ID
    flags[5]{name,short,type,default,desc}:
      follow,f,boolean,true,Poll for new events while run is active
      from-seq,,number,,Start from event sequence number (exclusive)
      since,,number,,Deprecated alias of --from-seq (an event sequence number, not a duration)
      tail,n,number,50,Last N events
      follow-ancestry,,boolean,false,Include ancestor run events root-to-current
  - name: events
    purpose: Query run event history with filters, grouping, and NDJSON output
    args[1]{name,type,required,desc}:
      runId,string,true,Run ID
    flags[8]{name,short,type,default,desc}:
      node,n,string,,Filter by node ID
      type,t,string,,"Category: agent|approval|frame|memory|node|openapi|output|revert|run|sandbox|scorer|snapshot|supervisor|timer|token|tool-call|workflow"
      since,s,string,,Recent duration window such as 5m or 2h
      limit,l,number,1000,Max events; capped at 100000
      json,j,boolean,false,Emit NDJSON
      group-by,,string,,"node | attempt"
      watch,w,boolean,false,Append new events as they arrive
      interval,i,number,2,Watch poll seconds
  - name: chat
    purpose: Show agent chat output for the latest run or a specific run
    args[1]{name,type,required,desc}:
      runId,string,false,Run ID; latest run if omitted
    flags[4]{name,short,type,default,desc}:
      all,a,boolean,false,Show every agent attempt
      follow,f,boolean,false,Watch for new output
      tail,n,number,,Last N chat blocks
      stderr,,boolean,true,Include agent stderr
  - name: chat-create
    purpose: Create and start a one-task auto-hijacked chat run
    flags[2]{name,short,type,default,desc}:
      agent,,enum,,claude-code|codex|antigravity|pi|kimi|amp
      cwd,,string,.,Working directory for the chat session
  - name: hijack
    purpose: Hand off the latest resumable agent session or Smithers-managed conversation
    args[1]{name,type,required,desc}:
      runId,string,true,Run ID
    flags[3]{name,short,type,default,desc}:
      target,,string,,"Expected engine such as claude-code or codex"
      timeout-ms,,number,30000,Wait time for live handoff
      launch,,boolean,true,Open session immediately
  - name: inspect
    purpose: Output detailed state of a run: steps, agents, approvals, timers, loops, outputs
    args[1]{name,type,required,desc}:
      runId,string,true,Run ID
    flags[2]{name,short,type,default,desc}:
      watch,w,boolean,false,Refresh continuously
      interval,i,number,2,Watch refresh seconds
  - name: node
    purpose: Show enriched node details for debugging retries, tool calls, and output
    args[1]{name,type,required,desc}:
      nodeId,string,true,Node ID
    flags[6]{name,short,type,default,desc}:
      run-id,r,string,,Run ID containing the node
      iteration,i,number,,Loop iteration; latest if omitted
      attempts,,boolean,false,Expand all attempts in human output
      tools,,boolean,false,Expand tool input/output payloads
      watch,w,boolean,false,Refresh continuously
      interval,,number,2,Watch refresh seconds
  - name: why
    purpose: Explain why a run is currently blocked or paused
    args[1]{name,type,required,desc}:
      runId,string,true,Run ID
    flags[1]{name,short,type,default,desc}:
      json,,boolean,false,Structured JSON diagnosis
  - name: what
    purpose: Summarize what happened in a run or node with a cheap fast agent (deterministic recap without one)
    args[1]{name,type,required,desc}:
      runId,string,false,Run ID (default: latest run)
    flags[4]{name,short,type,default,desc}:
      node,n,string,,Node ID: explain one node instead of the whole run
      iteration,i,number,,Loop iteration number (default: latest)
      json,,boolean,false,Structured JSON (summary, agentId, source, facts)
      timeout,,number,,Narrator agent timeout in seconds (default 60)
  - name: human
    purpose: List, answer, or cancel durable human requests
    args[2]{name,type,required,desc}:
      action,string,true,inbox|answer|cancel
      requestId,string,false,Human request ID for answer/cancel
    flags[2]{name,short,type,default,desc}:
      value,,string,,JSON response for answer
      by,,string,,Human operator identifier
  - name: ask-human
    purpose: Raise a blocking human-approval request from inside a run and wait for the decision
    args[1]{name,type,required,desc}:
      prompt,string,true,The decision or question to put to a human
    flags[7]{name,short,type,default,desc}:
      context,,string,,Extra context appended to the prompt
      choices,,string,,Comma-separated choices for a fixed-choice decision
      run-id,r,string,,Run to attach to (SMITHERS_RUN_ID or single active run)
      node,n,string,,Node id to attach to (SMITHERS_NODE_ID)
      iteration,,number,0,Loop iteration (SMITHERS_ITERATION or 0)
      timeout,,number,,Seconds before the request expires
      poll,,number,3,Poll interval in seconds while blocking
  - name: alerts
    purpose: List and manage durable alert instances
    args[2]{name,type,required,desc}:
      action,string,true,list|ack|resolve|silence
      alertId,string,false,Alert ID for ack/resolve/silence
  - name: approve
    purpose: Approve a paused approval gate; auto-detects the node if only one is pending
    args[1]{name,type,required,desc}:
      runId,string,true,Run ID
    flags[4]{name,short,type,default,desc}:
      node,n,string,,Node ID required if multiple approvals are pending
      iteration,,number,0,Loop iteration
      note,,string,,Approval note
      by,,string,,Approver identifier
  - name: deny
    purpose: Deny a paused approval gate
    args[1]{name,type,required,desc}:
      runId,string,true,Run ID
    flags[4]{name,short,type,default,desc}:
      node,n,string,,Node ID required if multiple approvals are pending
      iteration,,number,0,Loop iteration
      note,,string,,Denial note
      by,,string,,Denier identifier
  - name: signal
    purpose: Deliver a durable signal to a run waiting on Signal or WaitForEvent
    args[2]{name,type,required,desc}:
      runId,string,true,Run ID
      signalName,string,true,Signal name
    flags[3]{name,short,type,default,desc}:
      data,,string,,Signal payload as JSON; defaults to {}
      correlation,,string,,Correlation ID to match a specific waiter
      by,,string,,Signal sender identifier
  - name: cancel
    purpose: Safely halt agents and terminate one active run
    args[1]{name,type,required,desc}:
      runId,string,true,Run ID
  - name: pause
    purpose: Gracefully pause a run; let in-flight tasks finish, then park it resumably
    args[1]{name,type,required,desc}:
      runId,string,true,Run ID
  - name: down
    purpose: Cancel all active runs in the current Smithers workspace
    flags[1]{name,short,type,default,desc}:
      force,,boolean,false,Cancel runs even if they still appear live; without this only stale runs are cancelled
  - name: graph
    purpose: Render the workflow graph without executing it
    args[1]{name,type,required,desc}:
      workflow,string,true,Workflow ID or file path
    flags[3]{name,short,type,default,desc}:
      run-id,r,string,graph,Run ID for context
      input,,string,,Input JSON; overrides persisted input
      root,,string,,Tool sandbox root directory (same anchor as up)
  - name: gui
    purpose: Open a directory as a workspace in Smithers UI
    args[1]{name,type,required,desc}:
      path,string,false,Directory path (defaults to current working directory)
    flags[5]{name,short,type,default,desc}:
      gateway,g,string,,Gateway base URL (default http://127.0.0.1:<port>)
      port,,number,7331,Gateway port when --gateway is not set
      workflow,w,string,,Open this workflow's UI directly skipping run lookup
      open,,boolean,true,Open a browser; use --no-open to just print the URL
      autostart,,boolean,true,Start a local Gateway automatically when no Gateway is reachable
  - name: ui
    purpose: Open the custom UI for a workflow run in your browser
    args[1]{name,type,required,desc}:
      runId,string,false,Run to open. Defaults to the most recent run.
    flags[4]{name,short,type,default,desc}:
      gateway,g,string,,Gateway base URL (default http://127.0.0.1:<port>)
      port,,number,7331,Gateway port when --gateway is not set
      workflow,w,string,,Open this workflow's UI directly skipping run lookup
      open,,boolean,true,Open a browser; use --no-open to just print the URL
  - name: revert
    purpose: Revert the workspace to a previous task attempt's filesystem state
    args[1]{name,type,required,desc}:
      workflow,string,true,Workflow file path
    flags[4]{name,short,type,default,desc}:
      run-id,r,string,,Run ID
      node-id,n,string,,Node ID
      attempt,,number,1,Attempt number
      iteration,,number,0,Loop iteration
  - name: retry-task
    purpose: Retry a specific task within a run, then resume the workflow
    args[1]{name,type,required,desc}:
      workflow,string,true,Workflow file path
    flags[5]{name,short,type,default,desc}:
      run-id,r,string,,Run ID
      node-id,n,string,,Task/node ID to retry
      iteration,,number,0,Loop iteration
      no-deps,,boolean,false,Only reset this node; skip dependents
      force,,boolean,false,Allow retry even if run is still running
  - name: timetravel
    purpose: Time-travel to a task state; revert filesystem, reset DB, optionally resume
    args[1]{name,type,required,desc}:
      workflow,string,true,Workflow file path
    flags[8]{name,short,type,default,desc}:
      run-id,r,string,,Run ID
      node-id,n,string,,Task/node ID
      iteration,,number,0,Loop iteration
      attempt,a,number,,Attempt number; latest if omitted
      no-vcs,,boolean,false,Skip filesystem revert; DB only
      no-deps,,boolean,false,Only reset this node
      resume,,boolean,false,Resume after time travel
      force,,boolean,false,Force even if run is still running
  - name: replay
    purpose: Fork from a checkpoint and resume execution
    args[1]{name,type,required,desc}:
      workflow,string,true,Workflow file path
    flags[6]{name,short,type,default,desc}:
      run-id,r,string,,Source run ID
      frame,f,number,,Frame number to fork from
      node,n,string,,Node ID to reset to pending
      input,i,string,,Input overrides as JSON
      label,l,string,,Branch label for the fork
      restore-vcs,,boolean,false,Restore jj filesystem state to source frame revision
  - name: fork
    purpose: Create a branched run from a snapshot checkpoint
    args[1]{name,type,required,desc}:
      workflow,string,true,Workflow file path
    flags[6]{name,short,type,default,desc}:
      run-id,r,string,,Source run ID
      frame,f,number,,Frame number to fork from
      reset-node,n,string,,Node ID to reset to pending
      input,i,string,,Input overrides as JSON
      label,l,string,,Branch label
      run,,boolean,false,Immediately start the forked run
  - name: timeline
    purpose: View execution timeline for a run and its forks
    args[1]{name,type,required,desc}:
      runId,string,true,Run ID
    flags[2]{name,short,type,default,desc}:
      tree,,boolean,false,Include all child forks recursively
      json,j,boolean,false,Output as JSON
  - name: tree
    purpose: Print DevTools snapshot as an XML tree
    args[1]{name,type,required,desc}:
      runId,string,true,Run ID
    flags[6]{name,short,type,default,desc}:
      frame,,number,,Historical frame number
      watch,,boolean,false,Stream live DevTools events
      json,j,boolean,false,Emit snapshot JSON
      depth,,number,,Truncate depth
      node,,string,,Scope to subtree
      color,,enum,auto,auto|always|never
  - name: diff
    purpose: Print a node DiffBundle as unified diff
    args[2]{name,type,required,desc}:
      runId,string,true,Run ID containing the node
      nodeId,string,true,Node ID to diff
    flags[4]{name,short,type,default,desc}:
      iteration,,number,,Loop iteration; latest if omitted
      json,j,boolean,false,Emit raw DiffBundle
      stat,,boolean,false,Show stat summary only
      color,,enum,auto,auto|always|never
  - name: output
    purpose: Print a node output row
    args[2]{name,type,required,desc}:
      runId,string,true,Run ID containing the node
      nodeId,string,true,Node ID to fetch output for
    flags[3]{name,short,type,default,desc}:
      iteration,,number,,Loop iteration; latest if omitted
      json,j,boolean,true,Emit raw row as JSON
      pretty,,boolean,false,Schema-ordered render
  - name: rewind
    purpose: Rewind a run to a previous frame
    args[2]{name,type,required,desc}:
      runId,string,true,Run ID to rewind
      frameNo,number,true,Target frame number
    flags[2]{name,short,type,default,desc}:
      yes,,boolean,false,Skip confirmation prompt
      json,j,boolean,false,Emit JumpResult JSON
  - name: snapshots
    purpose: List durability snapshots (workspace checkpoints) for a run
    args[1]{name,type,required,desc}:
      runId,string,true,Run ID to list snapshots for
    flags[1]{name,short,type,default,desc}:
      json,j,boolean,false,Emit rows as JSON
  - name: restore
    purpose: Restore a worktree to a durability checkpoint (latest for the node, or --seq)
    args[2]{name,type,required,desc}:
      runId,string,true,Run ID containing the checkpoint
      nodeId,string,true,Node ID whose worktree to restore
    flags[2]{name,short,type,default,desc}:
      iteration,,number,,Loop iteration
      seq,,number,,Checkpoint seq; latest if omitted
  - name: snapshot-hook
    purpose: "Internal: PostToolUse hook that requests a Tier 1 durability snapshot"
  - name: observability
    purpose: Start or stop the local Docker Compose observability stack
    flags[2]{name,short,type,default,desc}:
      detach,d,boolean,false,Run containers in the background
      down,,boolean,false,Stop and remove the stack
  - name: ask
    purpose: Ask a question about Smithers using an installed agent and the Smithers MCP server
    args[1]{name,type,required,desc}:
      question,string,false,Question to ask
    flags[6]{name,short,type,default,desc}:
      agent,,enum,,claude|codex|antigravity|kimi|pi
      list-agents,,boolean,false,List detected agents and exit
      dump-prompt,,boolean,false,Print generated system prompt and exit
      tool-surface,,enum,semantic,semantic|raw
      no-mcp,,boolean,false,Disable MCP bootstrap and use prompt fallback
      print-bootstrap,,boolean,false,Print selected bootstrap configuration and exit
  - name: scores
    purpose: View scorer results for a specific run
    args[1]{name,type,required,desc}:
      runId,string,true,Run ID
    flags[1]{name,short,type,default,desc}:
      node,,string,,Filter scores to a specific node ID
  - name: usage
    purpose: Show how much rate limit or subscription quota each registered account has used
    flags[3]{name,short,type,default,desc}:
      account,,string,,Only report this account label
      provider,,string,,Only report accounts for this provider
      fresh,,boolean,false,Bypass the short usage cache while respecting provider rate-limit floors
  - name: docs
    purpose: Print llms.txt for this CLI version
    flags[2]{name,short,type,default,desc}:
      latest,,boolean,false,Fetch the latest docs from smithers.sh instead of docs for this CLI version
      docs-version,,string,,Fetch docs for a specific Smithers version, e.g. 0.22.0 or v0.22.0
  - name: docs-full
    purpose: Print llms-full.txt for this CLI version
    flags[2]{name,short,type,default,desc}:
      latest,,boolean,false,Fetch the latest docs from smithers.sh instead of docs for this CLI version
      docs-version,,string,,Fetch docs for a specific Smithers version, e.g. 0.22.0 or v0.22.0
  - name: update
    purpose: Check for a newer Smithers release and upgrade the install (or print how)
    flags[2]{name,short,type,default,desc}:
      check,,boolean,false,Only report current vs latest version; never upgrade
      dry-run,,boolean,false,Print the upgrade command without running it
  - name: upgrade
    purpose: "Run the agent-assisted Smithers upgrade workflow: fetch changelogs, upgrade with a cheap agent, and escalate to a smart agent only when needed."
    flags[8]{name,short,type,default,desc}:
      interactive,,boolean,false,Force the full-screen interactive TUI monitor (TTY only).
      detach,d,boolean,false,Launch the upgrade workflow in the background and print the run ID.
      dry-run,,boolean,false,Fetch changelogs and plan the upgrade without changing the install.
      run-id,,string,,Explicit run ID for the upgrade workflow.
      root,,string,,Tool sandbox root directory.
      log-dir,,string,,NDJSON event logs directory.
      backend,,enum,,"sqlite|pglite|postgres"
      auth-token,,string,,Bearer token passed to the interactive monitor gateway client.
  - name: agents.capabilities
    purpose: Print JSON capability registry for built-in CLI agents
  - name: agents.doctor
    purpose: Validate built-in CLI agent capability registries and command-surface contracts
    flags[1]{name,short,type,default,desc}:
      json,,boolean,false,Print doctor report as JSON
  - name: agents.add
    purpose: Register a Smithers agent account, interactively or with flags
    flags[9]{name,short,type,default,desc}:
      provider,,enum,,"claude-code|antigravity|codex|kimi|anthropic-api|openai-api|gemini-api"
      label,,string,,Unique account label
      config-dir,,string,,Per-account CLI config dir for subscription providers
      api-key,,string,,API key for API-key providers
      model,,string,,Default model for this account
      skip-login,,boolean,false,Skip credential-directory check
      force,,boolean,false,Register even if no credentials are present
      replace,,boolean,false,Overwrite an existing account with the same label
      loop,,boolean,false,Wizard mode; keep adding accounts until done
  - name: agents.list
    purpose: List registered Smithers agent accounts
  - name: agents.remove
    purpose: Remove a registered agent account by label
    args[1]{name,type,required,desc}:
      label,string,true,Account label
    flags[1]{name,short,type,default,desc}:
      silent,,boolean,false,Do not error if the label is not registered
  - name: agents.test
    purpose: Spawn an account's underlying CLI with --version
    args[1]{name,type,required,desc}:
      label,string,true,Account label
  - name: workflow.list
    purpose: List discovered workflows (local .smithers/workflows/ plus the global ~/.smithers/workflows/; each entry reports its scope, local shadows global)
  - name: workflow.run
    purpose: Run a discovered workflow by ID
    args[1]{name,type,required,desc}:
      name,string,false,Workflow ID (omit with --interactive to pick one)
    flags[35]{name,short,type,default,desc}:
      detach,d,boolean,false,Background mode; print runId/pid/logFile and exit
      run-id,r,string,,Explicit run ID
      max-concurrency,c,number,4,Maximum parallel tasks
      root,,string,,Tool sandbox root directory
      log,,boolean,true,Enable NDJSON event log file output
      log-dir,,string,,NDJSON event logs directory
      allow-network,,boolean,false,Allow bash tool network requests
      max-output-bytes,,number,,Max bytes a single tool call can return
      tool-timeout-ms,,number,,Max wall-clock time per tool call in ms
      hot,,boolean,false,Hot reload for .tsx workflows
      input,i,string,,Input data as JSON string or '-' to read JSON from stdin
      annotations,,string,,Run annotations as flat JSON string/number/boolean object or '-' to read JSON from stdin
      resume,,boolean|string,false,Resume an existing run; may be true or a run ID
      force,,boolean,false,Resume even if still marked running
      resume-claim-owner,,string,,Internal durable resume claim owner
      resume-claim-heartbeat,,number,,Internal durable resume claim heartbeat
      resume-restore-owner,,string,,Internal durable resume restore owner
      resume-restore-heartbeat,,number,,Internal durable resume restore heartbeat
      serve,,boolean,false,Start an HTTP server alongside the workflow
      supervise,,boolean,false,Run stale-run supervisor loop with --serve
      supervise-dry-run,,boolean,false,With --supervise; detect without resuming
      supervise-interval,,string,10s,Supervisor poll interval
      supervise-stale-threshold,,string,30s,Heartbeat staleness threshold
      supervise-max-concurrent,,number,3,Max runs resumed per poll
      port,,number,7331,HTTP server port when --serve
      host,,string,127.0.0.1,HTTP bind address when --serve
      auth-token,,string,,Bearer token for HTTP auth or SMITHERS_API_KEY env
      insecure,,boolean,false,Allow binding a non-loopback --host with NO auth (exposes unauthenticated approve/deny/cancel control of the run; dangerous)
      metrics,,boolean,true,Expose /metrics Prometheus endpoint when --serve
      backend,,enum,,Bootstrap storage selection for a workflow owner or workspace Gateway; not a run-discovery/control flag (sqlite|pglite|postgres)
      post-failure,,boolean,true,Auto-launch the post-failure autopsy workflow when this run fails (disable with --no-post-failure or SMITHERS_POST_FAILURE=0)
      verbose,,boolean,false,Show engine info logs on interactive runs; the default keeps progress + warnings only (non-TTY/structured output always gets full logs)
      report,,boolean,true,Narrate an interactive run's result with a cheap/fast agent and open an HTML summary in the browser (disable with --no-report or SMITHERS_NO_REPORT=1)
      prompt,p,string,,Shorthand for input.prompt when --input is omitted
      interactive,,boolean,false,Pick a workflow and inputs interactively then open the full-screen run monitor (no silent fallback: fails with TUI_MONITOR_UNAVAILABLE if the tui package is missing, leaving the detached run running)
  - name: workflow.path
    purpose: Resolve a workflow ID to its entry file path
    args[1]{name,type,required,desc}:
      name,string,true,Workflow ID
  - name: workflow.inspect
    purpose: Show workflow metadata and an agent-facing skill preview
    args[1]{name,type,required,desc}:
      name,string,true,Workflow ID
  - name: workflow.create
    purpose: Create a new flat workflow scaffold in .smithers/workflows/ (or ~/.smithers with --global)
    args[1]{name,type,required,desc}:
      name,string,true,New workflow ID
    flags[1]{name,short,type,default,desc}:
      global,,boolean,false,Create in the global ~/.smithers pack (honors SMITHERS_HOME) instead of the local .smithers
  - name: workflow.skills
    purpose: Generate agent-facing skill docs for discovered workflows
    args[1]{name,type,required,desc}:
      name,string,false,Workflow ID; omit for all workflows
    flags[3]{name,short,type,default,desc}:
      output,,string,,Output file for one workflow, or output directory for all
      force,,boolean,false,Overwrite existing skill files
      global,,boolean,false,Write skills into the global ~/.smithers pack instead of the local .smithers
  - name: workflow.doctor
    purpose: Inspect workflow discovery, preload files, bunfig, and detected agents
    args[1]{name,type,required,desc}:
      name,string,false,Workflow ID; omit for all
  - name: claude.tick
    purpose: One /workflows mirror frame for a run (Claude Code plugin protocol, contract v1); --wait blocks until a mirror-relevant event lands after --after-seq
    args[1]{name,type,required,desc}:
      runId,string,true,Run ID to mirror
    flags[6]{name,short,type,default,desc}:
      after-seq,,number,0,Event-log cursor from the previous tick's seq
      wait,,boolean,false,Block until a mirror-relevant event lands after --after-seq (or timeout)
      timeout-ms,,number,420000,Max wait in ms before returning timedOut true
      interval-ms,,number,750,Wait poll interval in ms
      max-output-chars,,number,2000,Truncate node outputs to this many chars
      collapse-phases,,boolean,false,Collapse the phase plan to a single phase
  - name: claude.node-wait
    purpose: Block until one node reaches a terminal state, then print its final state and output (returns timedOut true on expiry; re-invoke to keep waiting)
    args[1]{name,type,required,desc}:
      nodeId,string,true,Node ID to wait on
    flags[5]{name,short,type,default,desc}:
      run-id,,string,,Run ID that owns the node
      iteration,i,number,,Loop iteration (default latest)
      timeout-ms,,number,480000,Max wait in ms before returning timedOut true
      interval-ms,,number,1000,Poll interval in ms
      max-output-chars,,number,2000,Truncate the node output to this many chars
  - name: claude.monitor
    purpose: Follow local runs and print one NDJSON line per actionable transition (approval pending, human request, failed, stalled); --transitions all adds finished/cancelled/continued; backs the plugin's background monitor
    flags[4]{name,short,type,default,desc}:
      interval-ms,,number,2000,Poll interval in ms
      stalled-after-ms,,number,120000,Heartbeat age that flags a running run as stalled
      ticks,,number,,Stop after N polls (default run until killed)
      transitions,,string,actionable,Which transitions stream: actionable or all
  - name: cron.start
    purpose: Start the background scheduler loop in the current terminal
  - name: cron.add
    purpose: Register a new workflow cron schedule
    args[2]{name,type,required,desc}:
      pattern,string,true,Cron expression
      workflowPath,string,true,Path or ID of workflow to schedule
  - name: cron.list
    purpose: List registered background cron schedules
  - name: cron.rm
    purpose: Delete a cron schedule by ID
    args[1]{name,type,required,desc}:
      cronId,string,true,Cron ID
  - name: memory.list
    purpose: List all memory facts in a namespace
    args[1]{name,type,required,desc}:
      namespace,string,true,Namespace such as workflow:my-flow
    flags[1]{name,short,type,default,desc}:
      workflow,w,string,,Path to workflow file that locates the DB
  - name: memory.get
    purpose: Get a single memory fact by namespace and key
    args[2]{name,type,required,desc}:
      namespace,string,true,Namespace such as workflow:my-flow
      key,string,true,Fact key
    flags[1]{name,short,type,default,desc}:
      workflow,w,string,,Path to workflow file that locates the DB
  - name: memory.set
    purpose: Set a memory fact (value stored verbatim as the fact's JSON value)
    args[3]{name,type,required,desc}:
      namespace,string,true,Namespace such as workflow:my-flow
      key,string,true,Fact key
      value,string,true,Fact value stored as-is
    flags[2]{name,short,type,default,desc}:
      workflow,w,string,,Path to workflow file that locates the DB
      ttl,,number,,Time-to-live in milliseconds
  - name: memory.rm
    purpose: Delete a memory fact by namespace and key
    args[2]{name,type,required,desc}:
      namespace,string,true,Namespace such as workflow:my-flow
      key,string,true,Fact key
    flags[1]{name,short,type,default,desc}:
      workflow,w,string,,Path to workflow file that locates the DB
  - name: openapi.list
    purpose: Preview tools generated from an OpenAPI spec
    args[1]{name,type,required,desc}:
      specPath,string,true,File path or URL to OpenAPI spec
  - name: openapi.generate
    purpose: Generate an AI SDK tools module from an OpenAPI spec
    args[2]{name,type,required,desc}:
      specPath,string,true,File path to OpenAPI spec
      outputPath,string,true,Output JavaScript file for generated tools
  - name: token.issue
    purpose: Issue a local short-lived Gateway bearer token grant
    flags[6]{name,short,type,default,desc}:
      scopes,,string,run:read,Comma or space separated Gateway scopes
      role,,string,operator,Role recorded on the token grant
      user-id,,string,,User ID recorded on the token grant
      ttl,,string,1h,Token lifetime such as 15m or 1h
      action-id,,string,gateway,Action id allowed to resolve the brokered action token
      reveal-token,,boolean,false,Include the raw bearer token in CLI output
  - name: token.exec
    purpose: Resolve an action token locally and inject the bearer into a child process environment
    flags[5]{name,short,type,default,desc}:
      handle,,string,,Brokered action token handle
      action-id,,string,gateway,Action id expected by the brokered token
      scopes,,string,,Comma or space separated scopes required for this action
      env,,string,SMITHERS_API_KEY,Environment variable that receives the bearer token
      command,,string,,Shell command to run with the injected token
  - name: token.revoke
    purpose: Revoke a locally issued Gateway bearer token
    args[1]{name,type,required,desc}:
      token,string,true,Bearer token to revoke
  - name: completions
    purpose: Generate shell completion scripts
    args[1]{name,type,required,desc}:
      shell,string,true,bash|fish|nushell|zsh
  - name: mcp.add
    purpose: Register Smithers as an MCP server for an agent integration
    flags[3]{name,short,type,default,desc}:
      agent,,string,,Target agent such as claude-code or cursor
      command,c,string,,Override the command agents will run
      no-global,,boolean,false,Install to project instead of globally
  - name: skills.add
    purpose: Sync skill files to agent integrations
    flags[2]{name,short,type,default,desc}:
      depth,,number,1,Grouping depth for skill files
      no-global,,boolean,false,Install to project instead of globally
  - name: skills.list
    purpose: List available skills

Operational notes

  • Detached mode (up --detach): redirects stdout/stderr to a log file, prints runId/pid/logFile, and exits.
  • Serve mode (up --serve): starts the HTTP app and keeps the process alive until interrupted. Add --supervise to run stale-run recovery in the same process.
  • Watch mode: ps, events, inspect, node, and tree have watch-style behavior. They stop cleanly on SIGINT and most stop when the run becomes terminal.
  • DevTools commands: tree, diff, output, and rewind intentionally use command-scoped --json/-j and return exit code 1 for parser/user errors.
  • Account commands: agents add|list|remove|test manage ~/.smithers/accounts.json; subscription providers use CLI config directories, API providers use API keys. Legacy entries with an unknown provider are preserved across add/remove; agents remove <label> deletes one.
  • Output format: all commands honour --format toon|json|yaml|md|jsonl; --filter-output <key.path> extracts a nested field from JSON output.
  • Interactive TUI: use bunx smithers-orchestrator up --interactive or bunx smithers-orchestrator workflow run WORKFLOW_ID --interactive for the current full-screen terminal monitor. bunx smithers-orchestrator init also has a human setup flow (one agent question, then a hijacked tutorial). See Interactive TUI.