Skip to main content
px0 has a small vocabulary, and everything in the CLI is named after it. Commands read as entity then verb: px0 workflows new, px0 brain search, px0 guidelines edit. Once you know the nouns, you can guess most of the commands.

The store

Everything px0 knows lives in one directory, ~/.px0 by default. Set PX0_HOME to put it somewhere else - a synced folder, an encrypted volume, a second machine. The first three are ordinary Markdown you can open, edit, move, and grep. There is no database you have to go through and no compile step - edit a workflow by hand and the next run picks it up.
.state/ is the one folder not meant for hand-editing. It holds the retrieval index, the version manifest, credentials.toml (kept at mode 0600), and the daemon’s schedule state. Everything in it is either derived from your files or rebuildable.
px0 keeps its own history rather than relying on git, so a store works as a bare directory with nothing else installed alongside it. See The store.

Workflows

A workflow is one recurring job, stored as a Markdown file: YAML frontmatter as the machine contract, the body as the prompt the model receives.
You do not write that file by hand the first time. px0 workflows new interviews you about the job and generates it, then you edit whatever you like. The full field reference is in Workflow files. Two details are worth internalizing early, because they explain most of px0’s behaviour:
  • Inputs run before the prompt. Everything in inputs is resolved first and interpolated into the body, so the model starts with the context already gathered. Inputs must be read-only, since they run unconditionally.
  • Tools are called during the run. Everything in tools is what the model may call while working - which is where posting, sending, and commenting happen.

Tools and connections

A tool is how a workflow reaches outside px0. Most tools route through Composio, and there are four kinds:
  • Curated (slack.post_message, github.get_pr) - ten hand-written tools with stable argument names.
  • Discovered (composio:SLACK_SEND_MESSAGE) - anything px0 workflows new found by searching Composio’s catalogue, which is thousands of tools across more than 1,300 toolkits.
  • Local (file.read, shell.run, brain.add) - reaches this machine directly, never through Composio.
  • User-declared - a tool you describe yourself in a TOML file under the store’s tools/ folder, wrapping a script or command you already have.
They all execute the same way. The composio: prefix only tells you where a discovered tool came from. Every tool declares its access, taken from Composio’s own metadata rather than guessed from its name: px0 surfaces write tools everywhere it can: the builder calls them out before generating a workflow, --dry-run stubs them instead of executing them, and px0 runs marks any run that used one. See Tools. You set one Composio API key, and after that apps authorize themselves - the first time a workflow needs Gmail, px0 prepares Gmail’s authorization and hands you the URL to approve. px0 tools connect <app> does the same thing deliberately, ahead of time. See Connections.

Guidelines

Guidelines are prescriptive prose about how you work: how commit messages are written, what a Go review checks, how a summary should sound. They exist because a model’s default voice is not yours, and telling it again in every workflow does not scale. A workflow names the guideline files it needs, and those files are inlined verbatim into the prompt at run time. This is deliberate and deterministic - guidelines are never retrieved by similarity the way brain material is, because a convention you rely on should not depend on a search hit. You do not write one from scratch. There is no px0 guidelines new - the only way a guideline gets created is that px0 workflows new notices a workflow leans on a convention no file covers, drafts a defensible first version from the workflow itself, shows it to you, and lists it on the workflow so every run inlines it. px0 guidelines edit <name> is how a draft becomes yours. See Guidelines.

The brain

brain/ is the library of what you have read and kept: papers, blog posts, internal docs, video transcripts. Unlike workflows and guidelines it is not versioned, because it is bulk reference material and rebuildable from its source URL. It can be px0’s own folder or any folder of Markdown you already keep - including an Obsidian vault. Two things use it. px0 brain ask answers questions across the whole library, and a workflow can declare a retrieve: input to pull relevant passages into its prompt. See The brain.
Anything filed under brain/work/ is excluded from every retrieval px0 performs - search, ask, and workflow inputs alike. That is a hard exclusion, not a ranking penalty, so work material never leaks into a prompt that leaves your machine.

Runs

Every execution leaves a record: the inputs it resolved, the guideline versions it inlined, every tool call with its timing, and the outcome. Manual runs, scheduled fires, and px0 brain ask all produce one. That record is what makes px0 auditable. px0 runs why <run-id> walks the full chain behind an output - which guideline versions were inlined, which passages were retrieved, which tools were called - and it works offline, on a bare store, with nothing else installed. See Browse runs. Records are stamped with the store that produced them. Since logs.path defaults to one directory shared by every store on the machine, that stamp is what makes PX0_HOME genuinely isolate history rather than showing you another store’s runs.
A scheduled workflow writes to a file, never to stdout - nothing is watching a terminal when it fires. That is why the example above uses output: {target: file, ...}; px0 rejects the stdout combination at validation time.

The model backend

px0 has no model of its own and no direct-API backend. It shells out to a coding agent CLI in non-interactive mode - claude -p by default - and reuses that CLI’s login, model choice, and rate limits. This is a deliberate trade. You do not hand px0 a provider key, you do not manage a second billing relationship, and px0 stays useful with whichever agent CLI you already sign into. The cost is that a workflow can only be as capable as the harness behind it, and a broken harness login breaks every workflow - which is why px0 doctor invokes it for real rather than just checking that the binary exists. It also means prompts leave your machine through that CLI. What leaves your machine is the full accounting of where data goes.

The daemon

A workflow with a schedule does not fire on its own; something has to watch the clock. px0d is that something, and it is deliberately dumb: it polls workflows/, evaluates cron expressions in machine local time, spawns anything due, polls any trigger.watch whose interval has elapsed, and runs one housekeeping pass a day (checkpointing hand edits, reindexing the brain, draining queued ingests, applying log retention, checking weekly for updates). A workflow does not have to watch the clock at all - trigger.watch polls a read-only tool instead and fires when an item it has not seen before appears, which is how a laptop without a public endpoint still reacts to something happening rather than only to the time of day. Nothing about the daemon is required. Without it, trigger.schedule and trigger.watch are documentation and every run is one you started. See Schedules and the daemon.

History and provenance

Workflows, guidelines, and config are versioned by px0 itself. A change is one atomic write across the store - a workflow build, a guideline the build wrote, a hand edit px0 noticed - and px0 changes list|show|revert is the store-wide log of every one, newest first, undoing a whole change at once. Every file also carries its own version chain underneath, which is what a guideline’s claim history reads from: a section is addressed as <path>#<heading-slug>, and px0 guidelines log <claim-id> walks when it changed and what changed it. Hand edits are not invisible to this. The daemon’s nightly pass checkpoints anything you changed in an editor, so your own edits show up in the same history as px0’s, recorded under the user:manual actor. See History.