Skip to content

How to Run Parallel AI Coding Agents on One Python Project

Run each AI coding agent in its own git worktree, and give each worktree its own uv environment. A worktree is a second working directory on its own branch, backed by the same .git store. One uv sync per worktree produces an isolated virtual environment, so Claude Code, Codex, and Cursor can work in parallel, each on its own branch and in its own .venv, without sharing a working tree.

Confirm your starting point

You need an existing uv project with a pyproject.toml, uv installed, and Git with git worktree support. Begin in the original checkout, on main, with a clean working directory. Substitute the repository’s default branch if it uses a different name.

Commit the source, pyproject.toml, and uv.lock before creating worktrees. A new worktree starts from a commit; it does not copy uncommitted or untracked files. Check git status --short and expect no pending changes before continuing.

Create a worktree for each agent

Add one worktree per task, each on a fresh branch:

git worktree add ../myproject-auth -b agent-auth
git worktree add ../myproject-docs -b agent-docs

Each command creates a sibling directory (../myproject-auth) checked out to a new branch (agent-auth). Creating a worktree is cheap: it links to the existing .git store instead of copying history.

List what you have:

git worktree list
/path/to/myproject        a1e219e [main]
/path/to/myproject-auth   a1e219e [agent-auth]
/path/to/myproject-docs   a1e219e [agent-docs]

Give each worktree its own environment

Each worktree is a separate checkout, so give each its own environment rather than sharing one. A .venv records absolute paths tied to the directory it was created in, and for a workspace, sharing one sends imports to the wrong source tree (Keep uv workspaces isolated across worktrees).

cd ../myproject-auth
uv sync

Expect uv to create .venv and install the locked dependencies. Package counts and timings depend on the project.

uv reuses its package cache across worktrees, so separate environments do not require downloading every dependency again. Installation time and whether files are linked or copied depend on the platform and filesystem.

cd ../myproject-docs
uv sync

Add .venv/ to your .gitignore if it is not already there. Worktrees share one .git object store, so an agent that commits its .venv bloats that store for every worktree, and the bloat survives even after you delete the branch.

Point each agent at its worktree

For an app that creates worktrees, select its worktree mode and verify the resulting checkout before installing dependencies. A worktree is still a local environment; a cloud task needs its own setup. For manually created worktrees, open a separate terminal per worktree, cd into it, and start the agent there. For terminal agents like Claude Code and Codex:

cd ../myproject-auth && claude   # or: codex

For Cursor, open the worktree as a folder (File > Open Folder, then select ../myproject-auth) so the editor and its agent operate on that branch.

An agent started in the worktree runs its shell commands against that branch and .venv. For a uv project, uv run and uv sync select the .venv at the worktree (project) root, so uv run pytest from ../myproject-auth tests the agent-auth branch in its own environment. uv run selects the project environment without shell activation. Check that each agent reports its worktree as the working directory and runs tests there.

Warning

An absolute UV_PROJECT_ENVIRONMENT shared by several worktrees sends them to the same environment. Remove that override or assign a distinct path per worktree. Relative paths resolve from each project root and can remain isolated.

Keep uv workspaces isolated across worktrees

A uv workspace keeps its .venv and uv.lock at the workspace root. In a worktree, that root is the worktree’s own directory, so uv sync there builds a self-contained environment whose members resolve from that worktree’s source. No extra configuration is needed.

Don’t share one .venv across worktrees to save disk. Workspace members install as editable, so the environment stores an absolute path to one worktree’s source. A second worktree pointed at that shared environment imports the first worktree’s code:

# Correct: each worktree's own uv sync
wt-auth resolves shared_lib -> /path/to/myproject-auth/packages/shared-lib/src
wt-docs resolves shared_lib -> /path/to/myproject-docs/packages/shared-lib/src

# Broken: myproject-docs pointed at myproject-auth's shared .venv
myproject-docs imports shared_lib -> /path/to/myproject-auth/packages/shared-lib/src

An edit in one agent’s worktree then silently changes what the other runs. A separate uv sync per worktree costs little from uv’s cache and keeps each pointed at the right source.

Review and merge each agent’s work

Each agent’s changes live on its own branch. Review one worktree’s commits, then merge the branch or open a pull request:

git -C ../myproject-auth log --oneline main..agent-auth
git -C ../myproject diff main...agent-auth
git -C ../myproject merge agent-auth

Run the merge commands from the docs worktree created in this guide; ../myproject is the original checkout on main. Expect the log and diff to show the auth changes, then Git to report the merge result. Rerun the project checks after merging because isolated edits may conflict logically.

When several agents finish at once, open a pull request per branch (gh pr create from each worktree) so the reviews stay separate. Enough Git to Supervise Your AI Coding Agent covers branches and pull requests in more depth.

Clean up a worktree when the agent is done

After merging a branch, remove its worktree and delete the branch:

git -C ../myproject worktree remove ../myproject-auth
git -C ../myproject branch -d agent-auth

git worktree remove deletes the directory, including its .venv. Expect Git to refuse removal when tracked or untracked changes remain. Inspect and save that work before removing the checkout.

Last updated on