Worktree Cleanup
npx claude-code-templates@latest --command git-workflow/worktree-cleanup Content
Worktree Cleanup
Remove worktrees and branches that have been merged: $ARGUMENTS
Instructions
You are in the main repository (not a worktree). Clean up finished worktrees.
Branch Patterns
This project uses the following branch prefixes for worktrees:
claude/*— Claude Code auto-created worktreesclaude-daniel/*— User-created worktreesreview/*— Component review worktrees
All three prefixes must be checked in every step below.
Step 1: Validate Environment
- Verify this is the main working tree (first entry in
git worktree list) - If inside a worktree, warn: "Run
/worktree-cleanupfrom the main repo, not from a worktree." - Fetch latest from origin:
git fetch origin --prune - Get the main branch name (main or master)
Step 2: Parse Arguments
Parse $ARGUMENTS for options:
--all— clean up ALL merged worktrees and branches--branch <prefix>/<name>— clean up a specific worktree/branch--dry-run— show what would be cleaned up without doing anything--force-all— remove ALL worktrees regardless of merge status (asks confirmation per worktree)- No arguments — list worktrees and ask which to clean up
Step 3: Identify Worktrees
- List all worktrees:
git worktree list - List all matching branches:bash
git branch --list 'claude/*' 'claude-daniel/*' 'review/*' - For each matching branch, check if it's been merged into main:bash
git branch --merged origin/<main-branch> | grep -E '^\s+(claude/|claude-daniel/|review/)' - Also check remote branches:bash
git branch -r --merged origin/<main-branch> | grep -E 'origin/(claude/|claude-daniel/|review/)' - For squash-merged branches (not detected by
--merged), check if the branch diff is empty against main:If the diff is empty or very small (only whitespace), consider it merged.bash# A branch is effectively merged if its changes already exist in main git diff origin/main...<branch> --stat
Step 4: Display Status
Show a table of all worktrees/branches:
| # | Worktree | Branch | Merged? | Dirty? | Action |
|---|---------|--------|---------|--------|--------|
| 1 | eager-mendeleev | claude/eager-mendeleev | Yes | Clean | Will remove |
| 2 | agent-a7e312d0 | review/code-reviewer-2026-04-01 | No | Clean | Skipped |Step 5: Confirm and Execute
If --dry-run was specified, show the table and stop.
Otherwise, use AskUserQuestion to confirm cleanup (unless --all was specified with only merged branches).
For each worktree/branch to clean up:
Remove the worktree:
bashgit worktree remove <path>If that fails (dirty worktree), warn and skip — never force-remove.
Delete the local branch:
bashgit branch -d <branch>Use
-d(not-D) for merged branches. For--force-allunmerged branches, use-Donly after explicit user confirmation.Delete the remote branch (if it exists):
bashgit push origin --delete <branch>If the remote branch doesn't exist, ignore the error silently.
Step 6: Prune
After all removals:
git worktree pruneStep 7: Summary
Show what was cleaned up:
Cleanup Complete
──────────────────────────────────
Removed: <N> worktree(s)
Deleted: <N> local branch(es)
Deleted: <N> remote branch(es)
Skipped: <N> unmerged branch(es)
──────────────────────────────────If any unmerged branches were skipped, list them and suggest:
- Merge the PR first, then run cleanup again
- Or use
git worktree remove <path>andgit branch -D <branch>manually if the work is truly abandoned