What is git worktree and how do parallel agents use it?
A git worktree gives each coding agent its own files, but not everything is separate. We checked five tools and our repository.
Summary. A git worktree opens a second working directory from the same repository: the files are separate, while the commit history and the branches are shared. All five coding tools we looked at can open a worktree to keep agents that work in parallel apart. On 18 October 2026 we read in each tool’s own documentation how Claude Code, Codex, Cursor, Gemini CLI and GitHub Copilot open and close worktrees. The examples and the numbers come from the repository where we work with parallel agents every day. We added Google’s Antigravity CLI on 28 October 2026.
- A worktree separates the files and shares the repository. Each worktree has its own files, its own HEAD and its own index. Branches, the stash and the repository’s config (the hooks path included) are shared by all of them.
- All five tools support it, with different defaults. Where the worktree is opened, which commit it starts from, whether it brings over files such as
.env, and when it is removed all change from tool to tool. - The real problem is that they pile up. On 18 October 2026 our repository had 66 worktrees. The branches of at least 34 of them had already been merged.
- A check at session start is not enough. Of two sessions opened in the same directory, one can switch the branch the other is working on. So we use a hook that checks the branch and the commit again before every edit.
What breaks when two agents work in the same directory?
We now run coding agents in parallel most of the time: one session writes a new feature while a second one fixes a bug, and subagents change different files at the same time. If they all work in the same directory, they share the same files, the same branch and the same git index. In the repository where we build diffox, we paid for that several times. Each time left us with a rule:
- A bare commit took another agent’s work too.
git commitcommits whatever is in the index, including files that another agent in the same directory has staged. Our rule: agents working in parallel commit only their own files (git commit --only <paths>). - A
git checkout -bchanged another session’s branch. The agent’s shell goes back to its starting directory on every command, and a git command with no path given once changed the branch of a parallel session. Our rule: every git command names its path (git -C <absolute path>). - A session planned changes in a directory that switched branches 3 times in 40 minutes. That is why the session-start hook we described in the hooks post exists.
- Our cleanup script made the same mistake. The script that clears out merged branches used to switch every clean directory it found to
dev. But a clean directory can belong to another session that has not started writing yet; the script changed that session’s branch. Now it only moves a directory that is ondev, onmainor on a branch whose pull request has been merged.
What all of these have in common is a single directory. That is what a worktree is for: it gives each agent its own directory, its own branch and its own index. But as you will see below, it does not separate everything. We covered Claude Code’s isolation: worktree setting in the subagents post. This post looks at the repository the agents share.
What is a git worktree?
According to git’s documentation, a repository can support several working trees, so you can have more than one branch checked out at a time. The directory you get from git clone is the main worktree. The ones you open with git worktree add are linked worktrees.
A linked worktree shares everything with the repository except a few files of its own, such as HEAD and the index. The commit history is stored once; each worktree only carries its own copy of the files. These commands do most of the work:
git worktree add -b search ../project-search # new directory, new branch
git worktree list # every worktree
git worktree remove ../project-search # removes it if it is clean
git worktree prune # clears the entries of worktrees whose directory was deleted by handGit prevents some mistakes on its own. A branch can be checked out in only one worktree at a time: by default, add refuses a branch that is already checked out in another worktree. And remove only removes clean worktrees; to delete one with uncommitted changes or untracked files, you need --force.
The difference between a worktree and a branch. A branch is a name that points to a commit. A worktree is a directory where a branch’s files are checked out. When you switch branches in a single directory, the files change for everyone working in it. With worktrees, each agent stays in its own directory, on its own branch. One note: git’s own documentation still calls multiple checkouts experimental and says that submodule support is incomplete.
How do you open a worktree in coding tools?
All five tools can open a worktree themselves; in Gemini CLI the feature is experimental and you turn it on in the settings. The tools differ in where the worktree is opened, which commit it starts from, whether it brings over files that git ignores (such as .env), and when it is removed.
| Tool | How to open one | Where | Which commit it starts from | Files like .env | When it is removed |
|---|---|---|---|---|---|
| Claude Code | claude --worktree <name>; for a subagent, isolation: worktree | .claude/worktrees/<name>/ | The remote’s default branch; the local HEAD with worktree.baseRef: "head" | Copied if listed in .worktreeinclude | On exiting the session: automatically for an unnamed session if it is clean; if there is work in it, you are asked. Subagent and background worktrees once cleanupPeriodDays (default 30 days) has passed, if no work is left in them |
| Codex | Choose Worktree in a new chat | $CODEX_HOME/worktrees | The HEAD of the branch you choose, with its uncommitted changes; no branch is created, detached HEAD | Copied if listed in .worktreeinclude | Keeps the last 15 worktrees by default; takes a snapshot before deleting one |
| Cursor | Choose a worktree in the Agents Window; /worktree in the IDE | Not stated in the documentation | Not stated in the documentation | Not brought over on their own; set up by the commands in .cursor/worktrees.json | On an interval; keeps at most 25 worktrees per machine by default |
| Gemini CLI | Turned on in the settings (experimental), then gemini --worktree <name> | .gemini/worktrees/<name> | Not stated in the documentation | Not stated in the documentation | Never removed on its own; cleanup is up to you |
| GitHub Copilot CLI | copilot --worktree or /worktree in a session | <repo>.worktrees/ | The HEAD of the checkout you are in; the remote default branch with worktreeBaseRef: "defaultBranch" | Not stated in the documentation | Not stated in the documentation |
Source: each tool’s own worktree documentation, 18 October 2026. “Not stated in the documentation”: on the page we read that day, we found no sentence about this. The Codex row is about Codex in the ChatGPT desktop app, which is what the page describes. Cursor’s cleanup is described for version 3.5 and later. The GitHub Copilot app also opens a separate worktree and branch for each session.
The biggest difference is the starting point. By default, Claude Code starts from the remote’s default branch, so commits you have not pushed yet are not in the new worktree. Copilot CLI starts from the HEAD of the checkout you are in. Codex even carries the uncommitted changes of the branch you choose into the new worktree. Choose this setting on purpose, based on what the agent needs to see.
Files that git ignores do not come along to a new worktree. For this, Claude Code and Codex read a file with the same name: .worktreeinclude at the root of the repository. It is written in .gitignore syntax and copies only files that git ignores. In Cursor, setup commands in .cursor/worktrees.json do the same job; the example in its documentation copies .env with cp.
On dependencies, two tools give different advice. Cursor does not recommend symlinking dependencies into a worktree, because it can cause problems in the main worktree. Claude Code, on the other hand, can symlink large directories such as node_modules into every worktree with the worktree.symlinkDirectories setting.
There are ready-made commands for parallel work too. Claude Code’s /batch skill splits a large change across 5 to 30 subagents, each working in its own worktree. Cursor’s /best-of-n command runs the same task on several models and gives each run its own worktree. Claude Code’s agent teams, however, do not put teammates in separate worktrees; the documentation tells you to split the work so that each teammate owns a different set of files.
On 18 June 2026, Google stopped serving Gemini CLI to free users and to Google AI Pro and Ultra subscribers and pointed them to Antigravity CLI; with a paid API key or a company licence you can keep using Gemini CLI. We read Antigravity’s documentation on 28 October 2026. According to its subagent page, the main agent can give a subagent it starts its own Git worktree; when the subagent is killed, that worktree is removed automatically. The documentation does not say which commit the worktree starts from or whether it brings over files such as .env. Opening a new conversation directly in its own worktree is a feature of the desktop app; we found no flag that does this in the CLI.
What does a worktree keep separate, and what doesn’t it?
It is easy to think of a worktree as a full sandbox. But git gives each worktree only a few things of its own. The rest is shared, and some of it git does not deal with at all:

The config and the hooks path are shared. According to git, the repository’s config file is shared by all worktrees by default. In our repository, the location of the git hooks is also written in this file (core.hooksPath), as a single absolute path. So the pre-push hook, which runs before a push, runs from the copy in the main worktree, not from the copy on the branch you are pushing. On 24 August 2026 we added a new rule to this hook on a worktree branch, and its 11 tests passed. But a push from that same worktree still went through, because the main worktree held the old version. The same goes for other settings, such as your identity (user.email); for per-worktree settings you need to turn on git’s extensions.worktreeConfig.
The tools’ own permissions can be shared too. In Claude Code, a “Yes, and don’t ask again” approval you give in a worktree is written to the main worktree’s .claude/settings.local.json and applies in every worktree. In Copilot CLI, too, linked worktrees share the main repository’s permissions.
Branches and the stash are shared. According to git, every ref that starts with refs/ is shared between worktrees, and the latest stash is kept in refs/stash. A git stash pop with no stash named takes the latest one. Put these sentences from git’s documentation side by side and you get this: a git stash pop in one worktree takes the latest stash even if an agent in another worktree left it there. In a repository where agents work in parallel, a temporary commit is safer than a stash.
What lies outside git is not separated at all. A database, a port, a cache or an ignored data directory knows nothing about worktrees. In our repository we symlink a large measurement directory (.runs) into every worktree, because paid measurement results live there and must not be lost when a worktree is deleted. The .runs/ pattern in .gitignore matches only directories, so it did not ignore this link. On 21 August 2026, git status listed it as an untracked file in every worktree; it was one git add -A away from a commit. Our database tests also use a shared test database. We keep a lock directory so that tests in two worktrees do not run at the same time.
Why isn’t a check at session start enough?
Looking at the state of the directory when a session opens is useful, but only for that moment. The session-start hook in our repository tells a session that opens on a clean dev: “a branch is enough, no worktree needed”. If two sessions open on the same clean dev, both get that answer and both create a branch in the same directory. When the second one switches to its new branch, the branch the first one is working on has changed too.
So a second hook, which runs before every edit, compares the branch and the commit with what the session was last told. The details are in the hooks post; what we want to add here is what gets compared. The first thing that comes to mind is the number of uncommitted files. But on 12 September 2026 we saw that a single edit the session made itself makes a clean directory look dirty. A warning that looks at dirt mistakes the agent’s own work for someone else’s. That is why the hook looks only at the branch and the commit under it, and warns without stopping the action.
The hook cannot know who made the change, and it does not try to guess. A session that creates its own branch is also warned once; it recognises its own doing and carries on.
Claude Code also runs checks of its own for a session isolated in a worktree. According to its documentation, it refuses edits that target a path in the main checkout and commands that point git at the main checkout. The documentation also states the limit plainly: these checks do not track which files a shell command writes. A command that writes into the main checkout with cp or a redirect is not caught by them; according to the documentation, such a command is handled under your permission and sandbox settings. So what limits where an agent can write is those settings, not the worktree.
Why do worktrees pile up, and how do you clean them up?
Opening a worktree takes one command; closing it is often forgotten. As we described in the subagents post, on 27 August 2026 41 worktrees had piled up in our repository, and 37 of them were left over from a single review round. The clutter is made by workflows, not by people. That day we wrote a cleanup script. On 18 October 2026 we counted again:

git worktree list --porcelain and gh pr list; the commands and their output are in the post’s measurement file.None of the 34 worktrees whose branch had been merged had uncommitted changes. That is exactly the kind of worktree our cleanup script removes. But the script does not run by itself; the session-start hook only suggests running it, and until someone does, they all stay where they are. In all, 5 worktrees were in Codex’s directory (~/.codex/worktrees), and the other 61 under .claude/worktrees/. Going by the creation date of the directory git keeps for each worktree, 28 of those still there had been opened on a single day, 15 October. The draft of this post was also written in a worktree opened on 18 October 2026.
Git cannot tell you that a branch was merged. Our repository merges pull requests with squash, and a squash rewrites the commits. So a merged branch is neither an ancestor of dev nor a commit-for-commit match. We checked a branch a few minutes after it was merged: merge-base --is-ancestor said “not merged” and git cherry said “2 commits missing”; both were wrong. Another branch, whose entire content was in dev, showed as “36 commits ahead”. The only place that knows is the pull request. That is why our cleanup script asks GitHub, and removes only clean worktrees whose pull request has been merged.
The count itself can mislead. A worktree whose directory was deleted by hand stays in the list until git worktree prune runs, marked prunable. Our session-start hook used to count all the lines together. On 8 September 2026 it said 26 worktrees; a few commands later, git worktree list showed 7. Now it counts live and prunable entries separately, and suggests the cleanup script once there are more than 4 live worktrees or even a single prunable entry.
The tools’ own cleanup differs too. Codex keeps its last 15 worktrees by default. Cursor keeps 25 worktrees per machine by default and, according to its documentation, counts worktrees opened with git worktree add as eligible for deletion too. Claude Code sweeps up subagent and background worktrees, but leaves any that still hold work. Gemini CLI leaves the cleanup to you. If you use more than one tool in the same repository, know which one deletes what.
What should you watch for when you run agents in parallel?
Each mistake above gave us one item. Put together, they look like this:

git -C, lock and cleanup items are our repository’s rules; the stash item comes from git’s documentation, the setup item from the tools’ documentation.- Not every agent needs a worktree. A worktree is for when two pieces of work want the same repository at different commits at the same time. If a single session is working on a clean
dev, a branch is enough. Every worktree you don’t need is one more directory to clean up later. - Don’t forget the setup. A new worktree is a fresh checkout: no dependencies, no virtual environment and no
.env. The Claude Code and Gemini CLI documentation also tell you to set up your environment in each new worktree. In our repository, every worktree installs its own environment before its first test run. - Split the work by files. In our repository, tasks running at the same time were given separate files, every commit was made with
--only, and the test runs queued up behind the shared lock. - Parallel work isn’t free. According to Claude Code’s documentation, running several sessions or subagents at once multiplies token usage.
In the end, the work of parallel agents reaches the same branch as pull requests, and that branch moves forward each time one is merged. When diffox reviews a pull request, it measures the change from the point where the branch split off from the base branch (the merge base); this is the change GitHub shows on the pull request. It also reads the earlier version of the files from that same point. So if another agent’s work was merged into the base branch later, it does not get mixed into this review.
Frequently asked questions
What is a git worktree?
A git worktree is a second working directory opened from the same repository. Each worktree has its own files, its own HEAD and its own index; the commit history, the branches and the repository’s config are shared. You open one with git worktree add -b <branch> <directory> and remove it with git worktree remove <directory>. This lets you work on more than one branch at the same time, while the directory you are in stays as it is.
What is the difference between a worktree and a branch?
A branch is a name that points to a commit; a worktree is a directory where a branch’s files are checked out. When you switch branches in a single directory, the files change for everyone working in it. With worktrees, each branch stays checked out in its own directory. Git lets a branch be checked out in only one worktree at a time; if you try to check out the same branch in a second worktree, git worktree add refuses.
How do you open a worktree in Claude Code?
claude --worktree <name> (-w for short) opens a new worktree and starts the session in it. By default the worktree is created under .claude/worktrees/<name>/, on a new branch called worktree-<name>, and starts from the remote’s default branch. To make a subagent always work in its own worktree, add isolation: worktree to its definition. The documentation recommends adding the .claude/worktrees/ directory to .gitignore.
Where do Codex and Cursor keep worktrees, and when do they delete them?
In the ChatGPT desktop app, Codex opens worktrees under $CODEX_HOME/worktrees, in detached HEAD rather than on a branch. By default it keeps the last 15 worktrees and takes a snapshot of one before deleting it. In Cursor (3.5 and later), cleanup runs on an interval and by default keeps at most 25 worktrees per machine; every workspace counts toward the same limit. Cursor’s documentation does not say which directory worktrees are opened in.
Does a worktree copy the .env file and the dependencies?
Not on its own; a new worktree starts with only the files git tracks. Claude Code and Codex copy files that git ignores (such as .env) if they are listed in the .worktreeinclude file at the root of the repository. In Cursor, the setup commands go in .cursor/worktrees.json. You need to install the dependencies again in each worktree. Claude Code can symlink large directories with worktree.symlinkDirectories, while Cursor does not recommend this for dependencies.
How do you delete worktrees you no longer use?
git worktree remove <directory> removes a clean worktree; if there are uncommitted changes, you need --force. If you deleted the directory by hand, git worktree prune clears the entry left behind. Codex and Cursor delete old worktrees themselves once they pass a limit; Gemini CLI does not. Antigravity removes the worktree it gave a subagent once that subagent is killed. In a repository that merges pull requests with squash, git cannot tell whether a branch was merged; ask the pull request.