About cleanup-merged-branches
A skill for safely removing remote branches associated with merged pull requests and catching linked issues left open. It uses a dry-run plan and requires explicit confirmation before deletion.
Key features
- 01Dry-run branch planning
- 02Merged-PR and open-PR checks
- 03Protects default and staging branches
- 04Explicit confirmation before deletion
- 05Checks linked issues left open
Use cases
- 01Review remote branches eligible for cleanup
- 02Remove branches after approving the plan
- 03Close issues missed by integration-branch merges
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ timschoch/ mattpocock-skills --skill cleanup-merged-branchesAfter installing, type/cleanup-merged-branchesin Claude Code to confirm it loaded.
Bundled filesagents/openai.yamlscripts/plan.sh
Details
From the project READMEDelete remote branches that belong to a merged PR. Destructive, so it runs as a dry-run first and never deletes without explicit confirmation.
Delete rule
A branch is deletable iff all hold — encoded in scripts/plan.sh, the single source of truth:
- it still exists on the remote,
- it has a merged PR,
- it has no open PR,
- it is not protected.
Protected = the default branch + staging. Never delete these, even if a merged PR points at them. A branch with no PR, or only a closed-unmerged PR, is not deletable (it never "belongs to a merged PR"). Extend the protected set in is_protected() inside scripts/plan.sh, nowhere else.
Steps
- Dry-run. Run
bash scripts/plan.sh(pass a remote name as$1if notorigin). It prints deletable branches as<branch> #<pr> <title>, and deletes nothing. Done when you have the list. Empty output → report "nothing to clean up" and stop. - Show + confirm. Show the full list to the user and ask for explicit go. Do not delete on a vague reply — only on a clear yes. This gate is mandatory every run.
- Delete. For each confirmed branch:
git push origin --delete <branch>. Nothing outside the plan's list may be deleted. - Report. List what was deleted; note any push that failed.
Also: stale-open issues
Closes #N only auto-closes on merge into the default branch — a PR merged into an integration branch (e.g. rebuild/v1) leaves #N open forever. For each merged PR you clean up here, check its linked issue: if the work is on the default branch but the issue is still open, hand-close it (gh issue close #N --reason completed --comment "merged via #<pr>"). Same misfire hides "done" issues as open — this is where to catch them.