This skill should be used when starting work on a "new feature", "bug fix", "branch", "isolated development", when the user asks to "create a worktree", "set up a branch for development", "work on...
Git worktrees enable isolated development by creating separate working directories for different branches. This skill teaches the default workflow for all feature and bugfix development: always create a worktree before starting work on a new branch.
Core principle: Never use git checkout or git switch for feature/bugfix work. Always create a worktree instead.
EVERY SINGLE workbranch command MUST be invoked with the FULL path:
${CLAUDE_PLUGIN_ROOT}/scripts/wb new feature-x
${CLAUDE_PLUGIN_ROOT}/scripts/wb list
${CLAUDE_PLUGIN_ROOT}/scripts/wb status
NEVER EVER run bare wb commands - they will fail with "command not found". The ${CLAUDE_PLUGIN_ROOT} prefix is MANDATORY and non-negotiable.
When you see wb new, wb list, wb done, etc. in this document, you MUST execute them as:
${CLAUDE_PLUGIN_ROOT}/scripts/wb new <branch>${CLAUDE_PLUGIN_ROOT}/scripts/wb list${CLAUDE_PLUGIN_ROOT}/scripts/wb done <branch>wb new <branch>wb listwb done <branch>All workbranch commands support these flags to control output verbosity:
--verboseShow detailed output including git commands and progress steps. Use when:
Default behavior suppresses detailed output to reduce token usage by 60-80%.
--jsonOutput structured JSON instead of text. Use when:
# Default: minimal output
${CLAUDE_PLUGIN_ROOT}/scripts/wb new feature-x
# Verbose: see all git commands and progress
${CLAUDE_PLUGIN_ROOT}/scripts/wb new feature-x --verbose
# JSON: structured output
${CLAUDE_PLUGIN_ROOT}/scripts/wb list --json
# Combine with other flags
${CLAUDE_PLUGIN_ROOT}/scripts/wb done --skip-merge --verbose
When Claude should use verbose mode:
When Claude should NOT use verbose mode:
Create a worktree for:
The only exceptions:
The workbranch plugin provides scripts that MUST be invoked via ${CLAUDE_PLUGIN_ROOT}/scripts/wb:
REMINDER: Every command below REQUIRES the ${CLAUDE_PLUGIN_ROOT}/scripts/ prefix!
${CLAUDE_PLUGIN_ROOT}/scripts/wb newCreate a new worktree for a branch:
${CLAUDE_PLUGIN_ROOT}/scripts/wb new <branch-name> [source-branch]
IMPORTANT: You MUST use the full path ${CLAUDE_PLUGIN_ROOT}/scripts/wb new - do NOT run wb new.
.workbranch configurationnpm install)Example usage:
# Create worktree for new feature
${CLAUDE_PLUGIN_ROOT}/scripts/wb new feature-user-auth
# Create worktree from specific branch
${CLAUDE_PLUGIN_ROOT}/scripts/wb new hotfix-login-bug main
${CLAUDE_PLUGIN_ROOT}/scripts/wb listShow all worktrees with their status:
${CLAUDE_PLUGIN_ROOT}/scripts/wb list
# JSON output for programmatic use
${CLAUDE_PLUGIN_ROOT}/scripts/wb list --json
IMPORTANT: You MUST use the full path ${CLAUDE_PLUGIN_ROOT}/scripts/wb list - do NOT run wb list.
Output includes:
Run this to check existing worktrees before creating new ones.
${CLAUDE_PLUGIN_ROOT}/scripts/wb statusCheck current location before making changes:
${CLAUDE_PLUGIN_ROOT}/scripts/wb status
IMPORTANT: You MUST use the full path ${CLAUDE_PLUGIN_ROOT}/scripts/wb status - do NOT run wb status.
Output fields:
main or worktreeOptions:
--verbose: Show detailed output--json: JSON output for programmatic use--check-main: Exit 0 if on main, 1 otherwise--check-worktree: Exit 0 if in worktree, 1 otherwisePre-flight pattern:
${CLAUDE_PLUGIN_ROOT}/scripts/wb status
# If LOCATION: main and ON_DEFAULT: true, run 'wb new <branch>' first
${CLAUDE_PLUGIN_ROOT}/scripts/wb rmRemove a worktree when done:
${CLAUDE_PLUGIN_ROOT}/scripts/wb rm <worktree-path> [--delete-branch]
IMPORTANT: You MUST use the full path ${CLAUDE_PLUGIN_ROOT}/scripts/wb rm - do NOT run wb rm.
--delete-branch: also deletes the branch (only if merged)${CLAUDE_PLUGIN_ROOT}/scripts/wb moveMove uncommitted changes and/or local commits from main to a new worktree:
${CLAUDE_PLUGIN_ROOT}/scripts/wb move <branch-name> [--commits N]
IMPORTANT: You MUST use the full path ${CLAUDE_PLUGIN_ROOT}/scripts/wb move - do NOT run wb move.
--commits N to move only the last N commitsExample usage:
# Move all divergent changes to a new branch
${CLAUDE_PLUGIN_ROOT}/scripts/wb move feature-login
# Move only the last 2 commits
${CLAUDE_PLUGIN_ROOT}/scripts/wb move hotfix-auth --commits 2
${CLAUDE_PLUGIN_ROOT}/scripts/wb doneFinish work on a branch by merging to main and cleaning up:
${CLAUDE_PLUGIN_ROOT}/scripts/wb done [branch-name] [options]
IMPORTANT: You MUST use the full path ${CLAUDE_PLUGIN_ROOT}/scripts/wb done - do NOT run wb done.
Modes:
${CLAUDE_PLUGIN_ROOT}/scripts/wb done <branch> — Run from main worktree, specify branch to merge (recommended)${CLAUDE_PLUGIN_ROOT}/scripts/wb done — Run from feature worktree, infers branch from HEAD (legacy)Options:
--squash: Squash all commits into one before merging--rebase: Rebase onto target branch before merging--skip-merge: Skip merge (use when already merged via PR)--target <branch>: Target branch to merge into (default: auto-detect)--keep-remote: Don't delete the remote branch--dry-run: Show what would be done without executing--discard-changes: Discard uncommitted changes and force removal (DANGEROUS)Run from the main worktree with the branch name as argument. This avoids the deleted-directory problem:
# From main worktree
${CLAUDE_PLUGIN_ROOT}/scripts/wb done feature-branch # Standard merge + cleanup
${CLAUDE_PLUGIN_ROOT}/scripts/wb done feature-branch --squash # Squash merge
${CLAUDE_PLUGIN_ROOT}/scripts/wb done feature-branch --skip-merge # Already merged via PR
${CLAUDE_PLUGIN_ROOT}/scripts/wb done feature-branch --dry-run # Preview what would happen
Running from within a feature worktree still works but requires immediate navigation:
# From feature worktree
${CLAUDE_PLUGIN_ROOT}/scripts/wb done
cd /path/to/main # IMPORTANT: Navigate away immediately!
EXECUTE Output for Claude
When running ${CLAUDE_PLUGIN_ROOT}/scripts/wb done from a feature worktree, the script outputs an EXECUTE: line at the end:
EXECUTE: cd /path/to/main/worktree
When you see EXECUTE: in script output, immediately run that command.
${CLAUDE_PLUGIN_ROOT}/scripts/wb list to see current state${CLAUDE_PLUGIN_ROOT}/scripts/wb new <branch-name> for the feature/fixUse ${CLAUDE_PLUGIN_ROOT}/scripts/wb done to complete work on a branch. The recommended approach is to run from the main worktree with the branch name:
# From main worktree (recommended)
${CLAUDE_PLUGIN_ROOT}/scripts/wb done feature-branch
This handles the entire workflow: merge to main, push, remove worktree, and delete branches.
From the main worktree:
${CLAUDE_PLUGIN_ROOT}/scripts/wb done feature-branch # Standard merge
${CLAUDE_PLUGIN_ROOT}/scripts/wb done feature-branch --squash # Squash merge
${CLAUDE_PLUGIN_ROOT}/scripts/wb done feature-branch --rebase # Rebase then merge
git push -u origin <branch-name>${CLAUDE_PLUGIN_ROOT}/scripts/wb done feature-branch --skip-merge
The --skip-merge flag skips the merge phase (since it's already merged via PR) and just cleans up the worktree and branches.
You can still run ${CLAUDE_PLUGIN_ROOT}/scripts/wb done from within a feature worktree (without a branch argument). In this case, you must navigate away immediately after completion:
# From feature worktree
${CLAUDE_PLUGIN_ROOT}/scripts/wb done
cd /path/to/main # REQUIRED - directory was deleted!
The script outputs EXECUTE: cd /path/to/main which should be run immediately.
Note: For manual cleanup without wb done, use ${CLAUDE_PLUGIN_ROOT}/scripts/wb rm <path> --delete-branch. This only deletes branches that have been merged. If you need to abandon unmerged work, use git branch -D <branch> manually after removing the worktree.
When starting work and a worktree already exists for the target branch (from a previous interrupted session):
${CLAUDE_PLUGIN_ROOT}/scripts/wb list to check for existing worktreeNever silently create duplicate worktrees or fail without explanation.
Projects can customize worktree behavior with a .workbranch file in the project root:
# Files to copy (colon-separated globs)
copy=".env*:.vscode"
# Patterns to ignore when copying
ignore="node_modules:dist:.git"
# Path template ($NAME = branch name)
path="../$NAME"
# Commands to run after worktree creation
post_create="npm install"
# Delete branch when removing worktree (default: false)
delete_branch=false
| Field | Description | Default |
|---|---|---|
copy |
Colon-separated file globs to copy | (none) |
ignore |
Colon-separated patterns to skip | node_modules:dist:.git |
path |
Worktree path template | ../$NAME |
post_create |
Commands to run after creation | (none) |
delete_branch |
Auto-delete branch on remove | false |
If no .workbranch file exists, scripts use sensible defaults.
Scripts return structured error messages:
ERROR: <message> | ACTION: <what to do>
Common errors and actions:
| Error | Action |
|---|---|
| Not in a git repository | Navigate to a git repository first |
| Worktree already exists | Use existing worktree or remove with wb rm |
| Branch already checked out | Remove the other worktree first |
| Uncommitted changes | Commit or stash changes, or use --discard-changes to force |
| Cannot delete unmerged branch | Use git branch -D to force delete |
When an error occurs, read the ACTION portion and follow the guidance.
When the user asks to work on a feature or fix a bug:
git checkout or git switch for feature branchesOnce in a worktree:
After work is merged (via PR or direct merge):
${CLAUDE_PLUGIN_ROOT}/scripts/wb done for automatic cleanup (preferred)${CLAUDE_PLUGIN_ROOT}/scripts/wb rm for manual cleanup--delete-branch flag safely deletes only merged branchesWhen changes are accidentally made on main instead of a worktree:
${CLAUDE_PLUGIN_ROOT}/scripts/wb move <appropriate-branch-name>This handles both uncommitted changes and local commits that diverged from origin/main.
All scripts are in ${CLAUDE_PLUGIN_ROOT}/scripts/:
wb — unified dispatcher (routes to wb-new, wb-list, wb-status, wb-rm, wb-move, wb-done, wb-nuke)| Task | Command |
|---|---|
| Check status (pre-flight) | ${CLAUDE_PLUGIN_ROOT}/scripts/wb status |
| List worktrees | ${CLAUDE_PLUGIN_ROOT}/scripts/wb list |
| Create worktree | ${CLAUDE_PLUGIN_ROOT}/scripts/wb new <branch> |
| Create from branch | ${CLAUDE_PLUGIN_ROOT}/scripts/wb new <branch> <source> |
| Finish work (merge + cleanup) | ${CLAUDE_PLUGIN_ROOT}/scripts/wb done <branch> (from main) |
| Finish with squash merge | ${CLAUDE_PLUGIN_ROOT}/scripts/wb done <branch> --squash (from main) |
| Cleanup after PR merge | ${CLAUDE_PLUGIN_ROOT}/scripts/wb done <branch> --skip-merge (from main) |
| Remove worktree | ${CLAUDE_PLUGIN_ROOT}/scripts/wb rm <path> |
| Remove + delete branch | ${CLAUDE_PLUGIN_ROOT}/scripts/wb rm <path> --delete-branch |
| Rescue changes from main | ${CLAUDE_PLUGIN_ROOT}/scripts/wb move <branch> |
| Rescue specific commits | ${CLAUDE_PLUGIN_ROOT}/scripts/wb move <branch> --commits N |
Cause: Attempting to run wb commands without ${CLAUDE_PLUGIN_ROOT} prefix. This is the MOST COMMON ERROR with this skill.
Solution: ALWAYS use the FULL path - there are NO exceptions:
${CLAUDE_PLUGIN_ROOT}/scripts/wb <command>
If you (Claude) see this error in a Bash tool result:
${CLAUDE_PLUGIN_ROOT}/scripts/ prefixExamples of fixing this error:
wb new feature-x${CLAUDE_PLUGIN_ROOT}/scripts/wb new feature-xThe ${CLAUDE_PLUGIN_ROOT} variable is only available within Claude Code and is MANDATORY for all workbranch commands.
When developing the workbranch plugin, use relative paths:
./scripts/wb list
../workbranch/scripts/wb new feature-x