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

  • Persisted state lives in the nearest smithers.db (walk up from the working directory). Most read commands fail with a friendly message if no DB is found.
  • Task root: tools run from the project root (the nearest directory containing a .smithers/, walking up from the working directory), the same anchor as smithers.db. 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: up, graph, revert, replay, fork, retry-task, and timetravel take a workflow file path. eval accepts either a workflow path or a discovered workflow ID. 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

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 a keeper loop around the persisted run state: inspect with bunx smithers-orchestrator ps, bunx smithers-orchestrator why RUN_ID, bunx smithers-orchestrator inspect RUN_ID, and bunx smithers-orchestrator logs RUN_ID -f; clear gates with bunx smithers-orchestrator approve RUN_ID or bunx smithers-orchestrator deny RUN_ID; send signals with bunx smithers-orchestrator signal RUN_ID ...; then resume the same run with bunx smithers-orchestrator up <workflow.tsx> --resume RUN_ID. Use --force only after confirming the previous owner is gone or intentionally replacing it. 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.

Workflow UIs

Open a run’s custom browser UI with:
bunx smithers-orchestrator ui RUN_ID
If no Gateway is reachable on the default local port, bunx smithers-orchestrator ui starts smithers gateway automatically and then opens the UI. smithers gateway serves the workspace DB and auto-mounts .smithers/ui/<workflow>.tsx files for matching discovered workflow ids. 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[78]:
  - name: init
    purpose: Install the workflow pack into .smithers/ (local) or ~/.smithers/ (--global)
    flags[6]{name,short,type,default,desc}:
      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
      global,,boolean,false,Scaffold the global pack in ~/.smithers (honors SMITHERS_HOME) instead of ./.smithers
      template,,string,,Show next steps for a canonical starter template ID after init
  - 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: up
    purpose: Start or resume a workflow execution from a .tsx workflow file path (use `workflow run` to start from a discovered workflow id instead)
    args[1]{name,type,required,desc}:
      workflow,string,false,Workflow file path (omit with --interactive to pick one)
    flags[30]{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
      metrics,,boolean,true,Expose /metrics Prometheus endpoint when --serve
      interactive,,boolean,false,Pick a workflow and inputs interactively then live-render the run
      backend,,enum,,Storage backend for workflows using openSmithersBackend (sqlite|pglite|postgres)
  - 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,cerebras,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 the workspace DB; unlike up --serve, this is not tied to one run
    flags[3]{name,short,type,default,desc}:
      host,H,string,127.0.0.1,Gateway bind address
      port,p,number,7331,Gateway port
      backend,,enum,,Workspace storage backend (sqlite|pglite|postgres)
  - name: monitor
    purpose: Watch a single run, diagnose a stall or failure, and optionally apply the smallest safe self-fix behind an approval gate
    args[1]{name,type,required,desc}:
      runId,string,false,Run ID to monitor (default: the most recent active run)
    flags[4]{name,short,type,default,desc}:
      autofix,,boolean,false,Let the monitor apply the smallest safe self-fix and resume the run
      require-approval,,boolean,true,"With --autofix, pause for a human approval gate before any fix"
      stale-minutes,,number,15,Treat a non-terminal run idle past this many minutes as stuck
      ui,,boolean,true,Auto-open the monitored run's own custom UI when its workflow has one (use --no-ui to skip)
  - 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|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[4]{name,short,type,default,desc}:
      follow,f,boolean,true,Poll for new events while run is active
      since,,number,,Start after event sequence number
      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|gemini
      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: 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: down
    purpose: Cancel all active runs in the nearest smithers.db
    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 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|gemini|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: 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|gemini|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[31]{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
      metrics,,boolean,true,Expose /metrics Prometheus endpoint when --serve
      backend,,enum,,Storage backend for workflows using openSmithersBackend (sqlite|pglite|postgres)
      prompt,p,string,,Shorthand for input.prompt when --input is omitted
      interactive,,boolean,false,Pick a workflow and inputs interactively then live-render the run
  - 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: 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.
  • Output format: all commands honour --format toon|json|yaml|md|jsonl; --filter-output <key.path> extracts a nested field from JSON output.
  • Removed command: bunx smithers-orchestrator tui was removed in 0.20.2. Use ps, events, chat, inspect, node, tree, diff, output, or rewind instead. See tui.mdx for migration details.