Use when user says "/worktree", asks to create a worktree, switch worktrees, list worktrees, check worktree status, or work on a GitHub issue in isolation.
Two modes that Claude Code's built-in worktree support does not cover. Everything else has been sunset in favour of the built-in — see Sunset modes.
| Mode | Triggers | Description |
|---|---|---|
| Status | /worktree status, /worktree (no args) |
PR/CI status table across all worktrees |
| Issue | /worktree #<issue>, /worktree <issue-number> |
Name a branch from a GitHub issue (or resume its existing one), assign it, and move the session into a worktree |
IMPORTANT: Before doing anything else, identify the mode from the invocation arguments:
| Arguments | Mode | Instructions |
|---|---|---|
(none) or status |
Status | Read status.md |
#<number> or a bare number |
Issue | Read issue.md |
| anything else | — | Read Sunset modes below and tell the user the built-in equivalent. Do not improvise. |
First action: Read the appropriate .md file for your detected mode, then follow those instructions exactly.
Worktrees live where the built-in puts them, <repo>/.claude/worktrees/<name>, and are
created only by the built-in. Never run git worktree add from this skill, and do not
add WorktreeCreate/WorktreeRemove hooks to relocate them: a hook-relocated worktree
defeats the built-in's pre-removal safety check, so ExitWorktree(action: "remove") then
demands discard_changes: true on every removal — including a pristine worktree — which
trains the override into a reflex and destroys the guard.
The one thing the built-in gets wrong for this project is the branch name. It flattens
slashes and prefixes: worktree name feat/42-foo yields branch worktree-feat+42-foo.
(The name validator accepts slashes; only the derivation flattens them.) The fix is one
command inside the worktree, git branch -m feat/42-foo — or git switch when the issue
already has a branch — see issue.md Step 5. The directory keeps its flattened name;
nothing reads it.
.claude/worktrees/ is gitignored, so pre-commit run --all-files (which lists via
git ls-files) and ruff skip it, and testpaths = ["tests"] keeps pytest out.
Legacy worktrees made by the retired add mode live in the sibling directory
<repo>.worktrees/. Leave them there until their PRs merge, then retire each with
git worktree remove <path> and git branch -d <branch>. /worktree status still lists
them, and issue mode's Open case enters one by path. Don't git worktree move them
into .claude/worktrees/: ExitWorktree only removes worktrees it created itself, so the
move gains nothing.
These were removed. Point the user at the replacement rather than reimplementing it:
| Old mode | Use instead |
|---|---|
/worktree add <branch> |
claude -w <name> (new session), or ask Claude to "start a worktree" mid-session (EnterWorktree). Add --tmux for a dedicated pane. Rename the branch afterwards if it will become a PR. |
/worktree list |
git worktree list |
/worktree remove <branch> |
"exit the worktree and remove it" (ExitWorktree). It refuses to discard uncommitted or unmerged work unless told to. A branch renamed or switched to per issue.md Step 5 is left behind by design; delete it with git branch -d. |
/worktree prune |
git worktree prune --verbose |
feat/42-foo); worktree directory names cannot&& or variable assignmentEnterWorktree must move the user's
real session; from a forked or cwd-pinned agent it would only move the forkAgent(isolation: "worktree")) keep their
worktree-* branch names. That is fine — they are ephemeral and rarely become PRs