Claude Code: Parallel Development with /worktree
Building on my workflow with /todo and /commit, I've created the /worktree
command to enable parallel development on multiple tasks using Git worktrees.
This post is part of my Claude Code setup series.
Evolution of My Workflow
I started with a simple pattern: maintain a todo list and repeatedly run three commands:
/todo
- Implement one task/commit
- Create a commit/compact
- Manage the context window
This workflow steadily churned through my todo list, but LLMs can be slow. While waiting for one task to complete, I'd switch to working on a second task. Initially, I tried running Claude on two tasks in the same directory simultaneously, but they would trample each other's changes.
I started using Git worktrees. It worked well. Each instance of Claude works in its own directory, eliminating conflicts, while still working on a single git repository. Later, Anthropic officially recommended using worktrees in their documentation, which validated the approach.
Building the /worktree Command
While Anthropic recommends using worktrees, they don't provide any automation or commands for managing them yet. I found myself spending too much time creating worktrees, copying todo lists, and managing branches myself. That's where my /worktree
command comes in.
Using the command
This command can be used within claude, with a number of worktrees to create.
/worktree 3
⏺ 1 worktree has been created so far.
⏺ 2 worktrees have been created so far.
⏺ 3 worktrees have been created.
Even though the worktrees used for parallel work, they are created in serial. Each time a worktree is created, Claude also opens a new iTerm tab, and kicks off the command:
claude --dangerously-skip-permissions /todo
How It Works
The /worktree
command automates several key steps:
1. Find and mark the next available todo
- [ ] Implement user authentication with JWT
becomes:
- [>] Implement user authentication with JWT <!-- worktree: implement-user-auth-jwt -->
2. Create the worktree
git worktree add ../my-app-implement-user-auth-jwt -b task/implement-user-auth-jwt HEAD
3. Set up the worktree environment
# Copy environment files if they exist
cp .envrc ../my-app-implement-user-auth-jwt/
direnv allow ../my-app-implement-user-auth-jwt
# Trust the directory for mise
mise trust ../my-app-implement-user-auth-jwt
4. Create a focused todo file
mkdir ../my-app-implement-user-auth-jwt/.llm
echo "- [ ] Implement user authentication with JWT" > .llm/todo.md
5. Launch Claude in a new terminal tab
Launch a new iTerm tab and run:
cd ../my-app-implement-user-auth-jwt
claude --dangerously-skip-permissions /todo
And if we wrote /worktree 3
, the command will repeat these steps until 3 worktrees are created.
Integration with /todo Workflow
The /worktree
command creates a new worktree with its own .llm/todo.md
file containing just the single task. This means you can use the same /todo workflow we've already established, but now with better isolation and the ability to work on multiple tasks in parallel. Each worktree starts fresh from main, giving you a clean context for every task.
Managing Context Size
If we have a large number of tasks we want to run in parallel, we need to be careful about the context size. There are two ways I manage this.
A command like /worktree 10
can run out of context in a single Claude session, trigger auto-compaction, and get lost. To avoid this, I move the looping outside of Claude.
for i in $(seq 1 10); do claude --dangerously-skip-permissions --print /worktree; done
The second problem is that if we run too many tasks in parallel, we can quickly hit API usage limits. To avoid this, I sometimes downgrade the model. At the time of writing, that means switching from Opus 4 to Sonnet 4.
If I'm going step away for a while, I can also use the sleep
command to space out the requests. This allows me to run tasks overnight without hitting API limits.
for i in $(seq 1 11); do claude --dangerously-skip-permissions --print /worktree; sleep 1200; done
Finishing Up
After all parallel tasks complete, I cherry-pick the completed work into a single branch. This gives me a chance to review all the changes together and ensure they work well as a cohesive whole.
If there are any merge conflicts, and they look at all tricky to resolve, I just throw away the work and mark the todo as [ ]
again.
Finally, I clean up all worktrees except the current one.
git worktree remove ../myproject-add-user-auth-jwt
git branch -d task/add-user-auth-jwt
Or I ask Claude to do it for me. If you ask Claude to clean up worktrees, make sure to tell it not to use --force
.
Full /worktree Command
Here's the complete /worktree
command that automates the entire process:
# 🌳 Create Git Worktree for Next Available Todo
You are to create $ARGUMENTS new git worktree(s) in peer directories for the first available todo items (not completed and not already in progress).
## Todo Status Icons:
- `[ ]` - Not started
- `[x]` - Completed
- `[>]` - In progress in a peer directory/worktree
## Steps to follow:
1. **Find the next available todo**:
- Spawn a sub-agent or sub-task to find the next task in the todo list.
- Read the file `./.llm/todo.md`. The file will only exist in this directory. Don't look in other locations. Don't look in the home directory.
- Look for the first todo that is marked with `[ ]` (not `[x]` or `[>]`)
- This will be the todo to work on
- End the sub-agent or sub-task here and share back the entire task information verbatim.
- If no available todos exist, inform the user that all todos are either completed or in progress
2. **Update the todo status**:
- Spawn a sub-agent or sub-task to update the task to show that it's in progress
- Change the selected todo from `[ ]` to `[>]` in the original todo list
- Add a comment indicating which worktree it's being worked on in, e.g.:
```markdown
- [>] Implement user authentication with JWT <!-- worktree: implement-user-auth-jwt -->
```
3. **Create the git worktree**:
- In parallel with marking the task in progress, spawn a second sub-agent or sub-task to create the git worktree
- Determine the current repository's root directory
- Create a worktree name based on the todo item (use kebab-case)
- Create the worktree in a peer directory: `git worktree add ../<worktree-name> -b <branch-name> ${UPSTREAM_REMOTE:-origin}/${UPSTREAM_BRANCH:-main}`
- `<worktree-name>` and `<branch-name>` are placeholders for you to replace with names of your choice
- `UPSTREAM_REMOTE` and `UPSTREAM_BRANCH` are real environment variables
- The `<branch-name>` should be prefixed with `task/`
- The `<worktree-name>` should start with the original repository's directory name
- If there is a `.envrc` file in this directory, copy it into the new directory and run `direnv allow ../<worktree-name>`
- Run `mise trust ../<worktree-name>`
- Set up the todo file in the new worktree:
- Create the directory `.llm` if it doesn't exist
- Create `.llm/todo.md` with ONLY this single todo item:
```markdown
# Todo
- [ ] [Single todo item text here]
- [Other context that was under the original todo]
When this task is complete:
- Edit the original task list at `<this directory>/.llm/todo.md`, on line <line>
- Update the todo status from `[>]` to `[x]`
```
## Conclusion
Run a command to create a new terminal tab in tme newly created worktree, and run `claude --dangerously-skip-permissions /todo` in that tab.
If we are running in iTerm:
```console
osascript -e '
tell application "iTerm"
tell current window
create tab with default profile command "claude code --dangerously-skip-permissions /todo" working directory "../<worktree-name>"
end tell
end tell
'
```
If we are running in xfce4-terminal:
```console
xfce4-terminal --tab --working-directory="../<worktree-name>" -x bash -c "claude code --dangerously-skip-permissions /todo; exec bash"
```
## Loop
Say how many worktrees you have created.
Repeat the instructions to create another worktree until you have created $ARGUMENTS worktrees.