Stado CLI reference

This is the complete public command tree from the Stado dispatcher. Every command group and leaf has its own canonical page with the exact invocation, inputs, options, effects, and refusal boundary.

Stado accepts --help at every level. Parser or usage errors exit with code 2; runtime failures use the classified Stado failure contract documented below each command.

Command tree

  • stado onboarding Show the CLI first-use walkthrough or import an existing registry-v2 file
  • stado capabilities List Stado capability families, variants, providers and active selections
  • stado overview One operator snapshot: jobs, active workers, quota, budgets, burn and credits
  • stado blast-radius Inventory a dependency's live resources, auth, consumers, storage, and DR coverage
  • stado resources Inventory, plan, execute, verify, and restore resource operations
  • stado optimize Inspect and control autonomous placement and resource reconciliation
  • stado billing Inspect or refresh cross-cloud costs, grants, burn, and credit balances
    • stado billing show Read the last billing snapshot published by the coordinator
    • stado billing refresh Query billing providers now and publish a fresh snapshot
    • stado billing watch Foreground billing watchdog: poll, evaluate credit balance AND account health, and alert on transitions. Deliberately runnable outside the cloud it monitors (see `cli/billing.rs` module docs)
  • stado azure Authenticate an Azure operator and repair the Stado RBAC contract
  • stado cloudflare Configure Cloudflare Tunnel ingress and DNS through Stado-held credentials
  • stado mail Search and deterministically analyze Gmail messages without modifying them
  • stado disk-cleanup Run registry-authorized cleanup for this local target
  • stado install-disk-cleanup Install the registry-controlled cleanup watch on this Mac
  • stado workdirs Preview every directory directly under ~/.stado/work, including job and run areas. --apply removes them all, even when active
  • stado machine Stable JSON machine interface
  • stado submit Submit a job (or batch) to the queue
  • stado status Show job status
  • stado results Download job results
  • stado cancel Cancel a queued or running job
  • stado job Rerun or watch one job
  • stado agent Run local worker agent using live CPU, RAM, disk, and accelerator state
  • stado coordinator Run the provider-neutral scheduling tick locally. Reads cadence and identity from the named coordinator entry. Queue, registry, capacity, and schedule state use the configured Stado storage backend.
  • stado dashboard Run the Stado API listener for the wisent-compute queue. Serves native operator actions and the authenticated object, release, machine, service, host-health and enrollment routes over loopback HTTP. It serves no HTML page; the operator workspace is Stado Desktop. With --enrollment-only the listener serves nothing but the three enrollment routes, which is the only shape safe to publish.
  • stado quota GPU quota inspection and increase requests across WC_PROVIDERS. Default (no subcommand) is equivalent to `quota show` — prints live cloud quota minus reservation minus running per provider.
  • stado profiles List available submit profiles, or show one profile's JSON
  • stado config Inspect or change stado configuration: show | validate | init | migrate | set | unset
  • stado artifact Publish and consume immutable, versioned artifacts
  • stado release Build once, sign, promote, roll out, and roll back product releases
  • stado schedule Manage recurring (cron) jobs — submit a command on a cron schedule. A schedule is evaluated every coordinator tick; when due, the coordinator submits a fresh job with the same routing/sizing and secret-reference contract. Schedules live in configured Stado storage.
  • stado cost Per-job and per-batch cost reporting from observed wall-times
  • stado registry Manage the canonical compute-target registry in configured Stado storage
    • stado registry validate Validate a local registry-v2 JSON document
    • stado registry import Additively adopt an existing registry-v2 JSON document
    • stado registry push Upload local registry.json to the canonical registry object. With --if-generation the write is conditional on the generation the document was read at: a registry that has moved since is refused with exit 75 and, under --json, a `stado.registry-push-receipt.v1` object whose state is "conflict" and which names both generations. Exit 75 means only that, so a reconcile loop can re-pull, re-apply and push again; a storage or validation failure stays exit 1.
    • stado registry pull Print the canonical registry to stdout. Bare, this is the document alone. --with-generation prints one `stado.registry-pull-receipt.v1` object carrying the document and the token `push --if-generation` spends; --generation-only prints just the token. Both come from a single versioned read.
    • stado registry self Print which registry target is this machine
    • stado registry doctor Diff registry declarations against live host state
    • stado registry host Manage hosts in the canonical registry
    • stado registry beacon-age Table of every registry host and its last beacon, worst first
  • stado builds Manage native build recipes: poll a repo, build on new commits
    • stado builds list List every build recipe in the registry
    • stado builds add Add a build recipe. Recipes start disabled; enable one explicitly
    • stado builds edit Change a recipe's source or build definition in place. Every flag is optional and a flag not given leaves its field alone; `--artifact` and `--platform`, when given at all, REPLACE the recorded list. `enabled` is not editable here: `enable` and `disable` own it
    • stado builds remove Remove a build recipe
    • stado builds enable Enable a recipe: the control-plane poller starts building it
    • stado builds disable Disable a recipe without deleting it
    • stado builds run Enqueue one build job per platform for a recipe now, ignoring the poll cadence
    • stado builds status Show one recipe and the state of its per-platform build jobs
  • stado fleet Add machines to the fleet, group them, hold their SSH keys, and diagnose the workers: enroll, join/approve, key, doctor
  • stado identity Which host holds which identity, and whether that is still true
  • stado host Manage operating-system resources on registry hosts
    • stado host health Show the latest Stado health beacon and log tail for TARGET
    • stado host publish-beacon Publish one locally collected beacon through the scoped Stado health API. The `link` block (tailnet path, sleep/wake, interface changes) is collected here, on the host, and merged into the document about this machine before it is published.
    • stado host beacon-units The unit ids the registry declares for THIS host, one per line. What the health beacon must ask about. The collector's list was an operator-typed `WC_HEALTH_UNITS`, so a service the registry declared and the beacon never watched read as a unit that does not exist: `registry doctor` reported `missing-plist` for `com.wisent.compute.service.stado-resolver.service.service` on ubuntu-server-rtx-pro-6000 while that unit was active with a live pid. Prints nothing and succeeds when this machine is not in the registry or the registry cannot be read: a beacon that fails to collect reports nothing at all, which is worse than reporting the operator's own list.
    • stado host collect-beacon Collect THIS host's health beacon from the registry's declarations and the init system's own answers. One unit per identity the registry declares here, with the state launchd or systemd reports for it: `active`, `failed`, `inactive` when every domain answered that nothing is there, and `unreadable` with the cause when a domain refused the read or the read failed. A refused read is never published as `inactive` — the collector that did that published a loaded gateway as not loaded. Prints the document and publishes nothing unless `--publish` is given.
    • stado host reboot Request a graceful reboot of TARGET through its approved channel
    • stado host user Manage local macOS and Linux user accounts
    • stado host gpu-power-limit Persist and immediately reconcile TARGET's NVIDIA board power cap
    • stado host uptime Report TARGET's uptime, load averages and logged-in users
    • stado host ping Check TARGET's ssh reachability AND health-beacon age as one verdict
    • stado host gates Report HOST's measured disk space, its published memory refusal and the watermarks behind it, the published admission decision and the source, duration and error of every diagnostic read. Read-only. Each registry, host, storage, capacity and queue read has a ten-second budget. Completed readings survive failures; incomplete reports use claiming=null and never turn missing space into a full disk. A host whose own declaration refuses placement for memory pressure reports `memory_pressure_active` as a blocker with the reading and both watermarks beside it.
    • stado host link Why TARGET went quiet: beacon age, the path and endpoint it published, its last sleep and wake, its interface changes, the silences recorded against it, and what readers refused because of them. Read-only and safe against a live host. control-host was unreachable from 18:29 to 18:35 UTC on 2026-08-19 and came back on a direct path; nothing in this product carried a trace of it.
    • stado host unit-log The tail of one managed unit's own log on TARGET. A crash-looping unit says why in its log and nowhere else: the health beacon reports it failed and carries no log, and `host exec` is a read-only allowlist that cannot read a file.
    • stado host exec Run one approved command on TARGET (allowlist, not a shell). Every entry is read-only except the declared provider sign-in repairs. Retained Tailscale logs are available without changing logging settings, restarting a service, or opening a test network connection. macOS: log show --last 1h --style compact --info --debug --no-pager --process Tailscale --process IPNExtension --process io.tailscale.ipn.macsys.network-extension --process tailscaled Linux: journalctl --unit tailscaled --since -1h --no-pager --output short-iso These commands retain the native timestamps and messages. Empty output does not establish that Funnel works. Missing tools and access refusals remain command failures. Changed arguments or an extra process, path, or time window are refused before the host is contacted.
    • stado host deliver Deliver one local file or directory into a canonical run directory on TARGET. DESTINATION is relative to the registry-approved account's home and must be below `.stado/work/runs/<canonical lowercase UUID>/`. The command refuses a missing, special, or root-symlink SOURCE; an empty or malformed file list; and any destination outside that shape before contacting TARGET. On TARGET it refuses symlinked, foreign-owned, or wrong-kind destination state before rsync transfers a byte. The destination is replaced atomically after the transfer.
    • stado host build Build one declared Cargo binary inside a delivered managed run tree. The command is fixed to `cargo build --locked --release`; only the manifest and binary name vary. The manifest must resolve below the selected account's `$HOME/.stado/work/runs`.
    • stado host run-attached Run one executable from a managed run tree with this process's standard input, output, and error attached. SIGHUP, SIGINT, and SIGTERM received by Stado are forwarded to the remote program. Arguments are ordinary process arguments; sensitive input belongs on stdin and never in `--arg`.
    • stado host remove-run-directory Recursively remove one complete managed run directory. PATH must be one direct child of `$HOME/.stado/work/runs`. Absence is a retry-safe success; symlinks, foreign ownership, the shared root, and nested subdirectories are refused.
    • stado host cron Read TARGET's crontab, and optionally prune one entry from it. The periodic table is the one place a fleet host can declare a process that no launchd domain and no registry document mentions. charless-mac-mini carried four `@reboot` entries outside both, two of which restart duplicates that had just been retired with verified postconditions — so every repair on that host was one reboot from coming back, and the only way to change the table was a bare `crontab -e` over ssh. `--prune` previews by default and refuses anything but a single matching line that references `$HOME/.stado`; `--apply` saves the whole table under `$HOME/.stado/cron-backups` first and prints the `--restore` command that puts it back.
    • stado host render-spis-admission-trust Deliver the checked-in Weles receipt-trust renderer to TARGET and print the public five-field Spis receipt-trust document it builds from TARGET's own live Skarbiec. The admission authority's private half never leaves the host
    • stado host inventory Report TARGET's stado-managed binaries, fixed Cargo-home metadata and bin membership, forward markers and loopback listeners, and whether each marker still matches a live listener
    • stado host config-show Read TARGET's effective Stado configuration through its fleet channel
    • stado host config-set Persist one dotted Stado configuration value on TARGET
    • stado host config-unset Remove one dotted Stado configuration key from TARGET. A declaration that should never have been made is retracted, not overwritten with a null: a key present with a null value and a key that is absent read the same through `jq` and differently through the code that iterates the object.
  • stado bootstrap Provision wisent-compute services persistently across reboots
  • stado vast Vast.ai marketplace host-listing (rent our idle GPU)
    • stado vast list List the configured Vast.ai machine on the marketplace. Requires stado-vast/api_key in Skarbiec and WC_VAST_MACHINE_ID unless the machine can be discovered automatically
    • stado vast unlist Remove every offer for our Vast.ai machine, blocking new renters. Existing rentals are not terminated. Requires stado-vast/api_key in Skarbiec and a resolvable machine id
    • stado vast status Show Vast.ai's current view of our machine (rentals, listed)
    • stado vast monitor One-shot snapshot of the Vast bridge + wisent-compute state
    • stado vast auto-list Daemon: list on Vast.ai when wisent-compute is idle, unlist when work appears
  • stado instances Inspect and reap live agent VMs across the configured cloud providers
    • stado instances list List every live agent VM across the configured providers, flagging the ones no queue job or lease still references
  • stado recovery Transactional outage recovery: fence, migrate, verify, and cut over
  • stado storage Move queue state between storage backends (billing-outage migration)
    • stado storage copy Copy queue state from one storage backend to another
    • stado storage backup Copy the active queue store to the configured disaster-recovery store
    • stado storage ls List objects under a prefix, or per-prefix counts across the whole canonical prefix set when no prefix is given
    • stado storage stat Report one object: present, absent, or unreachable
    • stado storage cat Write one object's body to stdout
    • stado storage verify Compare two stores object-for-object. Read-only; copies nothing
    • stado storage archive Package one directory as a deterministic gzip-compressed release archive
    • stado storage put Upload a product object through the provider-neutral Stado namespace. Release objects are always create-only, even without --if-absent
    • stado storage get Download a product object through the provider-neutral Stado namespace
    • stado storage objects List product objects in one provider-neutral Stado namespace
    • stado storage abort-upload Discard the staged parts of one interrupted multipart upload. `put` stages a large body as `<key>.__stado_upload/<upload-id>/<index>` parts and composition promotes them in one step, deleting the parts as it goes. A publisher that dies between the last part and composition leaves the parts and no object: on 2026-09-04 the `stado` 0.15.25 darwin-arm64 archive sat as 19 unfinalised parts, 57 MiB of a coordinate nothing could read, and nothing in the product could remove them - `rm` refuses the whole `releases` namespace as immutable, which is true of published objects and false of staged parts. The object API already authorizes a part's DELETE against its TARGET's publisher, so the boundary for this was in place and only the command was missing.
    • stado storage rm Delete a product object through the provider-neutral Stado namespace. Release objects are immutable and cannot be deleted
    • stado storage url Print the gateway URL; only stado://releases/... is bearer-free
  • stado credentials Read, migrate, and manage application credentials in the selected store
    • stado credentials put Store an item in the selected credential store, reading from STDIN
    • stado credentials get Print one credential item value or one exact string field to stdout
    • stado credentials ls List metadata for items visible to the credential-store admin
    • stado credentials rm Delete one item from the selected credential store
    • stado credentials migrate Move every credential to a new backend and commit the selector
    • stado credentials mint-acquisition-token Mint one request-only bootstrap token directly into an owner-only file
    • stado credentials doctor Report whether any key on this machine can still open the vault, and which key files a restore needs when none can
    • stado credentials vault Report which vault this machine's credential operations resolve to, and why. Every write and every authoritative read here goes through one file, and until this command existed nothing said which — the answer lived in a discovery rule and one environment variable, and it surfaced only as a refusal from whatever command hit it. On 2026-09-05 that was `stado repair stado --step release-verifier`, after two vaults on this machine had been claiming one owner for long enough to close the fleet's release publication boundary. Exits non-zero when nothing resolves, so a script can gate on it.
    • stado credentials inspect-vault List nonsecret item metadata from one owner-controlled vault file. With `--host` the vault is the one THAT host holds, read through the registry's own channel with the same read-only `skarbiec list` the fleet's vault inventory already uses. A remote host's vault is a separate store from this machine's — its capability routes, its capability state and its items are all its own — and nothing else in the product could answer "does that host hold this item" without copying an encrypted vault around. Names, kinds, states and tags only, never a field value.
    • stado credentials bootstrap-weles Recreate Weles internal authorities in the canonical owner vault from surviving owner credentials
    • stado credentials adopt-weles-vault Merge the retired Weles-dedicated vault into the canonical owner vault. Copies only the ids the canonical vault does not already hold, reports one outcome per item, reads the side vault and never writes to it, and prints item names, field-level reasons and counts — never a value.
    • stado credentials harvest Inventory credentials recoverable from agent transcripts. Reports names and counts, never values
    • stado credentials try-unlock Test unlock phrases found in transcripts against a local or remote vault, reporting which source name worked. Never prints a phrase
    • stado credentials item Credential item operations on the host that owns the vault
    • stado credentials token Credential token operations on the host that owns the vault
    • stado credentials vaults Which Skarbiec vaults the fleet holds
    • stado credentials acquisition-scopes Acquisition-scope operations on a host vault
    • stado credentials grant Consumer grant operations on a host vault
    • stado credentials backup Backup operations associated with credential custody
    • stado credentials seed-freshness Whether login items still hold authenticator seeds their accounts accept
  • stado queue Maintenance mode: pause/resume dispatching, and drain the fleet
  • stado alerts Show which alert channels resolve, and page them on purpose
  • stado service Manage the services registry hosts run: list, status, restart, adopt, retire, deploy, logs, env
    • stado service directory Where a service is reachable from here, and who may use it
      • stado service directory show Print the whole service directory
      • stado service directory profiles The placement profiles the registry declares. A profile is what says a service is SUPPOSED to run somewhere, which is a different fact from the directory's `active_host` and from whether anything is listening. Reading it settles an argument this fleet has already had: `brama-skarbiec` declares units on two hosts, so a Brama missing from one of them is an unstarted unit rather than a service that lives elsewhere.
      • stado service directory bind The serving parameters for the host this service is placed on. The other side of `connect`: a caller asks how to reach the service, and the placed host asks how it should serve. Both answers come from the same placement and the same host records, so moving a service needs no edit on either side. Refused on a host the service is not placed on, because a gateway that binds where nothing placed it is the thing every caller then has to be protected from.
      • stado service directory connect A usable route to one service, derived from where it is placed. `endpoint` reports what the directory was told; this works out what is true. The service is placed on exactly one host, so the address is a function of that placement and of who is asking: loopback when the asker is the placed host, and the placed host's routable address otherwise. Nothing per-caller is stored, so moving the service moves every caller with it. There is no other address. If the service is placed somewhere that does not answer, that is what this says -- resolving to something local instead is how a caller ends up talking to a process nobody placed.
      • stado service directory endpoint The address this machine should use for one service. Resolves against the asking target rather than the active host, because a loopback-bound service has a different address on every client. A target with no entry is reported as exactly that.
      • stado service directory publish Write this machine's forward markers from the directory. Several products resolve a service's address from an owner-only file under `~/.stado/forwards/<service>.local` rather than an environment variable - Skarbiec's credential bridge reads `skarbiec.local`, and `weles-admission.local` the same way. Nothing wrote those files. They were produced by hand, which is why one on this fleet named a port no service has ever bound while the directory held the right answer for the same host all along. The address is per-caller, so this resolves for the asking target and writes only what the directory declares. A service with no endpoint for this machine is reported and skipped, never guessed. Markers the directory does not declare are reported as `fossil` on every run and removed only under `--prune`. Nothing has ever removed one: operator-host carries 11 markers of which the directory declares 3, including three different names for one endpoint and two different ports for one relationship, and a consumer holding an old name resolves it forever.
      • stado service directory consumer-add Declare that a consumer may use a service
      • stado service directory consumer-rm Remove a consumer's declaration
    • stado service catalog The preconfigured Wisent services, ready to deploy by name: no declaration to write, no flags to know. `service deploy <name>` and `service ensure <name>` resolve these when nothing else declares the unit
    • stado service list Every registry-managed service across all hosts, with its state. Answered from the latest health beacons, so it costs no ssh and reports on hosts that are not currently reachable. A host that has published no beacon reports `unknown`, which is deliberately not the same answer as `missing`. `OBSERVED` is a different question from `STATE` and is answered by a different party. `STATE` is what the host says about its own unit; `OBSERVED` is when anybody last went and looked at the service from outside. A host with a closed lid publishes no beacon and says nothing, so `STATE` goes quiet rather than wrong -- and quiet is what read as fine for twelve days. `never` in this column means no machine has ever confirmed this service from any vantage. `--unowned` answers the opposite question: which product processes are running that no launchd job or systemd unit owns. Two `stado agent` processes ran that way for four days, executing a binary older than the one on disk, and every answer in this group was about declared units and so said nothing about them. `--undeclared` answers the third question, which had no answer at all: which units launchd has LOADED that the registry does not declare. Neither of the other two can see one — `list` walks the document and asks the host about each entry, `--unowned` walks the processes and asks launchd who owns them, and a loaded job the document never heard of is in neither set. charless-mac-mini ran three queue agents at once in that blind spot for seven days.
    • stado service bootout Boot one exact launchd label or systemd unit out of its system or user scope. `stop` and `retire` require a registry declaration. This command is for a loaded unit the registry does not declare, including an obsolete duplicate that `service list --undeclared` found. It never removes the unit's file. On Linux the selected systemd manager stops and disables only the exact requested unit, then Stado reads back that it is inactive and not enabled. On Darwin the selected launchd domain is booted out as before.
    • stado service reap
    • stado service watch-spawn Sit on HOST and name the parent of the next process matching a program, while that parent is still alive. `reap` and `list --unowned` each take one snapshot, and a snapshot taken after a respawn can only ever report `ppid 1` — the parent backgrounded the child and exited, which is precisely why nothing could say what kept restarting an undeclared `stado agent` on charless-mac-mini. Driving a snapshot from here in a loop cannot sample faster than an SSH round trip; the loop has to run on the host. Reads `ps` on an interval and prints. It signals nothing, starts nothing and writes nothing, so it is safe to leave running while somebody else works on the box.
    • stado service label-print Ask the host init system what it holds under one named unit. This reader does not enumerate. The operator names the launchd label or systemd unit, so it can inspect a loaded unit whose file is gone. Fixed process, path, restart and trigger fields plus the five explicitly non-secret storage-routing variables are returned; no other service environment is read.
    • stado service verify Go to each consumer and check the endpoint it is told to use, and that the thing answering is the service that was declared. `list` reports what hosts say about their units. This reports whether the directory's addresses answer, from the machines that must call them -- the one question every other check in this binary skips. States are `observed`, `unreachable`, `misowned` for a port a different declared unit is holding, and `unverified` for a probe that could not run; the last is never folded into the others. `misowned` exists because an answer was once the whole of `observed`'s evidence. On the service's active host the port's owner is resolved by launchd label through the same reader `service serving` uses, so a declaration pointing at a port another job holds is a failure here rather than a green row. Other hosts reach the service through their own resolver adapter and are not judged on ownership, because that socket is owned by the resolver by design. Exits non-zero on `unreachable` and `misowned`, counted separately: the first usually means the service needs attention, the second means the declaration does.
    • stado service converge Is the host running the version the registry declares for it? `list` and `show` answer questions about the unit -- loaded, running, which program -- and every one of those answers stays true across a release that never reached the box. This compares `targets[].managed_versions`, the declared version of each managed binary on TARGET, against the version that host actually runs. Verdicts are `in-sync`, `drifted`, and `unknown` for a binary whose installed version could not be read; the third is never folded into either of the other two. Reporting exits non-zero on `drifted` alone, so an uninstalled reporting helper cannot masquerade as drift. `--apply` delivers the declared version of every drifted binary through `stado host release`, re-reads the installed versions afterwards, and exits non-zero unless every binary in scope is confirmed `in-sync`.
    • stado service onboarding-catalog Registry-managed services carrying Echo onboarding product metadata. Emits the versioned JSON envelope accepted by Echo's Stado catalog synchronization endpoint.
    • stado service status One service's state everywhere it is managed
    • stado service refresh-image Put one unit back on the file its `ProgramArguments` name, and prove it landed. The verb behind `registry doctor`'s `stale-unit-image` row. It refuses a unit that is not stale, naming the identity it found, because a command that restarts whatever it is pointed at is a restart button. It re-reads the image afterwards and exits non-zero if the restart did not change it: launchd re-execs the declared path, and on 2026-09-03 pid 49727 respawned under `KeepAlive` straight back onto the same unlinked inode it had just left. One unit per invocation. There is no `--all`: three stale units is three deliberate commands. Local only — which image a process is executing is readable only on the machine holding that process.
    • stado service repair-runner-runtime Restore upstream signed macOS GitHub runner apphosts without restarting
    • stado service restart Restart one managed unit, without a full host-recovery pass
    • stado service update Move an already-managed service onto a new artifact version. `deploy` installs a unit that is not yet managed and refuses to touch one that is. This is the other half: the unit is left exactly as it is, the new version is placed beside the running one and `current` is relinked, so the change takes effect on the next restart and a rollback is a relink rather than a redeploy.
    • stado service release Install and activate one service release, rolling back on failed readiness
    • stado service show What a managed unit actually runs: its program, arguments and unit file. `env` answers what the unit runs *with*; nothing answered what it runs. That gap is why a restart that dropped every argument after the program path looked like a broken service rather than a broken restart.
    • stado service stop Stop one managed unit, including a process the unit no longer owns. `retire` removes a service from management; this only stops it. The difference matters when a restart has previously spawned the program outside its own label: launchctl then disowns it, the stale process keeps the port, and every later restart dies on "address already in use" while the broken instance serves on.
    • stado service secret-sync Synchronize one Skarbiec field into a service's runtime env file. The value is read through the isolated service-verifier grant and carried in the SSH request body. It is never printed or placed in argv.
    • stado service file-sync Synchronize one local file into a managed service's target home. The content travels only inside the approved encrypted channel's request body. It is never printed or placed in an argument vector, and the destination is replaced atomically with owner-only permissions.
    • stado service file-fetch Copy one file OUT of a managed service's target home, byte-exact. The opposite direction of `file-sync`, and the byte-exact counterpart of `env-show`. `env-show` sanitizes every value it reports — printable ASCII, quotes and backslashes replaced, long values clamped — because its job is to let an operator judge a file without a secret crossing the channel. The consequence is that it can diagnose a file and can never reproduce one byte of it, so live operator tooling that exists only on a host could not be put under version control without copying it off by hand, outside the approved channel. The host hashes the file itself, the bytes travel base64 inside the same encrypted channel's response, and the digest is recomputed HERE over the decoded bytes: a payload that lost a chunk decodes into something shorter and perfectly valid, so only two independently computed SHA-256s catch it. A mismatch writes nothing and exits non-zero. `$HOME` confinement and symlink refusal are `env-show`'s, word for word.
    • stado service env-set Replace one key in a managed runtime env file or systemd definition. The value is read from an owner-only local file and travels only inside the approved encrypted channel's request body. A systemd unit or its own .conf drop-in is updated in place; the manager reloads changed definitions without restarting the running service.
    • stado service env-unset Remove one key from a managed env file or systemd definition
    • stado service env-show Read a managed service's owner-controlled env file, duplicates and all. The counterpart of `env-set`: same approved encrypted channel, same `$HOME` confinement, opposite direction. `service env` answers what the UNIT FILE declares; this answers what the file a launcher `.`-sources declares, which on this fleet is where the interesting values live. Every assignment is listed in FILE ORDER with its line number, and a key assigned twice is reported twice — `effective` for the last assignment, `shadowed` for every earlier one — because a sourced file assigns top to bottom and a later duplicate silently wins. A value whose key looks like a credential is withheld, and a URL carrying userinfo is withheld whatever its key is called. An endpoint, a port, a flag or a `$REFERENCE` is shown whatever its key is called: those are what an operator reads this file to verify. The decision is made ON THE HOST, so a withheld value never crosses the channel.
    • stado service endpoint-check Does this unit's env file agree with what is actually listening? The endpoint half of `env-show`: every loopback URL or port the file's effective assignments declare, checked against the host's own socket table, with the process that holds each port named. `host inventory` does this for forward markers; this does it for a unit's environment. Exits non-zero when a loopback endpoint is declared and nothing is listening there, and when the check could not be performed at all.
    • stado service serving Is the DECLARED unit the process on its own port? `show` reports what the unit file declares and used to spell that `runs`; `endpoint-check` reports whether anything answers on a declared port. Neither asks the one question an outage turns on. On 2026-08-30 `com.wisent.always-on.weles` was reported `runs` while both pids its last restart produced were already gone and its stderr ended in `EADDRINUSE 127.0.0.1:58101`: something WAS listening there, and it was a different launchd job — the undeclared unit the Weles release deployer bootstraps, running an identical argument vector. So ownership here is decided by launchd label, never by argv. The pid holding each port is walked up its own parent chain until a pid appears in `launchctl list`, because a launcher script is the job and the server it starts is the child that holds the socket. A label that cannot be read — a system LaunchDaemon is invisible to an unprivileged `launchctl list` — is reported `unknown`, never as "nobody owns it". Verdicts are `serving`, `not_serving`, and `unknown` for a question that could not be answered; the third is never folded into either of the others. Exits non-zero on anything but `serving`, because a control plane that cannot tell reported this host healthy for days.
    • stado service grant-sync Reconcile one Skarbiec consumer grant with an existing owner-only token file. The bearer never leaves the managed host: its local Skarbiec reads the raw file and records only its hash while replacing the declared grant.
    • stado service token-file-sync Write one Skarbiec item field into an owner-only raw bearer file. `WC_STADO_STORAGE_TOKEN_FILE` has to name a file whose entire content is the bearer, because `queue/stado_object.rs` resolves a token file and nothing else. `secret-sync` can put a Skarbiec field into a unit's env file, and `grant-sync` can reconcile a grant against a token file that is already on the host, but nothing could create that file. So the only remaining way to bind a host to the fleet object store was to hand-copy a secret onto it, which is the one thing the fleet-wide "everything through Stado" rule exists to prevent. Lacking the file, charless-mac-mini's queue agent bound its `JobStorage` to a device-local store instead and published no capacity for seven days while 74 fleet jobs waited on a host every surface reported as in-sync -- a fleet claim written to a device store does not fail, it succeeds where nobody else can see it. The value is read through the isolated service-verifier grant and carried in the SSH request body. It is never printed or placed in argv.
    • stado service auth-check Verify a managed service's bearer against a read-only loopback endpoint. With `--repair`, a failed check atomically synchronizes the secret, restarts the unit, and checks the endpoint once more.
    • stado service adopt Bring an existing launchd/systemd unit under management. The unit must already exist on the host — adoption claims what is there, it does not create anything. The host is probed first and the registry records what the host reported, not what was assumed.
    • stado service onboarding Attach central onboarding product metadata to a managed service. The metadata becomes part of the canonical Stado registry and is emitted by `service list --json` for Echo catalog synchronization.
    • stado service retire Remove a service from management: bootout/disable and forget. Unit files are left on disk. Retiring is a management decision, not a deletion.
    • stado service handoff-release-control Hand a placed logical service's lifecycle to its active signed release. The release must already be committed and ready, and the legacy unit must already be inactive. One conditional registry write then removes every legacy restart identity while preserving the logical route, placement dependency, probes, and release policy. Repeating an incomplete handoff rechecks the same release, rollout generation and exact legacy files before committing against the current registry. The prior commit remains in the receipt's recovery history. A completed receipt cannot be reapplied against a mismatching registry.
    • stado service remove Remove a service entirely: withdraw its declaration, stop it, and delete its unit file from the host — the operation an operator means by "remove this service", which `retire` deliberately is not. The file path comes from the registry declaration, never from operator words. A host failure restores the declaration; a file-delete failure leaves the service retired and reports that partial state
    • stado service deploy Install a new unit under management: render, push, bootstrap, record
    • stado service declare Declare a service against the fleet's one contract. Stado ships no list of services: a service is whatever its author declares — an immutable source the bytes come from, a run spec the unit is rendered from, how the service is observed, and who may call it. This command writes that declaration into the service directory; `deploy` then needs no flags beyond the name, because everything it would ask for is already written down.
    • stado service ensure Assert the unit a host must be running, over ssh, idempotently. `deploy` installs a unit and refuses one that is already declared, so there was no command an operator could run twice, or run from a script, to make a host run what it is supposed to run. This one reads what is there first: a unit already running the declared program is reported `already_correct` with nothing touched, a unit that exists but is not running is kicked in place, and a host with no unit gets one. It also works where `deploy` cannot. An ssh login has no Aqua session, `launchctl bootstrap gui/$uid` answers `Could not switch to audit session ... Operation not permitted`, and `deploy` returned that having installed nothing — which is how two `stado agent` processes came to run for four days with no unit behind them. Where the per-login domain does not exist, the unit is rendered for launchd's system domain and installed as a daemon in /Library/LaunchDaemons. An existing matching definition is restarted in place with `kickstart -k`. When launchd's retained Program or ProgramArguments differs from the desired definition, ensure first validates the replacement executable and complete rendered plist, then reloads that definition once and verifies launchd's readback and running executable. An unreadable retained definition is refused without touching the job.
    • stado service logs Tail a managed unit's log over the approved channel
    • stado service env The effective environment a managed unit runs with, secrets redacted. Parsed from the plist or systemd unit and its drop-ins. Values whose variable name looks like a credential are replaced, in the table and in `--json` alike.
  • stado egress Run host-local network egress processes under Stado service management
  • stado product Install, inspect, update, roll back and remove canonical Wisent products
  • stado placement Atomically relocate a declared service group between registered hosts
    • stado placement move Relocate one complete service group to another registered host
    • stado placement evict Stop an instance running where the directory places nothing. `doctor`'s placement row tells the operator to end exactly this, and until now no command could: `service stop` refuses a host that declares no such unit, which is the definition of the squatter it is asked to remove. The port comes from the directory, so an instance can only be evicted from a host the directory does NOT place it on.
  • stado resolver Resolve logical services and run the local Stado data plane
    • stado resolver resolve Resolve one logical service for an authorized workload
    • stado resolver serve Run the local resolution API and configured stable-port adapters
    • stado resolver status Whether this host's resolver is ready, and why not when it is not. A subcommand rather than another endpoint on the resolver's own API, for one reason: the question is asked when the resolver is DOWN. On 2026-08-19 this host's resolver sat in a launchd restart loop holding a dead ssh control socket, and an answer served on `api_bind` would have been unreachable for exactly the window an operator needed it. This reads the registry and the state `serve` publishes to [`state_path`], so it answers with the resolver stopped, and exits non-zero when the answer is not `ready` so a unit or a script can act on it. The live process's own `/health` remains where a workload checks a resolver it is already talking to.
  • stado database Resolve fleet databases: placement endpoint and credential coordinate
    • stado database list List declared databases and whether each is placed
    • stado database resolve Resolve one database for an authorized consumer. Returns the placement endpoint when the service directory places the database, and always the Skarbiec item to acquire the credential from. The consumer must be declared on the database; the credential value is never printed.
    • stado database declare Declare a database in the Stado configuration. Writes `database_api.databases.<name>` through the same validated, atomic write every other configuration change uses. The credential item `<name>-database` is implied; provision its fields with `stado secrets put <name>-database`.
    • stado database remove Remove a database declaration from the Stado configuration
    • stado database grant Grant one or more consumers access to a declared database
    • stado database revoke Revoke one or more consumers' access to a declared database
  • stado web Host a web product on the fleet: build it, run it, publish its hostname
    • stado web declare Declare a web product: where it runs, as whom, and on which hostname. With `--redirect-to` the product is a hostname and a target and nothing else: the edge answers it with a 308 and there is no unit, no release and no host, so `--host`, `--port` and `--consumer` are refused beside it.
    • stado web list List declared web products with their host, port, hostname and unit
    • stado web remove Remove a web product: stop and forget its unit, drop its DNS record
    • stado web deploy Install the published release as a managed unit and deliver its environment, then verify that it answers
    • stado web status Report each product's declared edge, live unit/port state, and observed DNS. A missing or invalid selected Stado edge is reported in edge_error, never accepted as an external edge with unknown addresses. Any non-serving product makes the command exit with status 1.
    • stado web route Publish a declared hostname: edge, then DNS, then wait for the certificate
    • stado web edge The public edge: the fleet host that holds an address and terminates TLS for every `stado`-edge hostname
      • stado web edge provision Create the edge host on Azure and record it as the fleet's edge
      • stado web edge declare Record an edge host that already exists, provisioning nothing. The path for a host Stado did not create: an operator's own VM, a colocated box, or an edge provisioned before this command existed.
      • stado web edge status The declared edge, whether it answers, and what it terminates
      • stado web edge hostnames Reconcile: the hostnames the edge must terminate against the ones its proxy currently does
      • stado web edge remove Undo `provision`: delete the edge's Azure resources and forget it. The one command that reverses the only thing in this capability that spends money. It refuses while any product still names the `stado` edge, because deleting the host those hostnames resolve to is an outage rather than a cleanup — retract them with `stado web remove` first, or pass `--orphan-hostnames` to say that is what you mean.
    • stado web origin Public origins: the hostnames the internet reaches a Stado surface through, and whether anything outside this network can resolve them
      • stado web origin list List every declared public origin
      • stado web origin status Report each declared origin's public resolution, its target's publication, and the origin the live public edge actually selected. Any origin that is not `serving` makes the command exit with status 1, and an origin the edge selected that nothing declares is reported as `origin-undeclared` rather than omitted.
      • stado web origin declare Declare one public origin in the canonical registry. Refused before any write when the hostname has no public A or AAAA record: a name nothing outside this network can resolve is not a public origin, whatever is listening behind it.
      • stado web origin remove Withdraw one declared public origin. The declaration goes; the target's publication is left exactly as it is, because a handler table is shared by every product on that hostname and this command owns only the declaration.
      • stado web origin converge Make the declared target publish every declared path, then read the node's own table and the public name back. Without `--apply` nothing is sent and the receipt is the plan.
    • stado web quality Install the locked dependency tree and run the product's own checks. Runs on a release worker, inside the checkout Stado prepared. The recipe in `.wisent-release.json` names this command; an operator does not run it by hand.
    • stado web build Build the checked-out web product and stage its runnable tarball. Runs on a release worker, inside the checkout Stado prepared.
  • stado dns Own the records of a DNS zone Stado manages at its registrar
    • stado dns list Print every record in one zone, as the registrar holds it
    • stado dns set Add or replace one record, preserving every other record in the zone. The zone is read, the one name and type are replaced, and the whole list is written back. The write is verified by reading the zone again; a record that is not visible afterwards is a failure, not a warning.
    • stado dns remove Remove one record, preserving every other record in the zone
  • stado inference Plan, deploy, route and operate local OpenAI-compatible inference. Being replaced by the service declaration contract: a model server is a service like any other, declared once with `stado service declare` and deployed with `stado service deploy`. This plane keeps working while its declarations migrate; add nothing new to it.
  • stado stream Provision and operate an interactive display session on a host, and stream it to a client (Moonlight): the way to use a fleet GPU interactively, since a board cannot be borrowed over a network
    • stado stream probe Report what a host could render and encode, without changing it
    • stado stream declare Declare that this host carries an interactive session, in the registry
    • stado stream apply Reconcile the host to its declaration: screen, session, Sunshine, units. Retains both native service definitions in the canonical registry, so later service repairs preserve Xorg ordering and Sunshine's session preconditions. Openbox diagnostics are retained by the service journal.
    • stado stream status What the session is doing right now, and where to point the client
    • stado stream pair Hand Moonlight's four-digit PIN to Sunshine (no browser involved)
    • stado stream stop Stop the session. `--purge` also removes the units and the screen
  • stado doctor Ordered deployment preflight: config, storage, provider auth, quota, release channel, agent template, VM identity, registry, queue pause state and alert channels. Exits non-zero if any check FAILs
  • stado workload Place declared work on an eligible fleet host and return its stream or receipt
  • stado repair Inspect and apply the ordered repair steps services declare
  • stado runner Operate declared GitHub runner profiles across registry hosts
    • stado runner list List the runner profiles compiled into this Stado build
    • stado runner install Install or reconcile one declared profile on a registry host
    • stado runner status Read one or every declared profile on a registry host
    • stado runner restart Restart one declared runner in place and wait for a fresh listener event
    • stado runner remove Deregister and remove one declared runner from a registry host
    • stado runner report Read installed profiles, registration scopes, listeners and job slots fleet-wide
    • stado runner credential Resolve the declared GitHub credential route and confront it with GitHub
    • stado runner model-review Mint the repository's Brama model-review bearer and install it as that repository's secret. Registering a runner does not do this: a Brama that refuses the route would otherwise stop a repository from getting a runner at all, for a secret its checks may never read
    • stado runner diagnostics Read what a runner that will not start is saying: its unit's verdict and its own diagnostic log, whole
  • stado space Read and reclaim a host's declared space, including guarded file operations
    • stado space report Read disk, memory, inventory, build caches, and janitor state as one report
    • stado space watermark Read or set the memory watermarks TARGET is measured against. With no write flag this prints the declaration in force. With one it rewrites `targets[].memory_reclaim` through the canonical registry's compare-and-swap, validating the whole document first.
    • stado space policies List the memory policies the fleet declares, and which of them fit a host. The catalog is `stado-rs/data/memory/policies.json`, compiled into this binary. With TARGET it also says which policy that host carries and whether its declaration is one this fleet reviewed.
    • stado space cleaners Read which janitor cleaners TARGET declares, and declare or withdraw one
    • stado space reclaim Reclaim only fleet-declared stages, previewing unless --apply is present
    • stado space file Perform one guarded single-file space operation
    • stado space relocate Relocate object-store keys on the host that holds their bytes
  • stado route Inspect and operate service-directory routing without naming a product
  • stado scratch Lease a disposable target on a registered host, and destroy it when the run ends