git-branches-cleanuplisted
Install: claude install-skill pivoshenko/pivoshenko.ai
# Cleanup Branches
Prune locals = merged OR remote gone. Destructive -> preview + confirm.
## Flow
0. If user mentioned keep-patterns inline (e.g. "but keep `spike/*`") -> capture them. Else assume none. Don't prompt up front
1. Parallel:
- `git fetch --all --prune`
- `git branch --show-current`
2. Base: user names one -> use it. Else detect: `git symbolic-ref --short refs/remotes/origin/HEAD` -> strip the `origin/`; ref missing -> `git remote set-head origin -a`, re-read; no remote -> `main`, fall back `master`. Why -> this is a delete path, and `--merged <wrong-base>` misclassifies live branches as merged. Compare against `origin/<base>`, not the local ref -> the local base is often stale or absent entirely (`git-branch-create` branches off `origin/<base>` without ever creating it), so a local-ref check either errors or reports branches as unmerged that the remote already has
3. Candidates:
- **Gone**: upstream gone
```
git for-each-ref --format='%(refname:short) %(upstream:track)' refs/heads \
| awk '$2 == "[gone]" {print $1}'
```
- **Merged**: fully merged into the remote base (step 1 already fetched + pruned)
```
git branch --merged origin/<base> --format='%(refname:short)'
```
- Note: squash-merged PRs leave no merge commit, so they won't appear in **Merged**. Closing the PR deletes the remote -> they show up in **Gone** instead. The Gone bucket is the catch-all for PR-merged work
- Union. **Exclude**:
- cur