WO

worktree-manager

A manager for creating and syncing git worktrees across multiple projects to enable parallel development.

Install

mkdir -p .claude/skills/worktree-manager-wirasm && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/11876" && unzip -o skill.zip -d .claude/skills/worktree-manager-wirasm && rm skill.zip

Installs to .claude/skills/worktree-manager-wirasm

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Create, manage, and cleanup git worktrees with Claude Code agents across all projects. USE THIS SKILL when user says "create worktree", "spin up worktrees", "new worktree for X", "worktree status", "cleanup worktrees", "sync worktrees", or wants parallel development branches. Also use when creating PRs from a worktree branch (to update registry with PR number). Handles worktree creation, dependency installation, validation, agent launching in Ghostty, and global registry management.
487 chars✓ has a “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)
Advanced

Key capabilities

  • Create Git worktrees for parallel development
  • Manage a global registry of worktrees across projects
  • Allocate unique port numbers for each worktree
  • Install dependencies within new worktrees
  • Clean up merged or orphaned worktrees

How it works

The skill creates and manages Git worktrees, tracks them in a global registry, allocates unique ports, and installs dependencies to facilitate parallel development.

Inputs & outputs

You give it
Request to create, manage, or clean up worktrees
You get back
Created Git worktrees, updated global registry, and allocated ports

When to use worktree-manager

  • Spin up multiple worktrees for parallel work
  • Clean up merged worktrees
  • Launch agents in a specific worktree
  • Sync worktree registry

About this skill

Global Worktree Manager

Manage parallel development across ALL projects using git worktrees with Claude Code agents. Each worktree is an isolated copy of the repo on a different branch, stored centrally at ~/tmp/worktrees/.

IMPORTANT: You (Claude) can perform ALL operations manually using standard tools (jq, git, bash). Scripts are helpers, not requirements. If a script fails, fall back to manual operations described in this document.

When This Skill Activates

Trigger phrases:

  • "spin up worktrees for X, Y, Z"
  • "create 3 worktrees for features A, B, C"
  • "new worktree for feature/auth"
  • "what's the status of my worktrees?"
  • "show all worktrees" / "show worktrees for this project"
  • "clean up merged worktrees"
  • "clean up the auth worktree"
  • "launch agent in worktree X"
  • "sync worktrees" / "sync worktree registry"
  • "create PR" (when in a worktree - updates registry with PR number)

File Locations

FilePurpose
~/.claude/worktree-registry.jsonGlobal registry - tracks all worktrees across all projects
~/.claude/skills/worktree-manager/config.jsonSkill config - terminal, shell, port range settings
~/.claude/skills/worktree-manager/scripts/Helper scripts - optional, can do everything manually
~/tmp/worktrees/Worktree storage - all worktrees live here
.claude/worktree.json (per-project)Project config - optional custom settings

Core Concepts

Centralized Worktree Storage

All worktrees live in ~/tmp/worktrees/<project-name>/<branch-slug>/

~/tmp/worktrees/
├── obsidian-ai-agent/
│   ├── feature-auth/           # branch: feature/auth
│   ├── feature-payments/       # branch: feature/payments
│   └── fix-login-bug/          # branch: fix/login-bug
└── another-project/
    └── feature-dark-mode/

Branch Slug Convention

Branch names are slugified for filesystem safety by replacing / with -:

  • feature/authfeature-auth
  • fix/login-bugfix-login-bug
  • feat/user-profilefeat-user-profile

Slugify manually: echo "feature/auth" | tr '/' '-'feature-auth

Port Allocation Rules

  • Global pool: 8100-8199 (100 ports total)
  • Per worktree: 2 ports allocated (for API + frontend patterns)
  • Globally unique: Ports are tracked globally to avoid conflicts across projects
  • Check before use: Always verify port isn't in use by system: lsof -i :<port>

Global Registry

Location

~/.claude/worktree-registry.json

Schema

{
  "worktrees": [
    {
      "id": "unique-uuid",
      "project": "obsidian-ai-agent",
      "repoPath": "/Users/rasmus/Projects/obsidian-ai-agent",
      "branch": "feature/auth",
      "branchSlug": "feature-auth",
      "worktreePath": "/Users/rasmus/tmp/worktrees/obsidian-ai-agent/feature-auth",
      "ports": [8100, 8101],
      "createdAt": "2025-12-04T10:00:00Z",
      "validatedAt": "2025-12-04T10:02:00Z",
      "agentLaunchedAt": "2025-12-04T10:03:00Z",
      "task": "Implement OAuth login",
      "prNumber": null,
      "status": "active"
    }
  ],
  "portPool": {
    "start": 8100,
    "end": 8199,
    "allocated": [8100, 8101]
  }
}

Field Descriptions

Worktree entry fields:

FieldTypeDescription
idstringUnique identifier (UUID)
projectstringProject name (from git remote or directory)
repoPathstringAbsolute path to original repository
branchstringFull branch name (e.g., feature/auth)
branchSlugstringFilesystem-safe name (e.g., feature-auth)
worktreePathstringAbsolute path to worktree
portsnumber[]Allocated port numbers (usually 2)
createdAtstringISO 8601 timestamp
validatedAtstring|nullWhen validation passed
agentLaunchedAtstring|nullWhen agent was launched
taskstring|nullTask description for the agent
prNumbernumber|nullAssociated PR number if exists
statusstringactive, orphaned, or merged

Port pool fields:

FieldTypeDescription
startnumberFirst port in pool (default: 8100)
endnumberLast port in pool (default: 8199)
allocatednumber[]Currently allocated ports

Manual Registry Operations

Read entire registry:

cat ~/.claude/worktree-registry.json | jq '.'

List all worktrees:

cat ~/.claude/worktree-registry.json | jq '.worktrees[]'

List worktrees for specific project:

cat ~/.claude/worktree-registry.json | jq '.worktrees[] | select(.project == "my-project")'

Get allocated ports:

cat ~/.claude/worktree-registry.json | jq '.portPool.allocated'

Find worktree by branch (partial match):

cat ~/.claude/worktree-registry.json | jq '.worktrees[] | select(.branch | contains("auth"))'

Add worktree entry manually:

TMP=$(mktemp)
jq '.worktrees += [{
  "id": "'$(uuidgen)'",
  "project": "my-project",
  "repoPath": "/path/to/repo",
  "branch": "feature/auth",
  "branchSlug": "feature-auth",
  "worktreePath": "/Users/me/tmp/worktrees/my-project/feature-auth",
  "ports": [8100, 8101],
  "createdAt": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'",
  "validatedAt": null,
  "agentLaunchedAt": null,
  "task": "My task",
  "prNumber": null,
  "status": "active"
}]' ~/.claude/worktree-registry.json > "$TMP" && mv "$TMP" ~/.claude/worktree-registry.json

Add ports to allocated pool:

TMP=$(mktemp)
jq '.portPool.allocated += [8100, 8101] | .portPool.allocated |= unique | .portPool.allocated |= sort_by(.)' \
  ~/.claude/worktree-registry.json > "$TMP" && mv "$TMP" ~/.claude/worktree-registry.json

Remove worktree entry:

TMP=$(mktemp)
jq 'del(.worktrees[] | select(.project == "my-project" and .branch == "feature/auth"))' \
  ~/.claude/worktree-registry.json > "$TMP" && mv "$TMP" ~/.claude/worktree-registry.json

Release ports from pool:

TMP=$(mktemp)
jq '.portPool.allocated = (.portPool.allocated | map(select(. != 8100 and . != 8101)))' \
  ~/.claude/worktree-registry.json > "$TMP" && mv "$TMP" ~/.claude/worktree-registry.json

Initialize empty registry (if missing):

mkdir -p ~/.claude
cat > ~/.claude/worktree-registry.json << 'EOF'
{
  "worktrees": [],
  "portPool": {
    "start": 8100,
    "end": 8199,
    "allocated": []
  }
}
EOF

Manual Port Allocation

If scripts/allocate-ports.sh fails, allocate ports manually:

Step 1: Get currently allocated ports

ALLOCATED=$(cat ~/.claude/worktree-registry.json | jq -r '.portPool.allocated[]' | sort -n)
echo "Currently allocated: $ALLOCATED"

Step 2: Find first available port (not in allocated list AND not in use by system)

for PORT in $(seq 8100 8199); do
  # Check if in registry
  if ! echo "$ALLOCATED" | grep -q "^${PORT}$"; then
    # Check if in use by system
    if ! lsof -i :"$PORT" &>/dev/null; then
      echo "Available: $PORT"
      break
    fi
  fi
done

Step 3: Add to allocated pool

TMP=$(mktemp)
jq '.portPool.allocated += [8100] | .portPool.allocated |= unique | .portPool.allocated |= sort_by(.)' \
  ~/.claude/worktree-registry.json > "$TMP" && mv "$TMP" ~/.claude/worktree-registry.json

What You (Claude) Do vs What Scripts Do

TaskScript AvailableManual Fallback
Determine project nameNoParse git remote get-url origin or basename $(pwd)
Detect package managerNoCheck for lockfiles (see Detection section)
Create git worktreeNogit worktree add <path> -b <branch>
Copy .agents/ directoryNocp -r .agents <worktree-path>/
Install dependenciesNoRun detected install command
Validate (health check)NoStart server, curl endpoint, stop server
Allocate portsscripts/allocate-ports.sh 2Manual (see above)
Register worktreescripts/register.shManual jq (see above)
Launch agent in terminalscripts/launch-agent.shManual (see below)
Show statusscripts/status.shcat ~/.claude/worktree-registry.json | jq ...
Cleanup worktreescripts/cleanup.shManual (see Cleanup section)

Workflows

1. Create Multiple Worktrees with Agents

User says: "Spin up 3 worktrees for feature/auth, feature/payments, and fix/login-bug"

You do (can parallelize with subagents):

For EACH branch (can run in parallel):

1. SETUP
   a. Get project name:
      PROJECT=$(basename $(git remote get-url origin 2>/dev/null | sed 's/\.git$//') 2>/dev/null || basename $(pwd))
   b. Get repo root:
      REPO_ROOT=$(git rev-parse --show-toplevel)
   c. Slugify branch:
      BRANCH_SLUG=$(echo "feature/auth" | tr '/' '-')
   d. Determine worktree path:
      WORKTREE_PATH=~/tmp/worktrees/$PROJECT/$BRANCH_SLUG

2. ALLOCATE PORTS
   Option A (script): ~/.claude/skills/worktree-manager/scripts/allocate-ports.sh 2
   Option B (manual): Find 2 unused ports from 8100-8199, add to registry

3. CREATE WORKTREE
   mkdir -p ~/tmp/worktrees/$PROJECT
   git worktree add $WORKTREE_PATH -b $BRANCH
   # If branch exists already, omit -b flag

4. COPY UNCOMMITTED RESOURCES
   cp -r .agents $WORKTREE_PATH/ 2>/dev/null || true
   cp .env.example $WORKTREE_PATH/.env 2>/dev/null || true

5. INSTALL DEPENDENCIES
   cd $WORKTREE_PATH
   # Detect and run: npm install / uv sync / etc.

6. VALIDATE (start server, health check, stop)
   a. Start server with allocated port
   b. Wait and health check: curl -sf http://localhost:$PORT/health
   c. Stop server
   d. If FAILS: report error but continue with other worktrees

7. REGISTER IN GLOBAL REGISTRY
   Option A (script): ~/.claude/skills/worktree-manager/scripts/register.sh ...
   Option B (manual): Update ~/.claude/worktree-registry.json with jq

8. LAUNCH AGENT
   Option A (s

---

*Content truncated.*

When not to use it

  • When only a single development branch is needed
  • When manual worktree management is preferred
  • When port allocation is not required for worktrees

Limitations

  • All worktrees are stored in `~/tmp/worktrees/`.
  • Port allocation is from a global pool of 8100-8199.
  • Branch names are slugified for filesystem safety.

How it compares

This skill centralizes worktree management, including global registry tracking and automated port allocation, providing a more organized and efficient way to handle parallel development than manual Git commands.

Compared to similar skills

worktree-manager side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
worktree-manager (this skill)07moCautionAdvanced
bash-linux76moReviewIntermediate
create-worktree-skill29moNo flagsIntermediate
domain-dns-ops22moReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

Search skills

Search the agent skills registry