mit einem Klick
using-git-worktrees
// 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
// 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
Analyze and enhance user stories with complete, implementation-ready technical detail from direct ticket input or Jira.
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
Analyze and enhance Jira user stories with complete, implementation-ready technical detail.
Create focused commits and pull requests following repository standards.
| name | using-git-worktrees |
| 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 |
| author | LIDR.co |
| version | 1.0.0 |
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: 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."
Before creating anything, check if you are already in an isolated workspace.
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:
# If this returns a path, you're in a submodule, not a worktree — treat as normal repo
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:
<path> on branch <name>."<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.
Has the user already indicated their worktree preference in your instructions? If not, ask for consent before creating a worktree:
"Would you like me to set up an isolated worktree? It protects your current branch from changes."
Honor any existing declared preference without asking. If the user declines consent, work in place and skip to Step 3.
You have two mechanisms. Try them in this order.
The user has asked for an isolated workspace (Step 0 consent). Do you already have a way to create a worktree? It might be a tool with a name like EnterWorktree, WorktreeCreate, a /worktree command, or a --worktree flag. If you do, use it and skip to Step 3.
Native tools handle directory placement, branch creation, and cleanup automatically. Using git worktree add when you have a native tool creates phantom state your harness can't see or manage.
If the native flow does not propagate Claude/Cursor settings and the user expects parity with the main checkout, copy .claude/settings.json and .claude/settings.local.json from the primary workspace using the same loop as Step 1b after the native tool finishes—only when files exist on disk.
Only proceed to Step 1b if you have no native worktree tool available.
Only use this if Step 1a does not apply — you have no native worktree tool available. Create a worktree manually using git.
Follow this priority order. Explicit user preference always beats observed filesystem state.
Check your instructions for a declared worktree directory preference. If the user has already specified one, use it without asking.
Check for an existing project-local worktree directory:
ls -d .worktrees 2>/dev/null # Preferred (hidden)
ls -d worktrees 2>/dev/null # Alternative
If found, use it. If both exist, .worktrees wins.
Check for an existing global directory:
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 there is no other guidance available, default to .worktrees/ at the project root.
Optional sibling-directory layout (only when the user or project docs declare it): keep worktrees outside the repo tree next to the project folder:
SOURCE_ROOT=$(git rev-parse --show-toplevel)
PROJECT_ROOT=$(basename "$SOURCE_ROOT")
LOCATION="../${PROJECT_ROOT}-worktrees"
# path="$LOCATION/$BRANCH_NAME"
This avoids nesting worktrees under SOURCE_ROOT; .gitignore checks for .worktrees / worktrees under the repo do not apply here.
MUST verify directory is ignored before creating worktree:
git check-ignore -q .worktrees 2>/dev/null || git check-ignore -q worktrees 2>/dev/null
If NOT ignored: Add to .gitignore, commit the change, then proceed.
Why critical: Prevents accidentally committing worktree contents to repository.
Global directories (~/.config/superpowers/worktrees/) need no verification.
Capture the main checkout root before git worktree add. After cd into the new worktree, git rev-parse --show-toplevel points at the worktree directory, not the checkout where .claude/settings*.json usually lives.
project=$(basename "$(git rev-parse --show-toplevel)")
SOURCE_ROOT=$(git rev-parse --show-toplevel)
# Determine path based on chosen location
# For project-local: path="$LOCATION/$BRANCH_NAME"
# For global: path="~/.config/superpowers/worktrees/$project/$BRANCH_NAME"
git worktree add "$path" -b "$BRANCH_NAME"
cd "$path"
Sandbox fallback: If git worktree add fails with a permission error (sandbox denial), tell the user the sandbox blocked worktree creation and you're working in the current directory instead. Then run setup and baseline tests in place.
After creating the worktree with git (Step 1b), copy local Claude settings from the main checkout so Cursor/Claude CLI behavior matches the primary workspace. These files are often untracked.
Do not copy if the user declines or if a native tool (Step 1a) already propagates settings—respect the harness.
Run after cd "$path" (still using SOURCE_ROOT captured above):
copied_claude_settings=false
for claude_settings in ".claude/settings.json" ".claude/settings.local.json"; do
if [ -f "$SOURCE_ROOT/$claude_settings" ]; then
mkdir -p ".claude"
cp -p "$SOURCE_ROOT/$claude_settings" "./$claude_settings"
echo "Copied $claude_settings to worktree"
copied_claude_settings=true
fi
done
if [ "$copied_claude_settings" = false ]; then
echo "No local Claude settings found (.claude/settings.json or .claude/settings.local.json)"
fi
Symlinks: If the source tree uses symlinks for .claude (e.g. .claude/skills → ../../ai-specs/skills), copying only these JSON files does not recreate symlink targets. Either repeat the same symlink layout in the worktree or rely on project-relative paths inside settings.json.
Auto-detect and run appropriate setup:
# Node.js
if [ -f package.json ]; then npm install; fi
# Rust
if [ -f Cargo.toml ]; then cargo build; fi
# Python
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
if [ -f pyproject.toml ]; then poetry install; fi
# Go
if [ -f go.mod ]; then go mod download; fi
Run tests to ensure workspace starts clean:
# 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.
Worktree ready at <full-path>
Claude settings copied (or none found / skipped per harness)
Tests passing (<N> tests, 0 failures)
Ready to implement <feature-name>
Run cleanup once the work is complete. "Done" means: branch merged, PR closed, the experiment was discarded, or the user has explicitly confirmed they no longer need the isolated workspace. Never remove a worktree that still contains uncommitted, unpushed, or unmerged changes the user may want.
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)
GIT_DIR == GIT_COMMON: You were never in a linked worktree (Step 0 sent you straight to Step 3). There is nothing to clean up — skip Step 5 entirely.GIT_DIR != GIT_COMMON: You are inside a linked worktree. Continue with cleanup.Before removing anything, confirm there is no work to lose:
git status --porcelain # Must be empty (no uncommitted changes)
git log @{u}.. 2>/dev/null # Must be empty (no unpushed commits)
If either command returns output: Stop. Report the unsaved work to the user and ask how to proceed (commit/push, stash, or force discard). Never delete a worktree with unsaved work without explicit user confirmation.
Capture the worktree path and branch name before leaving the directory:
WORKTREE_PATH=$(git rev-parse --show-toplevel)
BRANCH_NAME=$(git branch --show-current)
If you used a native worktree tool in Step 1a (EnterWorktree, WorktreeCreate, /worktree, etc.), use the matching native command to remove the worktree (e.g. LeaveWorktree, WorktreeRemove, /worktree remove). Native tools clean up directories, branches, and harness state consistently.
Only proceed to 5.3 if no native cleanup tool is available.
Only use this if Step 5.2 does not apply — you created the worktree manually in Step 1b.
# 1. Move out of the worktree before deleting it
cd "$GIT_COMMON/.." # or any path inside the main checkout
# 2. Remove the worktree
git worktree remove "$WORKTREE_PATH"
# 3. If files are still present (e.g. ignored artifacts blocking removal),
# confirm with the user, then force-remove
git worktree remove --force "$WORKTREE_PATH"
# 4. Delete the local branch only if it was created for this worktree
# AND has been merged or is no longer needed
git branch -d "$BRANCH_NAME" # safe delete (refuses if unmerged)
git branch -D "$BRANCH_NAME" # force delete (only with user confirmation)
# 5. Prune stale worktree metadata if the directory was deleted manually
git worktree prune
Sandbox fallback: If removal fails due to permissions, report the failure and the path that needs manual cleanup. Do not retry destructively.
git worktree list # WORKTREE_PATH must no longer appear
ls -d "$WORKTREE_PATH" 2>/dev/null # Must return nothing
Worktree removed: <full-path>
Branch <name> deleted (or kept, if still needed)
Main checkout left untouched
| 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 instruction file, then default .worktrees/ |
| User/project declares sibling worktrees | ../${PROJECT_ROOT}-worktrees (Step 1b item 5) |
| 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 |
| Work complete, in linked worktree | Run Step 5 cleanup |
| Never created a worktree | Skip Step 5 |
| Uncommitted/unpushed changes at cleanup | Stop and ask user |
| Native cleanup tool available | Use it (Step 5.2) |
| No native cleanup tool | git worktree remove (Step 5.3) |
| Worktree directory deleted manually | git worktree prune |
| Git fallback: clone Claude behavior into worktree | Copy .claude/settings*.json from SOURCE_ROOT (Step 1b) |
Repo uses .claude symlinks | Copy JSON only is not enough—recreate symlinks or paths |
git worktree add when the platform already provides isolationgit check-ignore before creating project-local worktreegit worktree remove --force discards uncommitted/unpushed changes silentlygit status --porcelain and git log @{u}.. before removal; stop and ask if either is non-emptygit branch -D destroys commits that were never merged or pushedgit branch -d (safe delete); only force-delete after explicit user confirmationgit worktree remove on a worktree created by a native tool leaves phantom harness stategit rev-parse --show-toplevel after cd into the new worktree resolves to the worktree path, so copies find no settings or copy from the wrong placeSOURCE_ROOT=$(git rev-parse --show-toplevel) in the main checkout before git worktree add, then use $SOURCE_ROOT in the copy loopNever:
git worktree add when you have a native worktree tool (e.g., EnterWorktree). This is the #1 mistake — if you have it, use it.git branch -D) without confirming it is merged or no longer neededgit worktree remove on a worktree created by a native toolAlways:
git status --porcelain, git log @{u}..)git worktree list and a directory check that cleanup actually completed.claude/settings.json and .claude/settings.local.json from SOURCE_ROOT captured before git worktree add