This skill should be used when managing Git worktrees for isolated parallel development. It handles creating, listing, switching, and cleaning up worktrees with a simple interactive interface.
Scanned 5/27/2026
Install via CLI
openskills install jikig-ai/soleur---
name: git-worktree
description: "This skill should be used when managing Git worktrees for isolated parallel development. It handles creating, listing, switching, and cleaning up worktrees with a simple interactive interface."
---
# Git Worktree Manager
This skill provides a unified interface for managing Git worktrees across your development workflow. Whether you're reviewing PRs in isolation or working on features in parallel, this skill handles all the complexity.
## What This Skill Does
- **Create worktrees** from main branch with clear branch names
- **List worktrees** with current status
- **Switch between worktrees** for parallel work
- **Clean up completed worktrees** automatically
- **Interactive confirmations** at each step
- **Automatic .gitignore management** for worktree directory
- **Automatic .env file copying** from main repo to new worktrees
- **Write guard enforcement** via PreToolUse hook (`.claude/hooks/worktree-write-guard.sh`) -- blocks Write/Edit to main checkout when worktrees exist
## CRITICAL: Always Use the Manager Script
**NEVER call `git worktree add` directly.** Always use the `worktree-manager.sh` script.
The script handles critical setup that raw git commands don't:
1. Copies `.env`, `.env.local`, `.env.test`, etc. from main repo
2. Ensures `.worktrees` is in `.gitignore`
3. Creates consistent directory structure
4. Detects bare repos (`core.bare = true`) and derives `GIT_ROOT` via `--absolute-git-dir` instead of `--show-toplevel`
5. Sources the shared `plugins/soleur/scripts/resolve-git-root.sh` helper -- all scripts that need `GIT_ROOT` should source this helper instead of inlining their own detection logic
**After creating a worktree**, run `npm install` if the project has a `package.json` — worktrees do not share `node_modules/` with the main working tree, and build commands (`npx @11ty/eleventy`, etc.) will silently hang instead of erroring.
```bash
# ✅ CORRECT - Always use the script
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh create feature-name
# ❌ WRONG - Never do this directly
git worktree add .worktrees/feature-name -b feature-name main
```
## When to Use This Skill
Use this skill in these scenarios:
1. **Code Review (`soleur:review`)**: If NOT already on the target branch (PR branch or requested branch), offer worktree for isolated review
2. **Feature Work (`soleur:work`)**: Always ask if user wants parallel worktree or live branch work
3. **Parallel Development**: When working on multiple features simultaneously
4. **Cleanup**: After completing work in a worktree
## How to Use
### In Claude Code Workflows
The skill is automatically called from the `soleur:review` and `soleur:work` skills:
```
# For review: offers worktree if not on PR branch
# For work: always asks - new branch or worktree?
```
### Manual Usage
You can also invoke the skill directly from bash:
```bash
# Create a new worktree (copies .env files automatically)
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh create feature-login
# List all worktrees
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh list
# Switch to a worktree
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh switch feature-login
# Copy .env files to an existing worktree (if they weren't copied)
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh copy-env feature-login
# Clean up completed worktrees
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh cleanup
```
## Commands
### `create <branch-name> [from-branch]`
Creates a new worktree with the given branch name.
**Options:**
- `branch-name` (required): The name for the new branch and worktree
- `from-branch` (optional): Base branch to create from (defaults to `main`)
**Example:**
```bash
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh create feature-login
```
**What happens:**
1. Checks if worktree already exists
2. Fetches `refs/remotes/origin/<from-branch>` (the local `<from-branch>` ref is NOT touched — this lets `create` succeed even when a sibling worktree has `<from-branch>` checked out; see #3741)
3. Creates the new worktree from `origin/<from-branch>` with `--no-track` (preserves the pre-fix upstream-unset state so downstream `git push -u origin <branch>` flows are unchanged)
4. **Copies all .env files from main repo** (.env, .env.local, .env.test, etc.)
5. Shows path for cd-ing to the worktree
**Opt-in: also update local `<from-branch>`**
Pass `--update-local-main` (as a global flag, before `create`) to additionally fast-forward the local `<from-branch>` ref. Default behavior leaves the local ref untouched.
```bash
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh --update-local-main create feature-login
```
### `list` or `ls`
Lists all available worktrees with their branches and current status.
**Example:**
```bash
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh list
```
**Output shows:**
- Worktree name
- Branch name
- Which is current (marked with ✓)
- Main repo status
### `switch <name>` or `go <name>`
Switches to an existing worktree and cd's into it.
**Example:**
```bash
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh switch feature-login
```
**Optional:**
- If name not provided, lists available worktrees and prompts for selection
### `cleanup` or `clean`
Interactively cleans up inactive worktrees with confirmation.
**Example:**
```bash
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh cleanup
```
**What happens:**
1. Lists all inactive worktrees
2. Asks for confirmation
3. Removes selected worktrees
4. Cleans up empty directories
### `sync-bare-files` or `sync`
Syncs stale on-disk files from git HEAD in a bare repo. Only needed when the repo uses `core.bare=true` — on-disk files at the bare root become stale after merges since git never updates them. Auto-called after `cleanup-merged` cleans branches in bare repo context.
**Example:**
```bash
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh sync-bare-files
```
**What it syncs:**
- `AGENTS.md`, `CLAUDE.md` (session-start instructions)
- `plugins/soleur/AGENTS.md`, `plugins/soleur/CLAUDE.md`
- `plugins/soleur/hooks/*` (plugin hooks: stop-hook, welcome-hook, hooks.json)
- `.claude/settings.json` (permission rules)
- `.claude/hooks/*.sh` (PreToolUse hooks)
- `plugins/soleur/scripts/resolve-git-root.sh`
- The `worktree-manager.sh` script itself
**Important:** Any file that Claude Code executes at runtime from the bare repo root (via `${CLAUDE_PLUGIN_ROOT}` or direct path) must be added to the sync list in `worktree-manager.sh`. Stale on-disk files cause silent regressions.
## Workflow Examples
### Code Review with Worktree
```bash
# Claude Code recognizes you're not on the PR branch
# Offers: "Use worktree for isolated review? (y/n)"
# You respond: yes
# Script runs (copies .env files automatically):
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh create pr-123-feature-name
# You're now in isolated worktree for review with all env vars
cd .worktrees/pr-123-feature-name
# After review, return to main:
cd ../..
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh cleanup
```
### Parallel Feature Development
```bash
# For first feature (copies .env files):
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh create feature-login
# Later, start second feature (also copies .env files):
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh create feature-notifications
# List what you have:
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh list
# Switch between them as needed:
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh switch feature-login
# Return to main and cleanup when done:
cd .
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh cleanup
```
## Key Design Principles
### KISS (Keep It Simple, Stupid)
- **One manager script** handles all worktree operations
- **Simple commands** with sensible defaults
- **Interactive prompts** prevent accidental operations
- **Clear naming** using branch names directly
### Opinionated Defaults
- Worktrees always created from **main** (unless specified)
- Worktrees stored in **.worktrees/** directory
- Branch name becomes worktree name
- **.gitignore** automatically managed
### Safety First
- **Confirms before creating** worktrees
- **Confirms before cleanup** to prevent accidental removal
- **Won't remove current worktree**
- **Clear error messages** for issues
## Integration with Workflows
### `soleur:review`
Instead of always creating a worktree:
```
1. Check current branch
2. If ALREADY on target branch (PR branch or requested branch) → stay there, no worktree needed
3. If DIFFERENT branch than the review target → offer worktree:
"Use worktree for isolated review? (y/n)"
- yes → call git-worktree skill
- no → proceed with PR diff on current branch
```
### `soleur:work`
Always offer choice:
```
1. Ask: "How do you want to work?
1. New branch on current worktree (live work)
2. Worktree (parallel work)"
2. If choice 1 → create new branch normally
3. If choice 2 → call git-worktree skill to create from main
```
## Troubleshooting
### "Worktree already exists"
If you see this, the script will ask if you want to switch to it instead.
### "Cannot remove worktree: it is the current worktree"
Switch out of the worktree first (to main repo), then cleanup:
Navigate to the repository root directory, then run:
```bash
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh cleanup
```
### Lost in a worktree?
See where you are:
```bash
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh list
```
### .env files missing in worktree?
If a worktree was created without .env files (e.g., via raw `git worktree add`), copy them:
```bash
bash ./plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh copy-env feature-name
```
Navigate back to the repository root directory.
## Sharp Edges
- If `worktree-manager.sh` reports success but `cd` to the worktree path fails or `git branch --show-current` returns an unexpected branch, the worktree was not properly created. Fall back to `git worktree add` directly: `git worktree add .worktrees/<name> -b <name> main`. The script includes post-creation verification (#1806) but edge cases on bare repos may still produce partial directories. Tracked in #1854.
- The `draft-pr` subcommand uses `SCRIPT_DIR` for path resolution -- invoke it from inside the worktree, not from the bare repo root.
- When creating worktrees manually (not via the script), always use absolute paths. Relative paths resolve from CWD, not from `GIT_DIR`, creating nested worktrees that are difficult to clean up. The script handles this correctly but manual `git worktree add` commands are susceptible.
- When lefthook hangs in a worktree (>60s), kill it (`pkill -f "lefthook run"`), verify checks manually, then commit with `LEFTHOOK=0 git commit`. This is a known lefthook/worktree interaction bug. (ex-`cq-when-lefthook-hangs-in-a-worktree-60s`; also guarded by `.claude/hooks/lib/incidents.sh` detect_bypass)
- Never pass `-c user.email=<fake>` / `-c user.name=<fake>` to `git commit` to bypass author-identity errors — fix the worktree's local git config instead (`worktree-manager.sh create` auto-runs `ensure_worktree_identity`). (ex-`hr-never-fake-git-author`; PR #2815 forced a destructive force-push after 4 commits were authored as `test@test` and blocked CLA; `knowledge-base/project/learnings/2026-04-24-fake-git-author-bare-repo-bot-override.md`)
- After `git worktree add` on bare repos, verify both `rev-parse --show-toplevel` (directory validity) and `git worktree list --porcelain` (registration). See learning: `knowledge-base/project/learnings/2026-04-10-worktree-registration-verification-insufficient.md`.
- In bare repos with multiple worktrees, `git fetch origin branch:branch` fails when the target branch is checked out in any worktree -- git rejects the refspec update. The fallback `git fetch origin branch` only updates `origin/branch`, NOT the local ref. Use `git update-ref refs/heads/branch origin/branch` to force-sync when the fetch refspec is rejected. As of #3741 (2026-05-14), `worktree-manager.sh create` bypasses this failure mode by default — new worktrees are based on `refs/remotes/origin/<from>` directly. The refspec-fetch path only runs when `--update-local-main` is passed.
- After creating a worktree via the script, always verify it exists in `git worktree list` before attempting to `cd` into it -- the script may report success for names that silently fail (e.g., excessively long names). A 2026-04-18 recurrence under a normal short name (#2611) confirms the silent-failure mode is not limited to edge-case names; see `knowledge-base/project/learnings/2026-04-18-worktree-manager-silent-registration-failure.md`.
- In bare repos, `git branch --show-current` from the bare root returns `main` (or empty), not the worktree's branch. Always ensure CWD is inside the target worktree before running branch-detecting git commands.
## Technical Details
### Directory Structure
```
.worktrees/
├── feature-login/ # Worktree 1
│ ├── .git
│ ├── app/
│ └── ...
├── feature-notifications/ # Worktree 2
│ ├── .git
│ ├── app/
│ └── ...
└── ...
.gitignore (updated to include .worktrees)
```
### How It Works
- Uses `git worktree add` for isolated environments
- Each worktree has its own branch
- Changes in one worktree don't affect others
- Share git history with main repo
- Can push from any worktree
### Performance
- Worktrees are lightweight (just file system links)
- No repository duplication
- Shared git objects for efficiency
- Much faster than cloning or stashing/switching
No comments yet. Be the first to comment!