worktree-agents
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:
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):
cp -r .agents worktrees/feature/dark-mode/.agents cp -r .agents worktrees/fix/login-bug/.agents - Install deps:
cd worktrees/feature/dark-mode && npm install cd worktrees/fix/login-bug && npm install - Register:
.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:
.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:
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.