clean-gone
Skill30 starsChanged 3 months agoMITView on GitHub
Delete local Git branches whose upstream was deleted on the remote ("[gone]"), and remove any worktrees attached to them. Use when the user asks to clean up merged/stale branches, prune gone branches, tidy local branches after merging PRs, or "delete branches that are gone on the remote".
In this repository23 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- change-briefSkill
- close-customer-loopSkill
- commitSkill
- finishSkill
- notificationsSkill
- plan-qaSkill
- plan-tddSkill
- release-notesSkill
- releaseSkill
- review-requestSkill
- reviewSkill
- review-watchSkill
- rfcSkill
- setupSkill
- standupSkill
- start-qaSkill
- startSkill
- statusSkill
- syncSkill
- tddSkill
- updateSkill
The file
We split this skill into the rules it gives an agent
8 rules. About 0 are common, 2 are distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 18
Default (no args): proceed through confirmation (Step 4) before any deletion.
- Very specific: line 22
Only when NOT --dry-run, prune stale remote-tracking refs so [gone] is accurate:
- Very specific: line 29
If fetch fails (offline, no remote), warn and continue with the current state.
- Very specific: line 74
If the output is empty (clean): remove it with git worktree remove "{worktree_path}" (no --force needed for a clean worktree).
- Very specific: line 75
If non-empty (dirty/untracked files): do NOT remove it unless the user explicitly confirmed discarding its contents in Step 4.
- Very specific: line 88
If -d fails because the branch is not merged, the branch has local commits that exist nowhere else.
- Very specific: line 100
Never force-delete (-D) unmerged branches without showing the commits and getting a clear yes.
- Distinctive: line 116
If nothing was gone, say so plainly: "No gone branches to clean up."
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Cross-runtime: follow runtime compatibility for invocation, delegation, configuration precedence, state paths, and permissions.
You are cleaning up local Git branches whose remote tracking branch has been deleted (shown as [gone] by Git), along with any worktrees checked out to them. This is destructive, so it is designed to be safe by default: it never discards uncommitted work or unmerged commits without explicit, informed confirmation. Follow each step in order.
Step 1: Parse Arguments
--dry-run→ show exactly what would be removed and stop. In dry-run, make no changes to Git state at all (no fetch/prune, no deletion).
Default (no args): proceed through confirmation (Step 4) before any deletion.
Step 2: Refresh Remote State (skip on --dry-run)
Only when NOT --dry-run, prune stale remote-tracking refs so [gone] is accurate:
git fetch --prune- On
--dry-run, do NOT run this (it mutates local refs). Use the current tracking state and note in the output that it may be stale — the user can re-run without--dry-runto refresh. - If
fetchfails (offline, no remote), warn and continue with the current state.
Step 3: Identify Gone Branches
List local branches whose upstream is marked [gone]:
git for-each-ref --format '%(refname:short) %(upstream:track)' refs/heads \
| awk '$2 == "[gone]" { print $1 }'Resolve the protected branches (never delete these) from .git-workflow/config.yaml, then .claude/config.yaml as a legacy read-only fallback, then defaults:
workflow.developmentBranch— defaultstagingworkflow.productionBranch— defaultmain- Also always protect: the current branch (
git branch --show-current), andmaster.
Exclude every protected branch from the deletion list even if it is marked [gone] (a gone staging/main is a config/remote quirk, not a signal to delete it).
Step 4: Assess Safety and Confirm
For each candidate branch, gather safety signals to show the user:
- Merged? Whether the branch's commits are already integrated (see Step 6 — prefer
git branch -d, which refuses unmerged branches). - Attached worktree? And whether that worktree is dirty (see Step 5).
Present a table: branch → merged/unmerged → worktree path (clean/dirty). Then:
- On
--dry-run: print the table and stop (no changes). - Otherwise, ask the user to confirm. Call out any unmerged branches and any dirty worktrees explicitly — these lose data if removed. Default to NOT removing those unless the user explicitly opts in.
Step 5: Remove Associated Worktrees (safely)
A branch checked out in a linked worktree cannot be deleted until the worktree is removed. Map worktrees to branches:
git worktree list --porcelainFor each gone branch with a worktree, check for uncommitted work first:
git -C "{worktree_path}" status --porcelain --untracked-files=all- If the output is empty (clean): remove it with
git worktree remove "{worktree_path}"(no--forceneeded for a clean worktree). - If non-empty (dirty/untracked files): do NOT remove it unless the user explicitly confirmed discarding its contents in Step 4. Only then use
git worktree remove --force "{worktree_path}". Otherwise skip the branch and report why.
Then prune administrative leftovers: git worktree prune.
Step 6: Delete the Branches (merged-safe)
For each confirmed branch, try the safe delete first:
git branch -d "{branch_name}"-dsucceeds only if the branch is already merged (into HEAD or its upstream). This is the desired path for the common "PR merged, remote branch deleted" case.If
-dfails because the branch is not merged, the branch has local commits that exist nowhere else. Show them:git log --oneline "{branch_name}" --not --remotesReport these commits and ask the user for explicit confirmation before force-deleting. Only on explicit confirmation:
git branch -D "{branch_name}"
Never force-delete (-D) unmerged branches without showing the commits and getting a clear yes.
Step 7: Report
Print a summary:
Pruned gone branches:
✓ feature/eng-123-old-thing (merged; worktree removed: ../wt-eng-123)
✓ fix/proj-456-done (merged)
⚠ spike/experiment (skipped: 3 unmerged commits — not deleted)
⚠ feature/wip (skipped: worktree has uncommitted changes)
Removed: 2 branches, 1 worktree. Skipped: 2.If nothing was gone, say so plainly: "No gone branches to clean up."
Error Handling
| Scenario | Action |
git fetch fails | Warn, continue with current tracking state |
| Branch is protected (current/dev/prod/master) | Skip it, note it is protected |
| Branch is unmerged | Skip by default; only force-delete after showing commits + explicit confirmation |
| Worktree is dirty | Skip by default; only --force remove after explicit confirmation |
| Worktree path is missing/locked | Report the error, skip that branch, continue |
git branch -d/-D fails | Report and continue with the rest |
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

