Audits git worktrees and removes the ones that are safe to delete — merged into the base branch (including squash-merges via `gh`), missing on disk, or explicitly confirmed by the user — then deletes the associated local branches and runs `git worktree prune`. Use when the user asks to clean up worktrees, prune worktrees, list stale worktrees, remove merged worktrees or branches, or reclaim disk space from old checkouts.
80
100%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
End state: stale, merged, and missing worktrees are removed; their local branches are deleted; git worktree prune has run; the user has signed off on every deletion.
--force remove a worktree without explicit user confirmation. Dirty worktrees stay until the user says otherwise.git rev-parse --show-toplevel of the primary checkout) or the worktree the agent is currently sitting in. Detect the agent's worktree by comparing pwd (or git rev-parse --show-toplevel from the current directory) against each path from git worktree list. If they match, refuse deletion and tell the user to move first via move_agent_to_root.AskQuestion with allow_multiple: true. Don't delete one-by-one without a single approval step.git branch -d (safe delete) by default. Only use -D for branches the user explicitly flags as okay to force-delete.git worktree list --porcelainParse into entries: path, branch, HEAD. Skip the primary worktree.
Check in order:
git symbolic-ref refs/remotes/origin/HEAD (gives e.g. refs/remotes/origin/main)main, then next, then masterUse origin/<base> for merge checks so local staleness doesn't matter. Run git fetch --prune origin first to make checks accurate.
For each non-primary worktree, compute one of:
| Status | Detection | Default action |
|---|---|---|
| missing | path does not exist on disk | prune only |
| merged-direct | git merge-base --is-ancestor <branch> origin/<base> succeeds | remove + delete branch |
| merged-squash | gh pr list --state merged --head <branch> --json number returns a PR (requires GitHub CLI — if gh is missing, skip this classification and flag the branch as active with a note to install gh or verify merge manually) | remove + delete branch (with -D after confirm, since -d will refuse) |
| dirty | git -C <path> status --porcelain is non-empty | flag, do not remove |
| unpushed | branch has commits not on origin/<branch> and no merged PR | flag, do not remove |
| active | none of the above | leave alone |
Also flag any worktree that is the current agent root — compare pwd / git rev-parse --show-toplevel against each worktree path, mark matches as such, and exclude them from the removable set.
Use AskQuestion with allow_multiple: true. Group by category in the prompt so the user can scan it. For each removable entry, the option label should include path, branch, and reason. Example option labels:
merged: ../more-dcr-oauths (branch more-dcr-oauths)missing: ../old-experiment (branch old-experiment)dirty: ../wip-bar (branch wip/bar) — has uncommitted changesFor dirty / unpushed entries, surface them as separate options so the user can opt in to force-removing if they really want to.
For each confirmed worktree:
git worktree remove <path> # safe path
git worktree remove --force <path> # only if user opted in for dirty
git branch -d <branch> # safe delete (refuses if unmerged)
git branch -D <branch> # only if user opted in (squash-merged or force); squash-merges leave the branch ahead/unmerged in topology so `-d` refuses — confirm merge via `gh pr list` firstFor missing entries, skip remove and rely on prune in the next step.
git worktree prune
git worktree list # show the user the new stateReport:
git worktree remove --force over every entry "to be safe". Force is for explicit user opt-in only.git branch -d will fail with "checked out at ...". Order is: remove worktree, then delete branch.gh pr list --state merged --head <branch> for that case.git worktree prune before listing — you'll lose the metadata you need to identify missing entries.git fetch --prune origin first; otherwise "merged into origin/main" checks can be wrong.User: "clean up my worktrees"
Agent flow:
git fetch --prune origingit worktree list --porcelain → 5 worktrees (1 primary + 4 others)../nv-100-x → merged-direct../nv-200-y → merged-squash (PR #4321 merged)../nv-300-z → dirty (3 modified files)../old-experiment → missing on diskAskQuestion: which of these to remove? (multi-select, dirty entry pre-flagged with a warning label)git worktree remove ../nv-100-x && git branch -d nv-100/xgit worktree remove ../nv-200-y && git branch -D nv-200/y (squash-merge needed -D, user confirmed)git worktree prune (cleans up ../old-experiment)git worktree list.d921755
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.