doctor exits 0 when everything passes and 4 when any check fails, so it works in a health-check script. Every failing check prints a concrete fix chosen for how it failed - the same check can fail for different reasons, and a missing binary and a version-drifted one need different commands.
--quick skips the slower checks (daemon, harness, index) that need a live subprocess or a filesystem walk. --json gives you the whole report as data.
The checks
Two of those never fail on purpose. A stopped daemon is a choice, not a fault, and being one release behind is not a broken store - reporting them as failures would train you to ignore
doctor output. private_folder is reported even when healthy, because the exclusion is invisible in normal use: a brain pointed at a vault with its own work/ folder can have all of it quietly missing from every search.
Fixing each failure
harness - your model backend did not respond
harness - your model backend did not respond
This is the one to fix first. Every workflow depends on it, and
doctor invokes your coding agent CLI for real rather than just checking that the binary exists.Three different failures hide behind this check, and the fix differs:- Not found. The binary is not on your
PATH. Install it, or pointmodel.harness_cmdat the right command. - Timed out. The backend is slow or hanging. Try invoking it directly to see whether it is px0 or the CLI.
- Exited non-zero. The backend itself refused, and usually that means authentication.
To switch backend or model, with verification before saving:
workflows - a file will not parse
workflows - a file will not parse
<unicode string>.Fix the frontmatter, or move the file out of workflows/ if you are not using it. The rest of your workflows keep working in the meantime: a broken file is skipped, not fatal, and the daemon keeps firing everything else.index - brain files exist but nothing is indexed
index - brain files exist but nothing is indexed
px0 brain ask and px0 brain search have nothing to retrieve from:qmd backend this check reports something different - the qmd version and whether you have consented to the model download:doctor prints the exact install command, and reminds you that dropping back to the built-in backend is a legitimate answer:credentials - file permissions are too open
credentials - file permissions are too open
locks - the store lock is held
locks - the store lock is held
doctor. If nothing is running, the process holding it died without releasing it, and deleting the lock file is safe:schema - store and binary disagree
schema - store and binary disagree
versions - the manifest will not open
versions - the manifest will not open
Rare, and it means the version manifest database is corrupt. Move it aside and re-run
px0 init to rebuild it. Past version content is kept, but the history linking it is lost - so if the store matters, copy the whole .state/versions/ directory somewhere before you do this.unreferenced_guidelines - informational, not a fault
unreferenced_guidelines - informational, not a fault
px0 init scaffolds starter guidelines before any workflow lists them. It is a nudge, not a problem: px0 guidelines list shows what is there, and px0 guidelines rm <name> clears out one you do not want, keeping its history.private_folder - how much retrieval is holding back
private_folder - how much retrieval is holding back
work/ can have all of it quietly missing from every search, ask, and workflow retrieve: input. If that is not what you want, rename or disable the private folder:Other common situations
”no px0 store at ~/.px0”
You have not initialized one, orPX0_HOME points somewhere unexpected:
A Composio call is refused with a 403 on auth_configs
Your API key is read-only. px0 needs write access to auth_configs to prepare an app’s authorization on your behalf. Grant it on the key in Composio. See Connections.
TLS certificate verification fails on a corporate network
px0 detects a TLS-intercepting proxy when you set the Composio key, finds a system CA bundle that trusts it, and records it asconnectors.ca_bundle. If none of the bundles it knows about work, point SSL_CERT_FILE at your corporate root:
A command needs an answer and stdin is exhausted
yes | ran out. Either run it interactively, or pass --yes to accept the defaults.
A scheduled workflow never fired
Work through these in order:px0 daemon status- is the daemon actually alive, and what does it think the next fire is?px0 daemon logs- did the tick happen? Log timestamps are UTC; cron is evaluated in machine local time.px0 runs list --workflow <id> --failed- did it fire and fail rather than never firing?
A workflow’s output is not what it used to be
Open the run inpx0 runs and read two fields: the rendered prompt (the exact text the model received) and guidelines inlined, which names each file with the version used. A guideline that changed between the two runs is the most common explanation.
A run failed on its output path
{date}, {datetime}, and {time} are substituted, in either brace style. A path that resolves outside the store’s output/ directory is rejected the same way. Both checks exist because the path can come from a model-written plan, so fix the output.path in the workflow’s frontmatter.

