From 4652e65ec8135ccd1e9199dbeab2bd4be5d9b85e Mon Sep 17 00:00:00 2001 From: Drew Ritter Date: Mon, 6 Apr 2026 14:30:07 -0700 Subject: [PATCH] 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) --- skills/using-git-worktrees/SKILL.md | 214 +++++++++++++++------------- 1 file changed, 115 insertions(+), 99 deletions(-) diff --git a/skills/using-git-worktrees/SKILL.md b/skills/using-git-worktrees/SKILL.md index e153843c..d16d2f4e 100644 --- a/skills/using-git-worktrees/SKILL.md +++ b/skills/using-git-worktrees/SKILL.md @@ -1,104 +1,126 @@ --- 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 ## 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." -## 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 `` on branch ``." +- Detached HEAD: "Already in isolated workspace at `` (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: -### 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 -# Check in priority order -ls -d .worktrees 2>/dev/null # Preferred (hidden) -ls -d worktrees 2>/dev/null # Alternative -``` +2. **Check for existing global directory:** + ```bash + project=$(basename "$(git rev-parse --show-toplevel)") + 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 -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// (global location) - -Which would you prefer? -``` - -## Safety Verification - -### For Project-Local Directories (.worktrees or worktrees) +#### Safety Verification (project-local directories only) **MUST verify directory is ignored before creating worktree:** ```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 ``` -**If NOT ignored:** - -Per Jesse's rule "Fix broken things immediately": -1. Add appropriate line to .gitignore -2. Commit the change -3. Proceed with worktree creation +**If NOT ignored:** Add to .gitignore, commit the change, then proceed. **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. - -## Creation Steps - -### 1. Detect Project Name +#### Create the Worktree ```bash 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" 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: @@ -117,23 +139,20 @@ if [ -f pyproject.toml ]; then poetry install; 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 -# Examples - use project-appropriate command -npm test -cargo test -pytest -go test ./... +# Use project-appropriate command +npm test / cargo test / pytest / go test ./... ``` **If tests fail:** Report failures, ask whether to proceed or investigate. **If tests pass:** Report ready. -### 5. Report Location +### Report ``` Worktree ready at @@ -145,16 +164,32 @@ Ready to implement | 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) | | 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 | +| Permission error on create | Sandbox fallback, work in place | | Tests fail during baseline | Report failures + ask | | No package.json/Cargo.toml | Skip dependency install | ## 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 - **Problem:** Worktree contents get tracked, pollute git status @@ -163,55 +198,36 @@ Ready to implement ### Assuming directory location - **Problem:** Creates inconsistency, violates project conventions -- **Fix:** Follow priority: existing > CLAUDE.md > ask +- **Fix:** Follow priority: existing > instruction file > default ### Proceeding with failing tests - **Problem:** Can't distinguish new bugs from pre-existing issues - **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 **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) - Skip baseline test verification - Proceed with failing tests without asking -- Assume directory location when ambiguous -- Skip CLAUDE.md check **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 - Auto-detect and run project setup - Verify clean test baseline +- Symlink hooks after creating worktree via 1b ## Integration **Called by:** -- **brainstorming** (Phase 4) - REQUIRED when design is approved and implementation follows -- **subagent-driven-development** - REQUIRED before executing any tasks -- **executing-plans** - REQUIRED before executing any tasks +- **subagent-driven-development** - Ensures isolated workspace (creates one or verifies existing) +- **executing-plans** - Ensures isolated workspace (creates one or verifies existing) - Any skill needing isolated workspace **Pairs with:**