I build a Mac app called Offrun. Everything in this post works with plain git and the agent CLIs; there's a short note about Offrun at the end.
The problem
Run Claude Code and Codex on the same repository at the same time and you hit three things fairly quickly:
- Both agents edit the same files, and one agent's changes break the other's working tree.
- One account hits its usage limit and the work stops halfway.
- Asking the agent that wrote a diff to review it tends to miss the same things it missed while writing it.
This post handles them one at a time: give each agent its own git worktree, have a different agent review the uncommitted diff, and split logins so a limit doesn't stop you. At the end there's a table of what I actually ran and what I didn't.
Tested on macOS with git 2.50.1, Claude Code 2.1.296 and Codex CLI 0.162.1.
1. One worktree per agent
A git worktree is an extra working directory attached to the same repository (the same .git). Each branch gets its own folder, so agents can edit freely in their own folder without touching each other's working tree.
cd ~/work/app
git worktree add ../app-refactor -b refactor
git worktree add ../app-bugfix -b bugfix
git worktree list
/Users/me/work/app c5cd751 [main]
/Users/me/work/app-bugfix c5cd751 [bugfix]
/Users/me/work/app-refactor c5cd751 [refactor]
Then start one agent per folder:
cd ../app-refactor && claude # first terminal
cd ../app-bugfix && codex # second terminal
Claude Code has a -w / --worktree [name] option that creates a worktree for the session itself. Codex has no equivalent, so this post sticks to plain git, which works for both.
Put worktrees next to the repository rather than inside it. If you do put them inside, add the folder to .gitignore, or the main working tree will show it as untracked.
2. The gotchas
Everything in this section was run against a throwaway repository.
The same branch can't be checked out in two worktrees
git worktree add ../dup refactor
fatal: 'refactor' is already used by worktree at '/tmp/.../app-refactor'
Git refuses to let two worktrees, and so two agents, share a branch. That's a useful safety net. If you want two attempts from the same starting point, create a second branch with -b.
.env and node_modules don't come along
A new worktree only checks out tracked files. A .env listed in .gitignore isn't there, and neither is node_modules from your last npm install. When an agent's first move fails with "missing environment variable" or "module not found", this is usually why.
A small function in ~/.zshrc creates the worktree and copies .env in one go:
wt() {
local name=$1 root dest
root=$(git rev-parse --show-toplevel) || return
dest="${root}-${name}"
git worktree add "$dest" -b "$name" || return
[ -f "$root/.env" ] && cp "$root/.env" "$dest/.env"
echo "$dest"
}
cd ~/work/app && wt refactor # creates ~/work/app-refactor with .env copied
I left dependency installation out because it differs per project. A package manager with a shared store, like pnpm, keeps disk use down as you add worktrees.
The stash is shared between worktrees
There's one .git, so there's one stash. A git stash made in another worktree showed up in the main worktree's git stash list:
$ git -C ../app-x stash -q
$ git stash list # in the main worktree
stash@{0}: WIP on x: c5cd751 init
Agents use git stash and git stash pop more often than you'd think. To stop one session popping another session's stash, add a line to the agent instruction files (CLAUDE.md, AGENTS.md) while you run in parallel: don't use stash; park work in progress with a temporary commit instead.
A worktree with changes can't be removed
$ git worktree remove ../app-refactor
fatal: '../app-refactor' contains modified or untracked files, use --force to delete it
--force removes it, along with any uncommitted changes. Run git -C ../app-refactor status before reaching for it. When the work is done, merge, then git worktree remove ../app-refactor and git branch -d refactor.
One more
This one I didn't test for this post; it's just a common parallel-work problem. Several agents starting dev servers will fight over the same port (3000 and so on). If the port comes from a PORT environment variable, you can give each worktree its own, like PORT=3001.
3. Have a different agent review the uncommitted diff
An agent reviewing its own diff tends to carry its own assumptions into the review. In my experience a model from a different company misses different things, which is what makes it useful as a reviewer.
Codex as the reviewer
Codex CLI has a review subcommand. According to its help, --uncommitted reviews staged, unstaged and untracked changes together:
cd ../app-refactor
codex review --uncommitted
Use --base main to review against a base branch, or --commit <SHA> for a single commit.
Claude Code as the reviewer
Claude Code runs non-interactively with -p (--print), so you can pipe the diff in:
git add -N . # so untracked files show up in the diff
git diff HEAD | claude -p "Review this diff. Point out bugs, missing tests and type mismatches. Don't change any code."
git add -N . (intent-to-add) is needed because git diff HEAD leaves out untracked files. I checked with a new file new.ts and an edit to the existing package.json:
$ git diff HEAD --stat
package.json | 1 +
$ git add -N . && git diff HEAD --stat
new.ts | 1 +
package.json | 1 +
Without it, the reviewer sees a diff with every new file silently missing. That's easy to overlook, so run add -N first.
What to do with the review
Let the reviewer point things out, and nothing more. Send the fixes back to the original agent, or make them yourself. If the reviewer edits code directly, you're back to the first problem: two agents touching the same files. Read the findings and pick the ones worth acting on before passing them along, so one off-target comment doesn't send the work sideways.
4. Plan for usage limits
Claude and Codex both cap usage over a period, and running agents in parallel gets you there faster. With more than one login, you can switch to another login when one runs out.
Separate config folders, separate logins
Both CLIs let you move their config and credentials with an environment variable: CLAUDE_CONFIG_DIR for Claude Code, CODEX_HOME for Codex. Pointing each at an empty folder confirmed the login state is separate:
$ CLAUDE_CONFIG_DIR=/tmp/cfgA claude auth status
{
"loggedIn": false,
...
}
$ CODEX_HOME=/tmp/cfgB codex login status
Not logged in
So make an alias per login:
alias claude-b='CLAUDE_CONFIG_DIR=$HOME/.claude-b claude'
alias codex-b='CODEX_HOME=$HOME/.codex-b codex'
claude-b auth login # sign in with the second account
Session history is stored per config folder too, so claude-b knows nothing about what claude did. That's the next problem.
When you switch mid-task, leave a handoff yourself
After a limit forces a switch, the new session doesn't know what the old one tried. I haven't tested copying session history files between config folders, so I won't recommend it. What reliably works is having the agent write its state to a file before the limit hits:
<!-- HANDOFF.md -->
## Goal
Move the auth middleware to TypeScript
## Done
- Migrated src/auth/session.ts, 0 type errors
## Tried and failed
- Staying on jose v4 breaks the ESM import. Needs v5
## Next
- Migrate src/auth/token.ts
Add a line to CLAUDE.md (or similar) saying to update HANDOFF.md at the end of each unit of work. Then tell the session on the new login "read HANDOFF.md and carry on", and it picks up what the last session tried.
5. What stays manual
All of the above gets you parallel agents, but some things stay manual:
- Opening each terminal tab to see which agent is working and which is waiting on you
- Checking each CLI separately to see which login is close to its limit
- Typing the commands to create worktrees, copy
.env, run reviews and clean up, every time
I built a Mac app that puts these in one place.
About Offrun
Offrun is a Mac app I'm building. It runs Claude Code, Codex and Antigravity CLI on your Mac with the logins you already have. Each chat gets its own git worktree, and one screen shows which agents are working, which are waiting on you, and how much usage each login has left. Pick another agent as the reviewer and its findings on the uncommitted diff land in the chat; the reviewer only points things out and never edits or merges code.
It's free with no card, though you need your own agent subscriptions. It runs on Apple Silicon Macs (M1 or later) with macOS 14 or later, and asks you to sign in to an Offrun account (Google or email) on first launch.
Everything in this post works without Offrun, so try it with plain git first.
What I checked and what I didn't
| What | Status |
|---|---|
Same branch can't be in two worktrees, .env doesn't come along, stash is shared, a worktree with changes can't be removed, git diff HEAD omits untracked files until add -N
|
Run against a test repository |
The wt function |
Run in zsh |
CLAUDE_CONFIG_DIR and CODEX_HOME separate the login state |
Checked with empty folders |
codex review --uncommitted and claude -w exist and do what's described |
Checked with --help
|
What the models actually say when reviewing via codex review and claude -p
|
Not run (command shape only) |
| Port clashes | Not tested |
This post was drafted with AI (Claude), and the commands in it were run to check the results.
Top comments (2)
The cross-review point is underrated, having Codex review Claude's uncommitted diff catches a different class of mistakes than self-review does. On the limits side, splitting logins works much better when you can see each account's remaining quota before kicking off a long task; I built TokenBar (tokenbar.site), a Mac menu bar app that shows Claude, Codex, Cursor and OpenAI usage and limits, for exactly that.
Solid writeup — the add -N trap and the shared stash are the two that bit me as well. Two additions from running the same shape:
Your wt() copies .env wholesale, so it copies PORT too. That puts the port clash you list as untested back into play through the helper itself: append a per-worktree PORT after the cp (e.g. PORT=$((3000 + RANDOM % 200))) and you close it at the same place you already have the hook.
And if an agent does rm -rf on its worktree folder instead of git worktree remove, git keeps the registration under .git/worktrees. From then on git worktree add -b fails with the same 'already used by worktree' message even though the folder is gone, and git worktree list points at a path that no longer exists. git worktree prune clears it. Worth a line next to the stash rule in CLAUDE.md / AGENTS.md, since agents reach for rm -rf more readily than for the git subcommand.