feat: rewrite using-git-worktrees with detect-and-defer (PRI-974)

Step 0: GIT_DIR != GIT_COMMON detection (skip if already isolated)
Step 0 consent: opt-in prompt before creating worktree (#991)
Step 1a: native tool preference (short, first, declarative)
Step 1b: git worktree fallback with hooks symlink and legacy path compat
Submodule guard prevents false detection
Platform-neutral instruction file references (#1049)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Drew Ritter
2026-04-06 14:30:07 -07:00
parent abaaf8a6e6
commit 4652e65ec8

View File

@@ -1,104 +1,126 @@
--- ---
name: using-git-worktrees name: using-git-worktrees
description: Use when starting feature work that needs isolation from current workspace or before executing implementation plans - creates isolated git worktrees with smart directory selection and safety verification description: Use when starting feature work that needs isolation from current workspace or before executing implementation plans - ensures an isolated workspace exists via native tools or git worktree fallback
--- ---
# Using Git Worktrees # Using Git Worktrees
## Overview ## Overview
Git worktrees create isolated workspaces sharing the same repository, allowing work on multiple branches simultaneously without switching. Ensure work happens in an isolated workspace. Prefer your platform's native worktree tools. Fall back to manual git worktrees only when no native tool is available.
**Core principle:** Systematic directory selection + safety verification = reliable isolation. **Core principle:** Detect existing isolation first. Then use native tools. Then fall back to git. Never fight the harness.
**Announce at start:** "I'm using the using-git-worktrees skill to set up an isolated workspace." **Announce at start:** "I'm using the using-git-worktrees skill to set up an isolated workspace."
## Directory Selection Process ## Step 0: Detect Existing Isolation
**Before creating anything, check if you are already in an isolated workspace.**
```bash
GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
BRANCH=$(git branch --show-current)
```
**Submodule guard:** `GIT_DIR != GIT_COMMON` is also true inside git submodules. Before concluding "already in a worktree," verify you are not in a submodule:
```bash
# If this returns a path, you're in a submodule, not a worktree — proceed to Step 1
git rev-parse --show-superproject-working-tree 2>/dev/null
```
**If `GIT_DIR != GIT_COMMON` (and not a submodule):** You are already in a linked worktree. Skip to Step 3 (Project Setup). Do NOT create another worktree.
Report with branch state:
- On a branch: "Already in isolated workspace at `<path>` on branch `<name>`."
- Detached HEAD: "Already in isolated workspace at `<path>` (detached HEAD, externally managed). Branch creation needed at finish time."
**If `GIT_DIR == GIT_COMMON` (or in a submodule):** You are in a normal repo checkout. Ask for consent before creating a workspace:
> "Would you like me to set up an isolated worktree? This protects your current branch from changes. (y/n)"
If yes, proceed to Step 1. If no, work in place — skip to Step 3 with no worktree.
## Step 1: Create Isolated Workspace
**You have two mechanisms. Try them in this order.**
### 1a. Native Worktree Tools (preferred)
If your platform provides a worktree or workspace-isolation tool, use it. You know your own toolkit — the skill does not need to name specific tools. Native tools handle directory placement, branch creation, and cleanup automatically.
After using a native tool, skip to Step 3 (Project Setup).
### 1b. Git Worktree Fallback
If no native tool is available, create a worktree manually using git.
#### Directory Selection
Follow this priority order: Follow this priority order:
### 1. Check Existing Directories 1. **Check existing directories:**
```bash
ls -d .worktrees 2>/dev/null # Preferred (hidden)
ls -d worktrees 2>/dev/null # Alternative
```
If found, use that directory. If both exist, `.worktrees` wins.
```bash 2. **Check for existing global directory:**
# Check in priority order ```bash
ls -d .worktrees 2>/dev/null # Preferred (hidden) project=$(basename "$(git rev-parse --show-toplevel)")
ls -d worktrees 2>/dev/null # Alternative ls -d ~/.config/superpowers/worktrees/$project 2>/dev/null
``` ```
If found, use it (backward compatibility with legacy global path).
**If found:** Use that directory. If both exist, `.worktrees` wins. 3. **Check your project's agent instruction file** (CLAUDE.md, GEMINI.md, AGENTS.md, .cursorrules, or equivalent) for a worktree directory preference. If specified, use it without asking.
### 2. Check CLAUDE.md 4. **Default to `.worktrees/`.**
```bash #### Safety Verification (project-local directories only)
grep -i "worktree.*director" CLAUDE.md 2>/dev/null
```
**If preference specified:** Use it without asking.
### 3. Ask User
If no directory exists and no CLAUDE.md preference:
```
No worktree directory found. Where should I create worktrees?
1. .worktrees/ (project-local, hidden)
2. ~/.config/superpowers/worktrees/<project-name>/ (global location)
Which would you prefer?
```
## Safety Verification
### For Project-Local Directories (.worktrees or worktrees)
**MUST verify directory is ignored before creating worktree:** **MUST verify directory is ignored before creating worktree:**
```bash ```bash
# Check if directory is ignored (respects local, global, and system gitignore)
git check-ignore -q .worktrees 2>/dev/null || git check-ignore -q worktrees 2>/dev/null git check-ignore -q .worktrees 2>/dev/null || git check-ignore -q worktrees 2>/dev/null
``` ```
**If NOT ignored:** **If NOT ignored:** Add to .gitignore, commit the change, then proceed.
Per Jesse's rule "Fix broken things immediately":
1. Add appropriate line to .gitignore
2. Commit the change
3. Proceed with worktree creation
**Why critical:** Prevents accidentally committing worktree contents to repository. **Why critical:** Prevents accidentally committing worktree contents to repository.
### For Global Directory (~/.config/superpowers/worktrees) Global directories (`~/.config/superpowers/worktrees/`) need no verification.
No .gitignore verification needed - outside project entirely. #### Create the Worktree
## Creation Steps
### 1. Detect Project Name
```bash ```bash
project=$(basename "$(git rev-parse --show-toplevel)") project=$(basename "$(git rev-parse --show-toplevel)")
```
### 2. Create Worktree # Determine path based on chosen location
# For project-local: path="$LOCATION/$BRANCH_NAME"
# For global: path="~/.config/superpowers/worktrees/$project/$BRANCH_NAME"
```bash
# Determine full path
case $LOCATION in
.worktrees|worktrees)
path="$LOCATION/$BRANCH_NAME"
;;
~/.config/superpowers/worktrees/*)
path="~/.config/superpowers/worktrees/$project/$BRANCH_NAME"
;;
esac
# Create worktree with new branch
git worktree add "$path" -b "$BRANCH_NAME" git worktree add "$path" -b "$BRANCH_NAME"
cd "$path" cd "$path"
``` ```
### 3. Run Project Setup #### Hooks Awareness
Git worktrees do not inherit the parent repo's hooks directory. After creating the worktree, symlink hooks from the main repo if they exist:
```bash
MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
if [ -d "$MAIN_ROOT/.git/hooks" ]; then
ln -sf "$MAIN_ROOT/.git/hooks" "$path/.git/hooks"
fi
```
This prevents pre-commit checks, linters, and other hooks from silently stopping when work moves to a worktree.
**Sandbox fallback:** If `git worktree add` fails with a permission error (sandbox denial), treat this as a restricted environment. Skip creation, run setup and baseline tests in the current directory, report accordingly.
## Step 3: Project Setup
Auto-detect and run appropriate setup: Auto-detect and run appropriate setup:
@@ -117,23 +139,20 @@ if [ -f pyproject.toml ]; then poetry install; fi
if [ -f go.mod ]; then go mod download; fi if [ -f go.mod ]; then go mod download; fi
``` ```
### 4. Verify Clean Baseline ## Step 4: Verify Clean Baseline
Run tests to ensure worktree starts clean: Run tests to ensure workspace starts clean:
```bash ```bash
# Examples - use project-appropriate command # Use project-appropriate command
npm test npm test / cargo test / pytest / go test ./...
cargo test
pytest
go test ./...
``` ```
**If tests fail:** Report failures, ask whether to proceed or investigate. **If tests fail:** Report failures, ask whether to proceed or investigate.
**If tests pass:** Report ready. **If tests pass:** Report ready.
### 5. Report Location ### Report
``` ```
Worktree ready at <full-path> Worktree ready at <full-path>
@@ -145,16 +164,32 @@ Ready to implement <feature-name>
| Situation | Action | | Situation | Action |
|-----------|--------| |-----------|--------|
| Already in linked worktree | Skip creation (Step 0) |
| In a submodule | Treat as normal repo (Step 0 guard) |
| Native worktree tool available | Use it (Step 1a) |
| No native tool | Git worktree fallback (Step 1b) |
| `.worktrees/` exists | Use it (verify ignored) | | `.worktrees/` exists | Use it (verify ignored) |
| `worktrees/` exists | Use it (verify ignored) | | `worktrees/` exists | Use it (verify ignored) |
| Both exist | Use `.worktrees/` | | Both exist | Use `.worktrees/` |
| Neither exists | Check CLAUDE.md → Ask user | | Neither exists | Check instruction file, then default `.worktrees/` |
| Global path exists | Use it (backward compat) |
| Directory not ignored | Add to .gitignore + commit | | Directory not ignored | Add to .gitignore + commit |
| Permission error on create | Sandbox fallback, work in place |
| Tests fail during baseline | Report failures + ask | | Tests fail during baseline | Report failures + ask |
| No package.json/Cargo.toml | Skip dependency install | | No package.json/Cargo.toml | Skip dependency install |
## Common Mistakes ## Common Mistakes
### Fighting the harness
- **Problem:** Using `git worktree add` when the platform already provides isolation
- **Fix:** Step 0 detects existing isolation. Step 1a defers to native tools.
### Skipping detection
- **Problem:** Creating a nested worktree inside an existing one
- **Fix:** Always run Step 0 before creating anything
### Skipping ignore verification ### Skipping ignore verification
- **Problem:** Worktree contents get tracked, pollute git status - **Problem:** Worktree contents get tracked, pollute git status
@@ -163,55 +198,36 @@ Ready to implement <feature-name>
### Assuming directory location ### Assuming directory location
- **Problem:** Creates inconsistency, violates project conventions - **Problem:** Creates inconsistency, violates project conventions
- **Fix:** Follow priority: existing > CLAUDE.md > ask - **Fix:** Follow priority: existing > instruction file > default
### Proceeding with failing tests ### Proceeding with failing tests
- **Problem:** Can't distinguish new bugs from pre-existing issues - **Problem:** Can't distinguish new bugs from pre-existing issues
- **Fix:** Report failures, get explicit permission to proceed - **Fix:** Report failures, get explicit permission to proceed
### Hardcoding setup commands
- **Problem:** Breaks on projects using different tools
- **Fix:** Auto-detect from project files (package.json, etc.)
## Example Workflow
```
You: I'm using the using-git-worktrees skill to set up an isolated workspace.
[Check .worktrees/ - exists]
[Verify ignored - git check-ignore confirms .worktrees/ is ignored]
[Create worktree: git worktree add .worktrees/auth -b feature/auth]
[Run npm install]
[Run npm test - 47 passing]
Worktree ready at /Users/jesse/myproject/.worktrees/auth
Tests passing (47 tests, 0 failures)
Ready to implement auth feature
```
## Red Flags ## Red Flags
**Never:** **Never:**
- Create a worktree when Step 0 detects existing isolation
- Use git commands when a native worktree tool is available
- Create worktree without verifying it's ignored (project-local) - Create worktree without verifying it's ignored (project-local)
- Skip baseline test verification - Skip baseline test verification
- Proceed with failing tests without asking - Proceed with failing tests without asking
- Assume directory location when ambiguous
- Skip CLAUDE.md check
**Always:** **Always:**
- Follow directory priority: existing > CLAUDE.md > ask - Run Step 0 detection first
- Prefer native tools over git fallback
- Follow directory priority: existing > instruction file > default
- Verify directory is ignored for project-local - Verify directory is ignored for project-local
- Auto-detect and run project setup - Auto-detect and run project setup
- Verify clean test baseline - Verify clean test baseline
- Symlink hooks after creating worktree via 1b
## Integration ## Integration
**Called by:** **Called by:**
- **brainstorming** (Phase 4) - REQUIRED when design is approved and implementation follows - **subagent-driven-development** - Ensures isolated workspace (creates one or verifies existing)
- **subagent-driven-development** - REQUIRED before executing any tasks - **executing-plans** - Ensures isolated workspace (creates one or verifies existing)
- **executing-plans** - REQUIRED before executing any tasks
- Any skill needing isolated workspace - Any skill needing isolated workspace
**Pairs with:** **Pairs with:**