global/skills/branch-cleanup/SKILL.md
Clean up merged and stale branches from local and remote repositories. Use when branch list is cluttered or after merging PRs.
npx skillsauth add kcenon/claude-config branch-cleanupInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Clean up merged and stale branches from local and remote repositories.
/branch-cleanup [<project-name>] [options]
/branch-cleanup [--dry-run] [--include-remote] [--stale-days <days>]
Example:
/branch-cleanup # Clean current repo, local only
/branch-cleanup --dry-run # Preview what would be deleted
/branch-cleanup hospital_erp_system # Clean specific project
/branch-cleanup --include-remote --stale-days 30 # Include remote, 30-day threshold
<project-name>: Optional project directory name (defaults to current directory)| Option | Values | Default | Description |
|--------|--------|---------|-------------|
| --dry-run | flag | false | Preview branches without deleting |
| --include-remote | flag | false | Also clean remote tracking branches |
| --stale-days | number | 90 | Days since last commit to consider stale |
The following branches are never deleted, regardless of their merge status:
| Branch Pattern | Rationale |
|----------------|-----------|
| main | Primary production branch |
| master | Legacy primary branch |
| develop | Development integration branch |
| release/* | Release preparation branches |
| hotfix/* | Emergency fix branches |
Execute the following workflow:
# If project name provided
cd <project-name> 2>/dev/null || { echo "Error: Project directory not found"; exit 1; }
# Fetch latest remote state
git fetch --prune origin
# Get current branch
CURRENT_BRANCH=$(git branch --show-current)
# List branches merged into develop, main, or master
MERGED_BRANCHES=$(
{ git branch --merged develop 2>/dev/null; \
git branch --merged main 2>/dev/null; \
git branch --merged master 2>/dev/null; } | sort -u
)
# Filter out protected branches and current branch
echo "$MERGED_BRANCHES" | grep -v -E "^\*|main|master|develop|release/|hotfix/"
# Find branches with no commits in the last N days
STALE_THRESHOLD=$(date -d "$STALE_DAYS days ago" +%s 2>/dev/null || date -v-${STALE_DAYS}d +%s)
for branch in $(git branch --format='%(refname:short)'); do
LAST_COMMIT=$(git log -1 --format='%ct' "$branch" 2>/dev/null)
if [[ -n "$LAST_COMMIT" && "$LAST_COMMIT" -lt "$STALE_THRESHOLD" ]]; then
echo "$branch (stale: no commits in $STALE_DAYS days)"
fi
done
Present categorized results:
## Branches Identified for Cleanup
### Merged Branches (safe to delete)
- feat/issue-123-add-login
- fix/issue-456-null-check
### Stale Branches (no commits in 90+ days)
- feat/old-experiment (last commit: 2024-06-15)
- fix/abandoned-fix (last commit: 2024-05-20)
### Protected Branches (will NOT be deleted)
- main
- develop
- release/v2.0
If --dry-run is NOT specified:
# Prompt for confirmation
echo "Delete the above branches? (y/N)"
read -r CONFIRM
if [[ "$CONFIRM" != "y" && "$CONFIRM" != "Y" ]]; then
echo "Aborted."
exit 0
fi
for branch in $BRANCHES_TO_DELETE; do
# Skip protected branches
if [[ "$branch" =~ ^(main|master|develop|release/|hotfix/) ]]; then
echo "Skipping protected branch: $branch"
continue
fi
# Delete local branch
git branch -d "$branch" 2>/dev/null || git branch -D "$branch"
echo "Deleted local branch: $branch"
done
if [[ "$INCLUDE_REMOTE" == "true" ]]; then
for branch in $REMOTE_BRANCHES_TO_DELETE; do
# Skip protected branches
if [[ "$branch" =~ ^(main|master|develop|release/|hotfix/) ]]; then
echo "Skipping protected remote branch: $branch"
continue
fi
git push origin --delete "$branch"
echo "Deleted remote branch: $branch"
done
fi
Provide summary of actions taken.
See _policy.md for common rules.
| Item | Rule | |------|------| | Protected branches | Never delete main, master, develop, release/, hotfix/ | | Current branch | Never delete the currently checked-out branch | | Confirmation | Always require confirmation unless --dry-run | | Remote deletion | Only with explicit --include-remote flag |
After completion, provide summary:
## Branch Cleanup Summary
| Item | Value |
|------|-------|
| Project | <project-name> |
| Mode | Dry-run / Executed |
| Stale threshold | 90 days |
### Deleted Branches
| Branch | Type | Last Commit |
|--------|------|-------------|
| feat/issue-123 | merged | 2024-12-01 |
| fix/old-bug | stale | 2024-06-15 |
### Skipped Branches
| Branch | Reason |
|--------|--------|
| main | Protected |
| develop | Protected |
| feat/current-work | Current branch |
### Statistics
- Local branches deleted: N
- Remote branches deleted: N
- Total branches cleaned: N
| Requirement | Error Message | Resolution | |-------------|---------------|------------| | git installed | "Git is not installed" | Install git from https://git-scm.com | | inside git repo | "Not a git repository" | Navigate to a git repository | | Project directory exists | "Project directory not found: [path]" | Verify project path |
| Error Condition | Behavior | User Action | |-----------------|----------|-------------| | No branches to clean | Report "No merged or stale branches found" | No action needed | | Branch deletion failed | Report specific branch and error, continue with others | Check if branch has unmerged changes | | Remote deletion failed | Report "Cannot delete remote branch: [name]" | Verify remote permissions | | Protected branch in list | Skip automatically with warning | No action needed | | Current branch selected | Skip automatically | Checkout different branch first | | Network error (remote) | Report "Cannot reach remote - check connection" | Verify internet connection |
development
Generate and validate the bidirectional traceability matrix linking requirements, design, code, tests, risk records, and standard clauses. Consumes docs/.index/{manifest,bundles,graph,router}.yaml plus an optional compliance/ directory and produces docs/.index/traceability.yaml (machine-readable) and docs/.index/traceability.md (human-readable). Read-mostly: writes only the two trace artifacts and never mutates source documents. Opt-in — no-op when docs/.index/graph.yaml is absent so non-regulated repos are unaffected.
development
Maintain a SOUP (Software Of Unknown Provenance) register for every third-party software item the project depends on. Discovers candidates from lockfiles (package-lock.json, go.sum, Cargo.lock, requirements.txt, pyproject.toml, pom.xml, packages.lock.json), enriches with human-supplied risk class and verification refs, validates against a license allow-list and the requirements catalogue, and emits a per-supplier report. Outputs docs/.index/soup.yaml plus docs/.index/soup.md. Subcommands: discover | enrich | validate | list | report. Bidirectional linking with traceability via the soup_ids[] field on requirement rows. Opt-in: no-op when no lockfile is detected and docs/.index/soup.yaml is absent. Atomic writes (*.tmp + rename); idempotent (records sorted by id). Implements IEC 62304 sections 5.3.3 (SOUP requirements) and 8.1.1 (configuration items).
devops
Parse sonarcloud[bot] PR comments, classify findings, codify whitelisted auto-fixes, escalate the rest.
testing
Manage Hazard and Risk records for projects on the regulated-industry track. Maintains a single normalized risk file (docs/.index/risk-file.yaml) holding hazard identification, initial and residual risk estimates, control measures with verification links, and bidirectional Risk<->Requirement linking via the requirements[] field. Subcommands: add | edit | evaluate | validate | list. Output is consumed by the traceability skill (matrix risk_ids[] field) and the evidence-pack skill (risk_file kind). Opt-in: no-op when docs/.index/manifest.yaml is absent so non-regulated repos are unaffected. Atomic writes via *.tmp + rename; idempotent for diffability. Implements ISO 14971 sections 5-9 operationally.