Contents

Run multiple Claude Code agents in parallel without conflicts

Give each Claude Code session its own git worktree, so no two sessions edit the same files. Then let gitta watch all the worktrees together. It tells a session when another session changed something its work uses, and it runs your tests on the combined work when you merge.

1. Set up gitta once

Run gitta init in the main checkout, with the command that runs your tests. gitta calls this command the gate.

 Terminal
$ cd ~/src/microblog
$ gitta init --gate "python3 -m unittest -q"
gitta is set up in microblog.

No agent worktrees exist yet. Every worktree an agent tool creates from now on is picked up on its own.
After every step an agent takes, gitta looks at what it changed. When one agent changes a function that another agent's new code calls, gitta tells that agent right away, so it can adapt before anything reaches main.
Merging works as always, with git merge, git pull or git push. gitta hooks into those commands and runs `python3 -m unittest -q` on the combined code first. If the tests fail, it stops the merge and says which test failed and why.
Claude Code hooks added to ~/.claude/settings.json (backup next to it). They stay silent outside gitta repositories.
When gitta tells an agent about a clash, the agent fixes its code itself and mentions it to you in one sentence in its chat.
gitta never asks you anything. When a merge removes tests or weakens a security check, it says so in the merge output and in the log. The merge goes ahead unless the committed .gitta.toml sets weakened_checks to block.
To share the test command and rules with your team and the CI check, run `gitta init --team` and commit .gitta.toml.

Start your agents the way you always do. `gitta watch` shows what gitta does as it happens, and `tail -f .gitta/gitta.log` follows the same story as plain lines.

The hooks go into your user settings, ~/.claude/settings.json. Claude Code loads that file in every session, also in worktrees. You do not need a settings file in each worktree.

2. Start each session in its own worktree

Open one terminal per task and start Claude Code with --worktree (or -w) and a name. Claude Code makes the worktree under .claude/worktrees/<name>/ on a new branch worktree-<name>. See Anthropic's page Run parallel sessions with worktrees.

 Terminal
$ claude --worktree detect-language
# in a second terminal
$ claude --worktree translate-api

You can also make the worktrees yourself and start Claude Code inside each one. gitta treats both the same way.

 Terminal
$ git worktree add -b detect-language ../detect-language
$ cd ../detect-language && claude

Subagents with isolation: worktree and sessions from the Claude desktop app also use worktrees. gitta picks up every worktree of the repository, whichever tool made it. Add .claude/worktrees/ to .gitignore, as Anthropic suggests.

3. What gitta does across the sessions

This run uses microblog, the Flask app of Miguel Grinberg's Flask Mega-Tutorial. The detect-language session makes the source language of translate optional, so the translation service can detect it, and moves it to the end of the parameters. It also updates the one call that already exists. The translate-api session writes a new API endpoint that calls translate in the old order.

 Terminal
$ git worktree list
~/src/microblog                                    a975ef6 [main]
~/src/microblog/.claude/worktrees/detect-language  a975ef6 [worktree-detect-language]
~/src/microblog/.claude/worktrees/translate-api    a975ef6 [worktree-translate-api]
$ gitta status
main is the branch gitta merges finished work into. Before each merge it runs `python3 -m unittest -q` on main combined with the agent's changes.
  worktree-detect-language 2 files changed, ready to merge
  worktree-translate-api 2 files changed, ready to merge
  worktree-detect-language changed `app.translate.translate`, which worktree-translate-api's new code in app/api/translate.py uses. Check that the two changes still work together.

You don't have to run gitta status. After each tool call, the hook tells the affected session what changed:

 In the translate-api session
Gitta: agent worktree-detect-language changed `translate`, which your new code in app/api/translate.py calls. Check that your code still fits. Their version: app/translate.py:6: def translate(text, dest_language, source_language=None):

If a merge of the session's work fails its tests, the session gets one short note with the failing test and its first error line. It fixes the code and merges again.

The session fixes its call and tells you in one sentence what gitta caught. Then you merge with git merge, as always. gitta runs the gate on the combined code during the merge. When the tests pass, it adds nothing to git's output.

If a session's code still fails the tests on the combined code, the merge stops with the failing test before main moves. See When gitta stops a merge. To follow all sessions at once, run gitta watch in a spare terminal.

How the hooks find the right session

Claude Code runs the same gitta hook in every session. Each call carries a cwd field with the session's current folder, and in a worktree session that is the worktree. gitta matches that folder to the worktree that holds it, so a warning goes to the session it is about. A session in the main checkout is not an agent, so the hook stays silent there.

Worktrees can sit inside other worktrees. If you start claude --worktree inside an agent's worktree, the new one goes under that worktree's .claude/worktrees/. gitta gives each folder to the deepest worktree that holds it, and it does not count the inner worktree as a change of the outer one.

Three Claude Code rules matter here. They come from Anthropic's worktrees, hooks and settings pages.

RuleEffect on gitta
~/.claude/settings.json applies in every session.The hooks from gitta init run in every worktree.
In a worktree, Claude Code reads .claude/settings.local.json at the main checkout's root. Desktop worktree sessions read all project settings there, and run hook commands in that root.gitta reads the session folder from cwd, never from the hook's working folder or CLAUDE_PROJECT_DIR. gitta install claude writes its hooks to the main checkout's local settings too.
The same hook command in several settings files runs once.The hooks never run twice in one step.

Git hooks in Claude Code worktrees

Claude Code issue #88747 reports that worktrees from the desktop app and from EnterWorktree can get an absolute core.hooksPath in their config.worktree. Git hooks such as pre-commit in that worktree then run the main checkout's copy. gitta's warnings do not depend on Git hooks, so this does not change what gitta tells your sessions. gitta's gate runs your test command in its own checkout of the merged work. To check a worktree, run:

 Terminal
$ git config --show-scope --get-all core.hooksPath

If a worktree line points into another checkout, follow the workaround in the issue.

Troubleshooting

What you seeWhat to do
A session gets no warnings.Run gitta status in the main checkout. If the worktree is missing, check git worktree list. If you used gitta init --no-claude, run gitta install claude.
The hooks are not in /status under setting sources.Check that ~/.claude/settings.json holds gitta hook claude. Cloud sessions do not read that file. Use the pull request check for them.
A warning names the wrong agent.Update gitta. Builds before the fix for nested worktrees could give an inner worktree's folder to the outer one.
A worktree's Git hooks run the main checkout's scripts.See Git hooks in Claude Code worktrees.

More cases are on the Troubleshooting page. For Cursor and Codex, see Agents.