On this page
Runner as a fleet capability
stado runner installs, reads, restarts, removes, and reports GitHub Actions runners by declared profile. The command vocabulary is independent of runner products: a third runner is another row in stado-rs/data/runner-profiles.json, not another command.
Invocations
stado runner list [--json]stado runner install <TARGET> --profile <PROFILE> [--repository <REPO>] [--json]stado runner status <TARGET> [--profile <PROFILE>] [--json]stado runner restart <TARGET> --profile <PROFILE>stado runner remove <TARGET> --profile <PROFILE> [--repository <REPO>]stado runner report [--json]stado runner credential [--json]stado runner model-review <TARGET> --repository <REPO> [--json]stado runner diagnostics <TARGET> --profile <PROFILE> [--json]
--repository is the GitHub repository name inside wisent-ai. It selects repository registration/removal, which uses the repository administrator permission rather than organization runner administration. Without it, Stado explicitly requests organization registration. An organization refusal is not a verdict about repository registration.
Runner installation no longer configures Brama model review. A repository whose CI needs BRAMA_MODEL_ROUTER_TOKEN uses runner model-review separately; its Brama refusal does not prevent an unrelated documentation or build job from obtaining a runner. Publisher installation still performs its declared App Store Connect, Sparkle and Developer ID setup.
status without --profile reads every declared profile on one target. report performs the same read for every local registry host. JSON status rows carry profile, installed, runner_scope, a typed listener object (connected plus state), and host_job_slot. The registration scope comes from the host's .stado/registered-runner record; it is unrecorded, never an invented organization default, when that record has no scope.
Installation compares the requested scope, group and labels with the host registration record. A changed registration is applied even when .runner already exists. An executing runner job prevents reconfiguration with runner is executing a job; registration was not changed. The previous local registration is retained during reconfiguration and restored if configuration fails. Changing scope does not claim that an old GitHub registration was deleted.
After installation, Stado reads the GitHub runner list at the requested scope, including subsequent pages. The command succeeds only after GitHub reports the named runner online. JSON adds registration.scope, runner, present, status and reconfigured; listener.connected reflects the successful GitHub observation. Absence, an unreadable list or a runner that remains offline is a failure, not a successful install. An unchanged repeat does not re-register the runner.
The Linux installer gives Rust toolchain setup access to .cargo, .rustup and the pre-created .profile file while retaining the service's other filesystem restrictions. Rustup can amend that profile without making the whole runner home writable.
GitHub credential
stado-rs/data/github-identity.json names the Skarbiec route, the required permission, and the exact diagnostic endpoint. Both runner lifecycle operations and runner credential resolve that route through Skarbiec's POST /v1/operator/routes/list, then read the returned item and field. The installation code does not carry a separate hardcoded credential item.
The shipped diagnostic reads the stado repository's runner list and requires repo. Its JSON names the resolved route, item, field, endpoint, granted permissions and HTTP status without printing the token. The route's existing name github:org-runner-admin is an identifier; it does not grant organization privileges. A successful diagnostic applies to the named endpoint, not to every repository or to organization-wide registration.
stado runner credential --json
stado runner install <TARGET> --profile precheck --repository <REPO> --json
stado runner status <TARGET> --profile precheck --json
Skarbiec's route declaration command is skarbiec routes add --resource <RESOURCE> --item <ITEM> --field <FIELD> --reason <TEXT>. A missing route is reported with its declaration source and this command; Stado does not search other credentials or silently substitute an item.
Declaration
The declaration is stado-rs/data/runner-profiles.json, compiled into the binary with include_str!. Each profile declares:
nameand host identityslug- every GitHub Actions
labelit registers github_runner_groupunit_label- an installer kind for
darwin-arm64andlinux-amd64 - the secret names its setup consumes
accepts_repository_scope- for a publisher that issues Developer ID, the declared
developer_id_account_item
The profiles are precheck (stado-precheck), repository-precheck (stado-repo-precheck) and publisher (stado-publisher). Each profile has one registration per host, not one per repository. Selecting another repository for an occupied profile changes its scope; it does not add a parallel registration. The installers retain the host-wide job gate.
Refusals
The capability's declaration and registry refusals are complete sentences:
runner profile '<PROFILE>' is not declared; add it to stado-rs/data/runner-profiles.jsonrunner profile '<PROFILE>' declares no repository scope; enable accepts_repository_scope in stado-rs/data/runner-profiles.jsonrunner profile '<PROFILE>' declares no installer for '<PLATFORM>'; add it to stado-rs/data/runner-profiles.json<TARGET> declares no host target; add it to the canonical fleet registry<TARGET> declares no local host provider; set its kind to a local host capability in the canonical fleet registry or select a local host target<TARGET> declares no reachable host destination; add a registry-managed ssh destination to the canonical fleet registry or run the command on that host<TARGET> declares no supported runner platform for "<PLATFORM>"; set release_platform in the canonical fleet registry to "darwin-arm64" or "linux-amd64"
GitHub authentication failures retain the provider's HTTP response and name the actual Skarbiec route and resolved item/field. Organization failures explain that --repository <NAME> selects a different operation; they do not claim the credential has been tested on that repository.
If registration finishes but cannot be verified, the failure identifies the requested scope and runner name. A runner that does not appear online within 60 seconds is refused with <TARGET>: <RUNNER> did not report online at <SCOPE> within 60 seconds. Use runner diagnostics to read the service verdict and runner log, not another unverified restart.
Replaced host verbs
The following host verbs were removed with no alias or compatibility wrapper:
host precheck-runner installhost precheck-runner statushost precheck-runner removehost precheck-runner restarthost precheck-runner repository-addhost precheck-runner model-review-addhost publisher-runner installhost publisher-runner statushost publisher-runner removehost publisher-runner bootstraphost publisher-runner developer-idhost publisher-runner repository-add
Stado Desktop
The host inspector's GitHub runners section offers all three profiles, read/install/restart/remove operations, Check GitHub credential, and Configure model review for the entered repository. Installation displays the actual GitHub runner, scope, online status and whether registration changed, separately from labels and the host job slot. Account operations display the product's response or refusal. The native client sends these requests through Stado's operator API.
Source: this website