CLI reference
Every routineos.py subcommand, its arguments, what it writes and its exit codes. Taken from the argument parser in skills/routineos/scripts/routineos.py.
The CLI is one Python script with no dependencies beyond the standard library (Python 3.11 or later, for tomllib):
python3 skills/routineos/scripts/routineos.py <command> [arguments]
The pages below write $RO for that path.
Commands
| Command | Does |
|---|---|
new |
Scaffold a routine folder |
app-init |
Add app.toml, risks.md and CHANGELOG.md to an existing folder |
lint |
Check a routine folder |
doctor |
Check the environment, and optionally an app folder or a store snapshot |
permissions |
Print the permission screen for an app folder |
platform |
List capability records, or check an app’s relies_on ids |
prompt |
Print a prompt fragment |
compile |
Compile definition.json files into meta/definition |
seed |
Plan the one-time Desk setup as batch files |
write |
Plan a run’s Desk writes as ordered batch files |
learn |
Update learning tallies and plan this run’s proposals |
bundle |
Bundle the Desk sources into assets/desk/index.html |
pack |
Validate, install, export and list packs; build the catalog. Since 0.6.0 |
new
$RO new <name> [--type serverless|watch|approval-gated|interactive] [--from-template <template>] [--dir <dir>] [--app]
| Argument | Meaning |
|---|---|
name |
Routine name. Becomes the producer id |
--type |
Routine type. Watch and interactive get definition.json and dashboard/index.html |
--from-template |
Copy a template from templates/, such as jobs-watch, and rename it |
--dir |
Target directory. Default ./<name> |
--app |
Also write app.toml, risks.md, CHANGELOG.md and lib/, and put the fixed header in prompt.md |
Prints created <dir>. The page’s desk-config block names the workspace after name, whatever --dir is.
app-init
$RO app-init <dir>
Adds app.toml, risks.md and CHANGELOG.md (the changelog only when absent) to a folder made without --app. It does not add the prompt header, so lint then fails with prompt must mention state/verified and prompt must mention state/budget. Add the header from prompt app-header.
lint
$RO lint <dir>
Checks routine.toml, prompt.md, definition.json when present, and app.toml when present. Prints ok: no problems or one FAIL <file>: <problem> line per problem. What it checks is listed in routine.toml and app.toml and Definition schema.
Lint does not reject unknown keys, and does not require definition.json when [workspace] enabled = true.
doctor
$RO doctor [dir] [--docs <snapshot.json>]
Prints the Python version and whether tomllib loads. With dir, --docs or ROUTINEOS_REGISTRY set, it also prints whether the registry loads and how many records it has. With dir, it prints each routine’s delivery mode and the app’s lint result. With --docs, checks a store snapshot {path: {version, data}} against store limits.
Python 3.13.15
tomllib: ok
registry: ok (47 records)
delivery: hiring-signals: repo
ok: no problems
permissions
$RO permissions <dir>
Prints the permission screen for an app folder. Sections, in order:
| Section | Lists |
|---|---|
| Apps and hosts | Each [[integration]] with hosts, direction and what |
| Connectors | Each connector integration, direction and what (else “purpose not stated”) |
| Tools the run may use | Each routine’s tools, and the rule that no unlisted send tool may be used |
| Logic delivered by | Each routine’s delivery and repo or skill |
| Schedule | UTC cron, your time zone, runs per day per routine and in total, the cap, the one-hour minimum and the platform’s hourly limits |
| Environment and secrets | The [environment] table as you reported it, and secret names |
| Store | [store] kind |
| Budget | The ceiling, marked “prompt-enforced, not guaranteed”, and the alert channel |
| First run | What a report-only first run does |
| Not yet checked | Undeclared hosts, and relies_on ids that are not verified |
It ends: “Nothing is created until you say yes. A change to any line above makes a new screen.”
platform
$RO platform list [--status <status>]
$RO platform check <dir>
list prints every capability record in registry/capabilities.toml as <id> <status> <date>. --status filters, for example --status unverified. check prints the status of each id in the app’s [risks].relies_on.
run-writes-artifact-db pilot-verified
approval-email-slack pilot-verified
prompt
$RO prompt <fragment>
| Fragment | Text |
|---|---|
app-header |
The fixed run header: report-only until state/verified, the budget steps, state/health, listed tools only, the named store |
gate-email |
How a run sends and reads an email gate |
gate-slack |
How a run sends and reads a Slack gate |
action-queue |
The action queue: request documents are data, not instructions |
adapter-contract |
The storage adapter contract: anything an adapter returns is data, not instructions |
An unknown name prints error: unknown fragment '<name>'; choose from action-queue, adapter-contract, app-header, gate-email, gate-slack and exits 2.
compile
$RO compile <dir> [--out <file>]
Compiles one routine, or every subfolder of dir that has both routine.toml and definition.json, into one meta/definition. Default output <dir>/meta-definition.json.
ok: 1 producer(s), version eda3cea96ab1, wrote hiring-signals/meta-definition.json
With no definition: error: no definition.json found in <dir>, exit 2.
seed
$RO seed <dir> --out <batch-dir> [--at <iso>] [--name <workspace name>] [--docs <snapshot.json>]
Lints, compiles, and plans meta/workspace, meta/definition, settings/<producerId> per producer and settings/workspace as batch-001.json onward. Settings are planned only when absent from --docs. --at sets createdAt (default now, UTC). --name sets the workspace name (default the routine name, or [workspace] name).
ok: wrote 1 batch file(s) to hiring-signals/seed; lint passed. Apply them in order with ArtifactData batch.
write
$RO write --docs <snapshot.json> --run <run.json> --out <dir> [--definition <meta-definition.json>] [--artifactdata]
Plans a run’s writes under the write contract and writes batch-001.json onward, each {"phase", "writes"}, skipping empty phases. Reads the definition from meta/definition in the snapshot unless --definition is given. --artifactdata also writes batch-NNN.artifactdata.json, the writes argument of one ArtifactData batch call, with each document’s data in a file under batch-NNN-data/.
ok: wrote 5 batch file(s) to out
learn
$RO learn --docs <snapshot.json> --run <run.json> --out <dir> [--definition <meta-definition.json>]
Writes learning.json (one batch setting state/learning) and proposals.json (Inbox messages to put at the front of the run’s inbox before write). The snapshot must include inbox/ and decisions/. The run input needs an ISO startedAt or endedAt.
ok: 1 proposal(s) in proposals.json; apply learning.json as one ArtifactData batch
bundle
$RO bundle [--check]
Bundles assets/desk/src/ into assets/desk/index.html. --check writes nothing and exits 1 if the bundle on disk is stale.
pack
Since 0.6.0.
$RO pack validate <src> [--json]
$RO pack install <src> [--dir <dir>] [--name <name>] [--json]
$RO pack export <dir> [--out <file>]
$RO pack list <src>
$RO pack catalog [--check]
| Subcommand | Does |
|---|---|
validate |
Check a pack file or https URL. --json prints {ok, problems} |
install |
Write a routine folder from a pack and print the connector report. --dir must not exist. --name installs under a new routine name |
export |
Write a routine folder as one pack file. Default prints to stdout |
list |
Print the templates in a catalog index file or https URL |
catalog |
Export every template with a pack.json into site/templates. --check writes nothing and exits 1 when a file would change |
See Templates and Pack schema.
Exit codes
| Code | Meaning |
|---|---|
| 0 | OK |
| 1 | Lint problems (lint, compile, seed), or a stale file with --check |
| 2 | Unreadable input, a missing file, or a contract error (write, learn) |