CLI v0 reference
Every verb the soyaos binary exposes in v0, with example output.
The soyaos binary exposes the verbs below in v0. Each verb is stable within v0 — flags may be added, never removed. Exit codes are stable too (see the table at the end).
Global flags
--config <path> Override config file (default: ~/.config/soyaos/config.yaml)
--log-level <level> trace | debug | info | warn | error (default: info)
--json Emit JSON-only on stdout (no progress UI)
--no-color Disable ANSI colors
--profile <name> Switch between named profiles in config (default: "default")
Environment variables override the config file; flags override env vars. SOYAOS_LOG_LEVEL, SOYAOS_CONFIG, SOYAOS_PROFILE are the most commonly used ones.
soyaos version
Print version, commit, build date, and the SoyaPack-v0 schema version.
$ soyaos version
soyaos 0.1.0 (commit 4a9b2c7, built 2026-05-14)
schema: soyapack v0.1.0
runtime: linux/amd64
JSON mode (handy in CI):
$ soyaos --json version
{"version":"0.1.0","commit":"4a9b2c7","built":"2026-05-14T08:11:43Z","schema":"v0.1.0","runtime":"linux/amd64"}
soyaos pack
Create, validate and run SoyaPack bundles locally.
| Subcommand | Purpose |
|---|---|
pack init <name> | Scaffold a new SoyaPack from a built-in template (--template <name>). |
pack validate . | Validate soyapack.yaml against the v0 schema. |
pack lint . | Stricter checks — style, examples coverage, capability narrowing. |
pack push <name> | Publish to the Moon configured in the current profile. |
pack list | List installed / published packs. |
pack rm <name> | Remove a pack locally (cannot remove a pack referenced by a live run). |
Example: scaffold + validate + run:
$ soyaos pack init hello --template echo
✓ wrote hello/soyapack.yaml
✓ wrote hello/prompts/reply.md
✓ wrote hello/examples/hello.json
$ soyaos pack validate hello
✓ apiVersion ok
✓ kind=Agent ok
✓ capabilities.egress empty (declaring `egress: []` makes intent explicit)
✓ inputs schema valid
✓ outputs map valid
✓ prompts.reply: file exists
ok · 0 errors, 0 warnings
pack lint is stricter — it’ll warn on things like missing examples for declared input fields, or capabilities wider than the example coverage justifies:
$ soyaos pack lint hello
warn examples cover 1 of 2 input variants — add a fixture for `topic=null`
warn capabilities.egress lists `api.openai.com` but no example exercises it
2 warnings · use --strict to fail on warnings
soyaos run
soyaos run <pack-dir> --input <json|@file>
Runs a SoyaPack in a local Comet sandbox. Streams Scope events to stdout when --json is set, otherwise renders a compact progress UI.
$ soyaos run hello --input '{"text":"hi"}'
▶ hello @0.1.0 · 1 stage · capabilities: none
reply ████████████ 0.8s
✓ run_018f3a · ok in 0.81s
{ "reply": "hi" }
JSON mode emits a stream of Scope events, one per line, ending in run_completed:
$ soyaos --json run hello --input '{"text":"hi"}'
{"kind":"run_started","run_id":"run_018f3a","pack":"[email protected]","ts":"…"}
{"kind":"stage_started","stage":"reply","ts":"…"}
{"kind":"stage_completed","stage":"reply","artifacts":["reply.v1"],"ts":"…"}
{"kind":"run_completed","ok":true,"ts":"…"}
Useful flags:
--input @path/to/input.json— read input from file.--timeout 30s— kill the run after 30s.--cache-mode <off|read|write|rw>— override the Comet’s cache for this run.
soyaos serve
soyaos serve --role <comet|moon|planet>
Starts a long-lived node in the given role. Multiple --role flags are allowed — --role moon --role comet is the default for the cluster edition. serve is mostly used implicitly via soyaos start --edition <name>; reach for it directly only when you want a non-standard role mix.
$ soyaos serve --role moon --bind 0.0.0.0:8443 --state postgres://…
▶ Moon listening on 0.0.0.0:8443
▶ Registry backend: s3://soya-packs/
▶ Scope broker: ws://0.0.0.0:8444
▶ ready in 312ms
soyaos start
Convenience wrapper around serve that picks the right --role set for the given edition.
soyaos start --edition <solo|cluster|cloud|hybrid|ent-cloud|ent-private>
$ soyaos start --edition solo
▶ solo: planet+moon+comet collapsed into one process
▶ Listening on 127.0.0.1:7474 (set --bind to change)
▶ Web UI: http://127.0.0.1:7474/
ready · paste 127.0.0.1:7474/v1 into any OpenAI-compatible client
soyaos auth
| Subcommand | Purpose |
|---|---|
auth login | Browser-based login to a Moon. |
auth logout | Drop cached credentials for the current Moon. |
auth whoami | Print the currently-authenticated user + Moon. |
auth keys create | Mint a new API key. |
auth keys list | List API keys (truncated; show full with --reveal). |
auth keys revoke <id> | Revoke an API key. |
$ soyaos auth whoami
[email protected] · moon.example.com · role=admin · 2 keys
soyaos join
Join an existing Moon as a Comet:
$ soyaos join --moon https://moon.example.com --token <invite>
▶ Verified Moon identity (planet=planet.soyaos.ai)
▶ Registered as comet cmt-a3f1 · pool=default
▶ Capabilities accepted: egress[api.openai.com:443], fs.read[/workdir], fs.write[/workdir/out]
ready · awaiting work
The invite token is single-use and expires after 15 minutes. You can mint one with auth keys create --kind comet-invite on the Moon.
soyaos pull / soyaos push
Mirror SoyaPacks between Moons (useful when promoting from staging to prod):
$ soyaos pull --moon https://stage.example.com soya:[email protected]
$ soyaos push --moon https://prod.example.com soya:[email protected]
soyaos config
Print and edit the current effective config:
$ soyaos config get default.moon
moon: https://moon.example.com
$ soyaos config set default.moon https://newmoon.example.com
Exit codes
| Code | Meaning |
|---|---|
0 | Success |
1 | Generic error |
2 | Validation error (manifest, input, etc.) |
3 | Sandbox / capability violation |
4 | Auth error |
5 | Upstream / network error |
6 | Timeout |
124 | (Reserved for timeout(1)-style wrappers) |
Exit codes are stable across the v0 series — you can script against them safely.
Common workflows
Test a pack locally then push to staging:
soyaos pack validate .
soyaos pack lint . --strict
soyaos run . --input @examples/hello.json
soyaos pack push hello --moon https://stage.example.com
Roll out a new pack version to prod:
soyaos pull --moon https://stage.example.com soya:[email protected]
soyaos push --moon https://prod.example.com soya:[email protected]
soyaos auth keys list --moon https://prod.example.com # sanity-check existing keys still work
Investigate a failing run:
soyaos run . --input @failed-input.json --log-level debug --json | tee run.log
soyaos --json run . --input @failed-input.json | jq 'select(.kind == "tool_called")'