
Ce Clean Gone Branches
Automatically find local git branches whose upstream was deleted after merge so you can prune stale feature branches safely.
Overview
ce-clean-gone-branches is an agent skill for the Ship phase that lists local git branches whose remote tracking branch is gone after fetch --prune.
Install
npx skills add https://github.com/everyinc/compound-engineering-plugin --skill ce-clean-gone-branchesWhat is this skill?
- Runs `git fetch --prune` then parses `git branch -vv` for lines marked `[origin/…: gone]`
- Skips the currently checked-out branch so cleanup does not stop mid-run on active HEAD
- Outputs one branch name per line (or nothing) for downstream delete or report steps
- Bash script with strict `set -euo pipefail` and validation to ignore hashes and HEAD
- Fits compound-engineering hygiene workflows after merged PRs remove remote branches
- Parses `git branch -vv` for `: gone]` tracking state
Adoption & trust: 1.5k installs on skills.sh; 20.5k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your laptop is cluttered with local feature branches whose remotes were already deleted on GitHub or GitLab after merge.
Who is it for?
Indie devs and small teams who merge via PRs, prune remotes on the host, and want an agent or script to surface stale locals before batch delete.
Skip if: Repos without remotes, workflows that never delete remote branches, or cases where you need to delete the branch you are currently on without switching first.
When should I use this skill?
When the user or workflow needs to list local branches whose remote tracking branch is gone after merge and remote deletion.
What do I get? / Deliverables
You get a clean, line-delimited list of gone-tracking branch names—excluding HEAD—ready for confirmed local deletion or CI cleanup.
- Newline-delimited list of local branch names marked gone on the remote
- Empty output when no stale tracking branches are found
Recommended Skills
Journey fit
How it compares
Focused list-only git hygiene script—not a full branch management UI or interactive rebase assistant.
Common Questions / FAQ
Who is ce-clean-gone-branches for?
Solo builders and agents using the compound-engineering plugin who want deterministic detection of local branches whose upstream disappeared after merge.
When should I use ce-clean-gone-branches?
Use it in Ship after merges when cleaning the repo—especially right after `git fetch --prune` on the remote—or when the user asks to find branches whose tracking remote is gone.
Is ce-clean-gone-branches safe to install?
See the Security Audits panel on this Prism page; the script only lists candidates and skips the current branch—it does not delete branches unless you run a separate delete step.
SKILL.md
READMESKILL.md - Ce Clean Gone Branches
#!/usr/bin/env bash # clean-gone: List local branches whose remote tracking branch is gone. # Outputs one branch name per line, or nothing if none found. set -euo pipefail # Ensure we have current remote state git fetch --prune 2>/dev/null # Find branches marked [gone] in tracking info. # `git branch -vv` output format: # * main abc1234 [origin/main] commit msg # + feature-x def5678 [origin/feature-x: gone] commit msg # old-branch 789abcd [origin/old-branch: gone] commit msg # # The leading column can be: ' ' (normal), '*' (current), '+' (worktree). # We match lines containing ": gone]" to find branches whose remote is deleted. gone_branches=() while IFS= read -r line; do # Skip the currently checked-out branch (marked with '*'). # git branch -D cannot delete the active branch, and attempting it # would halt cleanup before other stale branches are processed. if [[ "$line" =~ ^\* ]]; then continue fi # Strip the leading marker character(s) and whitespace # The branch name is the first non-whitespace token after the marker branch_name=$(echo "$line" | sed 's/^[+* ]*//' | awk '{print $1}') # Validate: skip empty, skip if it looks like a hash or flag, skip HEAD if [[ -z "$branch_name" ]] || [[ "$branch_name" =~ ^[0-9a-f]{7,}$ ]] || [[ "$branch_name" == "HEAD" ]]; then continue fi gone_branches+=("$branch_name") done < <(git branch -vv 2>/dev/null | grep ': gone]') if [[ ${#gone_branches[@]} -eq 0 ]]; then echo "__NONE__" exit 0 fi for branch in "${gone_branches[@]}"; do echo "$branch" done --- name: ce-clean-gone-branches description: Clean up local branches whose remote tracking branch is gone. Use when the user says "clean up branches", "delete gone branches", "prune local branches", "clean gone", or wants to remove stale local branches that no longer exist on the remote. Also handles removing associated worktrees for branches that have them. --- # Clean Gone Branches Delete local branches whose remote tracking branch has been deleted, including any associated worktrees. ## Workflow ### Step 1: Discover gone branches Run the discovery script to fetch the latest remote state and identify gone branches: ```bash bash scripts/clean-gone ``` [scripts/clean-gone](./scripts/clean-gone) The script runs `git fetch --prune` first, then parses `git branch -vv` for branches marked `: gone]`. If the script outputs `__NONE__`, report that no stale branches were found and stop. ### Step 2: Present branches and ask for confirmation Show the user the list of branches that will be deleted. Format as a simple list: ``` These local branches have been deleted from the remote: - feature/old-thing - bugfix/resolved-issue - experiment/abandoned Delete all of them? (y/n) ``` Wait for the user's answer using the platform's blocking question tool: `AskUserQuestion` in Claude Code (call `ToolSearch` with `select:AskUserQuestion` first if its schema isn't loaded), `request_user_input` in Codex, `ask_user` in Gemini, `ask_user` in Pi (requires the `pi-ask-user` extension). Fall back to presenting the list in chat only when no blocking tool exists in the harness or the call errors (e.g., Codex edit modes) — not because a schema load is required. Never silently skip the question. This is a yes-or-no decision on the entire list -- do not offer multi-selection or per-branch choices. ### Step 3: Delete confirmed branches If the user confirms, delete each branch. For each branch: 1. Check if it has an associated worktree (`git worktree list | grep "\\[$branch\\]"`) 2. If a worktree exists and is not the main repo root, remove it first: `git worktree remove --force "$worktree_path"` 3. Delete the branch: `git branch -D "$branch"` Report results as you go: ``` Removed worktree: .worktrees/feature/old-thing Deleted branch: feature/old-thing Deleted branch: bugfix/resolved-issue Deleted branch: experiment/abandoned Cleaned up 3 branches. ``` If the user declines,