Set Up Your Operator Repo
Set Up Your Operator Repo
Section titled “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
Section titled “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:
Terminal window bob operator show # exit 3 = no operator declared yet
What bob operator init writes
Section titled “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)
Section titled “Set it up (first time)”-
Scaffold and link.
Terminal window bob 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:Terminal window cd ~/projects/bob-operatorgit add -A && git commit -m "chore: scaffold operator repo"git -C ~/projects/bigbrain status --short # must print nothing -
Dry-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.
Terminal window bob 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.
Terminal window bob 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.
Terminal window cd ~/projects/bob-operator && git push -u origin HEAD # after creating the remotecd ~/projects/bigbrain && git push -u origin chore/2270-move-operator-datagh pr create --fill # merge it, then deploy
Verify
Section titled “Verify”bob operator show # exit 0: resolved and valid, names the rungnode ~/.claude/scripts/fleet/machine.js whoami # prints THIS machine's entrybob 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
Section titled “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:Terminal window cd ~/projects/bob-operatorgit rm --cached -q machines.json 2>/dev/null; mv machines.json ~/machines.scaffold.jsonnode ~/.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
Section titled “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:
git clone <your operator repo URL> ~/projects/bob-operatorbob operator show # resolves on the "default" rung — no pointer neededFor any other location, export BOB_OPERATOR=<dir> in your shell profile.
Related
Section titled “Related”- Operators: what lives where, and how the resolver picks a repo.
- Check Your Secrets: declare
secrets[]inoperator.jsonand verify them. - New Machine Setup