Worktree Agent Management
This skill helps manage parallel development using git worktrees with AI coding agents. Each worktree is an isolated copy of the repo on a different branch, allowing multiple Claude Code agents to work simultaneously without conflicts.
When This Skill Activates
Trigger phrases:
- •"spin up worktrees for X, Y, Z"
- •"create worktrees and launch agents"
- •"parallelize work on these features"
- •"what's the status of my worktrees?"
- •"launch agent in worktree X"
- •"clean up merged worktrees"
- •"clean up the X worktree"
Intent
The user wants to:
- •Create: Set up isolated worktrees for parallel feature development
- •Launch: Start Claude Code agents in those worktrees
- •Monitor: See what's running and what state each worktree is in
- •Cleanup: Remove worktrees after PRs are merged
CRITICAL: Directory Structure
All worktrees MUST be created in the worktrees/ subdirectory relative to the repo root.
repo-root/ ├── worktrees/ # All worktrees go here │ ├── feature/auth/ # Branch: feature/auth │ ├── feature/payments/ # Branch: feature/payments │ └── fix/login-bug/ # Branch: fix/login-bug ├── src/ ├── .claude/ └── ...
NEVER create worktrees as sibling directories (e.g., ../repo-feature-auth). This breaks:
- •Status tracking
- •Cleanup scripts
- •Registry path matching
Correct:
git worktree add worktrees/feature/auth -b feature/auth
Wrong:
git worktree add ../repo-feature-auth -b feature/auth # NO!
Architecture
.claude/skills/worktree-agents/
├── SKILL.md # This file - instructions for Claude
├── config.json # User preferences (terminal, shell, ports)
└── scripts/
├── launch-agent.sh # Opens terminal with Claude Code
├── status.sh # Shows worktree overview
├── register.sh # Adds worktree to registry
├── unregister.sh # Removes from registry
└── cleanup.sh # Full cleanup workflow
.claude/worktree-registry.json # Tracks active worktrees (in repo root)
What You (Claude) Do vs What Scripts Do
| Task | Who Does It | How |
|---|---|---|
| Create git worktree | You | git worktree add worktrees/<branch> -b <branch> |
| Copy .agents/ directory | You | cp -r .agents worktrees/<branch>/ (for plans, RCAs, etc.) |
| Install dependencies | You | cd worktrees/<branch> && npm install |
| Run validation | You | npm run type-check && npm run lint && npm test |
| Pick next available port | You | Look at registry, find unused port in range |
| Register worktree | Script | scripts/register.sh <branch> <path> <port> [task] |
| Launch agent in terminal | Script | scripts/launch-agent.sh <path> [task] |
| Show status | Script | scripts/status.sh |
| Full cleanup | Script | scripts/cleanup.sh <branch> [--delete-branch] |
| Check PR status | You | gh pr list --head <branch> --json number,state |
| Decide what to clean | You | Check if PR merged, ask user if unsure |
IMPORTANT: Copy .agents/ Directory
Why: Uncommitted files (plans, RCA reports, PRPs) only exist in the source worktree. New worktrees start clean from git, so these files won't be there.
Always copy the .agents/ directory to new worktrees so the agent has access to:
- •
.agents/plans/- Implementation plans to execute - •
.agents/rca-reports/- Root cause analysis reports - •
.agents/PRPs/- Product requirement plans
# After creating worktree, copy .agents/ cp -r .agents worktrees/<branch>/.agents
Port Allocation
Ports are assigned from the configured range (default: 8124-8128).
To find next available port:
- •Read
.claude/worktree-registry.json - •Get list of used ports:
jq '.worktrees[].port' .claude/worktree-registry.json - •Pick first unused port in range
Port range (from config.json):
- •Default: 8124, 8125, 8126, 8127, 8128
- •Maximum 5 concurrent worktrees
Workflows
1. Create Worktrees with Agents
User says: "Spin up worktrees for feature/auth and feature/payments"
You do:
1. For each branch:
a. Find next available port (check registry)
b. Create worktree:
git worktree add worktrees/<branch> -b <branch>
c. Copy .agents/ directory (plans, RCAs, PRPs):
cp -r .agents worktrees/<branch>/.agents
d. Install dependencies:
cd worktrees/<branch> && npm install
e. Run validation (optional but recommended):
npm run type-check && npm run lint && npm test
f. Register:
scripts/register.sh <branch> worktrees/<branch> <port> "[task]"
g. Launch agent:
scripts/launch-agent.sh worktrees/<branch> "[task]"
2. Report summary to user
Example commands:
# Create worktrees git worktree add worktrees/feature/auth -b feature/auth git worktree add worktrees/feature/payments -b feature/payments # Copy .agents/ directory (uncommitted plans, RCAs, etc.) cp -r .agents worktrees/feature/auth/.agents cp -r .agents worktrees/feature/payments/.agents # Install deps cd worktrees/feature/auth && npm install cd worktrees/feature/payments && npm install # Register (finds script in .claude/skills/worktree-agents/scripts/) .claude/skills/worktree-agents/scripts/register.sh feature/auth worktrees/feature/auth 8124 "Implement OAuth" .claude/skills/worktree-agents/scripts/register.sh feature/payments worktrees/feature/payments 8125 "Add Stripe" # Launch agents .claude/skills/worktree-agents/scripts/launch-agent.sh worktrees/feature/auth "Implement OAuth" .claude/skills/worktree-agents/scripts/launch-agent.sh worktrees/feature/payments "Add Stripe"
2. Check Status
User says: "What's the status?" or "Show my worktrees"
You do:
.claude/skills/worktree-agents/scripts/status.sh
This shows:
- •All registered worktrees
- •Port assignments
- •PR status (fetched from GitHub)
- •When agent was launched
- •Whether worktree directory exists
3. Launch Agent in Existing Worktree
User says: "Launch an agent in the auth worktree"
You do:
# Find the worktree path git worktree list | grep auth # Launch .claude/skills/worktree-agents/scripts/launch-agent.sh worktrees/feature/auth "Continue auth work"
4. Cleanup Worktrees
User says: "Clean up the auth worktree" or "Clean up merged worktrees"
For single worktree:
# Check if PR is merged first gh pr list --head feature/auth --state merged # If merged (or user confirms), clean up .claude/skills/worktree-agents/scripts/cleanup.sh feature/auth # To also delete the git branch: .claude/skills/worktree-agents/scripts/cleanup.sh feature/auth --delete-branch
For "merged" worktrees:
# Get list of registered worktrees cat .claude/worktree-registry.json # For each, check if PR is merged gh pr list --head <branch> --state merged --json number # Clean up those with merged PRs .claude/skills/worktree-agents/scripts/cleanup.sh <branch> --delete-branch
Cleanup script handles:
- •Killing processes on the port
- •Removing worktree directory
- •Pruning git references
- •Unregistering from registry
- •Optionally deleting local+remote branches
Registry Schema
Location: .claude/worktree-registry.json
{
"worktrees": [
{
"branch": "feature/auth",
"path": "worktrees/feature/auth",
"port": 8124,
"createdAt": "2025-12-02T10:00:00Z",
"agentLaunchedAt": "2025-12-02T10:05:00Z",
"task": "Implement OAuth login",
"prNumber": null
}
]
}
You update agentLaunchedAt after launching by re-running register.sh (it updates existing entries).
You update prNumber when you discover a PR exists:
# Check for PR PR_NUM=$(gh pr list --head feature/auth --json number --jq '.[0].number') # Update registry with jq jq ".worktrees |= map(if .branch == \"feature/auth\" then .prNumber = $PR_NUM else . end)" \ .claude/worktree-registry.json > tmp.json && mv tmp.json .claude/worktree-registry.json
Configuration
Location: .claude/skills/worktree-agents/config.json
{
"terminal": "ghostty", // ghostty, iterm2, or tmux
"shell": "fish", // fish, bash, or zsh
"claudeCommand": "cc", // command to launch Claude Code
"portRange": {
"start": 8124,
"end": 8128
}
}
Terminal options:
- •
ghostty- Opens new Ghostty window (macOS) - •
iterm2- Opens new iTerm2 window (macOS) - •
tmux- Creates new tmux session (cross-platform)
Script Reference
launch-agent.sh
./scripts/launch-agent.sh <worktree-path> [task-description] # Examples: ./scripts/launch-agent.sh worktrees/feature/auth ./scripts/launch-agent.sh worktrees/feature/auth "Implement OAuth login"
register.sh
./scripts/register.sh <branch> <path> <port> [task] # Examples: ./scripts/register.sh feature/auth worktrees/feature/auth 8124 ./scripts/register.sh feature/auth worktrees/feature/auth 8124 "Implement OAuth"
unregister.sh
./scripts/unregister.sh <branch> # Example: ./scripts/unregister.sh feature/auth
cleanup.sh
./scripts/cleanup.sh <branch> [--delete-branch] # Examples: ./scripts/cleanup.sh feature/auth # Keep git branch ./scripts/cleanup.sh feature/auth --delete-branch # Delete branch too
status.sh
./scripts/status.sh
Safety Guidelines
- •
Before cleaning up, check PR status:
- •If PR is merged: safe to clean up everything
- •If PR is open: warn user, confirm before proceeding
- •If no PR: warn user there may be unsubmitted work
- •
Before deleting branches, confirm with user if:
- •PR is not merged
- •No PR exists
- •Worktree has uncommitted changes
- •
Port conflicts: If a port is in use by a non-worktree process, pick a different port
- •
Max 5 worktrees: The default port range only supports 5 concurrent worktrees
Common Issues
"Port already in use"
# Find what's using it lsof -i :8124 # Kill if it's a stale process kill -9 <PID>
"Worktree already exists"
# Check existing worktrees git worktree list # Remove if stale git worktree remove worktrees/<branch> --force git worktree prune
"Branch already exists"
The git worktree command handles this:
# This tries -b (new branch) first, falls back to existing git worktree add worktrees/<branch> -b <branch> 2>/dev/null || git worktree add worktrees/<branch> <branch>
Registry out of sync
# Compare registry to actual worktrees cat .claude/worktree-registry.json git worktree list # Manually clean up stale entries .claude/skills/worktree-agents/scripts/unregister.sh <stale-branch>
Example Session
User: "Spin up 2 worktrees for feature/dark-mode and fix/login-bug, then launch agents"
You:
- •Check registry for used ports → none used, start with 8124
- •Create worktrees:
bash
git worktree add worktrees/feature/dark-mode -b feature/dark-mode git worktree add worktrees/fix/login-bug -b fix/login-bug
- •Copy .agents/ directory (so agents have access to plans, RCAs):
bash
cp -r .agents worktrees/feature/dark-mode/.agents cp -r .agents worktrees/fix/login-bug/.agents
- •Install deps:
bash
cd worktrees/feature/dark-mode && npm install cd worktrees/fix/login-bug && npm install
- •Register:
bash
.claude/skills/worktree-agents/scripts/register.sh feature/dark-mode worktrees/feature/dark-mode 8124 "Implement dark mode toggle" .claude/skills/worktree-agents/scripts/register.sh fix/login-bug worktrees/fix/login-bug 8125 "Fix login redirect bug"
- •Launch agents:
bash
.claude/skills/worktree-agents/scripts/launch-agent.sh worktrees/feature/dark-mode "Implement dark mode toggle" .claude/skills/worktree-agents/scripts/launch-agent.sh worktrees/fix/login-bug "Fix login redirect bug"
- •Report:
code
Created 2 worktrees with agents: | Branch | Port | Task | |--------|------|------| | feature/dark-mode | 8124 | Implement dark mode toggle | | fix/login-bug | 8125 | Fix login redirect bug | Both agents are now running in separate Ghostty windows. .agents/ directory copied to each worktree.