Appearance
Set Up Your Operator Repo
Your identity, fleet registry (machines.json) and project manifests (provisions/*.json) belong in an operator repo, a git repo of your own that is separate from the BoB source checkout. This page takes a machine from "no operator declared" to "operator repo holds the fleet, with history". For what the operator repo is and why it exists, see Operators.
Terminal only. These commands edit git repos and $BOB_HOME outside any session.
Before you start
A clean BoB source checkout (
git -C ~/projects/bigbrain statusshows nothing).Know where the operator repo should live.
~/projects/bob-operatoris the checked default, so a repo there is found with no pointer at all.Check where you stand:
bashbob operator show # exit 3 = no operator declared yet
What bob operator init writes
bob operator init <dir> --link does four things, and commits nothing:
| Writes | What it is |
|---|---|
operator.json | Your identity: id, label, forge, people[], routes, bob_upstream, secrets[] (names and sources only). |
machines.json | A placeholder fleet with one example machine, example-laptop — only when no fleet exists yet. While the BoB checkout still holds machines.json, init leaves it out ([=] machines.json (not written — the fleet at … still resolves …)), so this host keeps resolving until migrate moves the real fleet in. |
provisions/README.md, README.md, .gitignore, .github/workflows/validate.yml | The rest of the scaffold, plus the CI workflow that runs BoB's validators. |
$BOB_HOME/.bob-operator (only with --link) | The pointer that makes BoB resolve this repo. |
It also runs git init in <dir>, and prints the operator id it used — when you leave out --id, the id is derived from the directory name, so check it.
init exits 1 and writes nothing when <dir> is:
- inside the BoB source checkout,
$BOB_HOME, or any git worktree of the BoB repo — operator data never lives in the product or the deploy target, and no flag overrides this; - a directory that already holds
operator.json(--forcerewrites the scaffold files); - inside an existing git repo with tracked files (
--into-existingscaffolds into it anyway).
Set it up (first time)
Scaffold and link.
bashbob operator init ~/projects/bob-operator --id <your-slug> --label "<Your Name>" --linkPass
--forge-owner <account>if your repos live under a different account than the id.Make both trees clean.
migraterefuses unless the BoB checkout and the operator repo have no uncommitted changes, and the scaffold is uncommitted. Editoperator.jsonfirst (at leastpeople[]andforge), then commit the scaffold:bashcd ~/projects/bob-operator git add -A && git commit -m "chore: scaffold operator repo" git -C ~/projects/bigbrain status --short # must print nothingDry-run the move. This prints what moves (with each path's commit count), what stays in the source, and what happens to the placeholder. It changes nothing.
bashbob operator migrateExpect
machines.jsonand everyprovisions/<project>.jsonin "would move with history".provisions/_bob-home.jsonandprovisions/_default.jsonbelong to the product and stay in the source.Move it.
bashbob operator migrate --applyAdd
--forceonly if the dry run named a file already at a migrated path in the operator repo. The command:- replays every commit that touched those paths into the operator repo (
git format-patch→git am --3way), so history comes along; - removes the paths from the BoB checkout on a new branch,
chore/2270-move-operator-data.
- replays every commit that touched those paths into the operator repo (
Publish both sides.
bashcd ~/projects/bob-operator && git push -u origin HEAD # after creating the remote cd ~/projects/bigbrain && git push -u origin chore/2270-move-operator-data gh pr create --fill # merge it, then deploy
Verify
bash
bob operator show # exit 0: resolved and valid, names the rung
node ~/.claude/scripts/fleet/machine.js whoami # prints THIS machine's entry
bob doctor # the operator line names your repowhoami must print a real machine. If it still fails, the operator repo's machines.json is not your fleet. Check it before doing anything else.
Recovery: the scaffold is shadowing a live fleet
Only an operator repo scaffolded before #2627 can get here — init no longer writes the placeholder while a real fleet resolves. Symptom: you ran init --link but not migrate, and now machine: could not resolve current host, bob doctor and fleet snapshots all read example-laptop.
Park the placeholder so the fallback to the BoB checkout's
machines.jsontakes over again. This takes effect immediately:bashcd ~/projects/bob-operator git rm --cached -q machines.json 2>/dev/null; mv machines.json ~/machines.scaffold.json node ~/.claude/scripts/fleet/machine.js whoami # your real entry again (with a legacy-location warning)Commit so the operator tree is clean:
git add -A && git commit -m "chore: park the scaffold machines.json".Migrate deliberately: run step 3 (dry run) and step 4 above. With the placeholder gone,
migrate --applyneeds--forceonly if the dry run names another file already in the operator repo.
Deleting $BOB_HOME/.bob-operator is not the fix. A repo at ~/projects/bob-operator is still found on the default rung, so the placeholder keeps shadowing. At any other location, unlinking hides operator.json as well, and every manifest write (bob provision add, --init) is refused.
A second machine
The operator repo already exists, so do not run init again. It refuses a directory that holds operator.json, and --force would rewrite your files with the scaffold. Clone the repo to the checked default instead:
bash
git clone <your operator repo URL> ~/projects/bob-operator
bob operator show # resolves on the "default" rung — no pointer neededFor any other location, export BOB_OPERATOR=<dir> in your shell profile.
Related
- Operators: what lives where, and how the resolver picks a repo.
- Check Your Secrets: declare
secrets[]inoperator.jsonand verify them. - New Machine Setup