TL;DR
- Concurrent coding tasks need separate working directories. Branch names alone cannot separate edits inside one folder.
- Git worktrees let each task keep its own files and staging area while sharing the repository’s history.
- Claude Code, the Codex app, Cursor, and T3 Code have built-in worktree support, so you can let the tool handle setup.
- I recommend a worktree and branch per concurrent task. Review each result, then test the changes together. Merge conflicts can still happen.
One checkout used to be enough
Working on one task at a time gives you a manageable Git routine. Open the project, make your changes, commit them, and switch branches for the next thing. If a bug interrupts you, save the unfinished work in a commit or stash before moving on.
In that routine, another working directory can feel like something to set up later. The folder you have is enough for the task in front of you.
Add a second coding agent, though, and both tasks can stay active. One keeps editing while you explain the next task to the other. I think that’s where worktrees become much harder to ignore. A single developer can now have several writers working on the same codebase at once.
There’s a concrete account of this shift in incident.io’s write-up on Claude Code and Git worktrees . Rory Bain describes going from no Claude Code to four or five agents running at once, each on a different feature, and building a shell helper that creates a worktree and starts Claude in it. Each conversation got its own directory and branch.
Then several agents started editing the same project
Imagine a small application with two tasks waiting. The login form shows the wrong error after an expired session, and the reports page needs a CSV export. I’d like to give each task to an agent and let them work at the same time.
Start both in the same project folder and their changes share that folder too. The login agent edits a session helper. The export agent runs tests while that edit is half finished and sees a failure in code it hasn’t touched. It might spend its next turn trying to fix it.
The agents don’t even need to edit the same file to interfere. A command such as git add . can gather both tasks into one commit. If both rewrite the same file based on an earlier read, one can overwrite the other’s changes before Git ever gets a chance to report a merge conflict.
Giving them different branch names doesn’t create separate files on disk. Inside one checkout, switching branches changes the working directory that both agents are using.
Now the person reviewing the result has another job: work out which changes belong to which task, and whether either agent tested the code it meant to test.
A worktree gives each task room to work
A linked worktree is another checkout of the same repository in another directory. Each has its own working files, HEAD, and index, which is Git’s staging area. The worktrees share the repository’s object database and branch refs. Git’s worktree documentation explains that arrangement.
For the two tasks, I’d set things up like this:
projects/
app/ main
app-login/ fix/login-error
app-export/ feat/csv-exportThe login agent works in app-login. The export agent works in app-export. Each can edit and stage its own files without pulling the other task’s unfinished edits into the checkout. I can keep app available for review and integration.
That makes the unit of work easier to follow. Open the login directory and the diff belongs to the login task. Run its tests and the export agent’s latest edit won’t change the source files halfway through.
I’d tell each agent which directory to work in and what its task includes, and ask it to leave integration to me.
Your agent tool can handle the setup
You don’t have to manage every directory by hand. Several coding tools already make worktrees part of starting a task:
| Tool | Built-in support |
|---|---|
| Claude Code | Start a session with claude --worktree to create a separate worktree. |
| Codex app | Select Worktree under the composer when starting a task and choose the branch to base it on. |
| Cursor | Start or move an agent into a worktree in the Agents Window. |
| T3 Code | Choose New worktree for a task that needs a separate branch and working directory. |
I’d use those controls when they’re available. Knowing what Git creates underneath still helps me check where an agent is working and find its changes afterwards.
The tools don’t all manage branches the same way. Codex can start in a detached HEAD, with the worktree pointing at a commit before you give the work a branch name. Its Create branch here action lets you name that work before pushing it and opening a PR. The separate working directory exists either way.
Taking two tasks through review and merging
Here’s the manual version of the same workflow. If your tool created the worktrees, continue with setup and the task assignments below.
For a repository named app with a local main branch at the starting commit I want, I’d create both worktrees from the repository root:
git worktree add -b fix/login-error ../app-login main
git worktree add -b feat/csv-export ../app-export main
git worktree listBoth start from committed main; uncommitted edits in app stay there. The -b option creates the task branches and refuses to reuse a name that already exists. Git also refuses to check out a branch that another worktree already has, so each task gets a distinct branch. Command reference
Before starting the agents, run the project’s setup in each directory. A checkout doesn’t bring along your ignored .env file or installed dependencies. Provide the local configuration each task needs and check that its tests can run. I wouldn’t want an agent to spend its task debugging an environment I forgot to prepare. When the tool creates the worktree, Claude Code can copy ignored files listed in a .worktreeinclude file, and Cursor can run a setup script from .cursor/worktrees.json.
Next, open an agent session in each task directory. With Claude Code, for example, run these in separate terminals:
# Terminal one
cd ../app-login
claude# Terminal two
cd ../app-export
claudeThose paths assume both terminals begin in app.
Keep the assignments small. The login task should reproduce the expired-session error and fix that behavior. The export task should add the CSV download using the existing session interface. Ask both agents to test their changes and commit the finished result on their assigned branch.
After they finish, I’d review each diff and run the relevant checks in its worktree. From there, the task branches can go through pull requests or merge into main directly, depending on the project’s workflow.
Open a pull request for each task
If the project uses PRs, keep that process. A worktree gives the agent a place to make changes; its branch goes through the same review and CI checks as any other contribution.
For this example, push the finished branches from their worktrees. Run these commands from app, assuming the repository’s remote is named origin:
git -C ../app-login push -u origin fix/login-error
git -C ../app-export push -u origin feat/csv-exportThen open one PR from fix/login-error into main and another from feat/csv-export into main, using your hosting service or the agent tool’s PR action. On GitHub, the base branch is the destination and the head branch contains your changes .
I’d include what changed and how I tested it in each PR. Merge the login fix after review and required checks pass. Before merging the export, test it with the login fix included and address any conflicts. The worktree can stay available while the PR is open, so the agent has somewhere to make review changes.
Merge locally when that fits the project
For a project that allows direct local merges, return to app, make sure it has no uncommitted changes, and merge the login fix first:
git switch main
git merge fix/login-errorCheck the login behavior before bringing in the export:
git merge feat/csv-exportTest the combined application, including exporting a report after the session expires. If Git reports a conflict, resolve it and finish the merge before moving on. Git’s merge documentation covers conflict handling.
Clean up after integration
After the PRs or local merges are complete and you’ve tested the result, stop the task sessions and their dev servers. For the manually created worktrees above, remove them with:
git worktree remove ../app-login
git worktree remove ../app-exportRemoving a worktree leaves its branch in the repository. Inspect any changes Git says prevent removal before deciding what to keep. Cleanup reference
The changes still have to fit together
Return to that session helper. Suppose the login fix changes what it returns, while the export agent writes code that expects the old return value. Their edits might merge without a textual conflict and still break the export.
Separate directories let the agents work without disturbing each other’s files. They cannot make independently written changes agree. I’d decide shared interface changes before splitting the tasks, or finish the prerequisite change before assigning work that depends on it.
The application environment needs the same attention. Two dev servers can compete for one port. Two test runs can modify the same database. Assign separate ports and test databases when those tasks need them. The incident.io article describes this resource-management problem as part of running several sessions.
A worktree also isn’t a security sandbox. The repository has shared Git state, and an agent with permission to access other directories can still modify them. Filesystem permissions or a sandbox provide that restriction. Worktree isolation assumes the agent stays within its assigned checkout.
My take
I want a worktree and branch per concurrent coding task. That gives me a diff I can review on its own and a place to test it while another agent keeps working.
For one agent making one change, a single checkout is fine. Once I ask agents to work at the same time, setting up separate directories is worth the effort. I’d rather spend my review time deciding whether the login fix and the export behave correctly together than untangling which agent changed what.