bob CLI reference
bob CLI reference
Section titled “bob CLI reference”Every bob command on one page. Each command is one row in scripts/bob/commands.json (#2044), and this page is generated from those rows, so it always matches what bin/bob runs and what bob --help prints. The same information is available as JSON from bob help --json (bob-help/1), and the terminal version of any entry is bob <noun> [<verb>] --help. For why BoB has a single bob command and how to add one, see The bob CLI.
Commands for a Claude session. Slash commands and skills are a second set of commands, run inside a Claude session rather than a shell. Slash commands and skills at the end of this page lists the pairs that do the same job and links the full catalogs.
Start here: the everyday commands
Section titled “Start here: the everyday commands”bob with no arguments (or bob help) prints the few commands most sessions need, grouped by the situation that calls for them. bob help --all prints every command on one line each. The list is declared once, as everyday in the routing table.
$ bobbob — the BoB CLI. The everyday commands:
Is everything OK? bob status every scope at a glance, and the one command to run next bob doctor is this machine's BOB_HOME what was deployed? Start work bob ready start or resume a project: converge it to warp-ready bob preflight the warp-drive gate: doctor + ready --dry-run in one verdict bob warp start launch a warp-drive run in tmux, after the preflight gate Watch a run bob warp status the active run's phase, issue, chunk and metrics bob warp viz the live session graph in the browser Whole fleet bob viz every project on every fleet machine, in the browser
bob help --all every command, one line eachbob <noun> --help detail for one command: usage, flags, exit codesA command failed? Search docs/how-to/troubleshooting.md for the message it printed.Quick index
Section titled “Quick index”Daily driver
Section titled “Daily driver”Check this machine, catch up, and find out what needs you.
| Command | What it does |
|---|---|
bob doctor |
Assert this machine’s BOB_HOME is what deploy.sh produced from the commit it records, across every synced surface, every symlink, the toolchain and the settings.json hook wiring; … → |
bob status |
The front door: with no arguments, one line per scope — host, the project you are in, the fleet — from cached verdicts with no network, the warp run going here, and ONE next: … → |
bob asks |
Every open ask of the operator across the portfolio, in one list (#3801, cap #3800): one line per open todo without completed and per open brief in brief:new or brief:acting, … → |
bob brief |
One portfolio briefing as briefing/1 (#2243, cap #2224): Needs you / Done / Doing / Will do across every project since the previous briefing, assembled from source data with links … → |
bob tour |
What is provisioned here but never invoked, from session-ledger evidence: each item with one line on when to reach for it and the command to try, graded unknown / parked / in-use … → |
bob u |
Bob University (BobU) from a shell — a thin router over the disposition record (#2901), applicability and fleet usage (#2900, #2899) and the eval suites (#2390): status counts … → |
bob notify |
Send a Telegram message over the remote-decision bridge from a shell: reads BRIDGE_WORKER_URL/BRIDGE_SECRET from the environment, the project’s .mcp.json, or $BOB_HOME/.mcp.json, … → |
bob viz |
Open bob viz — every project on every fleet machine as small multiples, from the fleet feed (/bob on the dashboard server, same freshness and self-update path as bob warp viz); … → |
bob control |
Open BoB Control (#3813, cap #3812): /control on the dashboard server, one frame whose navigation is Now, Projects, Fleet and Costs (#3914, #4034), then the crumbs of where you … → |
Set up a project
Section titled “Set up a project”Bring a repo under BoB and keep its tooling converged.
| Command | What it does |
|---|---|
bob init |
Initialize a project with BoB tooling: the .claude/ directory, universal symlinks into BOB_HOME, and — when no manifest exists — an offer of one-shot auto-provisioning (bob … → |
bob ready |
The one command for starting or resuming a project: takes a new or existing directory, or an owner/repo it clones, to warp-ready and visible on bob viz — idempotent, no prompts, … → |
bob preflight |
The warp-drive preflight gate: doctor + ready --dry-run as one verdict. → |
bob provision |
Provision a project from its manifest — status / diff / check / refresh / prune / init / interview / detect / add / remove / decline / reconcile / overlay / untrack / ignore-paths … → |
bob link |
Link a global item (command, agent, hook) into the current project’s .claude/, link every missing one, or list what is available. → |
bob promote |
Promote a local .claude/ item (command, agent, hook, skill) to the global source and replace the local file with a symlink back. → |
bob promotion setup |
Scaffold a project’s dev → test → prod promotion ladder — detect → dev.json → wrangler → provision handoff → todo → verify; dry run by default, –apply writes (#931). → |
bob deploy |
Deploy this project to its test or prod environment through scripts/deploy/deploy.sh — the resolved adapter’s check → build → migrate → deploy → verify contract — with a D1 backup … → |
bob backup setup |
Render a project’s backup Worker from its dev.json environments.<env>.backup block (#3084, cap #3067): the Worker and its scheduled Workflow (templates/backup-worker/) written to … → |
bob backup status |
How old a project’s newest D1 backup is (#3085, cap #3067): per env whose dev.json declares environments.<env>.backup, the newest dump the backup Worker wrote (read from its … → |
bob backup run |
Take a D1 backup now (#3085, cap #3067): trigger the project’s backup Workflow — the one its nightly cron starts — through wrangler workflows trigger, then wait until the … → |
bob backup restore |
Load a backup into the restore-target env’s D1 and verify it (#3085, cap #3067): the newest dump (or –from <key>) fetched from the backup bucket, the target’s existing tables and … → |
Plan and run warp-drive
Section titled “Plan and run warp-drive”Groom the queue, freeze a flight plan, launch and steer autonomous runs.
| Command | What it does |
|---|---|
bob groom |
Run the /groom pass headless from a shell: claude -p over the inlined /groom command text and scope — an explicit DRY-RUN by default, –apply at automation Level 3 … → |
bob decompose |
Decompose an approved capability or use case into filed child requirements through six evidence-gated phases on the shared machine engine (#2975): sourcing (cap-status) → drafting … → |
bob do |
Run an hour of unstructured work as a state machine on the shared engine (#2975): framing (a one-line question and an artifact from the closed set decision · lesson · doc · spike … → |
bob plan build |
Derive a flight plan once and write/refresh its issue — flightplan.js build –no-interview with the mapped scope flags; prints the plan number. → |
bob plan remaining |
Runnable plan items in run order — flightplan.js remaining <N>, argv passed through unchanged. → |
bob plan status |
Plan progress — runnable vs gated vs withheld vs moot vs waiting, todo gate states, gate mode, integration branch, lifecycle — flightplan.js status <N>, argv passed through … → |
bob plan items |
The plan’s ordered items, todo rows marked — flightplan.js items <N>, argv passed through unchanged. → |
bob warp start |
Launch a warp-drive run in a named tmux session from any shell: bob preflight first (exit 1 with the verdict when it fails; on the BoB source checkout a failure that is only this … → |
bob warp attach |
Attach to the project’s live warp-drive run and follow it across segments: one name per run, no warp-seg-N to know. → |
bob warp status |
Show the active warp-drive phase, issue, chunk and metrics; –watch redraws in place, –log appends the phase history. → |
bob warp log |
The warp-drive phase-transition history for this project. → |
bob warp config |
Show the resolved workflow configuration (_workflow keys, kickoff options) for this project. → |
bob warp viz |
Open the live session graph in the browser (#1552); –tailnet serves it on this machine’s Tailscale address, the default where machines.json declares dashboard.bind: tailnet … → |
bob warp stop |
Abort the active warp-drive session — graceful (transitions to aborted) or –hard (deletes the state file, no cleanup). → |
bob warp reap |
GC leaked warp-seg-* tmux sessions and orphaned REPLs, and find Claude Code in every other tmux session graded stale or live by idle time (#3302) — dry run by default, –force … → |
bob warp session |
The integration-branch session: start <branch> [–area <slug>|–flightplan <N>] creates + checks out a scope-bound session branch (#1177), end clears it, status shows the resolved … → |
bob warp finalize |
Ship the integration branch to main — one PR at Level 2, rebase + merge at Level 3 (#268). → |
bob fork |
Fan out parallel warp-drive sessions into isolated git worktrees + tmux windows: fork <branch...> | fork –from-issues [N] | fork –from-flightplan <N> | status | drop | watch | … → |
bob pair |
The cross-repo, contract-driven shape of fork: paired worktrees in a backend and a frontend repo on one shared branch (the standalone form of bob fork pair). → |
bob swarm |
Run the full agent-swarm loop as one command — decompose → approve → capped dispatch via bob fork → gate → integrate → summary (#582). → |
Dev environment and dashboards
Section titled “Dev environment and dashboards”Bring the app up, clean residue, and serve the project dashboard.
| Command | What it does |
|---|---|
bob dev up |
Bring the dev environment to a fully testable state from dev.json: start the server, migrate, seed, provision test users, health-check, report the URL. → |
bob dev health |
Quick health check of the dev environment — the shortcut for dev up --check. → |
bob reap |
Reap regenerable working-tree residue per the project’s reap.json — dry run by default, –apply deletes; keep-list and liveness guards (#1664). → |
bob dash status |
The tooling dashboard: global items and every registered project’s symlink status, port band, warp-drive harness defects, and last bob ready verdict. → |
bob dash generate |
Generate a project’s static dashboard (bugs, releases, changes, incidents, journal, cross-refs) into .dash/ from the current directory. → |
bob dash serve |
Start the dashboard server for the current project on its ledger-assigned port, or list / stop running dashboards and show port allocations. → |
bob serve |
Converge this machine’s declared tailscale serve front door (#2407): one MagicDNS address, no port, with /bob and every declared project’s /<project>/warp path-routed to its … → |
Release, update and the farm
Section titled “Release, update and the farm”Ship BoB, move a machine to a release, and run the unattended cycle.
| Command | What it does |
|---|---|
bob release |
The BoB release engine from a shell: a stable release (bump + CHANGELOG + vX.Y.Z tag + GitHub Release), a nightly tag on a green, moved HEAD (#2045), or promote — stable from the … → |
bob update |
Converge this machine to a release channel or tag: fetch, fast-forward the BOB_SOURCE checkout to the newest stable/nightly tag (or –to), run deploy.sh, then doctor — refusing a … → |
bob tick |
One unattended maintenance cycle under a lock: bob groom –all –apply → bob plan build –from farm → the host converged on BOB_SOURCE when it is behind source and safe to deploy … → |
bob wiki maintain |
Consolidate one project’s traces into the skill-evolution wiki (#2389, part of #2387): a scrubbed, bounded packet of everything new since the watermark — loop notes, the decision … → |
bob wiki propose |
Propose one change to one skill, command or agent from the skill-evolution wiki (#2391, part of #2387): the item named, or with –auto the one with the most new wiki evidence … → |
bob eval run |
Run one item’s eval suite (#2390, part of #2387): evals/<item>/ in BOB_SOURCE through claude plugin eval with a with/without ablation, from the current directory, under a … → |
bob eval gate |
The acceptance rule for a skill change (#2390): pass only when a skill-eval/1 result’s with score is strictly higher than the best recorded for the same model in … → |
bob mirror |
Reconcile and publish to each repo’s declared second git host (mirrors.json): resolve / reconcile / publish / verify / status — dry run without –apply (#1747). → |
bob forge health |
Forge availability classified from real gh call outcomes — operational / degraded / unreachable / unknown; the exit code is the answer (#1748). → |
bob forge queue |
The durable write-ahead queue of issue mutations the forge could not take — status / list / show / resolve / drop / replay / clear; replay is dry-run by default, –apply delivers … → |
bob site publish |
Publish one site-publish/1 bundle to the operator’s site — the one publisher to it (#3103, decision on #3098): a producer (bob brief, release notes) hands over a section path and … → |
Operator and secrets
Section titled “Operator and secrets”Your operator repo — identity, fleet, manifests — the secrets it declares, the phone terminal kit, this machine’s model-route key, the model roles that fail over across routes, and this machine’s Cloudflare token.
| Command | What it does |
|---|---|
bob operator show |
Print the resolved operator profile and which rung found it — $BOB_OPERATOR → the $BOB_HOME/.bob-operator pointer → ~/projects/bob-operator — after validating operator.json … → |
bob operator init |
Scaffold an operator repo from templates/operator/ — operator.json, machines.json, provisions/, README, .gitignore and the validate workflow that runs BoB’s validators — git-init … → |
bob operator migrate |
Move the operator data out of the BoB source checkout into the resolved operator repo WITH HISTORY — machines.json, mirrors.json, config/cloudflare-accounts.json, … → |
bob secrets check |
Verify every secret the operator profile declares is PRESENT on this machine and name its source — env / file / keychain / gh-secret / op probed for existence and metadata only, … → |
bob ibob check |
Grade the iBoB terminal kit read-only (#2291, cap #2289): the declared phone setup in the operator repo’s config/ibob-kit.json — schema, every target a machines.json id, every … → |
bob ibob attach |
List the live warp and cdfork tmux sessions on one fleet machine and print, for each, the exact command to type in the phone client (mosh or ssh, from the kit’s declared client) … → |
bob route status |
What this machine’s model-route working key has used against its limit (#3590, cap #3866): one request to the route for the key’s own state — its label, usage, limit and what is … → |
bob route mint |
Create this machine’s model-route working key with the management key (#3590): named bob-<machine id>, limited to the monthly amount the machine’s machines.json entry declares … → |
bob route roles |
Every model role BoB declares (#1231, cap #3866) — default, reasoning, fast, cheap — with the Claude Code alias agents name for it and its candidates in the order they are tried, … → |
bob route run |
Run a headless command on a model role with failover (#1231, cap #3866): start it on the role’s first candidate in play; when it exits non-zero and its output shows a Claude API … → |
bob route failovers |
The newest model failovers on this machine (#1231): when, which role, the candidate that failed and why (its class and the matched text), what it fell back to, and the project — … → |
bob cloudflare verify |
Check this machine’s Cloudflare working token (#3583, cap #3581): the project’s account — its manifest _meta.cloudflare_account, else the operator’s default_account in … → |
bob cloudflare mint |
Create this machine’s Cloudflare working token with the operator’s root token (#3583): named bob-<machine id>, scoped to the account and all its zones, holding every permission … → |
Work attribution
Section titled “Work attribution”Agent hours and list-price COGS per project — this machine, and the fleet from its snapshots.
| Command | What it does |
|---|---|
bob labor report |
Agent active-hours from the Claude Code transcripts on this machine, one clock per project (#4420, cap #3135): every session transcript under ~/.claude/projects/<slug>/ (a Task … → |
bob labor reconcile |
Every transcript on this machine has one priced record in the token ledger (#4421, cap #3135): each session transcript under ~/.claude/projects/<slug>/ written since the window … → |
Rituals
Section titled “Rituals”Scheduled reviews: what is due, open, prepare, hold, close, decide.
| Command | What it does |
|---|---|
bob ritual due |
Which rituals are overdue, due or upcoming per project — the declared _meta.rituals schedule or liveness-scaled defaults, last run derived from closed ritual-run issues (#2230, … → |
bob ritual run |
Start the attended session of a ritual: resume its open run issue or open one, refuse a kit the machine role forbids (#2228), apply the ritual kit to the project checkout as a … → |
bob ritual open |
File one ritual-run issue with the standard body (marker, scope, kit, the declared checklist embedded as tickable items at its version (#2241), evidence placeholder, findings … → |
bob ritual prepare |
Gather a run evidence packet report-only and post (or replace) it as one comment on the run issue; –due prepares every farm-eligible ritual due soon, what bob tick runs (#2233). → |
bob ritual close |
Close a held ritual run with durable outputs: every finding links a bug, req, task, security or todo issue or says no-action (an empty run needs –no-findings, recorded), lessons … → |
bob ritual decide |
Write a portfolio-review decision into a project manifest: _meta.portfolio invest / maintain / park / archive, the dormant default cadence for a parked or archived project (and … → |
bob ritual sweep |
The portfolio sweep (#3609): inventory every directory under ~/projects and ~/Sites on every fleet machine — this one directly, the others over Tailscale SSH, nested repos … → |
Every command in full
Section titled “Every command in full”Every command below lists its usage, each of its flags, its exit codes, the engine that runs it, the issue that introduced it, the release it first shipped in (Since), and the page to read next.
Daily driver
Section titled “Daily driver”bob doctor
Section titled “bob doctor”Assert this machine’s BOB_HOME is what deploy.sh produced from the commit it records, across every synced surface, every symlink, the toolchain and the settings.json hook wiring; how far BOB_SOURCE has moved since the deploy is reported, never drift (#3160). The source is resolved through the #1220 chain (scripts/lib/bob-source-resolve.js: $BOB_SOURCE → the engine’s own checkout → ~/projects/bigbrain → BOB_HOME, flagged), never the engine’s own directory; on the BOB_HOME fallback the surfaces, settings_hooks and contract lines report not-measured under unmeasured, never PASS (#2315). Its dashboards INFO section ends each running server’s line with its /warp URL and closes with the machine’s /bob fleet URL (#2639).
bob doctor [--json] [--project <dir>] [--section <surfaces|symlinks|toolchain|settings_hooks>[,...]]| Flag | Meaning |
|---|---|
--json |
machine-readable verdict (schema bob-host-drift/1) |
--project <dir> |
also grade that project’s .claude/ links — reported as its own section, never folded into the machine verdict (#1953) |
--section <a,b> |
grade only the named sections: surfaces, symlinks, toolchain, settings_hooks |
| Exit | Meaning |
|---|---|
| 0 | converged |
| 1 | drift — the output names the remediation |
| 2 | error |
Engine: node scripts/checks/host-drift.js · Issue: #1921 · Since: v1.272.0 · Read next: Troubleshooting
bob status
Section titled “bob status”The front door: with no arguments, one line per scope — host, the project you are in, the fleet — from cached verdicts with no network, the warp run going here, and ONE next: command; with –scope, one health verdict for host (≡ doctor), project (≡ ready –dry-run) or fleet (the audit view; bob dash status’s views as flags) — as one bob-status/1 document. Each section embeds its engine’s own v1 document unchanged.
bob status [--json] [--live] | bob status --scope host|project|fleet [--json] [scope flags]| Flag | Meaning |
|---|---|
--scope <host|project|fleet> |
what to grade; omit it for the front door (every scope, one next: command) |
--live |
front door only: re-grade the project (ready –dry-run) and pull the fleet live instead of reading recorded verdicts |
--json |
machine-readable verdict (schema bob-status/1) |
--project <dir> |
host: also grade that project’s .claude/ links; project: the project to grade (or pass it positionally) |
--section <a,b> |
host only: grade only the named bob doctor sections |
--reconcile-preview |
project only: add rebob –report as an informational section |
--no-live |
fleet only: read cached snapshots; build nothing, pull nothing |
--<cdb-view> |
fleet only: –projects-only, –global-only, –matrix, –ports or –check <project> renders that bob dash status view unchanged (human output; no –json) |
| Exit | Meaning |
|---|---|
| 0 | ok |
| 1 | drift — host drift, NOT READY, or an unreachable/stale fleet machine |
| 2 | error or usage error |
Engine: node scripts/status/status.js · Issue: #2080 · Since: v1.274.0 · Read next: bob status
bob asks
Section titled “bob asks”Every open ask of the operator across the portfolio, in one list (#3801, cap #3800): one line per open todo without completed and per open brief in brief:new or brief:acting, across every registered, active project, with its project, priority, age in days and link. Each ask says what it unblocks (#3915): an item of a flight plan with a live run (running), of an open plan with no run (ready), an approved issue on no plan (approved), nothing (none), or unknown when the forge could not say; the asks are listed most-blocking first — by that tier, then the items gated, then priority, then oldest first — and a line whose ask holds work up ends with one sentence saying what. The lines are grouped into sittings (#3806), one per place, each headed with its place and total minutes, decisions before commands before checks, the sitting holding the first-listed ask first; an ask that states no minutes or place is listed in a last group, not yet estimated. The attention budget (#3805) caps the list: at most _workflow.ask_budget asks per project and _workflow.ask_budget_portfolio across all of them are shown, and the line under them says how many more are waiting behind the budget. bob asks recheck (#3808) lists every to-do untouched for longer than _workflow.ask_recheck_days with a verdict: moot when every issue it names is closed, else still needed; recheck –apply closes a moot to-do without completed and records the re-check on the rest. bob asks sources (#3810) reports, per filing path named by each to-do’s ask:source marker, the to-dos filed in the last 90 days (–days): filed, done, closed without completed, open and the median days to done, and marks each source whose share closed without completed exceeds _workflow.ask_moot_threshold; sources –file-bugs –apply files one deduplicated bug per marked source in the BoB tracker, naming its counts; –json prints one bob-asks-sources/1 document. bob asks draft / transition / status (#3811) run one ask through the declared lifecycle machine (scripts/asks/machine.json, on the shared machine engine #2975): drafted, admitted, queued, presented, done, declined, snoozed, consumed, one state file per ask under .claude/asks/ in the checkout; an event is named for the phase it reaches, admitted runs the admission gate (#3803) and a refused draft stays at drafted with the refusal recorded, an invalid transition changes nothing, done on a to-do adds completed to its issue before the phase moves, consumed is fired only by todo-consume.js once it has unblocked the issues the to-do named, and an issue-number id with no record is adopted at the phase its labels say; the brief states in scripts/brief/states.json map onto the same phases; –json prints one bob-ask/1 document. A project whose forge read fails is named as a gap with the forge state, never a silently shorter list; –json prints one bob-asks/1 document with the same rows and a count per project. bob asks done <owner/repo#N> (#3807) answers one ask from a shell as the asks page does through the brief-tick Worker: completed on a to-do, brief:done on a brief, anything else refused (exit 1); bob asks snooze <owner/repo#N> –until <date> writes one ask:snooze-until marker into the issue body, and an ask snoozed past today is not listed — –json names it under snoozed; both print one bob-ask-answer/1 document with –json and write nothing when the ask is already so. A to-do that declares a Done-check (#3986) is tested before it is listed: a pass adds completed and closes it with the evidence, so it is never shown, and a failure with a new reason is written into its body; –json counts them under done_checks. bob asks verify runs every open to-do’s done-check, report only without –apply; –apply closes the passing ones, records each new failure reason and re-runs a failed CI run once (what bob tick runs), and –json prints one bob-asks-verify/1 document. A projection: the issues stay the store, the only writes are the ask-waiting label under –reconcile –apply, the two answers and the done-check’s, and a todo carrying completed, a closed issue, or a brief in brief:done or brief:parked is never listed.
bob asks [--json] [--all] [--reconcile [--apply]] | bob asks recheck [--json] [--apply] | bob asks sources [--days <n>] [--json] [--file-bugs [--apply]] | bob asks draft <id> --body-file <path> [--title <t>] [--kind todo|brief] [--label <a,b>] [--repo <owner/repo>] [--source <name>] | bob asks transition <id> <event> [--number <n>] | bob asks status <id> [--cwd <dir>] [--json] | bob asks done <owner/repo#N> [--json] | bob asks snooze <owner/repo#N> --until <YYYY-MM-DD> [--json] | bob asks verify [--apply] [--json]| Flag | Meaning |
|---|---|
--json |
one bob-asks/1 document on stdout: verdict, count (asks inside the budget), open (every open ask), by_project {name: open count}, asks [{kind, project, repo, number, title, priority, state, created_at, age_days, ask_kind, minutes, place, url, unblocks {tier, items, plan, summary, reason}}], sittings [{place, minutes, asks}] (one per place, #3806), unestimated (the asks that state no minutes or place), waiting (the same rows, for the asks behind the budget), budget {portfolio, per_project, waiting}, projects {total, read, gaps [{project, repo, state, reason}], not_here}, error |
--all |
also list the asks waiting behind the budget, under the ones inside it |
--reconcile |
make the ask-waiting label match the budget: report each ask beyond the budget that lacks it and each ask inside that carries it (the document gains reconcile {applied, held, released, swept}) |
--apply |
with –reconcile: add or remove the label, one gh issue edit per ask, and sweep the handoff of each released to-do so its push is sent. With recheck: close each moot to-do without completed, with a comment naming the closed issues that made it moot, and put one comment recording the re-check date on each to-do still needed. With sources –file-bugs: file the bug of each source above the moot threshold that has no open bug yet |
| Exit | Meaning |
|---|---|
| 0 | listed — a project that could not be read is named as a gap |
| 1 | transition: the event is not one the ask’s phase allows, or draft: the ask already exists — nothing changed |
| 2 | usage error, no readable projects.json, or (transition, status) no such ask |
| 3 | no project could be read — every forge read failed; transition admitted: refused by the admission gate, the phase did not move |
| 4 | transition: the forge did not take the completed label, or the issue to adopt could not be read — the phase did not move |
Engine: node scripts/asks/asks.js · Issue: #3801 · Since: v1.279.0 · Read next: See everything waiting on you
bob brief
Section titled “bob brief”One portfolio briefing as briefing/1 (#2243, cap #2224): Needs you / Done / Doing / Will do across every project since the previous briefing, assembled from source data with links — gh (merged PRs, closed reqs and bugs, open todos, PRs awaiting review, releases, open flight plans), fleet snapshots (active warp sessions per machine, blocked runs, harness defects), this machine’s warp state and tick digests, rituals due (#2222) and rotations due (#2223). A source that cannot be read is one named gaps[] entry; the briefing is never failed for one source. The page (#2244) and the Telegram message (#2245) are views over this document: –write stores it as <generated_at>.json where /briefings lists it, –send stores it and posts a headline of at most 5 lines — the needs-you count, the done / doing / will-do counts, the top needs-you item and the tailnet link to the stored briefing — through bob notify, exiting by bob notify’s contract (0 delivered · 3 no bridge, the message printed · 4 transport); a quiet briefing is one line, or nothing under –on-quiet skip.
bob brief [--install-timer|--uninstall-timer|--timer-status [--machine <id>] [--dry-run]] [--json] [--write] [--send] [--scheduled] [--area <area:label>|all [--apply]] [--project <name>|all [--apply]] [--reconcile [--apply]] [--retain-days <N>] [--url <http://host:port>] [--on-quiet message|skip] [--since <ISO>] [--now <ISO>] [--offline] [--snapshots <dir>] [--ticks <dir>] [--briefings <dir>]| Flag | Meaning |
|---|---|
--area <area:label>|all |
one page per area label, rendered to the operator repo’s www/bob/briefings/area-<slug>.html — a view, not a brief; a brief issue is filed only when the area carries a decision (an open needs-clarification or blocked item, an open todo without completed, an untyped open issue, or a cap with no approved requirement past the staleness window), its Next action list naming exactly those items; an open area brief whose area no longer carries a decision is reported for –reconcile, never closed; one line and a URL per area; report-only without –apply; with –scheduled it writes inside the declared hours (#2820, #3101) |
--project <name>|all |
one brief per registered project (projects.json, resolved to its GitHub origin), filed as a brief issue in that project’s own repo on the area-brief model, with its page at the operator repo’s www/bob/briefings/project-<name>.html; all walks every project, an unknown name exits 2 listing the known ones, a project with nothing new in the window is reported quiet; report-only without –apply; with –scheduled it runs after the portfolio briefing is delivered (#3040) |
--reconcile |
tick every brief’s Next action whose named issues (#NN, owner/repo#NN, issue/PR URLs) have all closed — a todo only with completed; an action naming no issue is reported as needs judgment, never ticked; one line per open brief across the portfolio, report-only without –apply; –apply writes each body with –body-file, comments the evidence, moves the state label through states.json (all resolved → brief:done and closed) and, when a brief changed, rebuilds and publishes the index; a forge that answers nothing is reconcile: skipped (forge <state>), exit 3, nothing written; –json emits brief-reconcile/1 (#3100) |
--apply |
with –area: write each area’s page and file or update its brief issue only for a decision; with –project: file or update each project’s brief issue and write its page; with –reconcile: tick resolved actions, move state labels, close finished briefs, rebuild and publish the index |
--install-timer |
render bob-brief.service + bob-brief.timer from this machine’s machines.json bob_workload.brief into ~/.config/systemd/user and enable the timer — it runs bob brief –send –scheduled on the declared cadence (Linux only; idempotent; with –dry-run writes nothing, #2246) |
--uninstall-timer |
disable the briefing timer and remove both units (#2246) |
--timer-status |
the briefing timer declared vs installed: each unit absent / current / differs, the timer state and lingering (#2246) |
--machine <id> |
with a timer flag: the machines.json entry (default: the host it resolves) |
--dry-run |
with –install-timer / –uninstall-timer: report what would be written and run; write and run nothing |
--json |
the briefing/1 document on stdout (schemas/briefing.schema.json); the human rendering otherwise |
--write |
store the document in the briefings directory as <generated_at>.json (2026-09-16T06-00-00Z.json) — what /briefings lists and the next briefing’s window starts from (#2245) |
--send |
store it (implies –write), then post the headline — at most 5 lines: needs-you count, done / doing / will-do counts, the top needs-you item and its link, the page link — through bob notify at level warn when something needs you, else info; the exit code is bob notify’s (#2245) |
--scheduled |
a scheduled briefing (the bob-brief timer, the end of bob tick, #2246): inside this machine’s declared machines.json bob_workload.brief.quiet_hours nothing is made or stored and the exit is 0; an invalid declaration is exit 2; with –area it is the area pass, writing as –apply does (#3101) |
--retain-days <N> |
after a write, prune stored briefing/1 documents older than N days — never the newest, never a file that is not a briefing; default the declared bob_workload.brief.retention_days (90 when a brief block omits it), none when undeclared (#2246) |
--url <http://host:port> |
the Project Monitor base the page link uses instead of this machine’s tailnet address and the project’s ledger dashboard port |
--on-quiet message|skip |
what a quiet briefing (nothing needs you, nothing done in the window) sends: one line (default, or BOB_BRIEF_ON_QUIET) or nothing |
--since <ISO> |
the window start for Done — wins over the previous briefing; default: the newest briefing/1 under $BOB_HOME/briefings/, else 24 h back |
--now <ISO> |
the clock the window and every date comparison use (tests, replays) |
--offline |
read local files only — every gh source, rituals and rotations become offline gaps |
--snapshots <dir> |
the fleet snapshot directory (default $BOB_FLEET_SNAPSHOTS, else $BOB_HOME/fleet/snapshots) |
--ticks <dir> |
this machine’s tick digests (default $BOB_HOME/fleet/ticks) |
--briefings <dir> |
where previous briefings are read from and stored (default $BOB_BRIEFINGS, else the declared bob_workload.brief.dir, else $BOB_HOME/briefings) |
| Exit | Meaning |
|---|---|
| 0 | built — every source read in full; with –send: delivered (or quiet and skipped) |
| 2 | usage error |
| 3 | built — at least one source is a gaps[] entry (the document is still complete); with –send: no bridge configured — the message is printed instead (bob notify’s contract) |
| 4 | with –send only: transport error — curl failed or the bridge answered non-2xx (bob notify’s contract) |
Engine: node scripts/brief/brief.js · Issue: #2243 · Since: v1.274.0 · Read next: Get your briefing
bob tour
Section titled “bob tour”What is provisioned here but never invoked, from session-ledger evidence: each item with one line on when to reach for it and the command to try, graded unknown / parked / in-use — never useless. Backfills the ledger from transcripts when it is empty; carries the 2026-09-10 review’s unknown bucket as its seed; –tried / –park record the owner’s choice in .claude/.tour.json.
bob tour [--project <dir>] [--days N | --fleet [--min-events N]] [--all] [--no-backfill] [--json] | bob tour --tried <item> | bob tour --park <item> | bob tour --applicability [--no-infer] [--bucket <name>] [--json]| Flag | Meaning |
|---|---|
--project <dir> |
the project to tour — its nearest .git/.claude ancestor (default: the current directory) |
--days <N> |
count only ledger events from the last N days (default: all time) |
--all |
also list the in-use items (by default only unknown and parked are listed; the counts always cover all three) |
--fleet |
grade from fleet-wide usage — every project on every fleet machine, from the snapshots, this machine’s rebuilt live (#2899); each grade rests on a stated evidence base, and no use on a base below the minimum or with a machine missing reads insufficient-evidence; all time, so not with –days |
--min-events <N> |
with –fleet: the fewest fleet events a base needs before an unused item may read unknown or parked (default 200) |
--no-backfill |
do not mine transcripts into an empty ledger first (the backfill never runs on a ledger that has events) |
--tried <item> |
record that you tried <item> today — it grades in-use; clears a park |
--park <item> |
record that you chose not to use <item>, dated today — it grades parked; clears a try |
--applicability |
grade every registry item by applicability before usage (#2900): not-applicable-anywhere / applicable-unused / applicable-used / unscoped, from applies_to against each portfolio project’s declared or inferred stack and type, then fleet usage; missing or implausible metadata is flagged for a fix, not graded; –json emits one bob-applicability/1 document (docs/reference/applicability.md) |
--no-infer |
with –applicability: use declared profiles only — never run infer-profile.js on a project checkout |
--bucket <name> |
with –applicability: list one bucket only (the counts stay whole) |
--json |
one bob-tour/1 document on stdout: project, days, state_file, seeded_from, ledger {events, backfill}, counts {unknown, parked, in_use}, items [{name, type, grade, when, try, evidence}], action, error |
| Exit | Meaning |
|---|---|
| 0 | tour rendered, or the choice recorded |
| 2 | usage error, an item neither provisioned here nor in the seed, or an unreadable .claude/.tour.json |
Engine: node scripts/tour/tour.js · Issue: #2075 · Since: v1.274.0 · Read next: Tour what is provisioned
Bob University (BobU) from a shell — a thin router over the disposition record (#2901), applicability and fleet usage (#2900, #2899) and the eval suites (#2390): status counts each disposition, lists every undisposed item with its applicability bucket and usage, and names the certifications due for re-examination; exam runs an item’s suite under the project’s kit overlay and prints the disposition the result supports; dispose builds the item’s record from that evidence, checks it against the record’s gate, and writes it only under –apply — retire also drafts the retired-items.json entry.
bob u status [--no-infer] [--json] | bob u exam <item> [--model M] [--runs N] [--kit K | --no-overlay] [--project DIR] [--out FILE] [--json] | bob u dispose <item> <certified|needs-work|not-applicable|retire> --reason "…" [--exam FILE] [--model M] [--baseline PATH] [--retired-by #N] [--date YYYY-MM-DD] [--no-infer] [--apply] [--json]| Flag | Meaning |
|---|---|
--no-infer |
status, dispose: use declared project profiles only when grading applicability — never run infer-profile.js on a checkout |
--model <M> |
exam: the model to examine against (passed to the #2390 runner); dispose certified: the model the certification holds for (default: the exam’s model) |
--runs <N> |
exam: runs per case (passed to the runner) |
--kit <K> |
exam: apply session kit K as the provision overlay for the exam and restore it afterwards (default: the machine’s default kit; an overlay already active is used as is) |
--no-overlay |
exam: run the suite bare, with no kit overlay |
--project <dir> |
exam: the project checkout the exam runs in and whose overlay it uses (default: the current directory) |
--out <file> |
exam: also save the skill-eval/1 result to <file>, for dispose –exam |
--reason "…" |
dispose (required): the rationale — one or two sentences a reviewer can check against the evidence |
--exam <file> |
dispose: a skill-eval/1 result recorded as evidence.exam — required for certified |
--baseline <path> |
dispose certified: the eval baseline graded against (default: evals/<name>/baseline.json when it exists) |
--retired-by <#N|sha> |
dispose retire (required): the issue or commit that retires the item — goes into the record and the retired-items.json draft |
--date <YYYY-MM-DD> |
dispose: the decision date (default: today, UTC) |
--apply |
dispose: write the record to registry/dispositions.json (without it: report only) |
--json |
one versioned document on stdout, error set on failure: status → bob-u-status/1 (counts, undisposed [{type, name, bucket, usage, metadata_fix}], certifications [{type, name, certified_model, examined, runs_on, runs_on_id, runs_on_source, state, reason, message}], reexamine (the state re-examine subset), usage_base, gate); exam → bob-u-exam/1 (item, suite, model, overlay, result, supports, next); dispose → bob-u-dispose/1 (item, record (the replaced one moved into its history), replaces, ok, violations, applied, retire_draft, next_steps) |
| Exit | Meaning |
|---|---|
| 0 | status rendered · exam supports certified · dispose record valid (written with –apply) |
| 1 | status: the disposition record fails its gate · exam: the result supports needs-work (no-signal or regressed) · dispose: the record would fail its gate — nothing written |
| 2 | usage error, an unknown or ambiguous item, an item with no eval suite (exam), or an unreadable record |
| 3 | exam: the #2390 runner is missing or failed, or the kit overlay could not be applied |
Engine: node scripts/bobu/u.js · Issue: #2903 · Since: v1.276.0 · Alias: bob learn · Read next: Dispose of an item with Bob University
bob notify
Section titled “bob notify”Send a Telegram message over the remote-decision bridge from a shell: reads BRIDGE_WORKER_URL/BRIDGE_SECRET from the environment, the project’s .mcp.json, or $BOB_HOME/.mcp.json, POSTs /notify, and prints the message instead when no bridge is configured — never lost, never a silent drop.
bob notify <message> [--level info|warn|block] [--project <name>] [--session-id <id>] [--cwd <dir>] [--json]| Flag | Meaning |
|---|---|
--level <info|warn|block> |
severity shown on the message: info (default) · warn → warning · block → error |
--project <name> |
project label on the message (default: BRIDGE_PROJECT from the config, else the project root’s basename) |
--session-id <id> |
the sessionId the bridge groups by (default bob-notify) |
--cwd <dir> |
where to start looking for .mcp.json — the nearest .git/.claude ancestor is the project root (default $PWD) |
--json |
one bob-notify/1 document on stdout (the secret is never in it) |
| Exit | Meaning |
|---|---|
| 0 | delivered (2xx) |
| 2 | usage error |
| 3 | bridge not configured — message printed to stdout instead |
| 4 | transport error — curl failed or the bridge answered non-2xx |
Engine: bash scripts/rdb/notify.sh · Issue: #2048 · Since: v1.274.0
bob viz
Section titled “bob viz”Open bob viz — every project on every fleet machine as small multiples, from the fleet feed (/bob on the dashboard server, same freshness and self-update path as bob warp viz); each tile links to its bob warp viz card, and –tailnet serves it on this machine’s Tailscale address (#2070).
bob viz [--tailnet] [--page briefings] [--json] | --install-service | --uninstall-service [--dry-run]| Flag | Meaning |
|---|---|
--tailnet |
serve on the Tailscale address (reachable from any machine on the tailnet). Prints the MagicDNS URL first, then labelled MagicDNS: and tailnet IP: lines. A localhost bind on a tailnet host prints local only — not reachable from other machines and names this flag; a URL that would not open is never printed (#2918) |
--page briefings |
open /briefings instead — the latest briefing and its history on the same server (#2244) |
--json |
one bob-viz-launch/1 document instead of the lines: bind, url and the {magicdns, ip, localhost} URL set, null where the dashboard does not answer; implies no browser (#2918) |
--install-service |
install the always-on dashboard server (#3001): a launchd agent (com.bob.viz) on macOS or a systemd user unit (bob-viz.service) on Linux that starts it at login on this machine’s resolved bind and restarts it on exit; idempotent, prints what changed. bob viz and bob warp viz then reuse it instead of starting a second server |
--uninstall-service |
stop and remove the dashboard service; idempotent |
--dry-run |
with –install-service / –uninstall-service: report what would be written and run, change nothing |
| Exit | Meaning |
|---|---|
| 0 | served |
| 1 | no project here and no BoB source checkout, or the server failed to start; or a systemctl / launchctl step of –install-service failed |
| 2 | usage error (–dry-run without a service flag, an unknown flag) |
Engine: bash scripts/cli/warp viz --page bob · Issue: #2070 · Since: v1.274.0 · Read next: bob viz
bob control
Section titled “bob control”Open BoB Control (#3813, cap #3812): /control on the dashboard server, one frame whose navigation is Now, Projects, Fleet and Costs (#3914, #4034), then the crumbs of where you are (#4025) — /control is the Now page, /control?view=projects every registered, active project, /control?view=fleet bob viz’s notices, reports and briefings and /control?view=costs its GitHub quota line, neither with project tiles, /control?project=<name> that project’s own page, /control?project=<name>&session=<tmux name>[&host=<machine>] what runs in that tmux session (#4026): a run’s session screen (#3929) with its kind in the heading — what it is working on, its stepped state row, its status, tabs for acceptance criteria, feed, plan, commits and files, Steer this run, and its terminal — a bare tmux session’s terminal labelled terminal, or ended with a link back to the project; a warp run’s old segment name redirects to the session the run is in now, and an old session=<kind> address to the tmux session running that kind (bob warp viz keeps the full graph page). The same server, freshness and bind as bob viz; an unknown project or view is the frame with the reason and HTTP 404. bob control runs (#3821) prints every step run from an Ask screen’s Run button, and every action run from a project’s page (#3920), on this machine: the ask and step, or the project and command, the host, the time and who asked, read from $BOB_HOME/control-runs.jsonl, the one thing Control writes; –json prints one bob-control-runs/1 document.
bob control [--tailnet] [--json] | bob control runs [--json]| Flag | Meaning |
|---|---|
--tailnet |
serve on the Tailscale address, as bob viz –tailnet does |
--json |
one bob-viz-url/1 document for /control instead of the lines: running, url, the {magicdns, ip, localhost} URL set, port and bind; implies no browser. With runs: one bob-control-runs/1 document: log, count, unreadable and runs [{at, ask, step | project, action, command, dry_run, host, caller {identity, machine, local, address}}] |
| Exit | Meaning |
|---|---|
| 0 | served; runs: printed (an empty log is zero runs) |
| 1 | no project here and no BoB source checkout, or the server failed to start; runs: the log could not be read |
| 2 | usage error (an unknown flag) |
Engine: node scripts/dashboard/control-cli.js · Issue: #3813 · Since: v1.279.0 · Read next: BoB Control
Set up a project
Section titled “Set up a project”bob init
Section titled “bob init”Initialize a project with BoB tooling: the .claude/ directory, universal symlinks into BOB_HOME, and — when no manifest exists — an offer of one-shot auto-provisioning (bob provision –init –auto).
bob init [-y|--yes] [--auto-provision] [--force] [project-dir]| Flag | Meaning |
|---|---|
-y, --yes |
non-interactive: accept every default |
--auto-provision |
when no manifest exists, run bob provision –init –auto without prompting (#1161) |
--force |
init even if warp-drive is active; also overrides the non-project marker check (#707) — $HOME and BOB_HOME are always refused |
| Exit | Meaning |
|---|---|
| 0 | initialized (or already converged) |
| 1 | refused or failed — non-project target, protected directory, or a link step failed |
Engine: exec scripts/cli/cdi · Issue: #2059 · Since: v1.274.0 · Was: cdi · Read next: Project setup
bob ready
Section titled “bob ready”The one command for starting or resuming a project: takes a new or existing directory, or an owner/repo it clones, to warp-ready and visible on bob viz — idempotent, no prompts, never blocked by other running projects: repo → host → links → init → provision → labels → ports → manifests → viz, plus CI, automation level, RDB and mirror for a project it creates.
bob ready [project-dir | owner/repo | --all] [--new] [--start] [--vision <file|->] [--dry-run] [--json] [--name <project-name>]| Flag | Meaning |
|---|---|
--all |
grade every project projects.json declares that is checked out on this machine — one table, each verdict persisted (#2068) |
--dry-run |
report what each step would do; mutate nothing |
--json |
machine-readable verdict (schema project-ready/1; project-ready-all/1 with –all) |
--name <project-name> |
override the project name used for the provisions manifest |
--new |
create the forge repo for a directory that already has files (a missing or empty directory gets one without it) (#3158) |
--start |
once READY with approved work, run bob warp start and print its attach command (#3158) |
--vision <file|-> |
write docs/vision.md from the text (- reads stdin) when the project has none — the /vision template, the text under ## Vision; an existing one is never overwritten (#4033) |
| Exit | Meaning |
|---|---|
| 0 | READY |
| 1 | NOT READY — each blocker names its fix; with –all, any present project NOT READY |
| 2 | usage error |
Engine: node scripts/ready/ready.js · Issue: #1922 · Since: v1.272.0 · Was: bob-ready · Read next: bob ready
bob preflight
Section titled “bob preflight”The warp-drive preflight gate: doctor + ready --dry-run as one verdict. Non-mutating; a failure files one todo per machine + cause (host causes in bigbrain, project causes in the project repo), comments on it when it recurs, and a later pass closes it (#3161).
bob preflight [--project <dir>] [--converge] [--section host,project] [--issue <N>] [--no-file] [--json]| Flag | Meaning |
|---|---|
--project <dir> |
the project to grade (default: the current directory) |
--converge |
apply bob ready first (idempotent), then re-check |
--section host,project |
run only the named checks |
--issue <N> |
the requirement a filed todo should reference |
--no-file |
never file or bump a todo |
--json |
machine-readable verdict (schema warp-preflight/1) |
| Exit | Meaning |
|---|---|
| 0 | pass |
| 1 | fail — todo filed or bumped |
| 2 | usage error |
| 3 | engine error (fails closed) |
Engine: node scripts/warp-drive/host-preflight.js run · Issue: #1923 · Since: v1.272.0 · Read next: Warp Drive
bob provision
Section titled “bob provision”Provision a project from its manifest — status / diff / check / refresh / prune / init / interview / detect / add / remove / decline / reconcile / overlay / untrack / ignore-paths — through the node engine scripts/orchestrator/provision.js with argv passed through unchanged.
bob provision [--status [--context [--json]] | --diff [--json] | --check | --refresh | --prune | --init [--auto] [--no-infer] | --interview | detect | add <type> <name> | remove <type> <name> | decline <type>/<name> --reason <why> | reconcile [--apply] [--allow-remove] | overlay <apply|restore|status> ... | untrack [<dir>... or --fleet] [--apply] [--push] [--json] | ignore-paths [--json]] [project-dir]| Flag | Meaning |
|---|---|
--status |
the current provisioning state (exit 3 on drift) |
--context |
with –status: the description tokens a session here loads — global set, project manifest, manifest + each kit — per item type; –json = bob-context-cost/1 (#2229) |
--diff |
dry run — what would change, with a why: line per recommended item (#1879); –json = the explain.js document |
--check |
IaC compliance check: drift and undeclared items |
--refresh |
re-provision from the manifest (the default action) |
--init |
generate the manifest from stack detection; –auto = detect → write → refresh with no prompts (#506) |
--interview |
the orchestrator interview (#163) — the same engine bin/cdprov-interview wraps |
--prune |
remove dangling BoB symlinks (#304) |
--untrack |
untrack provisioned .claude/ symlinks a repo still commits — the #1479 migration (#2519); report-only without –apply, one commit per repo with it, –fleet for every checkout on this machine |
--ignore-paths |
print the path set the managed ignore block covers here (bob-ignore-paths/1 with –json) — read-only; what untrack selects against (#2536) |
| Exit | Meaning |
|---|---|
| 0 | converged, applied, or dry run printed |
| 1 | failure — a refused write, a broken link, or an engine error |
| 2 | usage error |
| 3 | drift (–status) |
Engine: exec scripts/cli/cdprov · Issue: #2059 · Since: v1.274.0 · Was: cdprov · Read next: Project setup
bob link
Section titled “bob link”Link a global item (command, agent, hook) into the current project’s .claude/, link every missing one, or list what is available.
bob link <type> <name> | --all | --list [type]| Flag | Meaning |
|---|---|
--all |
link every missing global item |
--list [type] |
list the available global items, optionally one type |
| Exit | Meaning |
|---|---|
| 0 | linked or listed |
| 1 | usage error, unknown type or item, or no project .claude/ found |
Engine: exec scripts/cli/cdl · Issue: #2059 · Since: v1.274.0 · Was: cdl · Read next: Project setup
bob promote
Section titled “bob promote”Promote a local .claude/ item (command, agent, hook, skill) to the global source and replace the local file with a symlink back.
bob promote <file>| Exit | Meaning |
|---|---|
| 0 | promoted and linked back |
| 1 | usage error, unsupported item type, the SkillSpector scan refused the item (#1328), or the copy / link failed |
Engine: exec scripts/cli/cdp · Issue: #2059 · Since: v1.274.0 · Was: cdp · Read next: Authoring a skill
bob promotion setup
Section titled “bob promotion setup”Scaffold a project’s dev → test → prod promotion ladder — detect → dev.json → wrangler → provision handoff → todo → verify; dry run by default, –apply writes (#931).
bob promotion setup [--apply] [--json] [project-dir]| Flag | Meaning |
|---|---|
--apply |
write dev.json + wrangler [env.test] and file the redaction / secrets-gate todo; idempotent, no-clobber |
--json |
the machine-readable report |
| Exit | Meaning |
|---|---|
| 0 | ladder green, or dry run printed |
| 1 | a red verify gate — the ladder is not done |
| 2 | usage error |
Engine: exec scripts/cli/setup-promotion · Issue: #2059 · Since: v1.274.0 · Was: setup-promotion · Read next: Set up dev → test → prod
bob deploy
Section titled “bob deploy”Deploy this project to its test or prod environment through scripts/deploy/deploy.sh — the resolved adapter’s check → build → migrate → deploy → verify contract — with a D1 backup taken before migrating when the env declares one and migrations are pending (#3087) — refused past the promotion ceiling (dev.json promotion.ceiling × automation level, the gate warp-drive’s promoting phase uses) with the gate’s reason; –dry-run prints the exact wrangler commands for that env. bob deploy --env prod is how TEST is promoted to PROD by hand; the release tag is its CI expression (#3081).
bob deploy [--env test|prod] [--dry-run] [--project <dir>] [--adapter <name>] [--skip-tests] [--skip-build] [--skip-backup] [--force] [--list]| Flag | Meaning |
|---|---|
--env <test|prod> |
target environment (default prod) |
--dry-run |
run the checks and print every step — the exact wrangler migrate and deploy commands for the env — without shipping; a ceiling breach only warns |
--project <dir> |
project root to deploy (default: the current directory) |
--adapter <name> |
force an adapter (cloudflare, node, drupal) instead of resolving one |
--skip-tests |
skip the contract’s check step |
--skip-build |
skip the contract’s build step |
--skip-backup |
migrate without the pre-migrate backup — the explicit override, printed as a warning (#3087) |
--force |
bypass the promotion-ceiling gate — a deliberate human override |
--list |
list the available adapters and exit |
| Exit | Meaning |
|---|---|
| 0 | deployed, or the dry run printed |
| 1 | a contract step failed, or a usage error |
| 3 | refused — past the promotion ceiling, or the adapter cannot map the env (reason on stderr) |
Engine: bash scripts/deploy/deploy.sh · Issue: #3081 · Since: v1.277.0 · Read next: Set up dev → test → prod
bob backup setup
Section titled “bob backup setup”Render a project’s backup Worker from its dev.json environments.<env>.backup block (#3084, cap #3067): the Worker and its scheduled Workflow (templates/backup-worker/) written to <project>/backup-worker/ with the project’s D1 id, account and schedule; the backup R2 bucket created if absent; the declared retention set as two R2 lifecycle rules (bob-backup-daily on <db>/, bob-backup-monthly on monthly/<db>/). Dry run by default; –apply writes and converges, and a second –apply reports no change. The Worker’s deploy and its D1_REST_API_TOKEN secret are printed as next steps, never run.
bob backup setup [--project <dir>] [--env <env>] [--apply] [--json]| Flag | Meaning |
|---|---|
--project <dir> |
project root (default: the current directory) |
--env <env> |
the environment whose backup block to render (default prod) |
--apply |
write the Worker, create the bucket and set the lifecycle rules; without it, print the plan |
--json |
one bob-backup-setup/1 document: files, bucket and rules with their action, changed, next steps |
| Exit | Meaning |
|---|---|
| 0 | planned, or applied and converged |
| 1 | a wrangler step failed under –apply |
| 2 | usage |
| 3 | the backup declaration, the project’s wrangler config or its D1 database is missing or invalid (named on stderr) |
Engine: node scripts/backup/setup.js · Issue: #3084 · Since: v1.277.0 · Read next: Set up dev → test → prod
bob backup status
Section titled “bob backup status”How old a project’s newest D1 backup is (#3085, cap #3067): per env whose dev.json declares environments.<env>.backup, the newest dump the backup Worker wrote (read from its latest/<db>.json pointer in the backup bucket), its age, size and per-table row counts from its sidecar, and the last restore drill; fresh when it is no older than the run the declared schedule last fired, with an hour’s grace, stale when it is older or absent, and unknown — never fresh — when the bucket cannot be read (#3086).
bob backup status [--project <dir>] [--json]| Flag | Meaning |
|---|---|
--project <dir> |
project root (default: the current directory) |
--json |
one bob-backup-status/1 document: verdict and, per env, newest, age_seconds, expected_by, drill, fresh, reason |
| Exit | Meaning |
|---|---|
| 0 | every declared backup is fresh |
| 1 | a backup is stale — older than the schedule allows, absent or unreadable |
| 2 | usage |
| 3 | no backup declared, or the declaration or wrangler config is invalid (named on stderr) |
Engine: node scripts/backup/ops.js status · Issue: #3085 · Since: v1.277.0 · Read next: Set up dev → test → prod
bob backup run
Section titled “bob backup run”Take a D1 backup now (#3085, cap #3067): trigger the project’s backup Workflow — the one its nightly cron starts — through wrangler workflows trigger, then wait until the latest/<db>.json pointer names a dump taken after the trigger. The primitive the deploy path’s backup-before-migrate calls.
bob backup run [--project <dir>] [--env <env>] [--timeout <min>] [--json]| Flag | Meaning |
|---|---|
--project <dir> |
project root (default: the current directory) |
--env <env> |
the env whose declared backup to run (default prod, or the one env that declares a backup) |
--timeout <min> |
how long to wait for the dump (default 30) |
--json |
one bob-backup-run/1 document: ok, worker, instance, sidecar, waited_seconds, error |
| Exit | Meaning |
|---|---|
| 0 | the new dump landed |
| 1 | the trigger failed, or no new dump within –timeout |
| 2 | usage |
| 3 | no backup declared, or the declaration or wrangler config is invalid (named on stderr) |
Engine: node scripts/backup/ops.js run · Issue: #3085 · Since: v1.277.0 · Read next: Set up dev → test → prod
bob backup restore
Section titled “bob backup restore”Load a backup into the restore-target env’s D1 and verify it (#3085, cap #3067): the newest dump (or –from <key>) fetched from the backup bucket, the target’s existing tables and views dropped, the dump loaded with wrangler d1 execute –file, and each table’s row count checked against the dump’s sidecar; the elapsed time is printed as the measured RTO, and a restore whose counts all match records itself as the drill at latest/<db>.drill.json, which bob backup status shows (#4266). The target is environments.<prod>.backup.restore_target (default test). Restoring into prod is refused unless a human gate passes — automation Level 1 or –i-understand-this-overwrites-prod, and the database name typed at a terminal — and never runs unattended. For a recent mistake in prod, D1 Time Travel comes first: runbooks/project-data-restore.md.
bob backup restore [--project <dir>] [--env <env>] [--from <key>] [--i-understand-this-overwrites-prod] [--json]| Flag | Meaning |
|---|---|
--project <dir> |
project root (default: the current directory) |
--env <env> |
the env to restore into (default the declared restore_target, test) |
--from <key> |
the dump to restore, e.g. app-db/2026-09-20T0300Z.sql (default the newest) |
--i-understand-this-overwrites-prod |
with –env prod above automation Level 1: allow the prod restore, still only after the typed confirmation |
--json |
one bob-backup-restore/1 document: from, target, dropped, counts, rto_seconds, drill, error |
| Exit | Meaning |
|---|---|
| 0 | restored and every row count matches the sidecar |
| 1 | a step failed, or a row count differs |
| 2 | usage |
| 3 | no backup declared, or the declaration, wrangler config or restore target is missing or invalid (named on stderr) |
| 4 | refused by the prod gate — nothing was touched |
Engine: node scripts/backup/ops.js restore · Issue: #3085 · Since: v1.277.0 · Read next: Set up dev → test → prod
Plan and run warp-drive
Section titled “Plan and run warp-drive”bob groom
Section titled “bob groom”Run the /groom pass headless from a shell: claude -p over the inlined /groom command text and scope — an explicit DRY-RUN by default, –apply at automation Level 3 (read-then-write logs and applies). AskUserQuestion and the RDB ask_remote tool are disallowed, so a decision that needs a human becomes a conforming todo and the item is left blocked; the run’s GROOM-RESULT summary line is the exit code.
bob groom [--area <slug> | --issues N,N | --all] [--apply] [--timeout <min>] [--route <name>[:<model>]] [--cwd <dir>] [--json]| Flag | Meaning |
|---|---|
--area <slug> |
groom every cap/req carrying area:<slug> as one set (/groom area:<slug>) |
--issues <N,N> |
groom these issues — one N is the single-target /groom N; several are groomed as one set |
--all |
every open cluster (bare /groom) — the default |
--apply |
Level 3: log the read-then-write plan inline and apply it; the project is switched to Level 3 first when below it (a settings.local.json edit, named on stderr) |
--timeout <min> |
kill the run after this many minutes (default 30) — reported as timed_out, exit 4 |
--route <name>[:<model>] |
run the groom on a model route (#3590), e.g. openrouter or openrouter:<model slug> — refused before anything runs for a client project, a key at its limit or an unknown model; without it the groom runs on the subscription |
--cwd <dir> |
the project to groom (default: the current directory) |
--json |
one bob-groom/1 document on stdout: scope, mode, level, timed_out, claude_exit, result {groomed, approved, blocked, todos, deferred}, output, verdict, exit |
| Exit | Meaning |
|---|---|
| 0 | groomed |
| 1 | the groom reported blockers (blocked>0), or produced no GROOM-RESULT summary line |
| 2 | usage or config error — bad flag, two scopes, no groom.md, the Level 3 switch failed |
| 3 | claude unavailable (not on PATH) or it failed to run |
| 4 | killed at –timeout |
Engine: bash scripts/groom/groom.sh · Issue: #2051 · Since: v1.274.0 · Read next: Warp Drive
bob decompose
Section titled “bob decompose”Decompose an approved capability or use case into filed child requirements through six evidence-gated phases on the shared machine engine (#2975): sourcing (cap-status) → drafting → deduping (issue-dedupe) → testability (the decompose-testability judge) → tracing → filed (gh read-back). Runs beside an active warp-drive session; creates no report, commit or branch (#2976).
bob decompose <N> | status | transition <event> [--data JSON | --file F] | stop [--cwd <dir>] [--json]| Flag | Meaning |
|---|---|
--data <JSON> |
the event’s payload — drafted: {children:[{title, body, labels}]}; deduped: {resolve:{c1:‘drop’|‘merge #N’}}; judged: {override:{child, n, by, why}} |
--file <path> |
read the event’s payload from a JSON file instead of –data |
--cwd <dir> |
the checkout whose .claude/.decompose-state.json holds the run (default: the current directory) |
--json |
one bob-decompose/1 document: phase, parent, refusal {gate, reason, detail, children}, children, co_running_warp, viz (bob-viz-url/1 for /warp?kind=decompose, #2978) — status without –json ends with the same link as a viz: line, or the command that starts the dashboard |
| Exit | Meaning |
|---|---|
| 0 | started, advanced, or status printed |
| 1 | invalid transition from the current phase, or a run already active |
| 2 | usage error, or no decompose run in this checkout |
| 3 | refused by the phase’s gate — the named refusal is recorded on the run’s state |
Engine: node scripts/decompose/decompose.js · Issue: #2976 · Since: v1.276.0 · Read next: Decompose a capability
bob do
Section titled “bob do”Run an hour of unstructured work as a state machine on the shared engine (#2975): framing (a one-line question and an artifact from the closed set decision · lesson · doc · spike · issue-set · discard) → working (bounded by a minutes or tokens budget, or ended by declaring enough) → landing (read-back evidence of the declared artifact) → recording (the artifact and its prompt linked both ways) → done, or discarded — a green terminal that requires a filed decision issue. Writes files, so it refuses to start while a warp-drive run is active here, and warp-drive refuses while it is (#2979).
bob do "<question>" [--artifact <type>] [--budget <N>m|<N>t|<N>k] | status | transition <event> [--data JSON] | stop [--cwd <dir>] [--json]| Flag | Meaning |
|---|---|
--artifact <type> |
frame the run at start: decision, lesson, doc, spike, issue-set or discard — anything else is refused at the framing gate |
--budget <N>m|<N>t|<N>k |
the working-phase budget — minutes (bare N or Nm), tokens (Nt) or thousands of tokens (Nk); default _workflow.do_budget_minutes |
--data <JSON> |
the event’s payload — framed: {artifact, question?}; worked: {enough:“<why>”}; landed: {issue:N} | {issues:[N…]} | {path:“docs/…”}; recorded: {prompted_by:“#N” | “<path>” | “none”}; discard: {decision:N} |
--pid <N> |
the process the run belongs to (default: the nearest claude ancestor) — the liveness anchor the concurrency rule reads |
--cwd <dir> |
the checkout whose .claude/.do-state.json holds the run (default: the current directory) |
--json |
one bob-do/1 document: phase, question, artifact, budget, budget_use, budget_exhausted, decision, outcome, artifact_ref, prompted_by, run_id, refusal, viz (bob-viz-url/1 for /warp?kind=do, #2978) — status without –json ends with the same link as a viz: line, or the command that starts the dashboard |
| Exit | Meaning |
|---|---|
| 0 | started, advanced (discarded included), stopped, or status printed |
| 1 | invalid transition from the current phase, or a run already active |
| 2 | usage error, or no do run in this checkout |
| 3 | refused by the phase’s gate, or by the concurrency rule (an active warp-drive run owns the checkout) |
Engine: node scripts/do/do.js · Issue: #2979 · Since: v1.276.0 · Read next: Run unstructured work with bob do
bob plan build
Section titled “bob plan build”Derive a flight plan once and write/refresh its issue — flightplan.js build –no-interview with the mapped scope flags; prints the plan number. Without –allow-unapproved un-approved work is never seated (the engine names each dropped issue).
bob plan build [--from approved|farm] [--from-issues N,N] [--area <slug>] [--plan <N>] [--name <name>] [--branch <name>] [--max-items <n>] [--after <N> | --no-after] [--allow-unapproved] [--allow-overlap] [--json]| Flag | Meaning |
|---|---|
--from <approved|farm> |
approved (default): the approved queue, no scope flag passed · farm: the unattended scope (#2052) → flightplan.js –from farm — only farm-eligible work is seated (eligibility.js), every exclusion named |
--from-issues <N,N> |
an explicit issue list → flightplan.js –issues N,N |
--area <slug> |
one workstream → flightplan.js –area <slug> |
--plan <N> |
with –from-issues: grow or re-scope THAT open issues: plan in place → flightplan.js –plan N — its scope marker is rewritten and every tick, branch, gate mode, depends_on edge and name carried, instead of a second plan for the new list (#2283) |
--branch <name> |
declare the plan’s integration branch (#1181) |
--name <name> |
name the plan: title Flight plan: <name> + a flightplan:name marker (#2309) — omitted, a new plan takes the name derived from its area labels and a refresh keeps the recorded one |
--max-items <n> |
seat at most n req/bug items in run order, each with the in-scope items it depends on; the rest are dropped and named (#2055 — the farm tick’s issue budget) |
--after <N> |
run after flight plan #N (#2298) → flightplan.js –after N — the plan waits while #N is open with unfinished items; repeatable or N,N |
--no-after |
clear the plan’s declared predecessor(s) → flightplan.js –no-after |
--allow-unapproved |
seat issues lacking approved (off by default) |
--allow-overlap |
with –from-issues: build even though an open plan already holds some of the items — without it the engine exits 3 naming that plan and the –plan <N> command to grow it (#3199) |
--json |
the engine’s JSON document: plan, scope, items, dropped, unapproved … |
| Exit | Meaning |
|---|---|
| 0 | plan created or refreshed |
| 1 | the engine rejected an argument (e.g. a non-git-safe –branch) |
| 2 | usage error — unknown flag, two scope sources, bad –from — or a gh/repo error from the engine |
| 3 | refused: a –from-issues plan shares items with an open plan (#3199) — grow it with –plan <N>, or pass –allow-overlap |
Engine: bash scripts/bob/plan.sh build · Issue: #2050 · Since: v1.274.0 · Read next: Flight plan
bob plan remaining
Section titled “bob plan remaining”Runnable plan items in run order — flightplan.js remaining <N>, argv passed through unchanged.
bob plan remaining <N> [--json] [--all]| Flag | Meaning |
|---|---|
--json |
an ARRAY of runnable items (the warp-drive consumer contract) |
--all |
widen –json to { gateMode, runnable, gated, withheld, moot, waiting } |
| Exit | Meaning |
|---|---|
| 0 | printed |
| 1 | usage — missing/invalid <N>, or a broken depends_on declaration |
| 2 | gh/repo error |
Engine: bash scripts/bob/plan.sh remaining · Issue: #2050 · Since: v1.274.0 · Read next: Flight plan
bob plan status
Section titled “bob plan status”Plan progress — runnable vs gated vs withheld vs moot vs waiting, todo gate states, gate mode, integration branch, lifecycle — flightplan.js status <N>, argv passed through unchanged.
bob plan status <N> [--json]| Flag | Meaning |
|---|---|
--json |
machine-readable status document |
| Exit | Meaning |
|---|---|
| 0 | printed |
| 1 | usage — missing/invalid <N> |
| 2 | gh/repo error |
Engine: bash scripts/bob/plan.sh status · Issue: #2050 · Since: v1.274.0 · Read next: Flight plan
bob plan items
Section titled “bob plan items”The plan’s ordered items, todo rows marked — flightplan.js items <N>, argv passed through unchanged.
bob plan items <N> [--json]| Flag | Meaning |
|---|---|
--json |
machine-readable item list |
| Exit | Meaning |
|---|---|
| 0 | printed |
| 1 | usage — missing/invalid <N> |
| 2 | gh/repo error |
Engine: bash scripts/bob/plan.sh items · Issue: #2050 · Since: v1.274.0 · Read next: Flight plan
bob warp start
Section titled “bob warp start”Launch a warp-drive run in a named tmux session from any shell: bob preflight first (exit 1 with the verdict when it fails; on the BoB source checkout a failure that is only this machine being behind source is fixed first — deploy.sh then bob doctor, when the checkout is the clean main branch and no Claude Code session is live, #2472), then the project’s dashboard on this machine’s resolved bind (reported, never blocking; –no-viz opts out, #2636), then a tmux session named warp-STEM[-SCOPE] in the project root (STEM is the project resolved from the main repository, or PROJECT-WORKTREE in a linked git worktree, #4041; the dashboard is the project’s own) receives the claude line with the level, -rdb and scope flags; prints the session, its tmux -CC attach line and the viz URL; refuses when that session already exists. Not bob warp session start — that binds an integration-branch stream and launches nothing.
bob warp start [--flightplan N | --issue N | --area <slug>] [--level 1-4] [--rdb] [--session <name>] [--attach] [--root <dir>] [--max-tokens <n>] [--dry-run] [--no-converge-host] [--no-viz] [--json]| Flag | Meaning |
|---|---|
--flightplan <N> |
scope the run to a flight-plan issue (session warp-<stem>-fp-N) |
--issue <N> |
scope the run to one issue (session warp-<stem>-issue-N) |
--area <slug> |
scope the run to one area workstream (session warp-<stem>-area-<slug>) |
--level <1-4> |
automation level passed as -a<level> (default: _automation.active_level in .claude/settings.local.json, else 3) |
--rdb |
pass -rdb so the run uses the remote-decision bridge (Telegram) |
--session <name> |
tmux session name instead of the derived warp-<stem>[-<scope>] |
--attach |
surface the session: iTerm2 control-mode window on an interactive Mac, plain tmux attach on a Linux TTY, the attach line otherwise |
--root <dir> |
project root (default: the git toplevel of –cwd / $PWD) |
--dry-run |
run the preflight (files nothing) and print the plan; no session created |
--no-preflight |
skip bob preflight (never the default) |
--no-converge-host |
do not converge the host at kickoff (also WARP_LAUNCH_CONVERGE_HOST=0). By default, on the BoB source checkout, a preflight that names this machine behind source (the host:behind advisory, or a host:surfaces finding — #3160) and no other failure, with the checkout on the clean main branch and no live Claude Code session, runs scripts/deploy.sh and bob doctor, then preflight again, before launching — recorded as host_converged {ran, verdict, deploy_rc, doctor_verdict, reasons} in warp-start/1 (#2472) |
--no-viz |
do not ensure the project’s dashboard (by default warp start runs bob warp viz –no-open — reuse a fresh server or start one on the machine’s resolved bind — prints the URL beside the attach line and carries it as viz.url in warp-start/1; a failure is reported, never blocking — #2636) |
--max-tokens <n> |
the run’s token ceiling — passed on the /warp-drive line as the kickoff flag, enforced by the session breaker (#2055) |
--json |
one warp-start/1 document on stdout |
| Exit | Meaning |
|---|---|
| 0 | started (or dry-run plan printed) |
| 1 | preflight failed — the verdict is printed, nothing started |
| 2 | usage error |
| 3 | refused — that tmux session already exists |
| 4 | tmux unavailable or session creation failed |
| 5 | refused — an active bob do run owns this checkout (it writes files; #2979), named with its question and phase |
Engine: bash scripts/warp-drive/launch.sh start · Issue: #2049 · Since: v1.274.0 · Read next: Warp Drive from the command line
bob warp attach
Section titled “bob warp attach”Attach to the project’s live warp-drive run and follow it across segments: one name per run, no warp-seg-N to know. When the run hands off to a new segment this terminal moves to it; it stops when you detach or the run ends (#3163).
bob warp attach [project] [--cc | --plain] [--print] [--command] [--json] [--session <name>] [--wait <s>] [--poll <s>]| Flag | Meaning |
|---|---|
--cc |
tmux -CC attach — iTerm2 control mode, the default inside iTerm2 (also over SSH); each segment gets its own -CC attach, so a continuation still opens as its own window (#1022) |
--plain |
tmux attach — the default on any other terminal |
--print |
print the run’s current tmux session and its tmux attach line; attach nothing |
--command |
print the one attach command for the project — by its projects.json name, else by path; needs no live run (what bob warp start, bob warp status and the viz card show) |
--json |
one warp-attach/1 document on stdout: root, live, phase, session, segment, basis (handoff | recorded | pid | newest | launcher), mode, command, tmux; attaches nothing |
--session <name> |
the tmux session to start on when the run has recorded none yet — bob warp start –attach passes the session it just made |
--wait <s> |
seconds to wait for the next segment’s session after one ends (default 120) |
--poll <s> |
seconds between checks for a handoff while attached (default 2) |
| Exit | Meaning |
|---|---|
| 0 | followed the run to its end, detached, or printed |
| 1 | no project found |
| 2 | usage error |
| 3 | no live run to attach to, or no tmux session hosts it |
| 4 | tmux unavailable, not a terminal, or the attach failed — the tmux line is printed |
Engine: node scripts/warp-drive/attach.js · Issue: #3163 · Since: v1.277.0 · Read next: Warp Drive from the command line
bob warp status
Section titled “bob warp status”Show the active warp-drive phase, issue, chunk and metrics; –watch redraws in place, –log appends the phase history.
bob warp status [--watch|--live|-w] [--interval <s>] [--log] [--json]| Flag | Meaning |
|---|---|
--watch, --live, -w |
live view — redraw in place |
--interval <s> |
refresh interval in seconds (default 5) |
--log |
append the phase-history log below the session info |
--json |
one-shot: the state machine’s status document plus viz (bob-viz-url/1) — the dashboard’s {magicdns, ip, localhost} URL set, or the command that starts it (#2639); {active: false, viz} when no session is active |
| Exit | Meaning |
|---|---|
| 0 | rendered |
| 1 | no project root, or the state file is unreadable |
| 2 | –json combined with –watch |
Engine: exec scripts/cli/warp status · Issue: #2059 · Since: v1.274.0 · Was: warp · Read next: Warp Drive from the command line
bob warp log
Section titled “bob warp log”The warp-drive phase-transition history for this project.
bob warp log| Exit | Meaning |
|---|---|
| 0 | rendered |
| 1 | no project root, or the state file is unreadable |
Engine: exec scripts/cli/warp log · Issue: #2059 · Since: v1.274.0 · Was: warp · Read next: Warp Drive from the command line
bob warp config
Section titled “bob warp config”Show the resolved workflow configuration (_workflow keys, kickoff options) for this project.
bob warp config| Exit | Meaning |
|---|---|
| 0 | rendered |
| 1 | no project root |
Engine: exec scripts/cli/warp config · Issue: #2059 · Since: v1.274.0 · Was: warp · Read next: Warp Drive from the command line
bob warp viz
Section titled “bob warp viz”Open the live session graph in the browser (#1552); –tailnet serves it on this machine’s Tailscale address, the default where machines.json declares dashboard.bind: tailnet (#2636).
bob warp viz [--tailnet] [--no-open] [--json]| Flag | Meaning |
|---|---|
--tailnet |
serve on the Tailscale address (farm-hosted project, reachable from a laptop on the tailnet); prints the MagicDNS URL first, then labelled MagicDNS: and tailnet IP: lines (#2918). Alias –tailscale. With no flag the bind is DASH_BIND, then this machine’s machines.json dashboard.bind, then localhost; any other -flag exits 2 (#2636) |
--no-open |
ensure the server and print the URL without opening a browser (what bob warp start runs, #2636) |
--json |
one bob-viz-launch/1 document instead of the lines: bind, url, the {magicdns, ip, localhost} URL set (null where the dashboard does not answer), project, bind_source, reused; implies –no-open (#2918) |
| Exit | Meaning |
|---|---|
| 0 | served |
| 1 | no project root, or the server failed to start |
Engine: exec scripts/cli/warp viz · Issue: #2059 · Since: v1.274.0 · Was: warp · Read next: Warp Drive from the command line
bob warp stop
Section titled “bob warp stop”Abort the active warp-drive session — graceful (transitions to aborted) or –hard (deletes the state file, no cleanup). Mutating, no dry run: the engine has no –help of its own, so bob warp stop --help is answered by the router and never reaches it (#2049).
bob warp stop [--hard|--reset]| Flag | Meaning |
|---|---|
--hard, --reset |
emergency reset — delete the state file with no cleanup |
| Exit | Meaning |
|---|---|
| 0 | aborted or reset |
| 1 | no active session, or the transition failed |
Engine: exec scripts/cli/warp stop · Issue: #2059 · Since: v1.274.0 · Was: warp · Read next: Warp Drive from the command line
bob warp reap
Section titled “bob warp reap”GC leaked warp-seg-* tmux sessions and orphaned REPLs, and find Claude Code in every other tmux session graded stale or live by idle time (#3302) — dry run by default, –force executes, –yes also reaps attached or warp-running sessions, –idle-shells also kills idle shell-only sessions; Claude outside tmux is reported only.
bob warp reap [--force] [--yes] [--idle <minutes>] [--idle-shells] [--json]| Flag | Meaning |
|---|---|
--force |
execute the reap (default: dry run); each pane’s scrollback is saved to .claude/scrollback/ first, then a stale Claude pane gets Escape, /exit, a wait, and the pane is killed |
--yes |
with –force, also reap attached sessions and Claude panes whose project has an active warp-drive run |
--idle <minutes> |
idle time after which a Claude pane is stale and a shell-only session is reported (default: _workflow.reap_idle_minutes, 240) |
--idle-shells |
with –force, also kill idle shell-only tmux sessions |
--json |
machine-readable plan: warp-seg classes plus claude, idle_shells, outside and the actions taken |
| Exit | Meaning |
|---|---|
| 0 | reported or reaped |
| 1 | a kill failed |
Engine: exec scripts/cli/warp reap · Issue: #2059 · Since: v1.274.0 · Was: warp · Read next: Warp Drive from the command line
bob warp session
Section titled “bob warp session”The integration-branch session: start <branch> [–area <slug>|–flightplan <N>] creates + checks out a scope-bound session branch (#1177), end clears it, status shows the resolved branch config.
bob warp session <start <branch> [--area <slug>|--flightplan <N>] | end | status>| Flag | Meaning |
|---|---|
--area <slug> |
(start) bind the session branch to one workstream |
--flightplan <N> |
(start) bind the session branch to a flight plan |
| Exit | Meaning |
|---|---|
| 0 | ok |
| 1 | usage error, or the branch could not be created / resolved |
Engine: exec scripts/cli/warp session · Issue: #2059 · Since: v1.274.0 · Was: warp · Read next: Warp Drive from the command line
bob warp finalize
Section titled “bob warp finalize”Ship the integration branch to main — one PR at Level 2, rebase + merge at Level 3 (#268).
bob warp finalize [--dry-run]| Flag | Meaning |
|---|---|
--dry-run |
print what would be shipped without pushing or merging |
| Exit | Meaning |
|---|---|
| 0 | shipped or previewed |
| 1 | no session branch, or the push / merge failed |
Engine: exec scripts/cli/warp finalize · Issue: #2059 · Since: v1.274.0 · Was: warp · Read next: Warp Drive from the command line
bob fork
Section titled “bob fork”Fan out parallel warp-drive sessions into isolated git worktrees + tmux windows: fork <branch...> | fork –from-issues [N] | fork –from-flightplan <N> | status | drop | watch | pair.
bob fork <fork <branch>... | fork --from-issues [N] | fork --from-flightplan <N> | status [--json] | drop <branch>|--all [--force] | watch [--once] [--json] | pair ...>| Flag | Meaning |
|---|---|
--from-issues [N] |
(fork) auto-discover up to N approved issues (default 4), serial-only excluded |
--from-flightplan <N> |
(fork) fan out flight-plan #N’s runnable wave (#1613) |
--dry-run |
(fork) preview the plan |
--include-serial |
(fork) include serial-only issues |
--json |
(status) machine-readable |
--force |
(drop) remove even with unmerged work |
| Exit | Meaning |
|---|---|
| 0 | ok |
| 1 | a fork, drop or status step failed |
| 2 | usage error, or git / tmux missing |
Engine: exec scripts/cli/cdfork · Issue: #2059 · Since: v1.274.0 · Was: cdfork · Read next: cdfork
bob pair
Section titled “bob pair”The cross-repo, contract-driven shape of fork: paired worktrees in a backend and a frontend repo on one shared branch (the standalone form of bob fork pair).
bob pair --contract <path> --backend <repo> --frontend <repo> --branch <name>| Flag | Meaning |
|---|---|
--contract <path> |
the shared contract document (required, non-empty) |
--backend <repo> |
the backend repo’s working tree (required) |
--frontend <repo> |
the frontend repo’s working tree (required) |
--branch <name> |
the shared branch name, same on both sides (required) |
| Exit | Meaning |
|---|---|
| 0 | both worktrees spawned |
| 1 | a worktree or tmux step failed |
| 2 | usage error, or git / tmux missing |
Engine: exec scripts/cli/cdfork-pair · Issue: #2059 · Since: v1.274.0 · Was: cdfork-pair · Read next: cdfork
bob swarm
Section titled “bob swarm”Run the full agent-swarm loop as one command — decompose → approve → capped dispatch via bob fork → gate → integrate → summary (#582).
bob swarm <run [--approval <path>] [--cap <n>] [--cwd <dir>] [--dry-run] [--finalize] | plan --plan <file> [--cap <n>] | summary [--plan <file>] [--results-dir <dir>]>| Flag | Meaning |
|---|---|
--approval <path> |
(run) the approved decomposition plan |
--cap <n> |
concurrency ceiling (default 4) |
--dry-run |
(run) verify and plan waves without dispatching |
--finalize |
(run) ship the integration branch when every wave passed |
--plan <file> |
(plan / summary) the decomposition plan |
| Exit | Meaning |
|---|---|
| 0 | ok |
| 1 | a gate, dispatch or integrate step failed |
| 2 | unknown subcommand |
Engine: exec scripts/cli/swarm · Issue: #2059 · Since: v1.274.0 · Was: swarm · Read next: Swarm decompose
Dev environment and dashboards
Section titled “Dev environment and dashboards”bob dev up
Section titled “bob dev up”Bring the dev environment to a fully testable state from dev.json: start the server, migrate, seed, provision test users, health-check, report the URL.
bob dev up [--verbose | --check | --regen | --regen-seed | --no-auto-seed] [project-dir]| Flag | Meaning |
|---|---|
--verbose |
full lifecycle with detailed output (the default) |
--check |
quick health check only |
--regen |
regenerate dev.json from the stack recipe (overwrites) |
--regen-seed |
delete auto-generated seed files (010+) and regenerate |
--no-auto-seed |
skip automatic seed generation |
| Exit | Meaning |
|---|---|
| 0 | every step completed |
| 1 | dev.json not found or invalid |
| 2 | server failed to start or the health check failed |
| 3 | migration failed |
| 4 | seed failed |
Engine: exec scripts/cli/dev-up · Issue: #2059 · Since: v1.274.0 · Was: dev-up · Read next: Dev lifecycle
bob dev health
Section titled “bob dev health”Quick health check of the dev environment — the shortcut for dev up --check.
bob dev health [project-dir]| Exit | Meaning |
|---|---|
| 0 | healthy, or n-a — the project has no dev environment to bring up (#853) |
| 1 | dev.json not found or invalid |
| 2 | server unreachable or the health check failed |
Engine: exec scripts/cli/dev-health · Issue: #2059 · Since: v1.274.0 · Was: dev-health · Read next: Dev lifecycle
bob reap
Section titled “bob reap”Reap regenerable working-tree residue per the project’s reap.json — dry run by default, –apply deletes; keep-list and liveness guards (#1664).
Warp-drive runs it at session end against the project’s declared reap.json, and it is a dry run by default; docs/reference/bob-reap.md documents the manifest, the keep-list and the liveness guards.
bob reap [project-root] [--apply] [--sync-ignore] [--owner <tool>[,<tool>]] [--manifest <path>] [--json]| Flag | Meaning |
|---|---|
--apply |
actually delete (default: dry-run report) |
--sync-ignore |
write the managed ignore block for every declared surface (.gitignore, or .git/info/exclude per _meta.ignore_placement) (#1688) |
--owner <t>[,<t>] |
only surfaces owned by these tools (warp-drive|swarm|dev-up|docs-site|dash|qa|misc) |
--manifest <path> |
explicit manifest path (default <root>/reap.json) |
--json |
machine-readable report |
| Exit | Meaning |
|---|---|
| 0 | clean |
| 1 | a deletion failed |
| 2 | config / usage error, including a keep-list refusal |
Engine: exec scripts/cli/bob-reap · Issue: #2059 · Since: v1.274.0 · Was: bob-reap · Read next: bob-reap
bob dash status
Section titled “bob dash status”The tooling dashboard: global items and every registered project’s symlink status, port band, warp-drive harness defects, and last bob ready verdict.
bob dash status [--projects-only | --global-only | --matrix | --ports | --check <project>]| Flag | Meaning |
|---|---|
--projects-only |
only the per-project symlink status |
--global-only |
only the global tooling inventory |
--matrix |
the project × item provisioning matrix |
--ports |
the per-project dev-port bands |
--check <project> |
grade one project and exit non-zero on a broken link |
| Exit | Meaning |
|---|---|
| 0 | rendered |
| 1 | usage error, unknown project, or –check found a broken link |
Engine: exec scripts/cli/cdb · Issue: #2059 · Since: v1.274.0 · Was: cdb · Read next: Port allocation
bob dash generate
Section titled “bob dash generate”Generate a project’s static dashboard (bugs, releases, changes, incidents, journal, cross-refs) into .dash/ from the current directory.
bob dash generate [project-dir]| Exit | Meaning |
|---|---|
| 0 | generated |
| 1 | build failed |
Engine: exec scripts/cli/cdg · Issue: #2059 · Since: v1.274.0 · Was: cdg · Read next: Port allocation
bob dash serve
Section titled “bob dash serve”Start the dashboard server for the current project on its ledger-assigned port, or list / stop running dashboards and show port allocations.
bob dash serve [--tailnet | --list | --stop <name> | --stop --all | --ports]| Flag | Meaning |
|---|---|
--tailnet |
bind this machine’s Tailscale address instead of localhost (#1736); refuses to start when Tailscale is down |
--list |
every dashboard with its running status |
--stop <name> |
stop every dashboard server for a project, any port and bind (#2563); –all stops every BoB dashboard on this machine |
--ports |
each project’s port band |
| Exit | Meaning |
|---|---|
| 0 | started, listed, or stopped |
| 1 | server failed to start, Tailscale down under –tailnet, or a server that would not stop |
Engine: exec scripts/cli/cds · Issue: #2059 · Since: v1.274.0 · Was: cds · Read next: Port allocation
bob serve
Section titled “bob serve”Converge this machine’s declared tailscale serve front door (#2407): one MagicDNS address, no port, with /bob and every declared project’s /<project>/warp path-routed to its loopback dashboard port, from the machines.json serve block; a report by default, –apply adds or updates BoB’s own routes, never removes a handler it did not declare, and installs and starts every routed project’s always-on dashboard unit; HTTP with https unavailable until tailnet certificates are on; tailscale funnel is refused in code (decision #1773).
bob serve [--apply] [--machine <id>] [--json]| Flag | Meaning |
|---|---|
--apply |
converge: add or update each declared route on the effective listener (:443 with certificates, else :80), remove BoB’s own routes from the other one, and install and start each routed project’s dashboard unit that is missing, stopped or out of date |
--machine <id> |
the machines.json entry to use (default: this machine, or BOB_MACHINE_ID) |
--json |
one bob-serve/1 document: host, scheme, https (on / unavailable / off), routes with state (ok / missing / differs / stale), upstream and URL, undeclared handlers, commands, services (each routed project’s dashboard unit and its state), verdict, error |
| Exit | Meaning |
|---|---|
| 0 | converged, applied, or no serve block declared |
| 1 | drift remains (a route, or a dashboard unit not running), or an apply step failed (named, with its fix) |
| 2 | usage or config error, including a declaration or argument naming funnel |
| 3 | Tailscale is not installed or not running |
Engine: node scripts/fleet/serve.js · Issue: #2407 · Since: v1.277.0 · Read next: Warp Drive — one address for the whole machine
Release, update and the farm
Section titled “Release, update and the farm”bob release
Section titled “bob release”The BoB release engine from a shell: a stable release (bump + CHANGELOG + vX.Y.Z tag + GitHub Release), a nightly tag on a green, moved HEAD (#2045), or promote — stable from the newest nightly, refused on an open p1-critical harness defect (#2057) and held (exit 4) while a release-gating ritual is overdue (#2236); every stable release and promote reports a docs currency gate line — stale pages and commands without a how-to — held when _workflow.docs_release_gate is on (#2554); publish <tag> backfills a missing GitHub Release, and a Release body over GitHub’s limit is published capped (#2557).
bob release [promote [--auto] [--allow-overdue <ritual>] | publish <vX.Y.Z> | notes --draft|--unreleased|check|next-version|render|index|url|show|site] [--channel stable|nightly] [--allow-stale-docs] [--dry-run] [--release-as patch|minor|major]| Flag | Meaning |
|---|---|
--channel <stable|nightly> |
stable (default): bump + CHANGELOG + vX.Y.Z tag + Release · nightly: lightweight nightly-YYYY-MM-DD tag |
--auto |
promote only: also refuse a nightly younger than 24 h, counted from the end of its UTC day |
--allow-overdue <ritual> |
promote only: promote over this overdue release-gating ritual (repeatable) — logged, and recorded as a decision issue before anything is released (#2236) |
--allow-stale-docs |
stable / promote: release over a held docs currency gate (stale pages or commands without a how-to) — logged, and recorded as a decision issue before anything is released (#2554) |
--dry-run |
run every gate, then preview without committing, tagging, pushing or publishing |
--release-as <patch|minor|major> |
stable only: force the bump type instead of deriving it from Conventional Commits |
| Exit | Meaning |
|---|---|
| 0 | released, tagged, or nothing to do |
| 2 | usage error |
| 3 | refused — a gate names why |
| 4 | held — a release-gating ritual is overdue while _workflow.ritual_release_gate is on; each ritual, why, and its run are named (#2236) — or the docs currency gate found stale pages or commands without a how-to while _workflow.docs_release_gate is on; each is named (#2554) |
| 5 | partial — the tag landed but its GitHub Release was not published; the cause, what landed and the finishing command (bob release publish <tag>) are named (#2557) |
Engine: exec scripts/cli/bob-release · Issue: #2059 · Since: v1.274.0 · Was: bob-release · Read next: Versioning
bob update
Section titled “bob update”Converge this machine to a release channel or tag: fetch, fast-forward the BOB_SOURCE checkout to the newest stable/nightly tag (or –to), run deploy.sh, then doctor — refusing a dirty tree or a live Claude Code session.
bob update [--channel stable|nightly] [--to <tag>] [--dry-run] [--json]| Flag | Meaning |
|---|---|
--channel <stable|nightly> |
which tag family to move to: stable = newest vX.Y.Z (default), nightly = newest nightly-YYYY-MM-DD |
--to <tag> |
an explicit tag instead of a channel’s newest (its name records the channel); excludes –channel |
--dry-run |
print the tag it would move to; fetches, writes nothing |
--json |
machine-readable result (schema bob-update/1) |
| Exit | Meaning |
|---|---|
| 0 | updated and bob doctor converged |
| 1 | updated; bob doctor reports drift |
| 2 | usage error, or no source checkout to update |
| 3 | refused — dirty tree, off the main branch, cannot fetch, unknown / no tag, not fast-forwardable, or deploy failed (the reason is named) |
| 4 | live-session — a Claude Code session is running on this machine (#2040 guard; no –force-live here) |
Engine: bash scripts/update/update.sh · Issue: #2046 · Since: v1.274.0 · Read next: Versioning
bob tick
Section titled “bob tick”One unattended maintenance cycle under a lock: bob groom –all –apply → bob plan build –from farm → the host converged on BOB_SOURCE when it is behind source and safe to deploy (deploy.sh + bob doctor, #2472) → one bob warp start run, waited for → flightplan reconcile → fleet snapshot → the wiki maintainer (bob wiki maintain, a real run only at automation Level 3, #2389) → the skill proposer on bigbrain only (bob wiki propose –auto, a real run only at Level 3, #2391) → nightly and promote –auto on BOB_SOURCE → bob update, whose guard refuses a live session only when the nightly would rewrite settings.json hooks (#2746) → a tick-digest/1 digest, commented on the plan and sent with bob notify → brief reconcile (bob brief –reconcile –apply, #3100) → the portfolio briefing (bob brief –send –scheduled, none inside the declared quiet hours, #2246). –dry-run runs every step read-only and files nothing.
bob tick [--dry-run] [--cwd <dir>] [--json] | bob tick --pause | --resume | bob tick --install-timer [--machine <id>] [--dry-run] [--json] | --uninstall-timer| Flag | Meaning |
|---|---|
--dry-run |
every step read-only — groom without –apply, the farm queue instead of a plan build, warp start –dry-run, release/promote/update –dry-run; creates no issue, branch, tag, PR or commit |
--cwd <dir> |
the project the tick maintains (default: the current directory); release, promote and update act on BOB_SOURCE |
--json |
the tick-digest/1 document on stdout (human lines to stderr) |
--pause |
write $BOB_HOME/.bob-tick.pause by hand — every later tick exits 3 as paused (two consecutive ticks ending 1 or 4 write it themselves and send one bob notify –level block, #2055) |
--resume |
remove the pause file and reset the failed-tick count |
--install-timer |
render bob-tick.service + bob-tick.timer from this machine’s machines.json bob_workload into ~/.config/systemd/user and enable the timer — Linux only (refused on macOS, where launchd is the path), idempotent, –dry-run writes nothing (#2056) |
--uninstall-timer |
disable the timer and remove both units (#2056) |
--machine <id> |
with –install-timer: the machines.json entry whose bob_workload is installed (default: the host machines.json resolves) |
| Exit | Meaning |
|---|---|
| 0 | tick complete or dry-run complete |
| 1 | run blocked — a pipeline step failed (named in the digest) |
| 2 | usage error |
| 3 | another tick holds $BOB_HOME/.bob-tick.lock, the tick is paused ($BOB_HOME/.bob-tick.pause — bob tick –resume), or the project is decided archive (#3609) |
| 4 | budget — the run outlived _workflow.tick_wall_clock_minutes (stopped gracefully) or spent more than _workflow.tick_max_tokens |
Engine: bash scripts/tick/tick.sh · Issue: #2054 · Since: v1.274.0 · Read next: Farm tick
bob wiki maintain
Section titled “bob wiki maintain”Consolidate one project’s traces into the skill-evolution wiki (#2389, part of #2387): a scrubbed, bounded packet of everything new since the watermark — loop notes, the decision log, harness defects, ledger no-trigger and improvised records, lesson and session-report issues — handed to one headless claude -p run of the wiki-maintainer prompt, whose patch edits, one log row and the regenerated index are opened as one PR on BOB_SOURCE; never a commit to master, and a second run over the same inputs is a no-op.
bob wiki maintain [--project DIR] [--source DIR] [--dry-run] [--max-records N] [--max-chars N] [--since YYYY-MM-DD] [--json]| Flag | Meaning |
|---|---|
--project <dir> |
the project whose traces are read (default: the current directory) |
--source <dir> |
the BOB_SOURCE checkout the PR is opened on (default: the BOB_SOURCE resolver) |
--dry-run |
collect and scrub only: print what a run would consume; no agent call, no watermark, no branch |
--max-records <n> |
the packet cap, oldest first (default 8); the rest waits for the next run |
--max-chars <n> |
each record is cut to this many characters (default 15000) |
--since <date> |
where a source with no watermark starts (default 30 days ago) |
--json |
one wiki-maintain/1 document |
| Exit | Meaning |
|---|---|
| 0 | done — a PR opened, a no-op, or a dry run |
| 1 | the run failed: the agent, the wiki lint, the push or the PR — nothing is consumed |
| 2 | usage or config error (no BOB_SOURCE checkout, no wiki store) |
Engine: node scripts/wiki/maintain.js · Issue: #2389 · Since: v1.281.0
bob wiki propose
Section titled “bob wiki propose”Propose one change to one skill, command or agent from the skill-evolution wiki (#2391, part of #2387): the item named, or with –auto the one with the most new wiki evidence among items with an eval suite, handed to one headless Read-only claude -p run of the skill-proposer prompt in a worktree; the change is run through the eval gate (bob eval run + gate) and opened as one PR labelled skill-proposal on BOB_SOURCE — a draft when the gate rejects it — whose body cites the pages, their traces and the gate document, with the skill-impact row recorded on the same branch; a person merges, never the proposer.
bob wiki propose (<item> | --auto) [--source DIR] [--dry-run] [--model M] [--max-cost-usd USD] [--runs N] [--json]| Flag | Meaning |
|---|---|
--auto |
propose for the item with the most new wiki evidence that has an eval suite |
--source <dir> |
the BOB_SOURCE checkout the PR is opened on (default: the BOB_SOURCE resolver) |
--dry-run |
pick the target and print what a run would read; no agent, no eval, no branch |
--model <model> |
the model the eval runs on (default: the session default) |
--max-cost-usd <usd> |
the eval cost ceiling (default _workflow.eval_max_cost_usd) |
--runs <n> |
eval runs per case |
--json |
one skill-propose/1 document |
| Exit | Meaning |
|---|---|
| 0 | done — a PR opened (a draft when the gate rejected), a no-op or a dry run |
| 1 | the run failed: the agent broke the contract, the eval or gate did not run, the push or the PR — nothing is left behind unless the branch was pushed |
| 2 | usage or config error (no item or –auto, an item with no eval suite, no BOB_SOURCE checkout) |
Engine: node scripts/wiki/propose.js · Issue: #2391 · Since: v1.281.0
bob eval run
Section titled “bob eval run”Run one item’s eval suite (#2390, part of #2387): evals/<item>/ in BOB_SOURCE through claude plugin eval with a with/without ablation, from the current directory, under a mandatory cost ceiling (–max-cost-usd, else _workflow.eval_max_cost_usd), and print one skill-eval/1 result — the mean case score with and without the item, the delta, the verdict (improved / no-signal / regressed), the trigger rate of the tool_used: Skill graders, cost, model, run id and date, validated against schemas/skill-eval.schema.json. A regressed verdict is a result, not a failure: rejecting a change is bob eval gate’s exit. bob u exam runs it.
bob eval run <item> [--model M] [--runs N] [--max-cost-usd USD] [--out FILE] [--root DIR] [--keep] [--json]| Flag | Meaning |
|---|---|
--model <M> |
the model every case runs on (default: the session default — $ANTHROPIC_MODEL, else BOB_HOME’s settings.json model) |
--runs <N> |
runs per case (default: each case’s runs:, else 3) |
--max-cost-usd <usd> |
the cost ceiling for the whole run (default: _workflow.eval_max_cost_usd, 2); 0 or less is refused |
--out <file> |
also write the skill-eval/1 result to <file>, for bob eval gate or bob u dispose –exam |
--root <dir> |
the BOB_SOURCE checkout to read the item and its suite from (default: the BOB_SOURCE resolver) |
--keep |
keep the temp dir (the assembled plugin, the platform’s result and its HTML report) and name it in the output |
--json |
print the skill-eval/1 document |
| Exit | Meaning |
|---|---|
| 0 | the eval completed — any verdict, a run the ceiling cut short included (partial: true) |
| 2 | usage: an unknown item, an item with no suite, a bad flag or no cost ceiling |
| 3 | it could not run: no claude, the platform failed or wrote no result, or the result is not a valid skill-eval/1 document |
Engine: node scripts/evals/run.js · Issue: #2390 · Since: v1.281.0 · Read next: Skill evals
bob eval gate
Section titled “bob eval gate”The acceptance rule for a skill change (#2390): pass only when a skill-eval/1 result’s with score is strictly higher than the best recorded for the same model in evals/<item>/baseline.json (with no best yet, the result’s own no-item arm is the floor); a neutral change and a partial run are rejected. –record raises the model’s best on accept and, accepted or rejected, appends one wiki/skill-impact.md row naming the proposal’s PR and the wiki pages it was built on.
bob eval gate <item> <result.json> [--model M] [--record --pr <#N|owner/repo#N> --pages <slug,slug>] [--date YYYY-MM-DD] [--root DIR] [--json]| Flag | Meaning |
|---|---|
--model <M> |
the model whose best is compared (default: the result’s model) |
--record |
write the outcome: raise the best in baseline.json on accept, append a wiki/skill-impact.md row either way |
--pr <#N> |
–record (required): the proposal’s pull request, #N or owner/repo#N |
--pages <slug,slug> |
–record (required): the wiki/patterns/ pages the proposal was built on |
--date <YYYY-MM-DD> |
–record: the row’s date (default: the result’s date) |
--root <dir> |
the BOB_SOURCE checkout holding evals/ and wiki/ (default: the BOB_SOURCE resolver) |
--json |
one skill-eval-gate/1 document |
| Exit | Meaning |
|---|---|
| 0 | accept — strictly above the recorded best |
| 1 | reject — equal, lower, or a partial run |
| 2 | usage: not a skill-eval/1 result, a result for another item, –record without –pr or –pages, or a page that does not exist |
Engine: node scripts/evals/gate.js · Issue: #2390 · Since: v1.281.0 · Read next: Skill evals
bob mirror
Section titled “bob mirror”Reconcile and publish to each repo’s declared second git host (mirrors.json): resolve / reconcile / publish / verify / status — dry run without –apply (#1747).
Operator-level plumbing configured once per repo in mirrors.json and run by the release and tick paths; docs/reference/mirror-remote.md is its home — declared state, commands, safety model and how to read a status report.
bob mirror <resolve|reconcile|publish|verify|status> [project|--all] [--apply] [--local] [--ref <branch>] [--path <dir>] [--json] [--no-probe]| Flag | Meaning |
|---|---|
--all |
every project with an enabled mirror |
--apply |
actually mutate (reconcile / publish are dry-run without it) |
--local |
(reconcile) wire the local remote only, never touching the mirror host |
--ref <branch> |
(publish / verify) this branch instead of the checked-out one |
--path <dir> |
operate on this working copy instead of the one in projects.json |
--json |
machine-readable output |
--no-probe |
(status) declared state only, no network probe |
| Exit | Meaning |
|---|---|
| 0 | ok |
| 1 | operational failure — unreachable, push rejected, or a stale mirror |
| 2 | declaration error — bad manifest, unknown project or host |
Engine: exec scripts/cli/bob-mirror · Issue: #2059 · Since: v1.274.0 · Was: bob-mirror · Read next: Mirror remote
bob forge health
Section titled “bob forge health”Forge availability classified from real gh call outcomes — operational / degraded / unreachable / unknown; the exit code is the answer (#1748).
bob forge health [status|record|observations|reset] [--json] [--no-probe] [--ttl <s>] [--window <s>]| Flag | Meaning |
|---|---|
--json |
machine-readable status |
--no-probe |
never probe; classify from the observation window alone |
--ttl <s> |
how long a probe result is trusted |
--window <s> |
the observation window |
| Exit | Meaning |
|---|---|
| 0 | operational |
| 3 | degraded — an empty result cannot be trusted |
| 4 | unreachable |
| 5 | unknown — no evidence and probing suppressed |
Engine: exec scripts/cli/forge-health · Issue: #2059 · Since: v1.274.0 · Was: forge-health · Read next: Forge health
bob forge queue
Section titled “bob forge queue”The durable write-ahead queue of issue mutations the forge could not take — status / list / show / resolve / drop / replay / clear; replay is dry-run by default, –apply delivers (#1750); an edit with an empty body is never queued or replayed, and drop sets one entry aside (#3186).
bob forge queue [status|list|show <id>|resolve <id>|drop <id>|replay [--apply]|clear] [--json]| Flag | Meaning |
|---|---|
--apply |
(replay) deliver the spooled mutations instead of previewing |
--json |
machine-readable output |
| Exit | Meaning |
|---|---|
| 0 | nothing pending, or replay drained cleanly and completely |
| 3 | (replay) something was skipped, failed, or left pending; (drop) no such pending entry |
Engine: exec scripts/cli/forge-queue · Issue: #2059 · Since: v1.274.0 · Was: forge-queue · Read next: Forge health
bob site publish
Section titled “bob site publish”Publish one site-publish/1 bundle to the operator’s site — the one publisher to it (#3103, decision on #3098): a producer (bob brief, release notes) hands over a section path and its files; the publisher refuses a file outside the section (exit 2), an undeclared section or one neither Access-gated nor public, a gated section any served host exposes without Access (#2895), an unresolvable Cloudflare account (#2984), and a live site built from a commit origin does not hold (#4418), then commits, pushes and deploys from a clean checkout of the declared target. Report-only without –apply; the site is config/site-publish.json in the operator repo.
bob site publish <bundle-dir> [--apply] [--deploy] [--force-live] [--json]| Flag | Meaning |
|---|---|
--apply |
copy, commit, push and deploy; without it the plan and the gate probes are printed and nothing is written |
--deploy |
with –apply, redeploy even when nothing changed |
--force-live |
deploy even when the live site was built from a commit origin does not hold, or what it was built from cannot be read (#4418) — the deploy replaces the whole site |
--json |
one site-publish/1 document — section, producer, files added / updated / unchanged / orphaned, gate probes, deploy account, commit, deploy |
| Exit | Meaning |
|---|---|
| 0 | reported, published or unchanged |
| 2 | usage, an invalid bundle, or a bundle file outside its section |
| 3 | no site declared, an invalid site, a refusal (undeclared section, ungated, exposed host, account) or a git failure |
| 4 | the deploy failed after the push landed |
Engine: node scripts/site/publish.js publish · Issue: #3103 · Since: v1.276.0 · Read next: Add a site producer
Operator and secrets
Section titled “Operator and secrets”bob operator show
Section titled “bob operator show”Print the resolved operator profile and which rung found it — $BOB_OPERATOR → the $BOB_HOME/.bob-operator pointer → ~/projects/bob-operator — after validating operator.json against schemas/operator.schema.json (#2267, decision #2266).
bob operator show [--json]| Flag | Meaning |
|---|---|
--json |
one bob-operator/1 document — resolution rungs, root, validity, the profile when valid |
| Exit | Meaning |
|---|---|
| 0 | resolved and valid |
| 2 | invalid profile — missing, unparseable or failing the schema; or usage |
| 3 | no operator declared — unresolved on every rung |
Engine: node scripts/operator/operator.js show · Issue: #2267 · Since: v1.274.0 · Read next: Set up your operator repo
bob operator init
Section titled “bob operator init”Scaffold an operator repo from templates/operator/ — operator.json, machines.json, provisions/, README, .gitignore and the validate workflow that runs BoB’s validators — git-init it, and write the $BOB_HOME/.bob-operator pointer only with –link (#2267).
bob operator init <dir> [--id <slug>] [--label <name>] [--forge-host <host>] [--forge-owner <owner>] [--upstream <owner/repo>] [--link] [--force] [--into-existing] [--json]| Flag | Meaning |
|---|---|
--id <slug> |
the operator id (default: the directory’s basename, kebab-cased) |
--label <name> |
the display name (default: the id) |
--forge-host <host> |
forge hostname (default github.com) |
--forge-owner <owner> |
the forge account or org that owns the operator’s repos (default: the id) |
--upstream <owner/repo> |
the BoB source repo this operator installs from (default: the declared BoB upstream, scripts/bob/upstream.json) |
--link |
also write $BOB_HOME/.bob-operator pointing at <dir> — the only way init touches BOB_HOME |
--force |
rewrite the scaffold files in a directory that already holds operator.json |
--into-existing |
scaffold into an existing git repo that already has tracked files (refused without it); never overrides the refusal of the BoB source checkout, BOB_HOME or a BoB worktree (#2627) |
--json |
one bob-operator-init/1 document |
| Exit | Meaning |
|---|---|
| 0 | scaffolded |
| 1 | refused — <dir> is inside the BoB source checkout, BOB_HOME or a worktree of the BoB repo (no override); already an operator repo (–force); an existing repo with tracked files (–into-existing); a bad id; or the scaffold failed validation |
| 2 | usage |
Engine: node scripts/operator/operator.js init · Issue: #2267 · Since: v1.274.0 · Read next: Set up your operator repo
bob operator migrate
Section titled “bob operator migrate”Move the operator data out of the BoB source checkout into the resolved operator repo WITH HISTORY — machines.json, mirrors.json, config/cloudflare-accounts.json, apps/intake/config/ and every provisions/*.json except the product’s _bob-home.json and _default.json: git format-patch –root from the source, git am –3way in the operator repo, then the files removed from the source on the branch chore/2270-move-operator-data for a PR; dry run by default (#2270).
bob operator migrate [--source <bigbrain checkout>] [--apply] [--force] [--json]| Flag | Meaning |
|---|---|
--source <dir> |
the BoB source checkout to move from (default: the resolved BOB_SOURCE) |
--apply |
perform the move; without it the plan is printed and nothing changes |
--force |
replace files the operator repo already holds (a real machines.json included) |
--json |
one bob-operator-migrate/1 document — source, operator, paths with commit counts, keep list, notes |
| Exit | Meaning |
|---|---|
| 0 | planned or moved |
| 1 | refused — a dirty tree, an existing file or branch, a git failure (am aborted, nothing applied) |
| 2 | usage |
| 3 | no operator repo resolved |
Engine: node scripts/operator/operator.js migrate · Issue: #2270 · Since: v1.274.0 · Read next: Set up your operator repo
bob secrets check
Section titled “bob secrets check”Verify every secret the operator profile declares is PRESENT on this machine and name its source — env / file / keychain / gh-secret / op probed for existence and metadata only, never a value (#2286): each secret is present, missing, insecure (a file readable by group or others) or unknown (a missing or unauthenticated op / gh CLI, no present_at locator) with a one-line fix; exit 1 when a required secret is not present.
bob secrets check [--json]| Flag | Meaning |
|---|---|
--json |
one bob-secrets/1 document — the operator, counts, one row per declared secret (name, kind, ref, state, source, fix); never a value |
| Exit | Meaning |
|---|---|
| 0 | every required secret is present (an unrequired gap is reported, never graded) |
| 1 | a required secret is missing, insecure or unknown |
| 2 | invalid operator profile, or usage |
| 3 | no operator resolved — bob operator init <dir> –link |
Engine: node scripts/security/secrets.js check · Issue: #2286 · Since: v1.274.0 · Read next: Check your secrets
bob ibob check
Section titled “bob ibob check”Grade the iBoB terminal kit read-only (#2291, cap #2289): the declared phone setup in the operator repo’s config/ibob-kit.json — schema, every target a machines.json id, every device key in secrets-inventory.json and operator.json secrets[] — then, for each target machine, reachable over the tailnet, SSH accepted (macOS Remote Login reported, never enabled), each device key authorized, mosh-server and tmux present, and the live warp/cdfork sessions listed; every failure names its fix.
bob ibob check [--machine <id>] [--json]| Flag | Meaning |
|---|---|
--machine <id> |
probe one target machine only |
--json |
one ibob-kit/1 document — the kit file, the declaration rows and one row per machine with its checks, fixes and sessions |
| Exit | Meaning |
|---|---|
| 0 | converged — every declaration row and every machine check passes |
| 1 | drift — a missing or invalid kit, an undeclared key, or a machine check failed |
| 2 | usage |
Engine: node scripts/ibob/kit.js check · Issue: #2291 · Since: v1.281.0
bob ibob attach
Section titled “bob ibob attach”List the live warp and cdfork tmux sessions on one fleet machine and print, for each, the exact command to type in the phone client (mosh or ssh, from the kit’s declared client) to attach to it (#2291). One SSH call through the fleet transport; the sessions are enumerated by seg-windows.js on the target.
bob ibob attach <machine> [--json]| Flag | Meaning |
|---|---|
--json |
one ibob-attach/1 document — the machine and each session with its command |
| Exit | Meaning |
|---|---|
| 0 | at least one session listed |
| 1 | nothing to attach to, or the machine could not be reached (the fix is printed) |
| 2 | usage |
Engine: node scripts/ibob/kit.js attach · Issue: #2291 · Since: v1.281.0
bob route status
Section titled “bob route status”What this machine’s model-route working key has used against its limit (#3590, cap #3866): one request to the route for the key’s own state — its label, usage, limit and what is left this period — read with the working key from the environment or the keychain. The key value is never printed.
bob route status [--route <name>] [--json]| Flag | Meaning |
|---|---|
--route <name> |
the route to report (default openrouter; the routes are declared in scripts/route/routes.json) |
--json |
one bob-route/1 document — route, key label, usage_usd, limit_usd, remaining_usd, limit_reset; never a value |
| Exit | Meaning |
|---|---|
| 0 | the key’s state was read |
| 1 | the route’s API failed |
| 2 | usage, or an unknown route |
| 3 | no working key on this machine, or the route rejected it |
Engine: node scripts/route/route.js status · Issue: #3590 · Since: v1.279.0
bob route mint
Section titled “bob route mint”Create this machine’s model-route working key with the management key (#3590): named bob-<machine id>, limited to the monthly amount the machine’s machines.json entry declares (routes.<route>.monthly_limit_usd, enforced by the route), and stored in this machine’s keychain — a dry run without –apply. The key value is never printed. A key of that name that already exists is left alone; –replace deletes it and mints again. A key that cannot be stored is deleted again.
bob route mint --machine <id> [--route <name>] [--apply] [--replace] [--json]| Flag | Meaning |
|---|---|
--machine <id> |
the machine the key is for — it must be the machine this runs on |
--route <name> |
the route to mint for (default openrouter) |
--apply |
create and store the key; without it, report what would be created |
--replace |
with –apply: delete the existing key of that name first, for a machine that no longer holds its value |
--json |
one bob-route/1 document — machine, key name, limit_usd, verdict, stored_at; never a value |
| Exit | Meaning |
|---|---|
| 0 | minted, already present, or a dry run |
| 1 | the route’s API failed, or the key could not be stored |
| 2 | usage, an unknown machine, a machine with no declared limit, or not this machine |
| 3 | no management key on this machine, or a key exists whose value this machine does not hold |
Engine: node scripts/route/route.js mint · Issue: #3590 · Since: v1.279.0
bob route roles
Section titled “bob route roles”Every model role BoB declares (#1231, cap #3866) — default, reasoning, fast, cheap — with the Claude Code alias agents name for it and its candidates in the order they are tried, each a model on the subscription or a route, marking any switched off: routes.<name>.enabled: false in scripts/route/routing.json, or BOB_ROUTING_DISABLE for this run.
bob route roles [--json]| Flag | Meaning |
|---|---|
--json |
one bob-failover/1 document — every role, its alias and its candidates with in_play and out_reason |
| Exit | Meaning |
|---|---|
| 0 | the roles were listed |
| 2 | scripts/route/routing.json does not load (each problem is named) |
Engine: node scripts/route/failover.js roles · Issue: #1231 · Since: v1.281.0
bob route run
Section titled “bob route run”Run a headless command on a model role with failover (#1231, cap #3866): start it on the role’s first candidate in play; when it exits non-zero and its output shows a Claude API failure — the usage limit, a 429, a 5xx or overloaded API, a retired model — or a route refuses before it starts (key at its limit, no key), start it again on the next candidate. Any other failure is the command’s own and is returned as it is. Each failover prints one line, tells the command what it fell back from (BOB_ROLE_FALLBACK_FROM) and is recorded in $BOB_HOME/route-failover.jsonl. BOB_ROUTING_DOWN=<route>[:<model>] simulates an outage. A route is per process, so failover restarts the command; an interactive session is never run through it.
bob route run --role <role> [--cwd DIR] [--result FILE] [--fresh-session-id] -- <command> [args…]| Flag | Meaning |
|---|---|
--role <role> |
the role to run on (bob route roles lists them) |
--cwd DIR |
the project to run in (default the current directory) |
--result FILE |
write a bob-failover/1 document: the candidate the command ran on, and every attempt |
--fresh-session-id |
give each restart of a command that passes –session-id <id> a new id, recorded on its attempt in –result |
| Exit | Meaning |
|---|---|
| 0 | the command succeeded |
| 2 | usage, an unknown role, or routing.json does not load |
| 3 | every candidate failed over or was out of play — nothing ran to completion |
| * | the command’s own exit, when it failed for a reason that is not the model’s |
Engine: node scripts/route/failover.js run · Issue: #1231 · Since: v1.281.0
bob route failovers
Section titled “bob route failovers”The newest model failovers on this machine (#1231): when, which role, the candidate that failed and why (its class and the matched text), what it fell back to, and the project — read from $BOB_HOME/route-failover.jsonl, which bob route run appends to.
bob route failovers [--limit N] [--json]| Flag | Meaning |
|---|---|
--limit N |
how many records to show (default 20) |
--json |
one bob-failover/1 document — the log path and the records |
| Exit | Meaning |
|---|---|
| 0 | the records were printed, or none were recorded |
Engine: node scripts/route/failover.js log · Issue: #1231 · Since: v1.281.0
bob cloudflare verify
Section titled “bob cloudflare verify”Check this machine’s Cloudflare working token (#3583, cap #3581): the project’s account — its manifest _meta.cloudflare_account, else the operator’s default_account in config/cloudflare-accounts.json — the working token that account names as its credential, read from the environment or the keychain, and one GET /accounts/{id}/tokens/verify: prints the account id, the token name and its status. With –write it also creates and deletes a KV namespace bob-verify-<timestamp> in the account and shows that a read of every other declared account with the same token is refused. The token value is never printed.
bob cloudflare verify [--cwd <dir>] [--account <key>] [--write] [--json]| Flag | Meaning |
|---|---|
--cwd <dir> |
the project whose account to use (default the current directory) |
--account <key> |
an account key from config/cloudflare-accounts.json, in place of the project’s |
--write |
also create and delete a KV namespace in the account, and read every other declared account to show it is refused |
--json |
one bob-cloudflare/1 document — account, account_id, token, status; never a value |
| Exit | Meaning |
|---|---|
| 0 | the working token is active in the account |
| 1 | the Cloudflare API failed |
| 2 | usage, or an unknown account |
| 3 | no working token on this machine, or Cloudflare rejected it |
| 4 | –write: the token could not write in its account, or another account answered it |
Engine: node scripts/cloudflare/cloudflare.js verify · Issue: #3583 · Since: v1.282.0
bob cloudflare mint
Section titled “bob cloudflare mint”Create this machine’s Cloudflare working token with the operator’s root token (#3583): named bob-<machine id>, scoped to the account and all its zones, holding every permission group Cloudflare lists except the API Tokens groups, and stored in this machine’s keychain under the account’s credential name — a dry run without –apply. The token value is never printed. A token of that name that already exists is left alone; –replace deletes it and mints again. A token that cannot be stored is deleted again. When Cloudflare refuses to let the root token grant some groups, it exits 4 naming them and files one todo for a dashboard-built token; a second run files no second todo.
bob cloudflare mint --machine <id> [--account <key>] [--apply] [--replace] [--json]| Flag | Meaning |
|---|---|
--machine <id> |
the machine the token is for — it must be the machine this runs on |
--account <key> |
an account key from config/cloudflare-accounts.json (default the default_account) |
--apply |
create and store the token; without it, report what would be created |
--replace |
with –apply: delete the existing token of that name first, for a machine that no longer holds its value |
--json |
one bob-cloudflare/1 document — machine, account_id, token, groups, excluded, verdict, stored_at; never a value |
| Exit | Meaning |
|---|---|
| 0 | minted, already present, or a dry run |
| 1 | the Cloudflare API failed, or the token could not be stored |
| 2 | usage, an unknown machine or account, or not this machine |
| 3 | the root token is missing or rejected, or a token exists whose value this machine does not hold |
| 4 | Cloudflare refused to let the root token grant some permission groups — the todo for a dashboard-built token is filed, or already open |
Engine: node scripts/cloudflare/cloudflare.js mint · Issue: #3583 · Since: v1.282.0
Work attribution
Section titled “Work attribution”bob labor report
Section titled “bob labor report”Agent active-hours from the Claude Code transcripts on this machine, one clock per project (#4420, cap #3135): every session transcript under ~/.claude/projects/<slug>/ (a Task subagent’s transcript under <session>/subagents/ folded into its parent session) is turned into active spans by the gap rule — consecutive transcript events closer than G (gap_minutes in the operator repo’s config/billing.json, else 10 minutes, else –gap; the report says which) form one span, a longer gap is idle — and the tool rule — the interval from a tool_use to its own tool_result is never idle, whatever its length. The spans of every session on one project (parallel terminals, bob fork worktrees, subagents) are unioned, so a project never accrues more than one hour per wall-clock hour. Prints hours per project per day over the window (–since, default the last 7 days, to –until, default now), one block per project that has a transcript in the window, or the one –project named (zero hours when it has none). Report only — nothing is filed, priced or billed; forward-only by decision on #3135, a historical number is one –since run over the transcripts that survive. With –fleet (#4422) the same hours and list-price COGS per machine and in total, for one –project or every project, read from the fleet snapshots each machine publishes (summary.labor, from this meter and the token ledger priced by token-report.js) — a machine is fresh, stale (its newest snapshot older than 24 h) or never (none), its figures add across machines, and the total is labelled partial whenever a machine is stale, never or carries no labor read; nothing is read live. With –by job (#4423) every project’s hours are grouped under the client job its manifest’s _meta.billing names ({job, billable}; BoB’s own projects declare overhead, not billable — #3134), and a project with no _meta.billing is listed under unbilled (unmapped) with the manifest and the key to add, never silently dropped and never silently billed.
the meter has one invocation shape and its rules are the content — docs/reference/work-attribution.md documents it; the how-to arrives with the pricing and export slices of #3135
bob labor report [--project <name|path>] [--since <iso>] [--until <iso>] [--gap <minutes>] [--projects-dir <dir>] [--by project|job] [--json] | bob labor report --fleet [--project <name>] [--json]| Flag | Meaning |
|---|---|
--project <name|path> |
one project only — its name (what project-name.js resolves a checkout to), a transcript-directory slug, or a checkout path; reported with zero hours when no transcript falls in the window |
--since <iso> |
the start of the window (a date is its local midnight); default the local midnight six days before –until |
--until <iso> |
the end of the window; default now |
--gap <minutes> |
G for this run, over billing.json and the default; the document names the source as flag |
--projects-dir <dir> |
read transcripts from this directory instead of ~/.claude/projects — an archived transcript tree for a one-off historical run |
--by project|job |
project (default): one block per project; job: one block per client job from each project’s manifest _meta.billing {job, billable} (operator repo, provisions/<project>.json), then unbilled (unmapped) listing every project in the window with no billing block and the key to add; a malformed block counts as unmapped. Not with –fleet (exit 2). |
--fleet |
hours and COGS per machine and in total from the fleet snapshots in $BOB_FLEET_SNAPSHOTS (else <BOB_HOME>/fleet/snapshots), each machine fresh / stale / never, the total partial when any is stale, never or unread; –since, –until, –gap and –projects-dir do not apply (exit 2) |
--json |
one bob-labor/1 document on stdout: generated_at, projects_dir, window {since, until}, gap_minutes, gap_source {source: billing.json | default | flag, path}, project (the selector, or null), rules, counts {transcript_dirs, projects, sessions}, projects [{project, transcript_dirs, hours, sessions [{id, file, events, subagents, spans, hours}], spans [{start, end, hours, sessions}], days [{date, hours, spans, sessions}]}], error; with –fleet one bob-labor-fleet/1 document: generated_at, snapshots_dir, stale_after_seconds, project, machines [{id, role, status, generated_at, age_seconds, readable, reason, window, hours_30d, usd_30d, qualified, unrecorded}], projects [{project, by_machine, hours_30d, usd_30d, qualified, unrecorded, partial, partial_reasons}], counts, partial, partial_reasons; with –by job also by: job, jobs [{job, billable, hours, projects [{project, hours, billable, manifest}]}] and unmapped {hours, projects [{project, hours, manifest, reason, fix}]} |
| Exit | Meaning |
|---|---|
| 0 | reported — a project with no transcript in the window is reported with zero hours |
| 2 | usage: a bad flag or date, a –gap that is not a positive number, or an unparsable config/billing.json (named; the gap is never silently defaulted over it); a meter flag beside –fleet; a –by that is not project or job |
Engine: node scripts/labor/labor.js report · Issue: #4420 · Since: unreleased · Read next: bob labor
bob labor reconcile
Section titled “bob labor reconcile”Every transcript on this machine has one priced record in the token ledger (#4421, cap #3135): each session transcript under ~/.claude/projects/<slug>/ written since the window opened (–since, default 30 days) is classified against the ledger’s session records by session id — recorded, unrecorded (no record and at least one priced API response: a session killed with its tmux window, a crash, a sleep, or one from before the SessionEnd hook existed), settling (no record but written inside –settle minutes, default 60: the session may be live or its hook still measuring — listed, never recorded) or empty (nothing to price). Without –apply, one line per unrecorded transcript (project, session id, last event, response count) and a summary; –apply appends one type: session record per unrecorded transcript — kind interactive, source reconcile, measured by token-snapshot.js the way every other writer measures (per-response counting #4204, provenance #1806), stamped at the transcript’s last event — and a second –apply appends nothing. One record per session id in both directions: the reconcile refuses a session any record names, and the SessionEnd hook refuses a session the reconcile recorded, naming it. The fleet snapshot and bob tick run it with –apply; bob status –scope project and bob doctor print the count.
the pass runs unattended inside the fleet snapshot and bob tick, and by hand only as the fix bob status and bob doctor name — docs/reference/token-monitoring.md documents it
bob labor reconcile [--apply] [--project <name>] [--since <iso>] [--settle <minutes>] [--projects-dir <dir>] [--json]| Flag | Meaning |
|---|---|
--apply |
append the records; without it, report what would be written |
--project <name> |
one project only — its checkout name or its transcript-directory slug |
--since <iso> |
the start of the window, by transcript write time (a date is its local midnight); default 30 days ago — a one-off over surviving history is one wide –since run |
--settle <minutes> |
a transcript written more recently than this is settling and is listed, not recorded (default 60; 0 records everything) |
--projects-dir <dir> |
read transcripts from this directory instead of ~/.claude/projects |
--json |
one bob-labor-reconcile/1 document on stdout: apply, ledger, projects_dir, window, settle_minutes, project, counts {transcripts, recorded, unrecorded, settling, empty, written, failed}, by_project {name: the same counts}, unrecorded [{session_id, project, dir, cwd, first_event, last_event, responses, model, mtime}], settling [the same, with settles_at], written [{session_id, project, timestamp, message_count, total_tokens, model}], failed [{session_id, reason}], ok, error |
| Exit | Meaning |
|---|---|
| 0 | no unrecorded transcript is left in the window |
| 1 | one or more unrecorded transcripts (report only), or –apply could not price one |
| 2 | usage: a bad flag, date or settle value |
Engine: node scripts/labor/labor.js reconcile · Issue: #4421 · Since: unreleased · Read next: bob labor
Rituals
Section titled “Rituals”bob ritual due
Section titled “bob ritual due”Which rituals are overdue, due or upcoming per project — the declared _meta.rituals schedule or liveness-scaled defaults, last run derived from closed ritual-run issues (#2230, #2231); a guide walkthrough is listed for each guide whose requirement still has the acceptance criterion that asked for it unticked (#3809).
bob ritual due [--project <p> | --all] [--json] [--repo owner/name] [--now YYYY-MM-DD] [--window P14D] [--runs FILE] [--snapshots DIR]| Flag | Meaning |
|---|---|
--project <p> |
one project, by _meta.project or manifest file name |
--all |
every active project manifest |
--window <duration> |
how far ahead counts as due (default P14D) |
--runs <file> |
last-run dates instead of the forge read |
--json |
one bob-rituals-due/1 document |
| Exit | Meaning |
|---|---|
| 0 | nothing overdue |
| 1 | at least one ritual overdue |
| 2 | usage or config error |
Engine: node scripts/rituals/ritual.js due · Issue: #2230 · Since: v1.274.0 · Read next: Hold a ritual
bob ritual run
Section titled “bob ritual run”Start the attended session of a ritual: resume its open run issue or open one, refuse a kit the machine role forbids (#2228), apply the ritual kit to the project checkout as a provision overlay, then print the evidence packet summary, the checklist the run embeds (#2241) and the previous run findings (#2234).
bob ritual run <ritual> [--project <p>] [--drill <name> | --drill-kind <kind>] [--machine <id>] [--guide <name|file>] [--repo owner/name] [--no-kit] [--dry-run] [--json]| Flag | Meaning |
|---|---|
--ritual <name> |
the ritual, instead of the positional name |
--project <p> |
the project (default: the one whose _meta.path holds the current directory) |
--drill <name> |
a BoB-level drill — restore, lost-laptop or farm-compromise — held on its home (bigbrain); its kind and runbook come from registry/rituals.json (#2240) |
--drill-kind <kind> |
a project’s own drill: restore, failover, credential-rotation or incident-response (required for drill without –drill) |
--machine <id> |
the machines.json id a drill rehearses losing or rebuilding — required by lost-laptop, whose run body embeds that machine’s inventory-generated revocation list |
--guide <name|file> |
guide-walkthrough only (#3809): the guide to walk — one the vocabulary lists, by name or by file, or any other .md file; the body carries the three-item walkthrough checklist |
--repo owner/name |
the repo holding the runs (default: the checkout github.com origin) |
--no-kit |
resume or open the run without applying the kit overlay |
--dry-run |
open nothing and apply nothing — report the run it would resume or open |
--json |
one bob-ritual-run/1 document: verdict, issue, url, opened, kit, checkout, machine, overlay, packet, previous {date, issue, findings}, error |
| Exit | Meaning |
|---|---|
| 0 | started, resumed, or –dry-run |
| 2 | usage or config error — unknown ritual or project, no checkout here without –no-kit |
| 3 | refused — this machine role forbids the ritual kit |
| 4 | not started — the forge could not be read, refused the create or spooled it |
| 5 | the run is open but its kit overlay could not be applied |
Engine: node scripts/rituals/ritual.js run · Issue: #2234 · Since: v1.274.0 · Read next: Hold a ritual
bob ritual open
Section titled “bob ritual open”File one ritual-run issue with the standard body (marker, scope, kit, the declared checklist embedded as tickable items at its version (#2241), evidence placeholder, findings checklist, delta against the previous run) after refusing a duplicate open run of the same ritual (#2231).
bob ritual open <ritual> [--project <p>] [--drill <name> | --drill-kind <kind>] [--machine <id>] [--guide <name|file>] [--replaces <todo>]... [--repo owner/name] [--held-on YYYY-MM-DD] [--dry-run] [--json]| Flag | Meaning |
|---|---|
--ritual <name> |
the ritual, instead of the positional name |
--project <p> |
the project (default: the one holding the current directory) |
--drill <name> |
a BoB-level drill — restore, lost-laptop or farm-compromise — filed on its home (bigbrain); the body carries the runbook’s timed checklist and an Outcome table (#2240) |
--drill-kind <kind> |
a project’s own drill kind — required for drill without –drill, refused on any other ritual |
--machine <id> |
the machines.json id the drill rehearses; required by lost-laptop, whose body embeds the machine’s revocation list from secrets-inventory.json |
--guide <name|file> |
guide-walkthrough only (#3809): the guide to walk — one the vocabulary lists, by name or by file, or any other .md file; the body carries the three-item walkthrough checklist |
--replaces <todo> |
guide-walkthrough only, repeatable (#3809): a to-do that asked the operator to follow the guide — once the run exists it gets a comment linking the run and is closed as not planned, without completed |
--held-on YYYY-MM-DD |
the held_on stamped in the marker (default today, UTC) |
--dry-run |
print the title, labels and body; file nothing |
--json |
one bob-ritual-open/1 document |
| Exit | Meaning |
|---|---|
| 0 | filed, queued, –dry-run, or every –replaces to-do converted onto the run |
| 2 | usage or config error |
| 3 | a run of this ritual is already open |
| 4 | nothing filed — the forge could not be read or refused the create; or a –replaces to-do could not be closed |
Engine: node scripts/rituals/ritual.js open · Issue: #2231 · Since: v1.274.0 · Read next: Hold a ritual
bob ritual prepare
Section titled “bob ritual prepare”Gather a run evidence packet report-only and post (or replace) it as one comment on the run issue; –due prepares every farm-eligible ritual due soon, what bob tick runs (#2233).
bob ritual prepare <run-issue> [--project <p>] [--repo owner/name] [--budget-seconds N] [--dry-run] [--json] | bob ritual prepare --due [--project <p> | --all] [--within P2D] [--budget-seconds N] [--dry-run] [--json]| Flag | Meaning |
|---|---|
--due |
prepare every farm-eligible ritual overdue or due within –within instead of one run issue |
--within <duration> |
(–due) the due window (default P2D) |
--budget-seconds <N> |
bound the whole gathering pass |
--dry-run |
gather and print (one run) or list the targets (–due); post nothing |
--json |
one bob-ritual-prepare/1 (or bob-ritual-prepare-due/1) document |
| Exit | Meaning |
|---|---|
| 0 | posted, updated, queued, or –dry-run (–due: every target prepared) |
| 1 | (–due) at least one target not prepared |
| 2 | usage or config error |
| 3 | nothing to prepare — the run is closed or declares no collectors |
| 4 | nothing posted — the forge could not be read or refused the write |
Engine: node scripts/rituals/ritual.js prepare · Issue: #2233 · Since: v1.274.0 · Read next: Hold a ritual
bob ritual close
Section titled “bob ritual close”Close a held ritual run with durable outputs: every finding links a bug, req, task, security or todo issue or says no-action (an empty run needs –no-findings, recorded), lessons and decisions are linked /journal issues never labels on the run (#2062), a checklist run records its version and the items not assessed and is refused with nothing ticked (#2241), and the closed body carries the delta against the previous run (#2234).
bob ritual close <run-issue> [--project <p>] [--repo owner/name] [--finding N]... [--no-action "<why>"]... [--journal N]... [--no-findings] [--held-on YYYY-MM-DD] [--dry-run] [--json]| Flag | Meaning |
|---|---|
--finding <N> |
a finding issue to add to the checklist (repeatable) |
--no-action <why> |
a finding that needs nothing, with its reason (repeatable) |
--journal <N> |
a /journal lesson or decision issue to link under Journal (repeatable) |
--no-findings |
close a run with an empty checklist, recording that it found nothing |
--held-on YYYY-MM-DD |
the day the ritual was held (default: the run marker) |
--dry-run |
run every check and print the closed body; write nothing |
--json |
one bob-ritual-close/1 document: verdict, findings, journal, no_findings, delta {previous, resolved, recurring, new}, problems, body, error |
| Exit | Meaning |
|---|---|
| 0 | closed, queued, or –dry-run |
| 2 | usage or config error — not a ritual-run issue, a project mismatch, a bad issue number |
| 3 | refused (each problem named; the run stays open) or already closed |
| 4 | the forge could not be read or refused the write |
| 5 | closed, but the kit overlay stamped with the run could not be restored |
Engine: node scripts/rituals/ritual.js close · Issue: #2234 · Since: v1.274.0 · Read next: Hold a ritual
bob ritual decide
Section titled “bob ritual decide”Write a portfolio-review decision into a project manifest: _meta.portfolio invest / maintain / park / archive, the dormant default cadence for a parked or archived project (and active: false for archive), only _meta rewritten in the file’s own style, projects.json regenerated when active changes; an archive is carried out on GitHub too — the repo is archived, never deleted, and un-archived when the project is revived (#3609) — report-only without –apply (#2235).
bob ritual decide <project> <invest|maintain|park|archive> [--apply] [--repo owner/name] [--keep-repo] [--json]| Flag | Meaning |
|---|---|
--apply |
write the manifest (and projects.json when active changes) and archive or un-archive the GitHub repo; without it, report what would change |
--repo owner/name |
the GitHub repo to archive, when the project has no checkout on this machine and its manifest names no remote |
--keep-repo |
record the decision and leave GitHub alone (a repo someone else owns) |
--json |
one bob-ritual-decide/1 document |
| Exit | Meaning |
|---|---|
| 0 | applied, unchanged, or a report without –apply |
| 2 | usage or config error |
| 4 | the manifest was written but projects.json could not be regenerated |
| 5 | the manifest was written but the GitHub repo was not archived |
Engine: node scripts/rituals/ritual.js decide · Issue: #2235 · Since: v1.274.0 · Read next: Hold a ritual
bob ritual sweep
Section titled “bob ritual sweep”The portfolio sweep (#3609): inventory every directory under ~/projects and ~/Sites on every fleet machine — this one directly, the others over Tailscale SSH, nested repos included, a machine that cannot be reached named as not inventoried — into the operator repo’s portfolio.json; decide records one outcome per row (invest / maintain / park / archive / scrap / not-a-project); status lists the rows still undecided; apply carries the decisions into the manifests — bob ready for a directory with no manifest, the manifest path corrected to the decided row, bob ritual decide — report-only without –apply; scrap prints the deletion list per machine, takes one approval of that exact list, and deletes only what is approved and holds nothing that exists only there; audit renders the dated audit page into the operator repo; record writes the decisions into the portfolio-review run issue.
bob ritual sweep <inventory [--write] [--machines id,id] | decide <row> <outcome> [--with <row>]... [--note "<why>"] [--discard] | status | apply [--apply] [--only <row>] | scrap [--approve <digest>] [--apply] | audit [--write] | record <run-issue> [--journal <N>] [--apply]> [--json]| Flag | Meaning |
|---|---|
--write |
inventory: save the list as the operator repo’s portfolio.json, keeping every decision already recorded; audit: save the dated audit there |
--machines id,id |
inventory: scan only these machines; the rest are listed as not inventoried |
--with row |
decide: another row decided as part of the same decision (a backup beside its original); repeatable |
--note "<why>" |
decide: one line recorded with the decision |
--discard |
decide <row> scrap: accept the loss of what exists only in that directory; the scrap list then says what is lost |
--only row |
apply: carry out this one decision |
--approve digest |
scrap: record the approval of the exact list the dry run printed |
--apply |
apply: write the manifests and archive repos; scrap: delete what this machine removes from the approved list; record: write the run issue; without it, report |
--journal N |
record: the /journal decision issue linked on every status change |
--json |
one bob-portfolio/1 document, or the subcommand’s (-decide/1, -status/1, -apply/1, -scrap/1, -audit/1, -record/1) |
| Exit | Meaning |
|---|---|
| 0 | inventory complete, decision recorded, every row decided, every decision carried out, or the scrap list printed, approved or removed |
| 1 | status: at least one row is undecided; apply: a decision is blocked or failed; scrap –apply: a path could not be removed |
| 2 | usage or config error, a scrap list that is not approved or changed since its approval |
| 3 | inventory: at least one machine was not inventoried |
| 4 | record: the forge could not be read or refused the write |
Engine: node scripts/rituals/sweep.js · Issue: #3609 · Since: v1.279.0 · Read next: Hold a ritual
Since: the release a command first shipped in
Section titled “Since: the release a command first shipped in”This site is built from master, which is usually ahead of the release installed on your machine. Since tells you whether a command on this page is in your release. It names the first release that included the command, linked to that release’s page. bob doctor prints the release you run on its version line. If that release is the same as or later than a command’s Since, you have the command.
- A release tag such as
v1.274.0: the first release that included the command. unreleased: the command is onmaster, but no release includes it yet. The page never guesses the next version number.unknown: this build could not read the release history. A callout at the top of the page gives the reason, for example a shallow clone or a repository with no release tags.
How it is derived. Nobody writes these values by hand, and they are never stored in scripts/bob/commands.json. scripts/bob/since.js (#2622) reads the history of the routing table, oldest commit first, and finds the first commit that declared each command, by its noun and verb. It then picks the lowest release tag whose history contains that commit. Release tags are the ones matching version.tag_pattern in docs-site.json (default v[0-9]*), the same setting the site’s build stamp uses. Moving the table file, or changing a command’s summary, engine or flags, does not change its Since. A command that is removed and added back keeps the release of its first appearance. A command whose route is renamed gets a new Since, because it is now a new route. Run node scripts/bob/since.js resolve --root . to print every value as JSON (bob-since/1).
Why the committed copy can lag. A new release changes some values from unreleased to a tag. The drift check in tests/test-bob-dispatch.sh therefore compares this page with the Since values masked out. The docs build renders the page again, so the published site always shows current values.
Slash commands and skills
Section titled “Slash commands and skills”Some jobs can be run either from a shell with bob, or inside a Claude session with a slash command. This table lists those pairs. Everything else a session can run is in the catalogs the site build generates: slash commands, skills and agents. On GitHub, where those pages don’t exist, use the Glossary instead. To find the phrasing that triggers each one, see the Natural-Language Guide.
| In a shell | In a Claude session | Difference |
|---|---|---|
bob warp start |
/warp-drive |
bob warp start launches the run in its own tmux session from any shell; /warp-drive runs it in the session you are in. |
bob warp stop |
/stop-warp-drive |
Same abort, from a shell or from the session. |
bob plan build |
/flightplan |
/flightplan can interview for scope; bob plan build never asks. |
bob groom |
/groom |
bob groom is the headless pass (dry run unless –apply); /groom is interactive. |
bob dev up |
/dev-up |
Same engine. |
bob fork |
/cdfork |
Same engine. |
bob swarm |
/swarm |
Same loop. |
bob decompose |
/capability |
/capability writes the parent and, at Level 2+, hands its child requirements to bob decompose, which runs the gated decomposition. |
bob provision |
/provision |
Same engine; the slash command adds guidance. |
bob promotion setup |
/setup-promotion |
Same scaffold. |
bob deploy |
/deploy |
Same dispatcher and ceiling gate; /deploy acts on the session’s project. |
bob release |
/release |
Same release engine. |
bob status |
/status |
Different jobs: bob status is a health verdict; /status is a project catch-up and next-work report (/what-next –report). |
Old name → bob command
Section titled “Old name → bob command”The old command names (cdi, cdprov, warp and the rest) still work until 2026-09-21. Each bin/<was> is now a shim generated from this table by scripts/bob/gen-shims.sh (#2060): it prints the bob spelling once per shell (BOB_SHIM_QUIET=1 silences it) and then runs the bob command, passing arguments, stdio and exit status through unchanged. The old engines moved from bin/ to scripts/cli/ unchanged (#2059); a verb becomes an argument prefix, so bob warp status runs scripts/cli/warp status. #2091 moves the remaining callers to the new names before the shims are removed.
| Was | Now | Engine |
|---|---|---|
bob-mirror |
bob mirror |
scripts/cli/bob-mirror |
bob-ready |
bob ready |
scripts/ready/ready.js |
bob-reap |
bob reap |
scripts/cli/bob-reap |
bob-release |
bob release |
scripts/cli/bob-release |
cdb |
bob dash status |
scripts/cli/cdb |
cdfork |
bob fork |
scripts/cli/cdfork |
cdfork-pair |
bob pair |
scripts/cli/cdfork-pair |
cdg |
bob dash generate |
scripts/cli/cdg |
cdi |
bob init |
scripts/cli/cdi |
cdl |
bob link |
scripts/cli/cdl |
cdp |
bob promote |
scripts/cli/cdp |
cdprov |
bob provision |
scripts/cli/cdprov |
cds |
bob dash serve |
scripts/cli/cds |
dev-health |
bob dev health |
scripts/cli/dev-health |
dev-up |
bob dev up |
scripts/cli/dev-up |
forge-health |
bob forge health |
scripts/cli/forge-health |
forge-queue |
bob forge queue |
scripts/cli/forge-queue |
setup-promotion |
bob promotion setup |
scripts/cli/setup-promotion |
swarm |
bob swarm |
scripts/cli/swarm |
warp |
bob warp status · bob warp log · bob warp config · bob warp viz · bob warp stop · bob warp reap · bob warp session · bob warp finalize |
scripts/cli/warp |
Not mapped
Section titled “Not mapped”bin/bob— the router itselfbin/bob-shell.zsh— sourceable shell integration (theclaudewrapper, #1195), not an invocable entrypointbin/cdprov-interview— an alias shim forbob provision --interview(#2060; the same engine,scripts/orchestrator/interview.sh, through the gated provision path);provisionis verb-less, so it cannot also carry a verbbin/gh— the forge-health PATH shim (#1748) — a transparentgh, not a command of its own