The roscoe CLI is a single binary that authors, runs, inspects, and serves workflows. Reach for it when you want to script Roscoe into a build step, kick off a quick run from the terminal, or stand up the web UI on a port of your choosing. Every subcommand is also reachable from source via bun apps/cli/src/index.ts <subcommand> while developing.
This page is a tour. For the exhaustive flag-by-flag reference, see /docs/reference/cli-commands. For the in-browser tour, see /docs/running/web-ui. For driving Roscoe from a Claude Code session, see /docs/running/mcp.
Authoring#
roscoe init#
One-shot setup: creates the data directory, runs DB migrations, seeds a set of starter workflows (including demo-1-the-panel, demo-2-week-of-dinners, and demo-4-second-draft), and writes a starter roscoe.yaml. When run inside a git repo it also scaffolds <repo>/.roscoe/ and drops a .roscoe/.gitignore so its regenerated schema files (and a stray DB) aren't committed. Your repo's root .gitignore is left untouched, and <repo>/.roscoe/workflows/ + roscoe.yaml are tracked so you can commit and share them. The database itself lives in the global home (~/.roscoe/), never in your repo.
roscoe init # default — touches both global and (if in git repo) project
roscoe init --global-only # skip repo scaffolding
roscoe init --repo-only # skip global init
roscoe init --force # overwrite existing example files
roscoe init --no-examples # skip seeding the nine example workflowsGlobal init (anything but --repo-only) also installs a /roscoe slash command
at ~/.claude/commands/roscoe.md, so Claude Code / Cowork users can launch a
workflow by typing /roscoe <workflow-name>. It's best-effort: a failure is
logged but never aborts init.
roscoe validate <file>#
Static check against the workflow JSON Schema and integrity rules (unreachable states, dangling transitions, unknown models). Run it in CI or as a pre-commit hook to catch malformed YAML before it ships.
roscoe validate .roscoe/workflows/release-train.workflow.yamlRun#
roscoe run <workflow> [--var key=value ...] [--source global|repo]#
Start a workflow. The first argument is either a workflow id (resolved against project then global, see /docs/configuration/workflow-sources) or an explicit path to a .workflow.yaml file.
roscoe run routes through a running server. Start roscoe serve (or bun run dev during development) in another terminal first. If nothing is listening, the command exits with a hint pointing at both startup paths.
In a TTY, roscoe run mounts a live Ink view: a node-by-node tree, a status line, and an interactive HITL prompt when the workflow pauses on a human node. Press q to detach (the run keeps executing on the server), c to cancel (with confirmation), or o to open the run page in the browser.
# By id — repo wins over global on collision
roscoe run demo-1-the-panel
# Force the global copy when a repo workflow shadows the same id
roscoe run demo-1-the-panel --source global
# Pass workflow inputs (repeatable -i / --input; values are JSON-parsed)
roscoe run demo-2-week-of-dinners --input days=3 --input diet=vegetarian
# By explicit path
roscoe run ./scratch/experiment.workflow.yaml
# Headless / CI / agent: emit JSON and exit
roscoe run demo-1-the-panel --json
# Cap the spend: stop the run once it exceeds $0.50 (or 200k tokens)
roscoe run expensive-flow --spending-cap 0.50
roscoe run expensive-flow --spending-cap-tokens 200000
# Reattach to a run that's still going
roscoe run --attach <runId>When stdout isn't a TTY (piped output, CI), the command degrades to a one-shot start: it waits for the run to settle, then prints a JSON object with the run id, status, and the cost rollup (totalCostUsd, meteredCostUsd, subscriptionEquivCostUsd, billingMode, inputTokens, outputTokens, plus stopReason when the run was stopped). AI nodes hit either the Anthropic SDK or the Claude CLI depending on your environment. See /docs/configuration/llm-backends.
Spending caps#
--spending-cap <usd> and --spending-cap-tokens <n> set an optional per-run
ceiling. Caps are off by default. After each node completes, Roscoe re-totals
the run's cost (metered out-of-pocket plus the subscription API-equivalent)
and tokens; if either cap is exceeded, the run stops cleanly: status
cancelled, stopReason: spending_cap_exceeded. Set both to stop on whichever
is reached first. The cap bounds the whole run, including consensus / map /
round_robin fan-out and nested sub-workflows, and applies to subscription runs
too (it bounds the would-be API cost). A workflow can also declare a default cap
in its YAML (see /docs/authoring/yaml-structure);
a flag here overrides that default for the run.
roscoe resume <runId> [transition]#
Continue a workflow paused at a human node. In a TTY, omitting the transition mounts the same interactive picker roscoe run uses. With a transition argument the command runs non-interactively (suitable for scripts and CI).
roscoe resume 01HXYZ... approve
roscoe resume 01HXYZ... reject
# Interactive picker — pick from the valid transitions in a Select
roscoe resume 01HXYZ...The valid transitions are listed in roscoe monitor and on the run page in the web UI.
Inspect#
roscoe list#
Lists every workflow Roscoe can see across both sources. Project entries appear first; the global entry is marked [shadowed by repo] when a project workflow with the same id is masking it.
roscoe listroscoe monitor <runId>#
In a TTY, roscoe monitor mounts the same live Ink view as roscoe run: a node tree, status line, and HITL prompt, without starting a new run. With --json or when piped, it prints a one-shot snapshot (run + node trace) and exits.
roscoe monitor 01HXYZ... # live TUI
roscoe monitor 01HXYZ... --json # one-shot snapshot for scriptsLike roscoe run, the live path requires a running server. The static --json path reads the local DB directly and works without one.
roscoe history#
Recent runs for the current project, newest first.
roscoe history # last 20 runs in this project
roscoe history -n 100 # bump the limit
roscoe history --all # include runs from every project on this machineProjects#
roscoe register / roscoe unregister#
Add or remove a project in the local registry that backs the web UI's project
switcher. Both default to the git root of the current directory; pass a path to
target another repo. Registration only records the path. unregister deletes
no files; it drops the entry from the switcher.
roscoe register # show the current repo in the project switcher
roscoe register --activate # …and make it the active workspace
roscoe unregister # remove the current repo from the switcher
roscoe unregister ~/dev/proj # remove a specific repoYou can do the same from the UI: the project switcher's + adds a project and each row's trash icon removes one.
Server#
roscoe serve [--port <port>]#
Boots the REST API and the embedded web UI on a single port. The compiled binary defaults to :7777; in dev mode the API and web run as separate processes (see /docs/configuration/environment).
roscoe serve # http://localhost:7777
roscoe serve --port 4000 # custom port
ROSCOE_PORT=4000 roscoe serve # equivalent via envIf the port is busy the binary auto-falls-back to the next free port and prints the chosen URL. Startup mounts a persistent Ink splash showing the bound URL, mode (standalone vs dev), data directory, and lock path. Press q (or send SIGINT/SIGTERM) to shut down: the lock at <ROSCOE_HOME>/serve.lock is removed on clean exit so roscoe run/monitor/resume can find the server while it's up.
MCP#
roscoe mcp#
Starts the MCP stdio server. Claude Code launches this for you via .mcp.json. You rarely run it by hand, but it is useful for debugging the MCP transport.
roscoe install-mcp [--project] [--path <file>]#
Registers the roscoe entry so Claude Code picks up the binary on its next launch. By default it writes the user-global ~/.claude.json (top-level mcpServers), so the install applies to every project. The entry points at process.execPath, meaning the same binary you ran install-mcp from.
roscoe install-mcp # user-global: writes ~/.claude.json
roscoe install-mcp --project # project-local: writes ./.mcp.jsonThe default user-global install also drops the /roscoe slash command at
~/.claude/commands/roscoe.md (same file roscoe init writes), so you can launch
a workflow with /roscoe <workflow-name> in Claude Code / Cowork. It's skipped
for --project, --client claude-desktop, and --path.
For the full MCP tour, see /docs/running/mcp: what the tools do, how the pause/advance loop works, and how Claude Code drives a run end-to-end.
See also#
- /docs/reference/cli-commands — full flag reference for every subcommand.
- /docs/running/web-ui — the in-browser editor and run viewer.
- /docs/running/mcp — driving Roscoe from Claude Code.
- /docs/configuration/environment — env vars that change CLI behaviour.