agentleFS
rlajousrlajous/claude-code-commands/skills/clean-gone/SKILL.md

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".

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
  1. Distinctive:

    Default (no args): proceed through confirmation (Step 4) before any deletion.

    line 18
  2. Very specific:

    Only when NOT --dry-run, prune stale remote-tracking refs so [gone] is accurate:

    line 22
  3. Very specific:

    If fetch fails (offline, no remote), warn and continue with the current state.

    line 29
  4. Very specific:

    If the output is empty (clean): remove it with git worktree remove "{worktree_path}" (no --force needed for a clean worktree).

    line 74
  5. Very specific:

    If non-empty (dirty/untracked files): do NOT remove it unless the user explicitly confirmed discarding its contents in Step 4.

    line 75
  6. Very specific:

    If -d fails because the branch is not merged, the branch has local commits that exist nowhere else.

    line 88
  7. Very specific:

    Never force-delete (-D) unmerged branches without showing the commits and getting a clear yes.

    line 100
  8. Distinctive:

    If nothing was gone, say so plainly: "No gone branches to clean up."

    line 116

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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-run to refresh.
  • If fetch fails (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 — default staging
  • workflow.productionBranch — default main
  • Also always protect: the current branch (git branch --show-current), and master.

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 --porcelain

For 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 --force needed 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}"
  • -d succeeds 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 -d fails because the branch is not merged, the branch has local commits that exist nowhere else. Show them:

    git log --oneline "{branch_name}" --not --remotes

    Report 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

ScenarioAction
git fetch failsWarn, continue with current tracking state
Branch is protected (current/dev/prod/master)Skip it, note it is protected
Branch is unmergedSkip by default; only force-delete after showing commits + explicit confirmation
Worktree is dirtySkip by default; only --force remove after explicit confirmation
Worktree path is missing/lockedReport the error, skip that branch, continue
git branch -d/-D failsReport and continue with the rest

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.