Commit a6be5a5febf5

Vincent Demeester <vincent@sbr.pm>
2026-01-27 15:31:39
refactor(skill): switch UsingGitWorktrees to sibling layout
Replace nested .worktrees/ pattern with sibling layout where main worktree and feature worktrees are siblings under a parent folder. Key changes: - Remove .worktrees/ and worktrees/ as options - Add detection logic for sibling layout (check if .git is file vs dir) - Add migration flow for repos not in sibling layout - Update all examples to use relative paths (../branch-name) - Update Python setup to use uv instead of pip Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent ab2f911
Changed files (1)
dots
.config
claude
skills
UsingGitWorktrees
dots/.config/claude/skills/UsingGitWorktrees/SKILL.md
@@ -1,11 +1,11 @@
 ---
 name: UsingGitWorktrees
-description: Creates isolated git worktrees with smart directory selection and safety verification for parallel development. USE WHEN starting feature work that needs isolation from current workspace OR before executing implementation plans OR working on multiple branches simultaneously OR need clean test environment. Creates isolated workspaces sharing the same repository.
+description: Creates isolated git worktrees using sibling layout for parallel development. USE WHEN starting feature work that needs isolation from current workspace OR before executing implementation plans OR working on multiple branches simultaneously OR need clean test environment. Creates isolated workspaces as siblings to main worktree.
 ---
 
 # UsingGitWorktrees
 
-Create isolated git workspaces for parallel development without switching branches.
+Create isolated git workspaces for parallel development using sibling layout.
 
 ## Overview
 
@@ -15,136 +15,202 @@ Git worktrees create isolated working directories that share the same repository
 - Clean baseline for new features
 - No stashing or switching required
 
-**Core principle:** Systematic directory selection + safety verification = reliable isolation
+**Core principle:** Sibling layout keeps worktrees organized as peers, not nested inside each other.
 
 **Announce at start:** "I'm using the UsingGitWorktrees skill to set up an isolated workspace."
 
-## Why Use Git Worktrees?
+## Sibling Layout
 
-### Benefits
+All worktrees live as siblings under a parent folder:
 
-✅ **Multiple branches active**: Work on feature branch while keeping main branch clean
-✅ **Isolated testing**: Each worktree has its own working directory and build artifacts
-✅ **No switching**: No need to stash changes or switch branches
-✅ **Clean baselines**: Start new work with verified clean state
-✅ **Parallel CI**: Run tests in multiple worktrees simultaneously
+```
+~/projects/my-project/           # parent folder
+├── main/                        # main git working tree (main branch)
+├── feature-auth/                # worktree for feature/auth branch
+├── bugfix-123/                  # worktree for bugfix/123 branch
+└── experiment-new-api/          # worktree for experiment/new-api
+```
 
-### vs. Branch Switching
+### Benefits of Sibling Layout
 
-| Aspect | Branch Switching | Git Worktrees |
-|--------|------------------|---------------|
-| Working directory | One (must switch) | Multiple (parallel) |
-| Uncommitted changes | Must stash | Keep in original worktree |
-| Dependencies | Reinstall on switch | Separate per worktree |
-| Build artifacts | Shared (conflicts) | Isolated |
-| Test runs | Sequential only | Parallel capable |
+- **No .gitignore needed:** Worktrees aren't inside any repo
+- **Clear organization:** All related work in one parent folder
+- **Easy navigation:** `cd ../feature-auth` to switch contexts
+- **No nesting confusion:** Each worktree is independent
+- **Clean main worktree:** No `.worktrees/` folder cluttering the repo
 
-## Directory Selection Process
+### vs. Nested Layout (NOT used)
 
-Follow this priority order:
+| Aspect | Sibling Layout | Nested Layout |
+|--------|----------------|---------------|
+| Worktree location | Siblings under parent | Inside repo (`.worktrees/`) |
+| Requires .gitignore | No | Yes (easy to forget) |
+| Navigation | `cd ../other-branch` | `cd .worktrees/other-branch` |
+| Visual clutter | None in repo | Extra folder in repo |
+| Risk of tracking | None | High if .gitignore missing |
 
-### 1. Check for Existing Worktree Directory
+## Detection: Is Repo in Sibling Layout?
+
+Check if the current repo is set up correctly:
 
 ```bash
-# Check in priority order
-if [ -d .worktrees ]; then
-    WORKTREE_DIR=".worktrees"
-elif [ -d worktrees ]; then
-    WORKTREE_DIR="worktrees"
+# Get git directory info
+GIT_DIR=$(git rev-parse --git-dir)
+
+# Check if .git is a file (worktree) or directory (main repo)
+if [ -f .git ]; then
+    # This is a worktree - .git is a file pointing to main repo
+    IS_WORKTREE=true
+else
+    # This is a main repo - .git is a directory
+    IS_WORKTREE=false
 fi
+
+# Get the toplevel of current worktree
+TOPLEVEL=$(git rev-parse --show-toplevel)
+PARENT_DIR=$(dirname "$TOPLEVEL")
+CURRENT_FOLDER=$(basename "$TOPLEVEL")
+
+# Check if parent has sibling worktrees
+# A sibling layout means: parent folder contains the main worktree
+# and worktrees are created as siblings
+git worktree list | while read -r path branch rest; do
+    WORKTREE_PARENT=$(dirname "$path")
+    if [ "$WORKTREE_PARENT" = "$PARENT_DIR" ]; then
+        echo "Sibling layout detected: parent is $PARENT_DIR"
+    fi
+done
 ```
 
-**If found:** Use that directory (`.worktrees` takes priority over `worktrees`)
+### Detection Logic
 
-### 2. Check CLAUDE.md for Preference
+1. **Get worktree list:** `git worktree list` shows all worktrees
+2. **Check parent directories:** All worktrees should share the same parent
+3. **Verify main worktree:** One worktree should be the default branch (main/master)
 
 ```bash
-if [ -f CLAUDE.md ]; then
-    grep -i "worktree.*director" CLAUDE.md
-fi
+# Full detection function
+detect_sibling_layout() {
+    local worktree_list
+    worktree_list=$(git worktree list --porcelain)
+
+    local parents=()
+    local main_found=false
+
+    while IFS= read -r line; do
+        if [[ $line == worktree\ * ]]; then
+            path="${line#worktree }"
+            parent=$(dirname "$path")
+            parents+=("$parent")
+        fi
+        if [[ $line == branch\ refs/heads/main ]] || [[ $line == branch\ refs/heads/master ]]; then
+            main_found=true
+        fi
+    done <<< "$worktree_list"
+
+    # All worktrees should have same parent
+    local unique_parents
+    unique_parents=$(printf '%s\n' "${parents[@]}" | sort -u | wc -l)
+
+    if [ "$unique_parents" -eq 1 ] && [ "$main_found" = true ]; then
+        echo "${parents[0]}"  # Return parent directory
+        return 0
+    fi
+    return 1
+}
 ```
 
-**If preference specified:** Use it without asking user
+## Migration to Sibling Layout
 
-### 3. Ask User
+If a repo is not in sibling layout, offer to migrate:
 
-If no directory exists and no CLAUDE.md preference:
+### Step 1: Explain the Situation
 
 ```
-No worktree directory found. Where should I create worktrees?
+This repository is not set up for sibling worktree layout.
 
-1. .worktrees/ (project-local, hidden, recommended)
-2. worktrees/ (project-local, visible)
-3. ~/worktrees/<project-name>/ (global location)
+Current location: /home/user/repos/my-project
+Git directory: /home/user/repos/my-project/.git (standard repo)
 
-Which would you prefer?
+Sibling layout organizes worktrees as peers:
+  ~/projects/my-project/
+  ├── main/              ← your repo moves here
+  ├── feature-branch/    ← worktrees as siblings
+  └── another-branch/
+
+Would you like me to migrate to sibling layout?
 ```
 
-**Recommendation:** `.worktrees/` keeps project directory clean while remaining local
+### Step 2: Get Migration Target
 
-## Safety Verification
+Ask user where to create the parent folder:
 
-### For Project-Local Directories (.worktrees or worktrees)
+```
+Where should the project parent folder be?
 
-**MUST verify directory is git-ignored before creating worktree:**
+1. ~/projects/my-project/ (Recommended)
+2. ~/src/my-project/
+3. Custom location
+
+Current repo will become: <parent>/main/
+Worktrees will be: <parent>/<branch-name>/
+```
+
+### Step 3: Perform Migration
 
 ```bash
-# Check if directory is properly ignored
-if ! git check-ignore -q .worktrees && ! git check-ignore -q worktrees; then
-    echo "WARNING: Worktree directory is not ignored!"
-    # Must fix before proceeding
-fi
+# Variables
+PROJECT_NAME="my-project"
+CURRENT_REPO="/home/user/repos/my-project"
+PARENT_DIR="$HOME/projects/$PROJECT_NAME"
+NEW_MAIN="$PARENT_DIR/main"
+
+# Create parent directory
+mkdir -p "$PARENT_DIR"
+
+# Move current repo to become 'main' worktree
+mv "$CURRENT_REPO" "$NEW_MAIN"
+
+# Navigate to new location
+cd "$NEW_MAIN"
+
+# Verify git still works
+git status
+git worktree list
 ```
 
-**Why critical:** Prevents accidentally committing worktree contents to repository
-
-**If NOT ignored - MUST fix immediately:**
+### Step 4: Verify Migration
 
 ```bash
-# Add to .gitignore
-echo ".worktrees/" >> .gitignore
-# OR
-echo "worktrees/" >> .gitignore
+# Should show:
+# /home/user/projects/my-project/main  abc1234 [main]
 
-# Commit the change
-git add .gitignore
-git commit -m "chore: ignore git worktree directory"
+git worktree list
+
+# Confirm structure
+ls -la "$PARENT_DIR"
+# Should show: main/
 ```
 
-### For Global Directory (~/worktrees)
+## Worktree Creation (Post-Migration)
 
-No .gitignore verification needed - outside project entirely
+Once in sibling layout, creating worktrees is simple:
 
-## Worktree Creation Steps
-
-### Step 1: Detect Project Name
+### Step 1: Determine Worktree Path
 
 ```bash
-PROJECT=$(basename "$(git rev-parse --show-toplevel)")
-```
+# Get project parent directory
+PARENT_DIR=$(dirname "$(git rev-parse --show-toplevel)")
 
-### Step 2: Determine Branch Name
-
-```bash
 # Sanitize branch name for filesystem
 BRANCH_NAME="feature/user-authentication"
 BRANCH_PATH=$(echo "$BRANCH_NAME" | tr '/' '-')  # feature-user-authentication
+
+# Worktree path is sibling to main
+WORKTREE_PATH="$PARENT_DIR/$BRANCH_PATH"
 ```
 
-### Step 3: Construct Worktree Path
-
-```bash
-case $WORKTREE_DIR in
-  .worktrees|worktrees)
-    WORKTREE_PATH="$WORKTREE_DIR/$BRANCH_PATH"
-    ;;
-  ~/worktrees/*)
-    WORKTREE_PATH="$HOME/worktrees/$PROJECT/$BRANCH_PATH"
-    ;;
-esac
-```
-
-### Step 4: Create Worktree with New Branch
+### Step 2: Create Worktree
 
 ```bash
 # Create worktree and branch in one command
@@ -160,7 +226,7 @@ cd "$WORKTREE_PATH"
 git worktree add "$WORKTREE_PATH" "$BRANCH_NAME"
 ```
 
-### Step 5: Auto-Detect and Run Project Setup
+### Step 3: Auto-Detect and Run Project Setup
 
 Detect project type and install dependencies:
 
@@ -176,14 +242,10 @@ if [ -f Cargo.toml ]; then
 fi
 
 # Python
-if [ -f requirements.txt ]; then
-    pip install -r requirements.txt
-fi
-
 if [ -f pyproject.toml ]; then
-    poetry install
-    # OR
-    pip install -e .
+    uv sync  # Prefer uv over pip
+elif [ -f requirements.txt ]; then
+    uv pip install -r requirements.txt
 fi
 
 # Go
@@ -197,7 +259,7 @@ if [ -f flake.nix ]; then
 fi
 ```
 
-### Step 6: Verify Clean Baseline
+### Step 4: Verify Clean Baseline
 
 Run tests to ensure worktree starts in working state:
 
@@ -230,12 +292,12 @@ make build
 - Show test count and duration
 - Confirm ready for work
 
-### Step 7: Report Worktree Ready
+### Step 5: Report Worktree Ready
 
 ```
 Worktree created successfully
 
-Location: /path/to/project/.worktrees/feature-user-authentication
+Location: ~/projects/my-project/feature-user-authentication
 Branch: feature/user-authentication
 Tests: ✓ 47 passing (2.3s)
 
@@ -250,21 +312,34 @@ Ready to implement user authentication feature
 git worktree list
 ```
 
-**Output:**
+**Output (sibling layout):**
 ```
-/path/to/project        abc1234 [main]
-/path/to/.worktrees/feature-auth  def5678 [feature/user-authentication]
-/path/to/.worktrees/bugfix-db     ghi9012 [bugfix/database-connection]
+/home/user/projects/my-project/main               abc1234 [main]
+/home/user/projects/my-project/feature-auth       def5678 [feature/auth]
+/home/user/projects/my-project/bugfix-db          ghi9012 [bugfix/database]
+```
+
+### Navigate Between Worktrees
+
+```bash
+# From main, go to feature-auth
+cd ../feature-auth
+
+# From any worktree, go to main
+cd ../main
+
+# List siblings
+ls ..
 ```
 
 ### Remove Worktree
 
 ```bash
 # Remove worktree (keeps branch)
-git worktree remove .worktrees/feature-auth
+git worktree remove ../feature-auth
 
 # Force remove (even with uncommitted changes)
-git worktree remove --force .worktrees/feature-auth
+git worktree remove --force ../feature-auth
 ```
 
 ### Prune Deleted Worktrees
@@ -274,26 +349,17 @@ git worktree remove --force .worktrees/feature-auth
 git worktree prune
 ```
 
-### Move to Different Worktree
-
-```bash
-# Just cd to it - no branch switching needed
-cd .worktrees/feature-auth
-```
-
 ## Quick Reference
 
 | Situation | Action |
 |-----------|--------|
-| `.worktrees/` exists | Use it (verify ignored) |
-| `worktrees/` exists | Use it (verify ignored) |
-| Both exist | Use `.worktrees/` (takes priority) |
-| Neither exists | Check CLAUDE.md → Ask user |
-| Directory not ignored | Add to `.gitignore` + commit immediately |
-| Tests fail during setup | Report failures + ask user |
-| No package.json/Cargo.toml | Skip dependency install |
-| Worktree no longer needed | `git worktree remove <path>` |
-| Manual deletion cleanup | `git worktree prune` |
+| First time with repo | Check if sibling layout → migrate if not |
+| Create new worktree | `git worktree add ../<branch-path> -b <branch>` |
+| Switch worktrees | `cd ../<other-worktree>` |
+| List worktrees | `git worktree list` |
+| Remove worktree | `git worktree remove ../<worktree>` |
+| Cleanup references | `git worktree prune` |
+| Check current branch | `git branch --show-current` |
 
 ## Common Patterns for Your Home Repository
 
@@ -302,10 +368,10 @@ Based on your NixOS home repository structure:
 ### Building a NixOS Configuration
 
 ```bash
-# Create worktree for system change
-git worktree add .worktrees/sakhalin-upgrade -b feature/sakhalin-upgrade
+# Create worktree for system change (from main/)
+git worktree add ../sakhalin-upgrade -b feature/sakhalin-upgrade
 
-cd .worktrees/sakhalin-upgrade
+cd ../sakhalin-upgrade
 
 # Build without switching main worktree
 make host/sakhalin/build
@@ -318,14 +384,14 @@ make host/sakhalin/switch
 
 ```bash
 # Multiple worktrees for different hosts
-git worktree add .worktrees/rhea-config -b feature/rhea-jellyfin
-git worktree add .worktrees/aion-config -b feature/aion-audio
+git worktree add ../rhea-jellyfin -b feature/rhea-jellyfin
+git worktree add ../aion-audio -b feature/aion-audio
 
 # Work on both simultaneously
-cd .worktrees/rhea-config
+cd ../rhea-jellyfin
 make host/rhea/build
 
-cd ../aion-config
+cd ../aion-audio
 make host/aion/build
 ```
 
@@ -333,9 +399,9 @@ make host/aion/build
 
 ```bash
 # Isolated worktree for flake updates
-git worktree add .worktrees/flake-update -b chore/flake-update
+git worktree add ../flake-update -b chore/flake-update
 
-cd .worktrees/flake-update
+cd ../flake-update
 
 # Update and test
 nix flake update
@@ -346,26 +412,26 @@ make dry-build
 
 ## Common Mistakes
 
-### ❌ Skipping Ignore Verification
+### ❌ Creating Worktrees Without Sibling Layout
 
-**Problem:** Worktree contents get tracked, pollute `git status` in main worktree
-**Fix:** Always use `git check-ignore` before creating project-local worktree
+**Problem:** Worktrees end up in random locations, hard to find
+**Fix:** Always migrate to sibling layout first
 
-### ❌ Assuming Directory Location
+### ❌ Forgetting to Migrate
 
-**Problem:** Creates inconsistency, violates project conventions
-**Fix:** Follow priority: existing → CLAUDE.md → ask user
+**Problem:** Old repos still use nested `.worktrees/` pattern
+**Fix:** Run migration when skill detects non-sibling layout
+
+### ❌ Using Absolute Paths Instead of Relative
+
+**Problem:** Commands are longer and harder to type
+**Fix:** Use `../branch-name` for sibling navigation
 
 ### ❌ 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, Cargo.toml, etc.)
-
 ### ❌ Forgetting to Remove Old Worktrees
 
 **Problem:** Disk space waste, confusion about active work
@@ -390,11 +456,11 @@ make dry-build
 **Cleanup after work:**
 ```bash
 # Merge work back to main
-git checkout main
+cd ../main
 git merge feature/user-authentication
 
 # Remove worktree
-git worktree remove .worktrees/feature-user-authentication
+git worktree remove ../feature-user-authentication
 
 # Delete branch if done
 git branch -d feature/user-authentication
@@ -402,75 +468,74 @@ git branch -d feature/user-authentication
 
 ## Examples
 
-**Example 1: Feature development in isolation**
+**Example 1: First-time setup (migration)**
 ```
-User: "Set up isolated workspace for authentication feature"
+User: "Set up worktree for new feature"
 
 → Invoke UsingGitWorktrees skill
 → Announce: "I'm using the UsingGitWorktrees skill to set up an isolated workspace"
-→ Check for existing worktree directory
-→ Find: .worktrees/ exists
-→ Verify: git check-ignore confirms .worktrees/ is ignored
-→ Create: git worktree add .worktrees/feature-auth -b feature/user-authentication
-→ Setup: npm install
-→ Test: npm test → 47 passing
-→ Report: "Worktree ready at /path/to/project/.worktrees/feature-auth"
-→ Ready for implementation
+→ Check: Is repo in sibling layout?
+→ Detect: No - .git is a directory, no sibling worktrees
+→ Explain: "This repo needs migration to sibling layout"
+→ Ask: "Where should the parent folder be? ~/projects/my-project/ recommended"
+→ User confirms
+→ Migrate: mv current-repo ~/projects/my-project/main
+→ Verify: git worktree list shows main
+→ Create: git worktree add ../feature-auth -b feature/auth
+→ Setup and verify
+→ Ready for work
 ```
 
-**Example 2: Parallel host configurations**
-```
-User: "I need to work on both rhea and aion configurations simultaneously"
-
-→ Invoke UsingGitWorktrees skill
-→ Create worktree for rhea: .worktrees/rhea-jellyfin
-→ Create worktree for aion: .worktrees/aion-audio
-→ Both worktrees have clean baselines
-→ Can build and test both in parallel
-→ Switch between with cd, no branch switching needed
-```
-
-**Example 3: First-time setup with no worktree directory**
+**Example 2: Repo already in sibling layout**
 ```
 User: "Create worktree for database migration"
 
 → Invoke UsingGitWorktrees skill
-→ Check: No .worktrees/ or worktrees/ directory exists
-→ Check: No CLAUDE.md preference
-→ Ask user: "Where should I create worktrees?"
-→ User selects: .worktrees/ (hidden)
-→ Verify: Not in .gitignore
-→ Fix: Add .worktrees/ to .gitignore
-→ Commit: "chore: ignore git worktree directory"
-→ Create: git worktree add .worktrees/db-migration -b feature/db-migration
-→ Setup and verify
-→ Ready for work
+→ Check: Is repo in sibling layout?
+→ Detect: Yes - all worktrees share parent ~/projects/my-project/
+→ Create: git worktree add ../db-migration -b feature/db-migration
+→ Setup: npm install
+→ Test: npm test → 47 passing
+→ Report: "Worktree ready at ~/projects/my-project/db-migration"
+```
+
+**Example 3: Parallel host configurations**
+```
+User: "I need to work on both rhea and aion configurations simultaneously"
+
+→ Invoke UsingGitWorktrees skill
+→ Verify sibling layout
+→ Create worktree: git worktree add ../rhea-jellyfin -b feature/rhea-jellyfin
+→ Create worktree: git worktree add ../aion-audio -b feature/aion-audio
+→ Both worktrees have clean baselines
+→ Can build and test both in parallel
+→ Switch between with cd ../rhea-jellyfin
 ```
 
 **Example 4: Cleanup after merge**
 ```
 User: "Clean up the authentication worktree now that it's merged"
 
-→ Navigate to main worktree
+→ Navigate to main worktree: cd ../main
 → Verify feature branch merged: git branch --merged
-→ Remove worktree: git worktree remove .worktrees/feature-auth
-→ Delete branch: git branch -d feature/user-authentication
+→ Remove worktree: git worktree remove ../feature-auth
+→ Delete branch: git branch -d feature/auth
 → Confirm: git worktree list shows worktree removed
+→ ls .. shows only remaining worktrees
 ```
 
 ## Red Flags
 
 **Never:**
-- Create worktree without verifying it's ignored (project-local)
-- Skip baseline test verification
+- Create worktrees in non-sibling layout
+- Skip migration when detected
 - Proceed with failing tests without explicit permission
-- Assume directory location when ambiguous
 - Leave old worktrees around indefinitely
 - Commit to wrong branch (verify with `git branch --show-current`)
 
 **Always:**
-- Follow directory priority: existing → CLAUDE.md → ask
-- Verify directory is ignored for project-local
+- Detect and migrate to sibling layout
+- Use relative paths (`../branch`) for navigation
 - Auto-detect and run project setup
 - Verify clean test baseline
 - Report clear status when worktree is ready