orbi setup verifies the local prerequisites and CLI, aligns repository labels, installs user units, and checks the configured checkout.
orbi setup is the one-time, config-driven initialization
entry for a new machine or a new task-pool repository. It verifies or
reinstalls the editable CLI install, verifies the local prerequisites,
aligns the platform labels, installs the systemd user units, checks
the checkout, and reports the optional model proxy — in one command,
with a stable machine-readable result.
--config remains available for a non-default config path. When the default
orbi.toml is absent, setup creates it from the adjacent
.orbi.example.toml when one exists and otherwise from the example
shipped inside the CLI package (Issue #163), and never overwrites an
existing file.
Run it once per machine (and once per new task-pool repository). It is
idempotent: re-running it never creates duplicate labels, units or
timers, and never touches business Issues or business labels.
What it does, in order
Setup is fail-fast: a core prerequisite failure stops the run before any later mutation, with the concrete reason on stderr and a non-zero exit code.- Commands —
git,gh,python3,uvand the installedorbiCLI on the PATH (you install these yourself — setup only checks them; a missing one fails fast with the actionable install guidance, e.g.required command missing: uv (not on PATH) — install uv first: curl -LsSf https://astral.sh/uv/install.sh | sh), and a reachablesystemctl --useruser bus (a container or headless session without a user bus fails with the bus error).ghmust be ≥ 2.94.0 — the queue scans needgh api --paginate --slurpand theblockedByfield, so an older distribution package (Ubuntu 24.04 ships 2.45.0) passes this check but fails every tick; Getting started carries the official install source and the repair. - CLI editable install (Issue #152) — the official local
deployment is the EDITABLE
uv toolinstall (the why — theExecStartPrecheckout sync — is defined in Getting started step 2). The install acts on the deployment home (deploy_home, defaulting torepo_dir— Issue #330): when the running process already imports from the configureddeploy_homethe step verifies it (no uv call,cli=verified); otherwise it runs the exact force editable reinstall (uv tool install --force --reinstall --editable --python <interpreter> <deploy_home>,cli=installed).<interpreter>follows the compatible selection rule (Issue #861):--python python3when the system Python satisfies Orbi’srequires-pythonfloor (>= 3.14— Fedora 43 and current Arch ship it), otherwise--python 3.14so uv provisions or selects a compatible interpreter (Ubuntu 24.04 ships Python 3.12 — an exact-path pin to that system interpreter exits 1 with a dependency resolution failure, while the barepython3/3.14forms let uv select or provision a satisfying one). In the external single-repo mode the CLI is NEVER (re)installed from the delivery checkout —repo_dirmay be a foreign repo X without any orbi packaging input. A failing install fails fast — no unit install, no half-initialized state. The step never touches a running Runner process (the new source is loaded by the next CLI start). - Auth —
gh auth status(logged in with a usable token). - Per target repository (every configured
source_reposentry by default; exactly one with--repo OWNER/REPO):- the repo exists and the viewer has write permission
(
gh repo view→viewerPermissionmust beWRITE,MAINTAINorADMIN). A GitHub App installation token (ghs_) reports an emptyviewerPermissionalthough its issues:write manages labels (Issue #613): setup decides the empty field with a one-shot create+delete label probe (gh api) and reportspermission=INSTALLATION; a user token keeps the plain permission requirement; - the fourteen platform labels (
ai-ready,ai-in-progress,ai-pr-opened,ai-fix-needed,ai-merged,ai-blocked,ai-awaiting-merge,p0,ai-epic,ai-release,ai-content-only,ai-ops-only,ai-human-review,ai-needs-detail) are aligned declaratively from the deployment home’slabels.toml(<deploy_home>/labels.toml, Issue #330) — the single source of truth for label name, color and description: a missing label is created, a drifted label is updated, nothing is deleted, and business labels (bug,enhancement, …) are never touched. In the external single-repo mode the labels come from the orbi checkout, never from the delivery checkout X.
- the repo exists and the viewer has write permission
(
- Systemd units — the deployment home’s templates
(
<deploy_home>/systemd/[email protected],<deploy_home>/systemd/[email protected]; in bootstrap mode the orbi checkout, Issue #330) are installed idempotently into the user unit directory (the same installinstall-unitsperforms: copy, migrate the pre-#149 non-templated units away once,daemon-reload, then enables@1formax_concurrency = 1or@1and@2for2(and disables surplus timers) — the service is never started, stopped or restarted), then each timer instance’s enabled/active state and next trigger time are reported. - Checkout + git transport — check of the configured delivery
checkout
repo_dir(the orbi checkout in bootstrap mode, the user repo X in the external single-repo mode): theoriginremote’s transport (Issue #114, #580), selected bygit_transportin orbi.toml.ssh(default): git data operations (fetch, push — including.github/workflows/*.yml) go over SSH ([email protected]:owner/repo.git), so an existing HTTPSoriginis migrated here with the plaingit remote set-url origin [email protected]:owner/repo.git(setup is the human-authorized migration path — the Runner itself never rewrites a remote).https(the token-only sandbox path): theoriginSTAYS onhttps://github.com/<repo>.gitand the credentials come from theghcredential helper (gh auth login --with-token) — an SSHoriginis migrated to the HTTPS URL here, and no SSH key is required anywhere. In both modes the URL must match the first configured source repo — a remote pointing at a DIFFERENT repo is never migrated (the rewrite would re-target the checkout at another repository) and fails withsetup_failed reason=... origin remote repo mismatch ...— andgit ls-remote <expected-url>must exit 0 (the configured transport reachable and authenticated — a failure issetup_failed reason=... ssh_unreachable ...in ssh mode or... transport_unreachable ...in https mode, no fallback). Then the read-only parts: current branch, clean worktree (a dirty checkout fails: the timer’sExecStartPrefast-forward refuses a dirty worktree, so the Runner could never start), and base freshness (localHEADvs freshly fetchedorigin/<base_branch>— reported, not a failure: the timer fast-forwards a clean checkout at each start). - Optional model proxy — the
local-llm-kv-cacheproxy health endpoint (http://127.0.0.1:18082/health) is checked and reported as optional: its absence or unhealthiness is a warning in the output and never blocks the core GitHub/Orbi setup.
External single-repo mode (deploy_home)
In the external single-repo mode (Issue #330, PR #334) the config separates the two checkouts:deploy_home is the orbi source checkout
and repo_dir is the user repo X. Setup routes accordingly — steps 2
(CLI editable install), 4 (labels.toml) and 5 (unit templates) act on
deploy_home, while step 6 (checkout + git transport) checks
repo_dir: X’s origin must match the configured git_transport for the first configured source
repo, X’s worktree must be clean, and X’s base freshness is reported.
Note that in external mode the timer’s ExecStartPre fast-forward acts
on the deploy home (the orbi checkout), not on X — X is only read from
when the Runner creates task worktrees. deploy_home absent means bootstrap mode: everything acts on
repo_dir exactly as before.
One practical consequence: the installed systemd unit reads its config
from <deploy_home>/orbi.toml (the {{ORBI_REPO_DIR}} placeholder
renders the deploy home path), so in external mode orbi.toml and the
optional .orbi/env live in the orbi checkout — run setup with
--config <deploy_home>/orbi.toml.
Options
Output
The default output is stablekey=value lines (one per concern; values
containing spaces are quoted), so agents and scripts can parse it:
cli=verified means the running CLI already imports orbi
from the deployment checkout (the editable install is in place);
cli=installed means the force editable reinstall ran. labels=12/12
means all twelve platform labels match labels.toml. There is one
timer= line per timer instance and its next is that instance’s next
trigger time (- when it has none). model_provider=NOT CONFIGURED
is a warning: it never changes the setup exit code; the following
model_provider_guide line tells you where to configure it. optional_proxy
is healthy, unhealthy or unavailable and never changes the exit code.
migrated=true means setup rewrote an origin on the opposite transport
to the configured transport’s URL (a re-run then reports migrated=false);
ssh_reachable is the SSH git ls-remote probe result (- in https mode
— no SSH probe runs there) and transport_reachable is the probe result
of the ACTIVE transport (Issue #580).
--json prints the equivalent JSON document:
Success and failure examples
Success (exit code0):
optional_proxy=unhealthy —
but the core setup still succeeds with exit code 0.)
Failures (non-zero exit code, setup_failed reason=... on stderr):
uv), a wrong repo, missing
labels that cannot be created (permission), a dirty checkout, an
an unreachable transport (no fallback) or a missing systemd user bus
all stop the setup with the concrete reason — nothing is
half-initialized without a clear signal.
Idempotency
Re-running setup on an already-initialized machine is a no-op for the external state: labels that already match are not rewritten, the unit templates are re-copied from the repo (drift repair), the configured timers retain their enabled or disabled states, and no Issues or business data are created or modified. The reported hashes and states are stable across runs. The transport migration is one-shot: after the first run theorigin remote matches
the configured git_transport and re-runs only re-verify it
(migrated=false).