Stop Committing Provisioned Links
Stop Committing Provisioned Links
Section titled “Stop Committing Provisioned Links”BoB links provisioned skills, commands and agents into a project’s .claude/.
Those links are derived: they are gitignored and rebuilt on each machine.
A repo provisioned before that rule still commits its links. Every
bob ready or bob provision refresh then retargets or prunes them for this
machine, which leaves git dirt (M and D under .claude/) after every run.
bob provision untrack is the one-time migration that fixes this.
Terminal only. It rewrites the git index and records a commit.
Before you start
Section titled “Before you start”- Stop any warp-drive run in the repo.
untrackrefuses a repo with an active warp-drive state file. - Commit or stash your own work.
untrackrefuses a staged index or a tracked change outside.claude/, and names the reason. - You do not need to commit the port settings that
bob initwrote. Those are the_bob_portskey,server.portand the port inserver.commandandaccess.localhostindev.json, and thebob:portsblock invite.config.*orwrangler.toml.untrackrecognises them and does not refuse the repo. The report lists each such file on aportsline, and the untrack commit includes it. A file with any other edit besides that is still refused.
1. See what it would untrack
Section titled “1. See what it would untrack”cd <project>bob provision untrackIt prints one line per repo and a summary. The summary looks like
1 repo(s): 0 link(s) to untrack; 1 clean, 0 skipped, 0 refused, 0 error — report only, re-run with --apply.
It exits 0 when the repo is already clean and 1 when there are links to
untrack. The report changes nothing.
It selects only symlinks (git mode 120000) under .claude/ whose target
resolves into BOB_HOME or the BoB registry, or to nothing on this machine. It
never selects a real file. It keeps, and reports, a symlink that points
anywhere else. A repo already reported clean needs nothing.
It also untracks only a path the managed ignore block covers (#2536).
Untracking a link the block will not ignore would turn a committed link into
permanent ?? dirt — the mess this migration removes. The covered set is not
guessed: it comes from the block’s one writer, which you can read yourself:
bob provision ignore-paths # the paths the block covers herebob provision ignore-paths --json # bob-ignore-paths/1A BoB-owned link outside it is reported uncovered, left tracked, and named:
uncovered /Users/me/projects/iwpi-lab — 0 link(s) 7 BoB link(s) the managed ignore block does not cover (.claude/journal/templates/decision.md, …) — left tracked: untracking them would leave permanent ?? dirt. Fix: declare the location in provision.js updateIgnoreBlock, or move the link under a covered .claude/ directory (#2536) uncovered .claude/journal/templates/decision.md -> ~/.claude/templates/journal/decision.mdThat is drift (exit 1), not a failure: the covered links in the same repo are
still untracked in the same run. Legacy link locations seen so far are
.claude/journal/templates/*.md and .claude/templates/journal. If the engine
cannot read the covered set at all, the repo is skipped and nothing is
untracked — coverage is never assumed.
2. Apply it
Section titled “2. Apply it”bob provision untrack --apply # untrack, ignore, one commit on the current branchbob provision untrack --apply --push # …and push itThe links stay on disk. Only the index changes. The managed ignore block in
.gitignore gains each path, and one commit is recorded:
chore: untrack provisioned .claude links (#1479).
Every repo on this machine
Section titled “Every repo on this machine”bob provision untrack --fleet # report for every active manifest's checkout herebob provision untrack --fleet --apply # one commit per repoRun it once on each machine. The farm cannot reach the laptops. A repo whose
manifest sets _meta.track_provisioned: true is skipped on purpose.
Verify
Section titled “Verify”bob provision untrack; echo "exit=$?" # 0: clean — a second run is a no-opbob provision refresh && git status --short .claude/ # prints nothingExit 1 after --apply means something is still left over, and the report
says which kind (#2536):
| Report | What it means | What to do |
|---|---|---|
dangling link(s) |
the link’s target is gone | bob provision prune --apply, then check again |
live link(s) still visible to git status |
the managed ignore block does not cover them — prune will not touch a live link |
declare the location in the block’s writer (provision.js updateIgnoreBlock), or move the link under a covered .claude/ directory |
uncovered |
the same cause, caught before anything was untracked | as above; nothing was left dirty |
Exit 3 means the repo was refused, and the report says why.
Related
Section titled “Related”- Project Orchestration Handbook: the authored-vs-derived rule, and why links are not committed.
- Project Setup Guide