CI integration
The CLI is built to slot into CI. It uses deterministic exit codes, it emits machine-readable event streams, and it has no interactive dependencies.
Exit codes
Section titled “Exit codes”| Outcome | Code |
|---|---|
succeeded | 0 |
failed / partial | 1 |
| usage or parse error | 2 |
| internal error | 3 |
cancelled | 130 |
A multi-target run exits with the worst of the runs’ codes. Internal error ranks above failed or partial, which ranks above cancelled, which ranks above success. This gives you one gate for a whole batch.
NDJSON event streams
Section titled “NDJSON event streams”The global --json flag emits machine-readable output. For run it is an
NDJSON event stream. Each line holds one kind-tagged execution event, and a
final summary line caps the stream:
flow run flow.flow --json | jq 'select(.kind=="summary")'These are the same execution events the desktop renders live and that Flow Server streams over SSE. All three surfaces share one event vocabulary.
Format gating
Section titled “Format gating”flow fmt --check exits non-zero when a .flow file is not in canonical
form. Wire it in next to your linters:
flow validate pipeline.flow # parse + static checks; errors as path:line:colflow fmt --check pipeline.flow # canonical-form gateConcurrent multi-target runs
Section titled “Concurrent multi-target runs”flow run smoke.flow integration.flow deploy-check.flow --jsonEvery target runs at once on the shared core, and each one has its own
execution id. Each JSON event carries its executionId, and each summary line
carries its target.
Isolation and unattended runs
Section titled “Isolation and unattended runs”- Set
FLOW_STUDIO_DIRto a temp path to isolate a CI run from any local state. - Headless runners bypass the interactive destructive-action confirmation gate. Review flows before you wire them into unattended pipelines, and prefer pre-apply verification warnings during authoring.
flow generate --autoexits0only on convergence. That makes “can the agent fix the flow” itself a gateable check.- Tracing goes to stderr (
FLOW_LOG/RUST_LOG), so stdout stays clean for results and--jsonstreams.