Clean up git worktrees whose associated feature PRs have been merged. Only removes worktrees where the PR is confirmed merged - never removes active development worktrees.
Removes git worktrees whose associated feature PRs have been merged.
/plugin marketplace add bacchus-labs/wrangler/plugin install bacchus-labs-wrangler@bacchus-labs/wranglerThis skill inherits all available tools. When active, it can use any tool Claude has access to.
MANDATORY: When using this skill, announce it at the start with:
Using Skill: cleanup-dangling-worktrees | [brief purpose based on context]
Git worktrees accumulate over time as features are developed and merged. This skill safely cleans up worktrees that are no longer needed because their associated feature PRs have been merged.
Core principle: Only remove a worktree if its feature PR is CONFIRMED merged. Never remove active development worktrees.
A worktree is ONLY considered dangling if ALL of these are true:
NEVER remove a worktree if:
git worktree list --porcelain
Parse output to get worktree paths and branches. Skip the main worktree (the bare repository or main checkout).
For each worktree (excluding main):
cd /path/to/worktree && git status --porcelain
If output is non-empty, SKIP - worktree has uncommitted changes.
cd /path/to/worktree && git log @{upstream}..HEAD --oneline 2>/dev/null
If output is non-empty, SKIP - worktree has unpushed commits.
If upstream doesn't exist, SKIP - branch was never pushed.
# Get the branch name
BRANCH=$(cd /path/to/worktree && git branch --show-current)
# Find PR for this branch
gh pr list --head "$BRANCH" --state all --json number,state,mergedAt --jq '.[0]'
If no PR found, SKIP - no PR means possibly active development.
Parse the PR info:
state is not "MERGED", SKIPmergedAt is null/empty, SKIPFor each worktree confirmed as dangling:
# Remove the worktree
git worktree remove /path/to/worktree
# Optionally delete the branch (if fully merged)
git branch -d branch-name
Note: Use git worktree remove not rm -rf - this properly unregisters the worktree.
After removals, clean up stale worktree metadata:
git worktree prune
Report findings in this format:
## Worktree Cleanup Report
### Worktrees Found
- Total worktrees: [N]
- Main/primary: 1 (skipped)
- Feature worktrees checked: [N-1]
### Status by Worktree
| Worktree | Branch | PR | PR Status | Action |
|----------|--------|-----|-----------|--------|
| .worktrees/auth | feature/auth | #42 | MERGED | Removed |
| .worktrees/api | feature/api | #51 | Open | Kept (PR open) |
| .worktrees/fix | bugfix/typo | - | No PR | Kept (no PR) |
### Actions Taken
- Worktrees removed: [count]
- Branches deleted: [count]
- Worktrees kept: [count]
### Kept Worktrees (Active Development)
- .worktrees/api (PR #51 still open)
- .worktrees/fix (no associated PR)
This skill is designed to run as a parallel agent during housekeeping (Phase 2).
When called from housekeeping:
Metrics to report:
worktrees_checked: Total feature worktrees examinedworktrees_removed: Worktrees successfully removedworktrees_kept: Worktrees retained (with reasons)branches_deleted: Branches deleted after worktree removalIf gh commands fail due to network:
Warning: Could not check PR status for branch 'feature/xyz' - keeping worktree
Never remove a worktree if PR status cannot be confirmed.
If worktree removal fails:
Error: Could not remove worktree at /path - manual cleanup may be needed
Continue with other worktrees, report failures at end.
If gh is not installed:
Error: GitHub CLI (gh) not found. Cannot verify PR status.
Worktree cleanup requires gh CLI to verify merged PRs.
Skipping all worktree cleanup.
| Situation | Action |
|---|---|
| PR merged | Remove worktree + delete branch |
| PR open | Keep worktree |
| PR closed (not merged) | Keep worktree (might reopen) |
| No PR exists | Keep worktree |
| Uncommitted changes | Keep worktree |
| Unpushed commits | Keep worktree |
| Network error | Keep worktree |
| gh CLI missing | Skip all cleanup |
Removing worktrees without checking PR status
Using rm -rf instead of git worktree remove
git worktree removeChecking PR state instead of mergedAt
mergedAt has a valueForce-removing worktrees with changes
# List worktrees
$ git worktree list
/Users/sam/project abc1234 [main]
/Users/sam/project/.worktrees/auth def5678 [feature/auth]
/Users/sam/project/.worktrees/api ghi9012 [feature/api]
# Check PR for auth branch
$ gh pr list --head "feature/auth" --state all --json number,state,mergedAt
[{"number":42,"state":"MERGED","mergedAt":"2024-01-15T10:30:00Z"}]
# PR is merged - safe to remove
$ cd /Users/sam/project/.worktrees/auth && git status --porcelain
# (empty - no uncommitted changes)
$ cd /Users/sam/project/.worktrees/auth && git log @{upstream}..HEAD --oneline
# (empty - no unpushed commits)
# Remove the worktree
$ git worktree remove /Users/sam/project/.worktrees/auth
$ git branch -d feature/auth
# Check PR for api branch
$ gh pr list --head "feature/api" --state all --json number,state,mergedAt
[{"number":51,"state":"OPEN","mergedAt":null}]
# PR is open - keep this worktree
# (no action taken)
# Prune stale metadata
$ git worktree prune
STOP if you see:
rm -rf on a worktree directoryALWAYS:
git worktree removegit worktree prune after cleanupBuild robust backtesting systems for trading strategies with proper handling of look-ahead bias, survivorship bias, and transaction costs. Use when developing trading algorithms, validating strategies, or building backtesting infrastructure.