Skip to main content
That is the whole command. Everything else on this page is about the cases where you want a little more control - trying a run safely, feeding it data, or working out why one failed.

Start with a dry run

A dry run is not a simulation. It loads and validates the workflow, resolves every input for real (so read tools are called and you see the actual data), renders the prompt, and runs the model. The one thing it does not do is execute write tools - those are stubbed and recorded as stubbed in the run record. This is the right way to try a workflow whose output goes somewhere public. You see exactly what would have been posted, without posting it. The record is marked as a dry run, which matters later: px0 runs list labels it, and px0 runs rerun replays it as a dry run rather than firing the write tools the original deliberately stubbed. To execute for real, run the workflow directly.

Pick from a list

Leave the id off and px0 shows you what you have:
j and k move too, and typing a digit jumps straight to that row. Over a pipe it falls back to a plain numbered prompt.
--stdin requires an explicit workflow id. The picker would otherwise read its keystrokes from the same stream carrying your input.

Pass data in

Two mechanisms, for two different shapes of input. Named values with --input, repeatable, available to the workflow body as input.<key>:
Piped text with --stdin, which fills any input declared as source: stdin:

Where output goes

A workflow’s output frontmatter decides this, and you can override the target for one run:
Every file output is confined to the store’s output/ directory. An absolute path, or a .. that climbs out of it, is rejected at run time - the path can come from a model-written plan, so this is a boundary px0 enforces rather than trusts. Writes are serialized with a store-wide lock, so two concurrent runs targeting the same path cannot interleave.
A scheduled workflow must write to a file. There is nowhere for stdout to go at 5pm on a Friday when nobody is watching, so px0 rejects that combination at validation time rather than silently dropping the output.

Retries

A workflow’s retry frontmatter block, or the store-wide runs.max_attempts, controls how many times a failed run is attempted before it is recorded as failed for good. --no-retry attempts once regardless - useful while debugging, since a workflow with retry.max_attempts: 3 would otherwise fail three times before telling you anything.

Quiet and JSON output

--json gives you the same record px0 runs show prints, which is the easiest way to script on top of a run.

What a run actually does

Understanding the stages makes failures much easier to read, because px0 names the stage that failed.
1

Load and validate

The workflow file is parsed and cross-checked: every guideline file exists, every tool reference resolves, no write tool sits in inputs, the cron expression parses, the output target is valid.
2

Checkpoint hand edits

Under the store lock, any edits you made in an editor since the last run are recorded as a new version - so the run you are about to do is attributable to a specific version of the file.
3

Resolve inputs

Each input is resolved in order: a tool call, a retrieval query, stdin, or a nested sub-workflow. Results become the template context.
4

Render the prompt

Guideline files are inlined verbatim - at an explicit {{guidelines}} placeholder if the body has one, otherwise prepended - and input values are interpolated into the body.
5

Run the model and its tool calls

The prompt goes to your harness. The model may call anything in tools, turn by turn, and every call is recorded with its timing. Write tools are stubbed here if this is a dry run.
6

Route the output

Printed to stdout or written under output/, per the workflow’s output block and any --output override.
7

Write the run record

Inputs, guideline versions, tool calls, timings, and outcome, saved whether the run succeeded or failed.

When something fails

A failed run is still a recorded run. px0 persists the record first and then reports the failure, so you can always go back and read what happened. A required input failed. The run stops there:
Mark an input optional: true if the workflow should degrade rather than stop. An optional input that fails resolves to nothing, the run continues, and the record marks it as degraded - which is the right call for a nice-to-have context source and the wrong call for the data the workflow is about. An app is not authorized. The failure carries the link you need:
If you started a consent and never finished it, px0 says exactly that instead of minting a second link you would also leave open:
A transient failure. Network blips and Composio 5xx responses are retried with exponential backoff, up to connectors.retries times (default 3), so a momentary outage does not fail a scheduled workflow. The harness did not respond. Every workflow depends on your coding agent CLI, so this fails the whole run. px0 doctor is the fastest way to confirm the harness itself is the problem rather than the workflow. The output path is not allowed. An unknown placeholder or a path that escapes output/ fails the run with the offending value named, rather than writing a file somewhere surprising:
The workflow file does not parse. The file is skipped rather than crashing every other command, and it is named - with its line - by px0 workflows list and the workflows check in px0 doctor.

Exit codes

Useful when a workflow runs inside a script or a CI job: A run that fails for any reason exits 1, with the reason on stderr and the full detail in the run record. Codes 2 and 3 come from connector and harness failures raised outside the run’s own control - during a build, or while setting up a connection - so a script can tell “your Slack consent lapsed” apart from “this workflow is wrong”. A store-integrity problem, such as a corrupt version manifest, is what px0 doctor and px0 store verify catch separately.

Timeouts

timeout in the frontmatter caps the wall clock for a run and defaults to 120s. It accepts ms, s, m, and h suffixes. Raise it for workflows that fan out across many tool calls; a long-running scheduled job is better slow than truncated.

After the run

timeout is the only bound on a run otherwise; px0 runs cancel sends SIGTERM so the run can finalize its record as failed, or --force for SIGKILL when it is not responding. See Browse runs for the interactive view and what each field of a record means.