Quick start
Docker is the recommended way to run Stageflow: pull the published image and open the console. Install Node when you want the sf command on the machine. Either way you author the stages yourself: Stageflow does not ship built-in stage types.
Docker (recommended)
The image is ghcr.io/tejasghutukade/stageflow. 0.39 is the current minor tag (0.39.0 is that exact release). Each release is also tagged x.y.z and x.y.
docker run --rm --name stageflow \
-e STAGEFLOW_ALLOW_UNAUTHENTICATED_BIND=1 \
-p 127.0.0.1:3847:3847 \
-v stageflow-data:/data \
ghcr.io/tejasghutukade/stageflow:0.39 \
sf ui
Open http://127.0.0.1:3847. Go to Settings → Providers and connect a model, then New pipeline on the Pipelines page. Pipelines you save in the console live on the stageflow-data volume, under /data.
The process inside the container binds 0.0.0.0, which is what Docker port publish needs. The -p address keeps the port on this machine, and STAGEFLOW_ALLOW_UNAUTHENTICATED_BIND=1 lets it start without a bearer. Do not publish the port on 0.0.0.0 with that flag set. Pass sf ui because the image command is sf mcp.
To browse a project that is already on the machine, mount it and register that path:
docker run --rm --name stageflow \
-e STAGEFLOW_ALLOW_UNAUTHENTICATED_BIND=1 \
-e STAGEFLOW_ENSURE_PROJECT_ROOTS=/project \
-p 127.0.0.1:3847:3847 \
-v stageflow-data:/data \
-v "$PWD":/project \
ghcr.io/tejasghutukade/stageflow:0.39 \
sf ui
That project needs the same files as the Node scaffold below (stageflow.yaml, a pipeline, a task), or you create them from the console. Building the image from a git checkout, instead of pulling it, is Docker — Local try.
Node
Use this when you want sf in the shell on the machine.
- Node.js ≥ 20
- A Pi-compatible model provider (connect after install)
npm i -g stageflow
1. Scaffold the catalog
In an empty project directory (preferably a git repo), run:
sf init
This creates:
| File | Purpose |
|---|---|
stageflow.yaml |
Manifest — declares which directories to browse and validate |
pipelines/hello.pipeline.yaml |
Single inline stage pipeline |
tasks/hello.task.yaml |
Task file |
Manual alternative — same shape without sf init:
stageflow.yaml
version: 1
catalog:
pipelines:
- pipelines
- workshop
tasks:
- tasks
- workshop
patterns:
pipeline: "*.pipeline.yaml"
task: "*.task.yaml"
workshop is the scan root for pipelines saved from Workshop Author. The directory is created on the first save.
pipelines/hello.pipeline.yaml
id: hello
stages:
- id: hello
system_prompt: Say hello and emit a success envelope.
model: CHANGE_ME/<provider-model>
sf init fills model from the single configured provider when one is logged in (for example openrouter/auto or anthropic/claude-sonnet-4-5). With none or more than one configured provider, it writes the loud placeholder CHANGE_ME/<provider-model> — replace it before running.
tasks/hello.task.yaml
id: hello
goal: Run the hello pipeline scaffold.
Stages are object entries with inline bodies or uses: paths — not bare string ids. Author contracts with io / verify / on_verify_fail — see YAML catalog.
2. Validate the catalog
sf validate --strict
With no flags, sf validate checks all pipelines and tasks declared in stageflow.yaml (manifest-all), plus the stages those pipelines reference. --strict promotes manifest warnings (missing manifest, empty catalog) to errors.
It does not prove provider auth or checkout paths.
3. Connect a provider
Either open the operator console:
sf ui
Go to Settings → Providers and connect a model, or use the CLI:
sf providers list
sf providers login anthropic --type api_key --api-key-env ANTHROPIC_API_KEY
See Providers for pi_home vs sf_owned credential storage.
4. Run the pipeline
sf run --pipeline pipelines/hello.pipeline.yaml --task tasks/hello.task.yaml
--pipeline and --task require filesystem paths — there is no bare-id fallback.
sf run is an HTTP client of a single global Stageflow service shared by every project on the machine — it auto-starts that service (headless, no browser) the first time anything needs it, and reuses it if sf ui/sf mcp is already running. Each stage runs in a fresh Pi session. When the stage agent finishes, it must call emit_stage_envelope once (see Envelopes). On success the pipeline completes and run state is stored under the global durable root ($STAGEFLOW_HOME, default ~/.stageflow/) — one shared store for every project, not a per-project .stageflow/ folder. See Data directory. Pipeline/task catalog resolution (stageflow.yaml, pipelines/, tasks/) still stays project-local, resolved from whichever git root you're running in.
5. Operate via the console
With sf ui running (default http://127.0.0.1:3847):
Start sf ui before running any pipeline if you want the console open: sf run (or any mutating sf runs command) auto-starts the same global service headlessly the first time it's needed, and a second process can't then bind the console to that already-occupied port. Running sf ui first — as in step 3 above — avoids this; it becomes the one running instance everything else talks to.
- Runs — see active and recent runs
- Run detail — spatial stage map; select a stage for transcripts, envelopes, and HITL
- Start a run — rail button or
#/newwith pipeline and task pre-filled - Workshop —
#/workshopdrafts a pipeline in chat and saves it intoworkshop/<pipeline-id>/. See Workshop Author.
If a stage calls ask_operator, the run pauses until you reply in the console. See Human-in-the-loop.
CLI smoke vs MCP smoke
CLI smoke path
sf init(or author the three files above)sf providers list/sf providers login …sf validate --strictsf run --pipeline pipelines/hello.pipeline.yaml --task tasks/hello.task.yaml
MCP smoke path
- Start a Host:
sf uiorsf mcp(defaulthttp://127.0.0.1:3847) - Ensure/register the catalog folder (
POST /api/projectson trusted loopback, or a prior localsf runensure) — or use seededproject_root: "examples" - MCP:
list_pipelines(catalog-relative paths; absolute paths →absolute_path_not_allowed) →start_run→wait_run - Compare homes/providers with
get_health(stageflow_home,boot_providers) and live auth vialist_providers
Details: MCP. Setup skill checklist: skills/stageflow-setup/SKILL.md.
For MCP without the console, use sf mcp — see MCP.
Multi-stage pipelines
Add more stage entries to the pipeline. Use uses: for external stage files or inline system_prompt / model. Declare wiring on the source stage with route:
id: linear
stages:
- id: clarify
uses: ../stages/clarify.yaml
entry: true
route:
- to: design-doc
- id: design-doc
uses: ../stages/design-doc.yaml
Canonical example: tests/fixtures/pipelines/linear-explicit.pipeline.yaml.
Multiple to: entries are unconditional fan-out — every listed target runs. See tests/fixtures/pipelines/parallel-after-clarify.pipeline.yaml and YAML catalog — route. Success vs failure uses on: on the source stage.
Headless / CI
sf validate --strict --json
sf run --pipeline pipelines/hello.pipeline.yaml --task tasks/hello.task.yaml --json
Exit codes: 0 success, 1 failure, 2 waiting on HITL. Details in CI / headless.
See also
- YAML catalog — author dialect
io/verify/on_verify_failandroute/entry/{ type: loop } - hello-world example —
task.input↔ entryio.input.schema - feature-loop example — pipeline
schemas:+$ref - CLI reference — all
sfcommands and selected env vars - Operator console — console navigation and settings
- MCP — Streamable HTTP tools (
sf uiorsf mcp) - Docker and self-hosting — published image, Compose from a checkout, stage sandbox in Compose
- YAML catalog — Stage MCP — attach project
.mcp.jsonservers to a stage - Envelopes — what stages must emit to advance
Older catalogs: upgrading — sf migrate-yaml converts contract keys (io / verify / on_verify_fail); wiring (needs / fork / feedback_loop) is a hard cutover to route (optional STAGEFLOW_LEGACY_YAML=0 after the contract migrate).