One of the things we have been experimenting with lately is running multiple AI coding agents in parallel using tools like Claude Code. The promise is real — you can hand off several independent tasks at once and get them all done simultaneously. What I found pretty quickly, though, is that having multiple agents working in the same workspace creates a new set of problems, especially around pull requests. I started looking into using git worktrees to solve this and it has made a noticeable difference in how clean and manageable the resulting PRs are.
The Problem: Multi-Agent Workflows Without Isolation
One of the most exciting promises of tools like Claude Code is true parallelism. Instead of waiting for one AI agent to finish a task before starting the next, you can spin up three, four, or five agents and let them work simultaneously. Your sprint finishes much quicker this way.
In practice, though, running multiple agents in a single workspace creates a new kind of chaos:
- Dirty working trees: Agent A modifies a shared file while Agent B is also working on it for an unrelated reason. One of them ends up working against changes it didn’t expect.
- Context collisions: Agents reading the same files at the same time can make contradictory decisions about shared utilities, config files, or types.
- Large, unfocused PRs: Everything lands on the same branch. When you go to open a PR you end up with a large number of changed files spanning multiple unrelated features. That makes the PR hard to review and hard to reason about.
The bottleneck is not the agents themselves. It is the shared workspace that forces them to step on each other.
What are Git Worktrees?
Git worktrees are a built-in Git feature that let you check out multiple branches from a single repository simultaneously, each into its own directory on disk. They share the same .git object store, so there is no duplication of history or pack files. It is lightweight by design and does not require you to clone the repo multiple times.
The basic structure looks like this:
.git/ ← shared Git database (objects, refs, etc.)
repo/ ← primary worktree (branch: main)
repo-agent-1/ ← linked worktree (branch: feature/auth-refactor)
repo-agent-2/ ← linked worktree (branch: feature/payment-api)
repo-agent-3/ ← linked worktree (branch: feature/dashboard-ui)
Each directory is a fully functional working tree. You can build, test, and commit from any of them. The key constraint is that each branch can only be checked out in one worktree at a time.
Core Commands
Add a worktree on a new branch:
git worktree add ../repo-agent-1 -b feature/auth-refactor Add a worktree on an existing branch:
git worktree add ../repo-agent-2 feature/payment-api List all work trees:
git worktree list Remove a worktree when done:
git worktree remove ../repo-agent-1 Prune stale worktree references (e.g., after manually deleting a directory):
git worktree prune That is really all you need. The rest is just workflow.
How do you Set Up Worktrees for a Multi-Agent Workflow?
Recommended Directory Layout
I recommend keeping your worktrees as siblings to the main repo directory so paths stay predictable:
projects/
├── my-repo/ ← primary worktree (main branch)
├── my-repo-agent-1/ ← feature/auth-refactor
├── my-repo-agent-2/ ← feature/payment-api
└── my-repo-agent-3/ ← feature/dashboard-ui
Step-by-Step Setup
From inside your primary repo directory, run a git worktree add for each task you want to run in parallel:
git worktree add ../my-repo-agent-1 -b feature/auth-refactor
git worktree add ../my-repo-agent-2 -b feature/payment-api
git worktree add ../my-repo-agent-3 -b feature/dashboard-ui Each command creates the directory, creates the branch from your current HEAD, and checks it out. You now have three fully independent working trees ready for agents.
Pointing an Agent at a Worktree
Agents like Claude Code respect the directory they are launched from. Simply navigate into the worktree and start the agent:
cd ../my-repo-agent-1
claude # Claude Code now operates in this isolated worktree The agent will read, modify, and commit files only within my-repo-agent-1/ on branch feature/auth-refactor. It has no awareness of what is happening in the other worktrees.
Scripting the Setup
If you are regularly spinning up multiple agents it is worth putting together a small shell script to save time:
Practical Workflow: Running Claude Code Agents in Parallel
To make this more concrete, here is an example of what a typical sprint setup looks like with three agents running in parallel:
| Ticket | Task | Agent |
| AUTH-42 | Refactor auth module to use JWT | Agent 1 |
| PAY-17 | Implement Stripe payment webhook | Agent 2 |
| UI-88 | Build analytics dashboard components | Agent 3 |
Launch Agents in Parallel
Using a terminal multiplexer like tmux or separate terminal tabs, start each agent in its own worktree:
# Terminal 1
cd ../my-repo-auth-42
claude "Refactor the auth module to use JWT. Replace the existing session-based auth in src/auth/. Keep the existing test coverage passing."
# Terminal 2
cd ../my-repo-pay-17
claude "Implement a Stripe payment webhook endpoint at POST /webhooks/stripe. Handle payment_intent.succeeded and payment_intent.payment_failed events."
# Terminal 3
cd ../my-repo-ui-88
claude "Build the analytics dashboard components in src/components/dashboard/. Include a traffic chart, conversion funnel, and summary stats card." Each agent works in complete isolation. Agent 1 can refactor src/auth/index.ts without Agent 2 picking up unexpected changes. Agent 3 can add new component files without creating conflicts in shared utility files.
Opening PRs
When each agent finishes, push its branch and open a PR:
cd ../my-repo-auth-42 && git push origin feature/AUTH-42-jwt-refactor
cd ../my-repo-pay-17 && git push origin feature/PAY-17-stripe-webhook
cd ../my-repo-ui-88 && git push origin feature/UI-88-dashboard The result is three small, focused PRs instead of one large mixed one. Each reviewer only needs to understand one concern and each PR maps cleanly to a single ticket.
Cleanup
After PRs are merged:
git worktree remove ../my-repo-auth-42
git worktree remove ../my-repo-pay-17
git worktree remove ../my-repo-ui-88
git branch -d feature/AUTH-42-jwt-refactor feature/PAY-17-stripe-webhook feature/UI-88-dashboard What are the Benefits?
Once I started using this pattern consistently, a few things improved noticeably:
- Cleaner, smaller PRs: Each PR maps to one task, one agent, and one branch. Reviewers can understand the full scope in a reasonable amount of time rather than spending hours trying to untangle unrelated changes.
- True parallelism without collisions: Agents are working in different directories so there is no file contention or unexpected dirty state for other agents to deal with.
- Faster code reviews: A small focused PR gets reviewed and merged much faster than one that spans multiple features. The worktree approach structurally enforces this.
- Cleaner CI/CD: Each branch gets its own pipeline run. When something fails it is easy to see which agent’s work caused it without needing to sort through unrelated commits.
- Better auditability: The git log for each branch tells the story of exactly one task. That makes it easier to trace issues back to their source when something goes wrong.
- No wasted disk space: Unlike cloning the repo multiple times, linked worktrees share the .git object store. You only have one copy of your repository history regardless of how many worktrees you spin up.
Tips and Best Practices
There are a few things I have picked up along the way that make this workflow smoother:
- Name worktrees and branches consistently. A pattern like <repo>-<ticket-id> for directories and feature/<ticket-id>-short-description for branches makes it easy to match them up at a glance:
my-repo-AUTH-42/ → feature/AUTH-42-jwt-refactor
my-repo-PAY-17/ → feature/PAY-17-stripe-webhook - Scope tasks tightly before handing them to agents. Worktrees amplify good task decomposition. An agent given a vague task will still produce a messy result even in its own worktree. The cleaner the input, the cleaner the output.
- Rebase onto main regularly for long-running agent tasks to keep the branch from drifting too far. This is especially important if agents are modifying shared files like json or build.gradle.
- Use a shared .env or secrets manager. Do not duplicate secrets files across worktrees. Either symlink the file or use a secrets manager that all environments pull from:
ln -s ../my-repo/.env ../my-repo-agent-1/.env - Use a terminal multiplexer. Tools like tmux, zellij, or Windows Terminal with split panes make it easy to monitor multiple agents at once without constantly switching windows.
- Require CI to pass before review. Since branches are isolated, a failing build in one PR does not block the others. This makes it safe to run reviews in parallel as well.
There are a few things to watch out for when using this approach:
- One branch per worktree: You cannot check out the same branch in two worktrees simultaneously. Git will refuse with an error if you try. Plan your branch names upfront before spawning agents.
- git stash is global: Stashes are stored in the shared .git directory, so a stash created in one worktree is visible in all of them. It is rarely a problem in practice but worth knowing. Name your stashes to keep things clear: git stash push -m “agent-1 WIP auth”.
- Build tool isolation: Some build tools are not worktree-aware and need a bit of extra attention:
- js: Each worktree needs its own node_modules. Run npm install in each worktree directory.
- Gradle: The Gradle daemon is shared, which is usually fine, but build caches can occasionally conflict. Use –no-daemon if you see unexpected behavior.
- Docker Compose: If your setup uses hardcoded port numbers in docker-compose.yml, parallel worktrees will conflict on those ports. Override them per-worktree using .env
- IDE support varies: Not all IDEs handle multiple open worktrees the same way:
- VS Code: Open each worktree as a separate workspace window, or set up a multi-root workspace.
- JetBrains IDEs: Open each worktree as a separate project window. The IDE will index each one independently.
- Xcode: Works without any changes since each worktree is just a directory. Open the .xcodeproj or .xcworkspace from within the worktree as you normally would.
- Agents only see their worktree: If an agent needs context from another part of the codebase that it would not naturally browse to, you need to include that context explicitly in the prompt. Provide relevant file snippets or architecture notes upfront.
- Worktrees are local: The worktree setup only exists on your machine. Teammates who need to pick up the work will need to set up their own. For team-wide workflows it is a good idea to document the setup in a md or wrap it in a script.
Open Source Tools That Can Help
The console workflow above works well, but there are a handful of open source tools that reduce the friction of managing agents and worktrees, especially once you are running more than two or three in parallel.
Claude Squad
Claude Squad is a TUI application built specifically to manage multiple AI coding agents — Claude Code, Aider, Codex CLI, and others — each running in its own git worktree. It is the most direct match for the workflow described in this post.
Key features:
- One command to create an agent and worktree: Claude Squad creates the branch and worktree, launches the agent, and tracks its status all in one step.
- Live status dashboard: See all running agents, their current task, and which files they have modified in a single view.
- Pause and resume: Suspend an agent session and come back to it later without losing context.
- Multi-agent support: Works with Claude Code, Aider, OpenAI Codex CLI, and custom shell commands.
- Auto-commit and auto-push: Optionally push branches automatically when an agent signals it is done.
Install:
brew install smtg-ai/tap/claude-squad # macOS
# or
go install github.com/smtg-ai/claude-squad@latest
Launch:
cs # opens the TUI dashboard If you are going to adopt the worktree-per-agent pattern regularly, Claude Squad is worth trying first. It handles the setup and monitoring work that you would otherwise be doing manually across multiple terminal windows.
Lazygit
Lazygit is a popular open source terminal UI for Git that has solid built-in worktree support. It will not manage your agents, but it is a fast way to:
- See all your active worktrees and their branches at a glance
- Switch between worktrees and inspect their status without navigating around in the terminal
- Stage, commit, push, and open PRs across worktrees from one interface
Press w in Lazygit to open the worktrees panel. For the human side of the workflow — reviewing what agents committed, resolving conflicts, and pushing branches — Lazygit is a good addition.
Install:
brew install lazygit # macOS
winget install lazygit # Windows
sudo apt install lazygit # Ubuntu/Debian GitButler
GitButler is an open source desktop Git client built around the concept of virtual branches. It manages multiple lines of work simultaneously in the same working directory through a visual drag-and-drop interface. It takes a different approach than worktrees but solves an overlapping problem: keeping parallel work separated and turning it into clean PRs.
It is particularly useful if your agents produce changes that you want to sort into different branches after the fact. You can drag individual file hunks between branches in the UI. GitButler is available as a desktop app from gitbutler.com or built from source.
Zellij
Zellij is a modern open source terminal multiplexer with a friendlier setup than tmux and a built-in plugin system. For multi-agent workflows it lets you define a saved layout that opens each agent in its own pane, so you can monitor everything at once without switching windows.
A Zellij layout for three agents might look like:
// zellij-agents.kdl
layout {
pane split_direction="vertical" {
pane {
cwd "../my-repo-auth-42"
command "claude"
}
pane {
cwd "../my-repo-pay-17"
command "claude"
}
pane {
cwd "../my-repo-ui-88"
command "claude"
}
}
}
Launch with:
zellij --layout zellij-agents.kdl
All three agents start in their respective worktrees and are visible simultaneously. Zellij also supports session persistence, so if you disconnect and reconnect the agents are still running.
| Tool | Type | Best For |
| Claude Squad | TUI | Full lifecycle: create worktrees, launch agents, monitor, push |
| Lazygit | TUI | Reviewing and managing git state across worktrees |
| GitButler | GUI desktop | Visual branch management, sorting agent output post-hoc |
| Zellij | Terminal multiplexer | Monitoring multiple agent sessions simultaneously |
For most workflows, Claude Squad paired with Lazygit covers the most ground. Claude Squad handles the agent lifecycle and worktree creation while Lazygit handles the git review and PR process.
Conclusion
Git worktrees are one of those built-in Git features that does not get enough attention. They are lightweight, require no extra tooling to get started, and solve a real problem that comes up quickly when you start running multiple AI agents in the same repository. By giving each agent its own isolated branch and working directory, you end up with pull requests that are focused, reviewable, and easier to reason about.
The pattern itself is straightforward. Before spinning up agents, take a few minutes to create a worktree per task, point each agent at its own directory, and let them run. When they are done you push separate branches and open separate PRs. The improvement in PR quality is noticeable immediately.
If you are already using Claude Code or similar tools for parallel work I would encourage you to give this a try on your next sprint. Even running just two agents in separate worktrees instead of a shared workspace will show you the difference right away.
Disclaimer
This article was developed with the assistance of artificial intelligence tools to support drafting, editing, and clarity. The core ideas, structural planning, and technical insights reflect the original thinking and professional experience of the RBA consultant who authored the piece. AI was used as a productivity aid, while all concepts, recommendations, and perspectives remain the author’s responsibility.
About the Author
Adam Utsch & Robby Sarvis
Software Engineering & Development Team Members
Adam is a seasoned software professional with deep experience in development, deployment, and application support. With a strong engineering foundation, they specialize in building scalable solutions and mentoring others in the technologies that drive real impact. Adam is passionate about continuous improvement, collaboration, and staying ahead of the tech curve.
Robby is a full-stack developer at RBA with a deep passion for crafting mobile applications and enhancing user experiences. With a robust skill set that encompasses both front-end and back-end development, Robby is dedicated to leveraging technology to create solutions that exceed client expectations.