Run BoB as a New Operator
Run BoB as a New Operator
Section titled “Run BoB as a New Operator”This page installs BoB for a second operator: a different OS user, with an
operator repo of their own that names a different forge owner. It ends with
bob doctor and bob ready both passing on a sample project, and nothing of
the first operator anywhere in the install. For what an operator is, see
Operators.
The steps are the same ones, in the same order, that
tests/acceptance/operator-clean-install.sh runs. The last section runs that
script to prove the install (#2273).
Terminal only. Run every step from a plain shell, logged in as the new
user. deploy.sh refuses while a Claude Code session is running on this
machine — any user’s, not only yours (step 2 has the command for a shared
host).
Before you start
Section titled “Before you start”- A user account with an empty home: no
~/.claude, no~/projects/bigbrain, no~/projects/bob-operator. git,node(18+),jqandghonPATH.- Your forge owner (a GitHub user or org) — this page uses
bob-operator-scratch; put yours in its place.
1. Clone BoB and check out the newest stable tag
Section titled “1. Clone BoB and check out the newest stable tag”git clone https://github.com/paulirv/bigbrain.git ~/projects/bigbraincd ~/projects/bigbraingit checkout "$(git tag -l 'v*' --sort=-v:refname | awk '/^v[0-9]+\.[0-9]+\.[0-9]+$/ && !f { print; f = 1 }')"You should see: HEAD is now at … naming a vX.Y.Z tag.
Broken looks like: fatal: could not read Username — the clone needs
access to the BoB repo. Stop and paste me what you got.
2. Deploy it to ~/.claude
Section titled “2. Deploy it to ~/.claude”bash ~/projects/bigbrain/scripts/deploy.sh --first-run --forceYou should see: the deploy summary end without a red line, and a version file:
cat ~/.claude/.bob-versionshows "channel": "stable" and the tag you checked out.
Broken looks like: exit 4 (live-session). The guard lists every
user’s processes, so it refuses while any Claude Code session runs on this
machine. If the session is yours, quit it and run the step again. If it is
another user’s (a shared host — it reads their own ~/.claude, never yours),
hand the guard only your own processes, the way the acceptance script does:
ps -U "$(id -u)" -o pid=,command= > "${TMPDIR:-/tmp}/bob-ps-$(id -un).txt"BOB_RECONCILE_PS_FILE="${TMPDIR:-/tmp}/bob-ps-$(id -un).txt" \ bash ~/projects/bigbrain/scripts/deploy.sh --first-run --forceBOB_RECONCILE_PS_FILE is the guard’s process-list seam; the guard counting
other users’ sessions is a defect of the guard, not of your install.
3. Install the shell line, then open a new terminal
Section titled “3. Install the shell line, then open a new terminal”bash ~/projects/bigbrain/scripts/bob-install.shThis adds one guarded line to ~/.zshrc or ~/.bashrc. Open a new
terminal, then:
command -v bobYou should see: /home/<you>/.claude/bin/bob (or /Users/<you>/… on a Mac).
Broken looks like: nothing printed — you are still in the old terminal.
4. Create your operator repo
Section titled “4. Create your operator repo”bob operator init ~/projects/bob-operator --id scratch-tenant --label "Scratch Tenant" \ --forge-host github.com --forge-owner bob-operator-scratch --linkThen make two edits inside the operator repo — the only files you edit on this page:
operator.json: your people (people[].name,forge_login) and, if you want them, routes. The scaffold already names your forge owner.machines.json: replace theexample-laptopentry with this machine —id,hostname(whathostname -sprints),tailscale_name,role(dev-laptop,farm-worker,serverorutility-host) andos(macOSorlinux). Without it,bob readycannot put the project onbob viz, because the fleet feed does not know this machine.
Commit, then check:
cd ~/projects/bob-operator && git add -A && git commit -m "operator: scratch-tenant"node ~/.claude/scripts/checks/check-operator.js ~/projects/bob-operatorbob operator showYou should see: check-operator exit 0 with no problems, and
bob operator show print
operator: scratch-tenant — Scratch Tenant root: /home/<you>/projects/bob-operator (resolved via pointer) forge: github.com/bob-operator-scratchresolved via pointer means --link wrote ~/.claude/.bob-operator.
Broken looks like: resolved via default — the pointer was not written
(--link left off). The repo still resolves, because ~/projects/bob-operator
is the default place, but write the pointer so it does not depend on that. Do
not re-run bob operator init … --force: it rewrites the scaffold files and
loses the edits above. Write the pointer by hand instead:
printf '%s\n' "$HOME/projects/bob-operator" > ~/.claude/.bob-operatorbob operator showA check-operator problem names the field; fix it in operator.json or
machines.json, commit, and run the check again.
5. Make a sample project
Section titled “5. Make a sample project”mkdir -p ~/projects/clean-install-sample && cd ~/projects/clean-install-samplegit init -q && git symbolic-ref HEAD refs/heads/mainprintf '# clean-install-sample\n' > README.md && git add README.md && git commit -qm "initial commit"git remote add origin https://github.com/bob-operator-scratch/clean-install-sample.gitTo have BoB create the repo on your forge instead, leave out the
git remote add line and add --new to bob ready in step 8 (needs
gh auth login).
6. On a shared host only: move the dashboard band
Section titled “6. On a shared host only: move the dashboard band”Skip this step on a machine nobody else runs BoB on.
Port bands come from a hash of the project name, so on a host where another user already serves the BoB fleet dashboard, yours wants the same ports. Pin the source project’s band in your ledger to a free one:
node ~/.claude/scripts/port-ledger.js allocate bigbrain --pin 7010 --note "shared host"cd ~/projects/bob-operator && git add -A && git commit -m "ports: pin bigbrain"You should see: a JSON band with "base": 7010.
Broken looks like: later, bob ready blocks at viz with already running on port … on another bind — pick another free base and run this step again.
7. Check the machine
Section titled “7. Check the machine”bob doctorYou should see: the run end with exit 0 — converged — and an INFO operator: scratch-tenant line.
Broken looks like: a FAIL or DRIFT line. Each names its fix; run it,
then run bob doctor again.
8. Make the project ready
Section titled “8. Make the project ready”bob ready ~/projects/clean-install-sampleYou should see: READY — clean-install-sample is warp-drive-ready on this machine. Advisories (labels not checked without gh auth login, no default
automation level, no default CI locus) are fine — they never block.
Broken looks like: NOT READY with provision: … Refusing to write manifest under …/bob-operator/provisions — that is the BOB_HOME deploy target. That is
a known defect of the stable release: bob ready, run from ~/.claude, hands
its own directory to bob provision as BOB_SOURCE when BOB_SOURCE is not
exported. Until it is fixed, run it with the source named:
BOB_SOURCE=~/projects/bigbrain bob ready ~/projects/clean-install-sample9. Confirm you edited nothing outside the operator repo
Section titled “9. Confirm you edited nothing outside the operator repo”git -C ~/projects/bigbrain status --shortgit -C ~/projects/clean-install-sample status --short --ignoredYou should see: nothing from the first command — the BoB checkout is still the tag, untouched. The second shows only what BoB writes into a project by design, all of it derived:
.claude/—bob init’s links into~/.claudeand its session state.gitignore— the managed ignore block that keeps those links out of git
Under the hood, bob ready also installs two git hooks
(.git/hooks/pre-commit, the secret scan, and .git/hooks/commit-msg) and
ignores its .logs/ in .git/info/exclude; outside the project it writes
runtime state under ~/.claude and ~/.local/state/. The project’s manifest
and projects.json land in ~/projects/bob-operator. None of it is an edit
you made: the only files you edited by hand were operator.json,
machines.json and, on a shared host, provisions/ports.json — all in the
operator repo.
Broken looks like: a changed file you did not expect (M README.md, or a
line in ~/.zshrc other than the one BoB block). Stop and paste me what you
got.
Prove it: run the acceptance script
Section titled “Prove it: run the acceptance script”The script does steps 1–9 for you in a fresh HOME. Its step 9 is stricter
than yours: it snapshots the whole HOME before bob doctor and diffs it after
bob ready, and fails on any changed path outside the operator repo that is
not on its explicit list of BoB’s own writes (the ones listed in step 9). Then
it adds the leak scan: it fails if anything the run printed (every report and
--json document), or any file in the ~/.claude it produced, carries a
literal from the operator-literal set (scripts/checks/operator-literals.json),
in any case, percent-encoded or \u-escaped, in text or binary files. The one
exemption is BoB’s declared upstream repo as a whole token, read from
scripts/bob/upstream.json; another repo whose name only starts with it is
still a leak. A file it cannot read fails the scan too.
The acceptance run — as the new user, on a host with a second user:
sudo -n -u bobtest -i bash /path/to/bigbrain/tests/acceptance/operator-clean-install.sh \ --expect-user bobtest --org bob-operator-scratch --evidence /tmp/2273-evidence.jsonIt refuses (exit 2) unless it runs as the named user with a fresh HOME. Add
--dashboard-base auto on a host where another user serves the BoB dashboard
(step 5), and --create-remote to let bob ready --new create the sample repo
on the org.
A developer run — as yourself, in a throwaway HOME:
bash tests/acceptance/operator-clean-install.sh --local --source-url ~/projects/bigbrainIt records user_isolation: false, so it can never stand in for the
acceptance run.
You should see: one line per step and PASS — …, exit 0. The evidence file
(operator-clean-install/1) holds the tag, org, user, host, the doctor and
ready verdicts, the leak list and the allow-list entries still carried until a
requirement retires them.
Broken looks like: FAIL — leaks with LEAK BOB_HOME:<file>:<line> [<literal>] lines. Each is a file BoB ships that still names its original
operator — a product fix, never a reason to edit your install. Stop and paste me
what you got.