← All Articles
ArchitectureMulti-Agent•8 min read•Oct 8, 2026

OpenClaw Worktree Architecture for Coding Agents: The Parts Git Still Shares

A worktree gives each agent its own files. Everything behind the files is still one repository.

Here is the failure I set my worktrees up against. Two coding agents work on the same site from the Mac mini, each in its own worktree, each on its own branch. The first one hits a failing build, runs git stash to set its half-finished edit aside, and goes to look at something else. A few minutes later the second agent, in a completely different directory, runs git stash pop to recover an experiment of its own. It gets the first agent's edit instead. The patch applies cleanly, onto a branch where it makes no sense, and the second agent commits it with a confident message about what it fixed.

Neither directory ever touched the other.

What the Worktree Guides Agree On

The top results for running parallel AI coding agents in git worktrees range from about 1,800 words to well over 6,000, and the core of each one is the same. Create a worktree per agent with git worktree add -b. Install dependencies in each one, because node_modules does not follow you. Copy the .env file, which is gitignored and therefore missing. Give every dev server its own port and every agent its own database, then review each branch before it merges, and clean up with git worktree remove and prune when you are done.

All of that is right, and I do all of it. What none of them write down is the list of things that stay shared after you have done it, or who should be doing the merging once there are more finished branches than a person wants to read before breakfast. Those two gaps are where parallel agents actually collide.

One Task, One Worktree, One Branch You Can Read

The guides mostly say one worktree per agent. I make one per task. An agent that finishes a content contract and picks up a bug fix should not carry the first job's untracked files or build cache into the second. The worktree is created when the job is claimed from the work queue and it belongs to that job for its whole life.

The branch name carries the contract. Today's branch for this page is bb/20261008-content-the, which is the prefix plus the first twenty characters of the contract ID. Ugly. Also greppable at 2 a.m., which is the only property of a branch name I have ever needed.

#!/bin/bash
# new-task.sh <contract-id> <repo>
set -eu
id="$1"; repo="$2"
wt=~/worktrees/$id/$(basename "$repo")
branch="bb/$(echo "$id" | cut -c1-20)"

git -C "$repo" worktree add -b "$branch" "$wt" main
cd "$wt" && npm ci --prefer-offline

# per-task temp dir, outside the worktree so it can never be committed
export TMPDIR=~/worktrees/$id/tmp
mkdir -p "$TMPDIR"

That last line looks fussy. It is there because of the next section.

What Every Worktree Still Shares

A linked worktree gets its own files, plus a private HEAD and index. The object database, the refs, the config and the hooks all live in the common .git directory of the main checkout, and every worktree reads and writes the same copy.

The stash. This is the one from the opening, and it deserves the most space. The stash is a single ref, refs/stash, so all worktrees push onto and pop off one stack. A bare git stash pop takes whatever is on top, from whoever put it there. The rule in every agent's instructions now is that work gets set aside with a temporary WIP commit on its own branch. If an agent really must stash, it uses git stash push -u -m "<unique-tag>", records the SHA from git stash list --format='%H %gs' immediately, restores with git stash apply <sha>, and drops its own entry by finding the tag again. Never pop. A commit on a private branch is invisible to every other agent, and a stash entry is visible to all of them.

Hooks. One agent that "fixes" a failing pre-commit hook by editing .git/hooks/pre-commit has changed the hook for every worktree at once, including the ones that never failed.

Branches. Git refuses to check out the same branch in two worktrees, which is a good guarantee. It will happily let one agent run git branch -D on another agent's branch, or reset main out from under everyone, because refs are global.

Temp directories and caches. These are outside git entirely, so no worktree guide mentions them. On macOS $TMPDIR is set per user account, so every agent session running under that account gets the same one, and any build tool that caches there can pick up another session's leftovers. Hence the per-task TMPDIR in the script above.

The path to the real checkout. Every agent knows where the live repository lives, because it is in its memory and in half the project's docs. Put an agent in ~/worktrees/<id>/openclaw-blueprint and sooner or later it will read a file from /Users/jkw/projects/openclaw-blueprint instead, or worse, fix something there. Instructions alone do not stop this. What stops it is a sandbox whose write allowlist names the worktree plus the few shared .git subdirectories a commit needs (objects, refs, logs, and the worktree's own folder under .git/worktrees) and nothing else. The security architecture piece covers the same idea for tools. Here it applies to the filesystem.

The Agent Never Pushes

Nothing a coding agent makes leaves the machine until something that is not that agent decides it should.

Merging Belongs to the Sweep

"Review each branch before merging" is good advice for one developer with three agents. It breaks down when contracts finish overnight, because the reviewer is asleep and the branches pile up. In the human-in-the-loop tiers, branch commits inside a worktree are Tier 1, autonomous and cheap to undo. Merging to main on a site that deploys from main is a different tier, so a separate process does it, with checks the agent cannot argue with.

# sweep-one.sh <branch> <allowed-paths-regex>
set -eu
b="$1"; allowed="$2"
changed=$(git diff --name-only main..."$b")

# leak: anything outside the contract's allowed paths
leak=$(echo "$changed" | grep -Evc "$allowed" || true)

# ignored files that slipped into a commit anyway
ignored=$(echo "$changed" | git check-ignore --no-index --stdin | wc -l)

[ "$leak" -eq 0 ] && [ "$ignored" -eq 0 ] || exit 1
git merge --no-ff "$b" -m "merge $b: contract ... (QA PASS, leak $leak)"
npm run build   # again, on main, after the merge

The leak count ends up in the merge message. Yesterday's merge on this repo reads merge bb/20261007-content-the: contract 20261007-content-theopenclawblueprint-com-daily (bb conveyor, QA PASS, leak 0), and the zero is the number I check first, before QA, before the diff. A branch that passes every test but touched a file outside its contract is a branch whose agent misunderstood the job, and I would rather know that than ship it.

Merge order matters more than the guides suggest. Every daily content contract on this site appends one entry to the same array in src/app/blog/page.tsx, so two of them finishing on the same night will always conflict on that file even though their pages never overlap. The sweep merges in contract-date order and re-runs the build on main after each one. A conflict on the second branch sends it back to the queue as a new job ("rebase onto main, resolve the index entry") instead of letting the sweep resolve it, because the sweep does not know which description the author meant.

Keep the Failed Worktrees

Every guide ends with cleanup. I clean up merged worktrees right after the merge with git worktree remove and git branch -d, and run git worktree prune weekly for anything deleted by hand.

Failed ones stay for seven days. A worktree from a contract that failed QA is the only complete record of what the agent actually did, including untracked files and whatever landed in the temp directory it was told to use. Deleting it on failure repeats the mistake from the self-healing article, where the restart destroys the evidence you needed to understand the crash.

Internal Links & Further Reading

FAQ

Q: Why not give each agent a full clone instead of a worktree?

A clone does isolate the stash and the hooks. It also copies the whole history and turns every merge into a push between repositories on the same disk. Worktrees plus a sandbox and a no-stash rule give me nearly the same isolation for a fraction of the disk.

Q: Can the agent run the build inside its own worktree?

It should, since the sweep rejects branches whose build fails. Point its temp directory somewhere private first, and give its dev server a port no other worktree uses, or two agents running QA at once will test each other's pages.

The Bottom Line

Give every task its own worktree and a branch name that carries the contract. Then treat the stash, the hooks, the refs and the live checkout path as shared territory, fence the filesystem with a sandbox, and let a separate sweep do the merging with a leak count it refuses to round.

The worktree keeps the files apart. You still have to keep the agents apart.

Get the free OpenClaw deployment checklist

Production-ready setup steps. Nothing you don't need.