Operator console
The operator console is a local web UI started by sf ui. Default URL: http://127.0.0.1:3847.
It is the primary surface for triaging runs, connecting providers, answering HITL gates, and inspecting stage transcripts and envelopes. The same process also serves MCP at /mcp.
The run store and catalog browse resolve to the project git root — starting sf ui from a subdirectory still uses <git-root>/.stageflow/ and the repo's stageflow.yaml manifest.
Starting the console
sf ui
sf ui --port 9000
On start, Stageflow prints the console URL and MCP endpoint, then opens your default browser. The process runs until you stop it (Ctrl+C).
Navigation (app rail)
Left rail items (ui/src/components/AppRail.tsx):
| Rail id | Route | Purpose |
|---|---|---|
| Today | #/today |
Triage home — waiting, in flight, broken, finished. Eligible waiting cards can Accept from Today. |
| Runs | #/runs |
All runs, filterable All / Waiting / Running / Failed / Finished |
| Pipelines | #/pipelines |
Browse manifest-declared pipeline files; scaffold a new pipeline or stage into the catalog |
| Tasks | #/tasks |
Browse manifest-declared task files |
| Skills | #/skills |
Browse Pi skills for stages — not the harness skills suite |
| Extensions | #/extensions |
Browse Pi extensions for stages |
| Settings | #/settings |
Appearance, Providers, MCP how-to, Concurrency (session slots), waiting notifications |
Start a run — primary button in the rail → #/new (optional ?pipeline= and ?task= query params with filesystem paths).
Brand click returns to Today.
Waiting runs show a count badge on Today when gates need replies.
Runs and Pipelines list rows stack identity above a full-width mini track so catalog paths stay readable.
Key routes
Hash-based routing (ui/src/routes.ts):
| Path | View |
|---|---|
#/today |
Triage dashboard (waiting / in flight / broken / finished) |
#/runs |
Runs index (All / Waiting / Running / Failed / Finished) |
#/runs/<runId> |
Run detail — spatial stage map; select a node for the workspace |
#/runs/<runId>/stages/<stageId> |
Deep link — select that stage on the map and open its workspace |
#/runs/<runId>/stages/<stageId>/envelope |
Envelope inspector for a stage |
#/runs/<runId>/artifacts?path=… |
Artifact viewer |
#/new |
Start run form |
#/pipelines |
Pipeline catalog (manifest paths) |
#/pipelines/<id> |
Single pipeline detail |
#/tasks |
Task catalog |
#/tasks/<id> |
Single task detail |
#/skills, #/skills/<name> |
Skills browser |
#/extensions |
Extensions index |
#/extensions/packages/<scope>/<source> |
Extension package detail |
#/extensions/files/<path> |
Extension file viewer |
#/settings |
Settings (Appearance, Providers, MCP, Concurrency, waiting notifications) |
#/connect |
Provider connect flow |
Recent runs show stored pipeline_path and task_path locators when present on the run record.
Run detail
The live pane is a zoomable spatial stage map (SpatialRunMap). Selecting a stage opens a gated, resizable workspace for logs, files, envelopes, and HITL. Hide the workspace to return to the map; drag the splitter to resize. Fit run recenters the graph.
A created run shows status not started. The primary action is Start run until history exists; after that it is Start fresh (rerun).
#/runs/<runId>/stages/<stageId> selects that stage on the map and opens the workspace.
Failed stage nodes offer Retry. When a failed completion check has
recovery.mode: manual, the selected stage instead shows its verification history
and offers Retry with guidance or Stop recovery. Running stage nodes offer
Abandon. A stage waiting on HITL uses the workspace reply surface (answer_gate),
not retry.
Use the envelope view to read summary, payload, and artifact paths without parsing logs.
Diamond fan-in {#diamond-fan-in}
A generic fan-in join renders as a diamond: two (or more) incoming wires into the join node. While the join is blocked, blocked_by lists every unresolved parent — not only the first. After one parent reaches an accepted terminal, that parent drops off blocked_by and the remaining wires stay.
Walkthrough: examples/generic-fan-in/. Fixture: diamond-fan-in.pipeline.yaml. Clone-list joins stay one catalog parent with instance nodes — see Clone tracks.
Clone tracks {#clone-tracks}
Fan-out clones appear as distinct spatial nodes labeled definition · N (for example work · 1). Selecting a node uses the instance id (work~1) as the key. A run-once successor stays the catalog id (work).
When the selected stage has an envelope, the first Files row is Handoff envelope — it opens the envelope inspector; meta is the instance id. Artifact rows keep that same instance id. Walkthrough: examples/clonable-fanout/ scenario A, step 6.
Run detail keeps refreshing a run whose overall status is failed while another clone is still waiting_for_input or running after retry.
Answering HITL on a selected clone: HITL.
Capacity indicator
The rail footer can show active run count vs soft max (get_health semantics) — same data as MCP get_health.
Settings
Appearance — theme for this machine.
Providers — connect, disconnect, and inspect Pi model providers (pi_home vs sf_owned). See Providers.
MCP — how to point a client at this console process (/mcp while sf ui is running).
Concurrency — session slots (how many stage sessions may be alive at once). A stage waiting on you still holds its slot.
Held stages — waiting notifications (system notification or off). A held stage is invisible if this window is closed.
MCP co-location
MCP Streamable HTTP is available at <console-origin>/mcp while sf ui runs (sessions by default). For MCP without the console, use sf mcp instead — do not run both against the same project store. See MCP.
Screenshots
docs/img/ holds brand assets (stageflow-og.svg, stageflow-icon.svg).
See also
- Quick start — first console session
- HITL — answering gates from Today or the run workspace
examples/clonable-fanout/— clone walkthroughexamples/generic-fan-in/— diamond join + envelope inspector- Providers — Settings → Providers
- MCP — automation alongside the UI
- CLI reference —
sf ui --port - Harness skills suite — operator harness jobs (not the Skills rail)