bob status
bob status — one engine, one contract over the health readers
Section titled “bob status — one engine, one contract over the health readers”Six engines answered “is it healthy” with four contracts: bob doctor
(bob-host-drift/1), bob ready --dry-run (project-ready/1), the readiness
probe, the fleet snapshot (bob-fleet-snapshot/1), audit.js view and bob dash status,
plus rebob --report. bob status composes them behind one bob-status/1
document and one renderer (#2080). It grades nothing itself: each section embeds
the composed engine’s document unchanged, so a consumer of a v1 contract
reads the same bytes inside the section.
bob status [--json] [--live]bob status --scope host [--json] [--project <dir>] [--section <a,b>] [--in-flight-base <ref>]bob status --scope project [--json] [project-dir] [--dry-run] [--name <n>] [--reconcile-preview]bob status --scope fleet [--json] [--no-live] [--projects-only | --global-only | --matrix | --ports | --check <project>]Exit 0 ok · 1 drift (host drift, NOT READY, a never-published or stale fleet
machine) · 2 error or usage error. Engine:
scripts/status/status.js.
bob status never mutates. The project scope always grades as a dry run;
--dry-run is accepted so the spelling matches bob ready --dry-run. To
converge a project, run bob ready; to converge the machine, run
scripts/deploy.sh.
The front door (no arguments, #2641)
Section titled “The front door (no arguments, #2641)”bob status with no --scope answers “is everything OK, and if not, what do I
run?” on one screen:
bob status — farm-01 (cached; --live to re-grade) host OK project bigbrain NOT READY (2) — graded 6h ago fleet 1 stale (of 3)
running here: warp-drive run bigbrain: coding on #2641 dashboard bigbrain http://farm-01.example.ts.net:6952/warp fleet view http://farm-01.example.ts.net:6952/bob
next: bob ready| Line | Where it comes from |
|---|---|
host |
the live bob doctor probe (host-drift.js probe()), which reads only local files, git and ps |
project |
the project the working directory is in (its git root, with a .claude/): its last recorded bob ready verdict in .claude/.project-ready.json, with its age. --live runs bob ready --dry-run instead. Outside a project the line reads project — not in a project |
fleet |
the cached fleet snapshots, as --scope fleet --no-live reads them. --live pulls each machine |
running here: |
what runs on this machine now: the warp-drive run (phase, issue) in this project and in any project a dashboard serves; each dashboard server with its viz URL; and the fleet view. The URLs come from the one resolver in dashboard-servers.js (list() + preferredUrl(), #2639): a live serve route, else MagicDNS, else the tailnet IP, else localhost. The block is left out when nothing runs |
Without --live it makes no network call: no gh, no ssh, no pull. The only
calls leave nothing on the machine: tailscale status and the host probe’s loopback
freshness check of this machine’s own dashboards. It
finishes in a few seconds. The exit code is the worst of the graded lines under the
contract above. A running warp run and a project with no recorded verdict are listed
but never move it.
It ends with exactly one next: line. The command comes from one declared table,
NEXT in status.js; the first finding present, in
this order, wins:
| Finding | next: |
|---|---|
| the host probe could not run | bob doctor |
| host drift | the host engine’s own Fix: command, e.g. scripts/deploy.sh |
| the project is NOT READY | bob ready — the one convergence command, never its individual steps |
| a warp run is going here | bob warp status |
| a fleet machine is stale or never reported | bob status --scope fleet |
| the project has no recorded verdict here | bob ready --dry-run --record |
| none of these | nothing — all green |
--json emits bob-status/1 with scope: "all" and the host, project and
fleet sections, each embedding its engine’s document as the scoped forms do
(the project section embeds the recorded verdict). Each section also carries its
line and finding, and the document carries running (warp[], dashboards[] with each url and its
full urls set, fleet_url) and
next: {finding, command, why}.
Scopes
Section titled “Scopes”| Scope | Section | Engine | Embedded document | Graded |
|---|---|---|---|---|
host |
host |
scripts/checks/host-drift.js probe() |
bob-host-drift/1 |
yes |
project |
project |
scripts/ready/ready.js ready({dryRun: true}) |
project-ready/1 |
yes |
project |
readiness |
scripts/fleet/readiness.js projectReadiness() |
the readiness record the fleet snapshot carries | no |
project |
rituals |
scripts/rituals/ritual.js due() for the manifest whose _meta.path holds the project |
bob-rituals-due/1 |
no |
project |
backups |
scripts/backup/freshness.js over bob backup status --json |
the backup freshness record (null when none is declared) |
yes, when a backup is declared |
project |
reconcile_preview |
scripts/rebob/index.js --report --json (only with --reconcile-preview) |
rebob’s {summary, findings} report |
no |
fleet |
snapshot |
scripts/fleet/audit.js buildSnapshot() (skipped with --no-live) |
bob-fleet-snapshot/1 for this machine |
no |
fleet |
fleet |
scripts/fleet/audit.js aggregate() |
the audit.js view --json rows |
yes |
fleet |
rituals |
scripts/fleet/audit.js rollupFleetRituals() over those rows (absent when no machine reports rituals) |
the fleet ritual roll-up | no |
A graded section decides the scope’s verdict: the worst of them, error >
drift > ok. An informational section carries its own verdict — drift when
a readiness stage is broken or the rebob preview has findings — but never moves
the scope’s, so the exit code stays the v1 command’s.
Rituals (#2232). Both the project and the fleet scope carry the overdue
ritual count at the top of the document as rituals_overdue: the project’s
summary.overdue from ritual.js due,
or the fleet roll-up’s overdue. It is null when nothing measured it (the host
scope, an unmanaged project, a fleet whose snapshots predate #2232). The
rituals section is drift when anything is overdue, but it is informational:
an overdue ritual is something to schedule, not a health failure, so it never
changes the verdict or the exit code. An unmanaged project is a rituals
section with verdict: "error" and the engine’s message. The fleet roll-up
counts a project checked out on several machines once, taking the machine
that could read most of its run history: {projects, overdue, due, upcoming, unknown, overdue_projects: [{name, machine, keys}]}.
Backups (#3086). A project whose dev.json declares
environments.<env>.backup gets a graded backups section: ok when the
newest backup is fresh against its schedule, drift when it is stale (a missed
run, or no backup yet), error when the bucket could not be read — an
unknown backup is never ok. A project that declares no backup gets an
ungraded backups line (backups: none declared). The record and its fields
are the one the fleet snapshot carries, described in
Dev lifecycle.
It reads the bucket through wrangler. The other network reads of the project
scope are the forge reads of the project’s next step.
The fleet scope builds this machine’s snapshot once and hands it to
aggregate(), so the snapshot section and this machine’s fleet row describe
the same document. A cdb view flag (--projects-only, --global-only,
--matrix, --ports, --check <project>) renders that bob dash status view unchanged;
it is human output only, and --json with one is a usage error.
The project’s next step (#3921)
Section titled “The project’s next step (#3921)”The project scope ends with one next step for the project, as next in the
document and a next: line in the human rendering. The rules are applied worst
first, and the first one that applies wins:
| Finding | When | next.command |
|---|---|---|
warp-run |
A warp-drive run is going in the checkout (its state file’s phase is not completed). |
bob warp status |
blocking-ask |
An open ask (a todo without completed, or an open brief) holds up work: what it unblocks is an item of a running plan, a ready plan or an approved issue (#3915). The most-blocking one is named. |
gh issue view <N> --repo <owner/repo> |
project-not-ready |
The project section’s ready dry run says NOT READY. |
bob ready |
plan-runnable |
An open flight plan has a runnable item (flightplan.js remaining <N> --json) and no run is going. The newest such plan is named, of the first five open plans. |
bob warp start --flightplan <N> |
approved-unplanned |
Approved issues exist and no flight plan is open. | bob plan build |
vision-draft |
docs/vision.md still carries the vision-draft marker bob ready --vision wrote (#4033) — the project’s vision is the operator’s few sentences, and /vision removes the marker once it has worked the sections through. Last, so it never outranks real work. |
/vision |
When nothing applies, next is null and the line reads
next: nothing to do here right now. An open plan with nothing runnable is
nothing to do: bob plan build is suggested only when no plan is open.
next is {finding, command, why}. A blocking-ask also carries
ask: {ref, repo, number, title, url}, from which
BoB Control draws the ask’s Do it.
The step is informational: it never moves the verdict or the exit code.
What it reads. A run going wins before anything else is read. Otherwise the
project’s open asks (todo and brief), its open flight plans and its approved
issues are read with three gh issue list calls in the checkout, and the flight-plan
engine is asked what is runnable. A read that fails is named in next_unread
([{part, reason}], parts asks, plans, approved or plan #<N>) and its
rules are skipped. A forge that could not be read is never a suggestion, and
it is never reported as nothing to do without saying so.
The rules live in scripts/status/project-next.js.
$BOB_STATUS_FLIGHTPLAN names the flight-plan engine (default
scripts/warp-drive/flightplan.js). gh is the one on PATH.
The document
Section titled “The document”{ "schema": "bob-status/1", "scope": "host", "machine": "farm-01", "generated_at": "2026-09-12T21:00:00.000Z", "verdict": "drift", "ok": false, "rituals_overdue": null, "sections": [ { "name": "host", "engine": "scripts/checks/host-drift.js", "schema": "bob-host-drift/1", "graded": true, "verdict": "drift", "document": { "schema": "bob-host-drift/1", "…": "the engine's own document" } } ]}schema on a section names the embedded contract, or null when the engine’s
document is unversioned (readiness, the audit view rows, rebob). A section whose
engine could not answer has verdict: "error", document: null and an error
string.
The human rendering is one table — section, verdict (* marks informational),
schema, engine — followed by each engine’s own human rendering under its section
name, and the scope verdict last.
Relation to the v1 commands
Section titled “Relation to the v1 commands”| v1 command | bob status spelling |
What is equal |
|---|---|---|
bob doctor [--project D] [--section S] |
bob status --scope host [--project D] [--section S] |
the host section’s document and the exit code |
bob ready D --dry-run |
bob status --scope project D --dry-run |
the project section’s document and the exit code |
bob dash status --ports (and the other view flags) |
bob status --scope fleet --ports |
the rendered view and the exit code |
rebob D --report --json |
bob status --scope project D --reconcile-preview |
the reconcile_preview section’s document |
The v1 commands keep emitting their v1 documents for existing consumers —
make check-host, make ready, the warp-drive preflight
(host-preflight.js) and the fleet
snapshot read them directly and are unchanged. A /2 bump of any embedded
contract is out of scope.
tests/test-bob-status.js proves each row of
the table above under a throwaway BOB_HOME / BOB_SOURCE: the section
document equals the v1 command’s output (minus generated_at) and the exit
codes match, through the bin/bob router. It also proves the fleet scope
against audit.js view --no-live --json and asserts bin/cdb stays a router.
$BOB_STATUS_REBOB names the rebob entrypoint (default
scripts/rebob/index.js) so the test can stub the preview, as
$BOB_READY_TOOLS does for bob ready. Section 5b drives the project’s next step through
every rule with gh and the flight-plan engine stubbed, and through a forge that
is down.
Related: bob ready · bob CLI reference · Verification System.