no git worktrees
rule
git worktrees are forbidden. work directly on the current branch in the shared checkout. never create, enter, adopt, repair, prune, move, or remove a worktree.
why: a separate checkout hides concurrent edits, splits local state, makes the working tree harder to observe, and creates late merge conflicts invisible while the work happened. isolation is not a substitute for visible specs, file headings, focused changes, and verification against shared state.
why
the active checkout is the one source of current local truth. a worktree forks that truth: concurrent edits become invisible to each other, git's textual conflict detection cannot catch the logical incompatibility, and the failure surfaces only after the broken merge is pushed. the shared tree forces coordination through visible signals — specs, file headings, focused scope — where the conflict should have been resolved in the first place.
operating boundary
| situation | required action |
|---|---|
| starting a feature, repair, or docs change | use the current repository checkout. |
a tool proposes git worktree add | reject that step; continue in the shared checkout. |
| concurrent uncommitted changes exist | preserve unrelated work, narrow the edit, re-read affected files before integration. |
| another branch/worktree in local git metadata | do not enter or alter it; inspect the current checkout only. |
| isolation seems attractive | reduce scope, stage specs first, use focused validation — never duplicate the tree. |
rare branch handoff
the current branch is the default even for "features". when an external process genuinely requires a feature branch: make and verify the change in the shared checkout first, then write one short-lived bash integration script declaring all branch mutation before it executes:
| script declaration | required detail |
|---|---|
| target branch | exact branch receiving the final merge. |
| feature branch | exact branch to create for the handoff. |
| commit boundary | exact changed files + one concise commit message. |
| verification | commands that must pass before commit and merge. |
| merge action | exact merge direction and expected resulting commit. |
| cleanup | branch deletion only after merged state is verified. |
- the script is a fast, reviewed handoff transaction — not an interactive workflow. no manual branch switching.
- never run it while another agent may be editing: branch switching changes the shared tree underneath them. wait for edits to stop, run once without pauses, verify the final current branch, remove the disposable script.
- branch handoff never authorizes a worktree. if the script cannot state exact files, branches, commit, merge, and verification, keep working on the current branch until that boundary is clear.
- no worktree even for experiments, parallel agents, review, long-running tasks, or perceived safety. the active checkout is the one source of current local truth.
good and bad
bad
$ git worktree add ../feature-xPreparing worktree (checking out 'main')$ cd ../feature-x && edit src/workspace/project# meanwhile, in the shared checkout:$ git statusnothing to commit, working tree clean# agent A's in-flight edit to service.ts is invisible here$ git worktree list/workspace/project main # agent B works here/workspace/project main # agent A edits here, unseen
agent A worktrees away and adds createUserWithBatch to
src/workspace/project; agent B stays in the main checkout refactoring
createUser into smaller steps. they never see each other's changes. A merges
back; git finds no conflict (different regions), the merge succeeds — but:
createUserWithBatchcalls the old three-stepcreateUserB removed.- imports break only at runtime because the old shape is gone.
- B never saw A's pending work; B's refactor assumed the old function could be removed.
the worktree hid the concurrent change; git's conflict detection missed the logical incompatibility; the problem appears only after the broken merge is pushed. what follows is late, expensive repair: a runtime break no diff reviewer can see coming, a bisect across two divergent histories, and two agents who both believed their own checkout was the truth. the cost grows with every additional agent — each isolated copy multiplies invisible concurrent edits.
good
both agents work in the shared checkout. agent A reads the file heading and sees
agent B's ongoing marker:
/*** ongoing:* - refactor createUser into named single-responsibility functions for better reuse.** completed:* - none.*/export async function createUser(params: CreateUserParams) {/* ... */}
agent A knows a refactor is in flight. they either:
- wait for B to finish and remove the
ongoingmarker, then buildcreateUserWithBatchagainst the new functions. - coordinate with B to define the new interface together.
one shared truth plus visible signals scales to any number of concurrent agents: each coordinates by reading the same live state, so conflicts are resolved before they are written, not after they are merged.
verification
- before changing files, confirm current repository root, branch, and status.
- do all reads, edits, generation, and validation from that checkout.
- before a final claim, re-read changed files and status on the same checkout — concurrent state must not be hidden by a detached copy.
- search procedure/config changes for
git worktreecommands; remove them from the workflow. - before executing a branch handoff script, confirm it has no manual prompt, undeclared path, or worktree command.