Skip to content

New Machine Setup

Step-by-step guide to get BoB running on a fresh machine.

Terminal only — runs before BoB/Claude is available. Every command in this guide is a shell command. New-machine setup bootstraps BoB before any Claude Code session exists, so none of these steps has a slash-command equivalent. Run them from a terminal.

Dependency Minimum Version Install
macOS or Linux macOS 13+ / Ubuntu 22+ —
Git 2.30+ brew install git or apt install git
Node.js 18+ brew install node or nvm
jq 1.6+ brew install jq or apt install jq
Claude Code CLI Latest npm install -g @anthropic-ai/claude-code

Clone the BoB source repo to a dedicated projects directory (not ~/.claude/):

Terminal window
git clone git@github.com:paulirv/bigbrain.git ~/projects/bigbrain

Add to ~/.zshrc or ~/.bashrc:

Terminal window
export BOB_HOME="$HOME/.claude" # Runtime directory (Claude Code reads this)
export BOB_SOURCE="$HOME/projects/bigbrain" # Source repo
export PATH="$HOME/.claude/bin:$PATH" # Deployed entrypoints (cdi, cdb, warp, dev-up, …)

(The bob-shell.zsh snippet installed in Step 4 also guards this PATH entry, so the export is belt-and-braces.)

Then reload: source ~/.zshrc

Deploy from the source repo to ~/.claude/:

Terminal window
# If ~/.claude/ already exists from a previous installation:
bash ~/projects/bigbrain/scripts/deploy.sh --first-run
# For a fresh machine where ~/.claude/ doesn't exist yet:
bash ~/projects/bigbrain/scripts/deploy.sh

The deploy script:

  • Syncs skills, commands, agents, hooks, scripts, templates, registry to ~/.claude/
  • Preserves machine-specific files (settings.json, settings.local.json, CLAUDE.local.md)
  • On --first-run: removes legacy .git/ and .claude/ dirs from ~/.claude/, and retires legacy ~/bin cd* shims via scripts/migrate-cd-entrypoints.sh (#1194)

BOB_HOME is never a clone. ~/.claude/ is pure deploy output plus the protected machine-specific files — first-run setup is deploy.sh --first-run, never git clone. A .git/ inside ~/.claude/ is a stale bootstrap fossil that tooling can mistake for a source checkout (#1476); routine deploys warn about it and the fleet snapshot flags it as bob_home_git_fossil (#1477).

Terminal window
bash ~/projects/bigbrain/scripts/bob-install.sh
source ~/.zshrc

This adds one guarded line to ~/.zshrc (#1195):

Terminal window
[ -f "$HOME/.claude/bin/bob-shell.zsh" ] && source "$HOME/.claude/bin/bob-shell.zsh"

The sourced snippet — deployed and version-controlled, never hand-edited — defines the claude() wrapper (-a1…-a4, -rdb flags), the cdr alias, and a guarded PATH prepend for ~/.claude/bin. It deliberately defines no aliases for bob provision/bob fork: those are bin/ entrypoints resolved via PATH, and an alias would shadow them.

When claude -aN trusts a directory (#3622). Launching with an automation flag skips Claude Code’s trust dialog, so the wrapper records the trust itself — but only for a project the operator manages. A directory is trusted when it has an operator manifest (provisions/<directory name>.json in the operator repo), or when it has no committed .claude/settings.json for trust to switch on. A directory with that file and no manifest — a repo you just cloned — is left untrusted: the wrapper prints the allow rules and hooks the file declares and the command that trusts it deliberately, bash ~/.claude/scripts/lib/trust-workspace.sh --yes <dir>. Provisioning the project (bob provision --init --auto) and launching again trusts it the ordinary way.

Migrating an older machine: if your ~/.zshrc carries the legacy inline wrapper/alias block (fenced by # --- BoB Claude Wrapper ---), just re-run bob-install.sh — it replaces the whole fenced block with the source line. Inline definitions outside the fence must be removed by hand.

Step 5: Put the Deployed Entrypoints on PATH

Section titled “Step 5: Put the Deployed Entrypoints on PATH”

No per-command symlinks are needed (#1194): the deployed ~/.claude/bin/ directory IS the command surface (bob init, bob dash status, bob promote, bob link, bob dash generate, bob dash serve, bob provision, bob warp, bob dev up, …). Just make sure it’s on PATH:

Terminal window
# In ~/.zshrc (bob-install.sh adds this on new machines)
export PATH="$HOME/.claude/bin:$PATH"

Migrating an older machine: if hand-made ~/bin shims from an earlier setup exist, they shadow ~/.claude/bin (~/bin usually precedes it on PATH). deploy.sh --first-run retires them automatically, or run the migration directly:

Terminal window
bash "$BOB_SOURCE/scripts/migrate-cd-entrypoints.sh" --dry-run # preview
bash "$BOB_SOURCE/scripts/migrate-cd-entrypoints.sh" # converge

It backs up every shim it removes to ~/bin/.bob-shim-backup/, refuses to touch files that aren’t recognizably BoB’s, and is safe to re-run. make check warns if a shadowing shim reappears.

The one-command answer is bob doctor (make check-host from the source checkout, #1921): it grades every deploy-managed surface, every symlink, the toolchain and the settings.json hook wiring on this machine, and names the fix for anything behind — Converged means the machine is what deploy.sh would produce.

Terminal window
bob doctor # exit 0 converged · 1 drift (output names the fix) · 2 error

Or piece by piece:

Terminal window
# Check deployed runtime
ls ~/.claude/skills/ ~/.claude/commands/ ~/.claude/hooks/
# Check source repo
ls ~/projects/bigbrain/scripts/ ~/projects/bigbrain/registry/
# Check CLI tools work
bob dash status --global-only
# Check dependencies
node --version # Should be 18+
jq --version # Should be 1.6+

bob ready is the one command for starting or resuming a project (#3158). Given an owner/repo it clones into this machine’s projects_root (declared in machines.json, default ~/projects) and carries on to READY:

Terminal window
bob ready example/bodmail # clone → bob init → provision → labels → ports → on bob viz, then READY / NOT READY

bob ready is idempotent and never prompts — re-run it any time; a NOT READY verdict names the fix per blocker (see bob ready). It never deploys BoB and is never blocked by another project’s live run. bob init alone still works, but it is only one of the steps.

Step 8: Publish the Fleet Snapshot on a Timer

Section titled “Step 8: Publish the Fleet Snapshot on a Timer”

audit.js view and bob status --scope fleet report a machine as never until it publishes a snapshot, and as stale once its newest snapshot is older than 24 h. Install the timer once per machine:

Terminal window
node ~/projects/bigbrain/scripts/fleet/audit.js snapshot --install-timer # launchd agent on macOS, systemd user timer on Linux

On Linux, turn on lingering too, so the user timer keeps firing while nobody is logged in:

Terminal window
loginctl enable-linger "$USER" # if polkit refuses, run it with sudo

The install is idempotent: running it again reports every unit as unchanged. To publish a snapshot right away and check the result, follow Verify an install.

Step 9: Machine-Specific Overrides (Optional)

Section titled “Step 9: Machine-Specific Overrides (Optional)”
Terminal window
cat > ~/.claude/CLAUDE.local.md << 'EOF'
# Machine: (your machine name)
- Projects directory: ~/Sites/ (or ~/Work/, etc.)
- Any machine-specific notes here
EOF

This file is gitignored and protected by deploy.sh.

  • echo $BOB_SOURCE shows ~/projects/bigbrain
  • bob dash status shows global tooling inventory
  • bob init is available (which bob)
  • Opening Claude Code in any linked project loads BoB’s CLAUDE.md
  • Skills are available (start a Claude session, type /journal)
  • Hooks fire (try editing a file on main branch – should be blocked)
  • bob doctor prints INFO snapshot timer: installed (…, every 60 min), and audit.js view --no-live shows this machine as cached

Pull the latest source, then re-deploy:

Terminal window
cd ~/projects/bigbrain && git pull
bash scripts/deploy.sh
make check

Then re-provision active projects from their manifests:

Terminal window
cdr reprovision # disaster-recovery CLI: re-applies every project's manifest

For a single project, cd <project> && bob provision --refresh is enough.

Symlinks are broken after clone:

Terminal window
# In the project directory:
bob init # Re-creates all symlinks from BOB_SOURCE

bob dash status command not found:

Terminal window
# Check ~/.claude/bin is on PATH (the deployed entrypoints live there)
echo $PATH | tr ':' '\n' | grep claude
# If missing, add to ~/.zshrc:
export PATH="$HOME/.claude/bin:$PATH"
# Then redeploy if ~/.claude/bin/bob itself is absent:
bash ~/projects/bigbrain/scripts/deploy.sh

Hooks not firing: Check that the project’s .claude/settings.json references hook paths correctly. Hooks should point to .claude/hooks/*.sh (relative to project root), and those should be symlinks to $BOB_SOURCE/hooks/.

Skills not loading: Skills auto-load from ~/.claude/skills/. If they’re missing, re-deploy:

Terminal window
bash ~/projects/bigbrain/scripts/deploy.sh