home / skills / terrylica / cc-skills / worktree-manager

This skill creates and manages alpha-forge git worktrees with auto-naming based on natural descriptions, enabling rapid parallel feature development.

npx playbooks add skill terrylica/cc-skills --skill worktree-manager

Review the files below or copy the command above to add this skill to your agents.

Files (5)
SKILL.md
13.0 KB
---
name: worktree-manager
description: Create alpha-forge git worktrees with auto branch naming. TRIGGERS - create worktree, new worktree, alpha-forge worktree.
---

# Alpha-Forge Worktree Manager

<!-- ADR: /docs/adr/2025-12-14-alpha-forge-worktree-management.md -->

Create and manage git worktrees for the alpha-forge repository with automatic branch naming, consistent conventions, and lifecycle management.

## When to Use This Skill

Use this skill when:

- Creating a new worktree for alpha-forge development
- Setting up a worktree from a remote branch
- Using an existing local branch in a new worktree
- Managing multiple parallel feature branches

## Operational Modes

This skill supports three distinct modes based on user input:

| Mode             | User Input Example                            | Action                                |
| ---------------- | --------------------------------------------- | ------------------------------------- |
| **New Branch**   | "create worktree for sharpe validation"       | Derive slug, create branch + worktree |
| **Remote Track** | "create worktree from origin/feat/existing"   | Track remote branch in new worktree   |
| **Local Branch** | "create worktree for feat/2025-12-15-my-feat" | Use existing branch in new worktree   |

---

## Mode 1: New Branch from Description (Primary)

This is the most common workflow. User provides a natural language description, Claude derives the slug.

### Step 1: Parse Description and Derive Slug

**Claude derives kebab-case slugs following these rules:**

**Word Economy Rule**:

- Each word in slug MUST convey unique meaning
- Remove filler words: the, a, an, for, with, and, to, from, in, on, of, by
- Avoid redundancy (e.g., "database" after "ClickHouse")
- Limit to 3-5 words maximum

**Conversion Steps**:

1. Parse description from user input
2. Convert to lowercase
3. Apply word economy (remove filler words)
4. Replace spaces with hyphens

**Examples**:

| User Description                        | Derived Slug                    |
| --------------------------------------- | ------------------------------- |
| "sharpe statistical validation"         | `sharpe-statistical-validation` |
| "fix the memory leak in metrics"        | `memory-leak-metrics`           |
| "implement user authentication for API" | `user-authentication-api`       |
| "add BigQuery data source support"      | `bigquery-data-source`          |

### Step 2: Verify Main Worktree Status

**CRITICAL**: Before proceeding, check that main worktree is on `main` branch.

```bash
/usr/bin/env bash << 'GIT_EOF'
cd ~/eon/alpha-forge
CURRENT=$(git branch --show-current)
GIT_EOF
```

**If NOT on main/master**:

Use AskUserQuestion to warn user:

```yaml
question: "Main worktree is on '$CURRENT', not main. Best practice is to keep main worktree clean. Continue anyway?"
header: "Warning"
options:
  - label: "Continue anyway"
    description: "Proceed with worktree creation"
  - label: "Switch main to 'main' first"
    description: "I'll switch the main worktree to main branch before creating"
multiSelect: false
```

If user selects "Switch main to 'main' first":

```bash
cd ~/eon/alpha-forge
git checkout main
```

### Step 3: Fetch Remote and Display Branches

```bash
cd ~/eon/alpha-forge
git fetch --all --prune

# Display available branches for user reference
echo "Available remote branches:"
git branch -r | grep -v HEAD | head -20
```

### Step 4: Prompt for Branch Type

Use AskUserQuestion:

```yaml
question: "What type of branch is this?"
header: "Branch type"
options:
  - label: "feat"
    description: "New feature or capability"
  - label: "fix"
    description: "Bug fix or correction"
  - label: "refactor"
    description: "Code restructuring (no behavior change)"
  - label: "chore"
    description: "Maintenance, tooling, dependencies"
multiSelect: false
```

### Step 5: Prompt for Base Branch

Use AskUserQuestion:

```yaml
question: "Which branch should this be based on?"
header: "Base branch"
options:
  - label: "main (Recommended)"
    description: "Base from main branch"
  - label: "develop"
    description: "Base from develop branch"
multiSelect: false
```

If user needs a different branch, they can select "Other" and provide the branch name.

### Step 6: Construct Branch Name

```bash
/usr/bin/env bash << 'SKILL_SCRIPT_EOF'
TYPE="feat"           # From Step 4
DATE=$(date +%Y-%m-%d)
SLUG="sharpe-statistical-validation"  # From Step 1
BASE="main"           # From Step 5

BRANCH="${TYPE}/${DATE}-${SLUG}"
# Result: feat/2025-12-15-sharpe-statistical-validation
SKILL_SCRIPT_EOF
```

### Step 7: Create Worktree (Atomic)

```bash
/usr/bin/env bash << 'GIT_EOF_2'
cd ~/eon/alpha-forge

WORKTREE_PATH="$HOME/eon/alpha-forge.worktree-${DATE}-${SLUG}"

# Atomic branch + worktree creation
git worktree add -b "${BRANCH}" "${WORKTREE_PATH}" "origin/${BASE}"
GIT_EOF_2
```

### Step 8: Generate Tab Name and Report

```bash
/usr/bin/env bash << 'SKILL_SCRIPT_EOF_2'
# Generate acronym from slug
ACRONYM=$(echo "$SLUG" | tr '-' '\n' | cut -c1 | tr -d '\n')
TAB_NAME="AF-${ACRONYM}"
SKILL_SCRIPT_EOF_2
```

Report success:

```
✓ Worktree created successfully

  Path:    ~/eon/alpha-forge.worktree-2025-12-15-sharpe-statistical-validation
  Branch:  feat/2025-12-15-sharpe-statistical-validation
  Tab:     AF-ssv
  Env:     .envrc created (loads shared secrets)

  iTerm2: Restart iTerm2 to see the new tab
```

---

## Mode 2: Remote Branch Tracking

When user specifies `origin/branch-name`, create a local tracking branch.

**Detection**: User input contains `origin/` prefix.

**Example**: "create worktree from origin/feat/2025-12-10-existing-feature"

### Workflow

```bash
/usr/bin/env bash << 'GIT_EOF_3'
cd ~/eon/alpha-forge
git fetch --all --prune

REMOTE_BRANCH="origin/feat/2025-12-10-existing-feature"
LOCAL_BRANCH="feat/2025-12-10-existing-feature"

# Extract date and slug for worktree naming
# Pattern: type/YYYY-MM-DD-slug
if [[ "$LOCAL_BRANCH" =~ ^(feat|fix|refactor|chore)/([0-9]{4}-[0-9]{2}-[0-9]{2})-(.+)$ ]]; then
    DATE="${BASH_REMATCH[2]}"
    SLUG="${BASH_REMATCH[3]}"
else
    DATE=$(date +%Y-%m-%d)
    SLUG="${LOCAL_BRANCH##*/}"
fi

WORKTREE_PATH="$HOME/eon/alpha-forge.worktree-${DATE}-${SLUG}"

# Create tracking branch + worktree
git worktree add -b "${LOCAL_BRANCH}" "${WORKTREE_PATH}" "${REMOTE_BRANCH}"
GIT_EOF_3
```

---

## Mode 3: Existing Local Branch

When user specifies a local branch name (without `origin/`), use it directly.

**Detection**: User input is a valid branch name format (e.g., `feat/2025-12-15-slug`).

**Example**: "create worktree for feat/2025-12-15-my-feature"

### Workflow

```bash
/usr/bin/env bash << 'VALIDATE_EOF'
cd ~/eon/alpha-forge

BRANCH="feat/2025-12-15-my-feature"

# Verify branch exists
if ! git show-ref --verify "refs/heads/${BRANCH}" 2>/dev/null; then
    echo "ERROR: Local branch '${BRANCH}' not found"
    echo "Available local branches:"
    git branch | head -20
    exit 1
fi

# Extract date and slug
if [[ "$BRANCH" =~ ^(feat|fix|refactor|chore)/([0-9]{4}-[0-9]{2}-[0-9]{2})-(.+)$ ]]; then
    DATE="${BASH_REMATCH[2]}"
    SLUG="${BASH_REMATCH[3]}"
else
    DATE=$(date +%Y-%m-%d)
    SLUG="${BRANCH##*/}"
fi

WORKTREE_PATH="$HOME/eon/alpha-forge.worktree-${DATE}-${SLUG}"

# Create worktree for existing branch (no -b flag)
git worktree add "${WORKTREE_PATH}" "${BRANCH}"
VALIDATE_EOF
```

---

## Naming Conventions

### Worktree Folder Naming (ADR-Style)

**Format**: `alpha-forge.worktree-YYYY-MM-DD-slug`

**Location**: `~/eon/`

| Branch                                          | Worktree Folder                                                 |
| ----------------------------------------------- | --------------------------------------------------------------- |
| `feat/2025-12-14-sharpe-statistical-validation` | `alpha-forge.worktree-2025-12-14-sharpe-statistical-validation` |
| `feat/2025-12-13-feature-genesis-skills`        | `alpha-forge.worktree-2025-12-13-feature-genesis-skills`        |
| `fix/quick-patch`                               | `alpha-forge.worktree-{TODAY}-quick-patch`                      |

### iTerm2 Tab Naming (Acronym-Based)

**Format**: `AF-{acronym}` where acronym = first character of each word in slug

| Worktree Slug                   | Tab Name   |
| ------------------------------- | ---------- |
| `sharpe-statistical-validation` | `AF-ssv`   |
| `feature-genesis-skills`        | `AF-fgs`   |
| `eth-block-metrics-data-plugin` | `AF-ebmdp` |

---

## Stale Worktree Detection

Check for worktrees whose branches are already merged to main:

```bash
/usr/bin/env bash << 'PREFLIGHT_EOF'
cd ~/eon/alpha-forge

# Get branches merged to main
MERGED=$(git branch --merged main | grep -v '^\*' | grep -v 'main' | tr -d ' ')

# Check each worktree
git worktree list --porcelain | grep '^branch' | cut -d' ' -f2 | while read branch; do
    branch_name="${branch##refs/heads/}"
    if echo "$MERGED" | grep -q "^${branch_name}$"; then
        path=$(git worktree list | grep "\[${branch_name}\]" | awk '{print $1}')
        echo "STALE: $branch_name at $path"
    fi
done
PREFLIGHT_EOF
```

If stale worktrees found, prompt user to cleanup using AskUserQuestion.

---

## Cleanup Workflow

### Remove Stale Worktree

```bash
# Remove worktree (keeps branch)
git worktree remove ~/eon/alpha-forge.worktree-{DATE}-{SLUG}

# Optionally delete merged branch
git branch -d {BRANCH}
```

### Prune Orphaned Entries

```bash
git worktree prune
```

---

## Error Handling

| Scenario                 | Action                                           |
| ------------------------ | ------------------------------------------------ |
| Branch already exists    | Suggest using Mode 3 (existing branch) or rename |
| Remote branch not found  | List available remote branches                   |
| Main worktree on feature | Warn via AskUserQuestion, offer to switch        |
| Empty description        | Show usage examples                              |
| Network error on fetch   | Allow offline mode with local branches only      |
| Worktree path exists     | Suggest cleanup or different slug                |

### Branch Not Found

```
✗ Branch 'feat/nonexistent' not found

  Available branches:
  - feat/2025-12-14-sharpe-statistical-validation
  - main

  To create from remote:
  Specify: "create worktree from origin/branch-name"
```

### Worktree Already Exists

```
✗ Worktree already exists for this branch

  Existing path: ~/eon/alpha-forge.worktree-2025-12-14-sharpe-statistical-validation

  To use existing worktree:
  cd ~/eon/alpha-forge.worktree-2025-12-14-sharpe-statistical-validation
```

---

## Integration

### direnv Environment Setup

Worktrees automatically get a `.envrc` file that loads shared credentials from `~/eon/.env.alpha-forge`.

**What happens on worktree creation**:

1. Script checks if `~/eon/.env.alpha-forge` exists
2. Creates `.envrc` in the new worktree with `dotenv` directive
3. Runs `direnv allow` to approve the new `.envrc`

**Shared secrets file** (`~/eon/.env.alpha-forge`):

```bash
# ClickHouse credentials, API keys, etc.
CLICKHOUSE_HOST_READONLY="..."
CLICKHOUSE_USER_READONLY="..."
CLICKHOUSE_PASSWORD_READONLY="..."
```

**Generated `.envrc`** (in each worktree):

```bash
# alpha-forge worktree direnv config
# Auto-generated by create-worktree.sh

# Load shared alpha-forge secrets
dotenv /Users/terryli/eon/.env.alpha-forge

# Worktree-specific overrides can be added below
```

**Prerequisites**:

- direnv installed via mise (`mise use -g direnv@latest`)
- Shell hook configured (`eval "$(direnv hook zsh)"` in `~/.zshrc`)
- Shared secrets file at `~/eon/.env.alpha-forge`

### iTerm2 Dynamic Detection

The `default-layout.py` script auto-discovers worktrees:

1. Globs `~/eon/alpha-forge.worktree-*`
2. Validates each against `git worktree list`
3. Generates `AF-{acronym}` tab names
4. Inserts tabs after main AF tab

---

## References

- [Naming Conventions](./references/naming-conventions.md)
- [ADR: Alpha-Forge Git Worktree Management](/docs/adr/2025-12-14-alpha-forge-worktree-management.md)
- [Design Spec](/docs/design/2025-12-14-alpha-forge-worktree-management/spec.md)

---

## Troubleshooting

| Issue                     | Cause                          | Solution                                        |
| ------------------------- | ------------------------------ | ----------------------------------------------- |
| Branch already exists     | Local branch with same name    | Use Mode 3 (existing branch) or rename slug     |
| Remote branch not found   | Typo or not pushed yet         | Run `git fetch --all --prune` and list branches |
| Worktree path exists      | Previous worktree not cleaned  | Remove old worktree or use different slug       |
| direnv not loading        | Shell hook not configured      | Add `eval "$(direnv hook zsh)"` to ~/.zshrc     |
| Shared secrets not found  | ~/eon/.env.alpha-forge missing | Create shared secrets file with required vars   |
| iTerm2 tab not appearing  | Dynamic layout not refreshed   | Restart iTerm2 to trigger layout regeneration   |
| Main worktree not on main | Previous work not switched     | Run `git checkout main` in main worktree first  |
| Stale worktree detected   | Branch merged but not cleaned  | Run `git worktree remove <path>` to cleanup     |

Overview

This skill creates and manages git worktrees for the alpha-forge repository with automatic branch naming, consistent folder/tab conventions, and lifecycle tools for cleanup. It derives kebab-case slugs from natural language, constructs dated branch names, and performs atomic worktree creation with direnv and iTerm2 integration. The skill supports new-branch creation, remote tracking, and attaching existing local branches.

How this skill works

Given a natural-language description or explicit branch reference, the skill derives a compact slug (3–5 meaningful words), prompts for branch type and base, verifies the main worktree state, fetches remotes, and builds a branch name like type/YYYY-MM-DD-slug. It then creates an atomic git worktree at ~/eon/alpha-forge.worktree-YYYY-MM-DD-slug, generates an AF-{acronym} tab name, writes a .envrc that points to shared secrets, and reports the created path and branch. Alternative modes handle origin/branch (remote track) and existing local branches.

When to use it

  • Start a new feature, fix, refactor, or chore for alpha-forge from a short description
  • Create a worktree that tracks an existing remote branch (origin/...)
  • Open a worktree for an already-created local branch
  • Manage multiple parallel feature branches without touching main worktree state
  • Detect and clean stale worktrees after branches are merged

Best practices

  • Keep the main worktree on main before creating worktrees; the skill will warn and offer to switch
  • Follow the word-economy rule in descriptions: remove filler words and limit to 3–5 meaningful words
  • Choose appropriate branch type (feat/fix/refactor/chore) and base branch (main or develop) when prompted
  • Use the generated worktree path and tab naming to quickly identify active worktrees in iTerm2
  • Run git fetch --all --prune regularly and prune worktrees after branch deletion

Example use cases

  • "create worktree for sharpe statistical validation" -> creates feat/YYYY-MM-DD-sharpe-statistical-validation with AF-ssv tab
  • "create worktree from origin/feat/2025-12-10-existing-feature" -> creates local tracking branch and worktree
  • "create worktree for feat/2025-12-15-my-feature" -> attaches an existing local branch to a new worktree
  • Detect stale worktrees whose branches are merged to main and prompt to remove them
  • Generate .envrc in each worktree that loads shared secrets from ~/eon/.env.alpha-forge

FAQ

What if the main worktree is not on main?

The skill warns and offers to switch the main worktree to main before creating a new worktree; you can continue anyway or choose to switch first.

How is the branch name constructed?

Branch names follow type/YYYY-MM-DD-slug, where type is one of feat/fix/refactor/chore, date is today (or parsed from an existing branch), and slug is a kebab-case, word-economy-derived identifier.