Skip to content
Back to skills

Git Clean Gone

ASecurity

Clean up local branches with deleted remote tracking and their worktrees. Use after merging PRs to remove stale branches, detect squash-merged and rebased branches, and clean up associated worktrees.

  • 5 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 6, 2026
toolsgobashgit

Works with

  • claude code
  • cli

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned October 4, 2026

npx -y skills add smykla-skalski/sai --skill git-clean-gone --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Git Clean Gone?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Git Clean Gone
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/smykla-skalski-git-clean-gone-sai/badge)](https://www.skillsdirectory.com/skills/smykla-skalski-git-clean-gone-sai)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: git-clean-gone
description: Clean up local branches with deleted remote tracking and their worktrees. Use after merging PRs to remove stale branches, detect squash-merged and rebased branches, and clean up associated worktrees.
license: MIT
compatibility: Works in Claude Code, Codex, opencode and Copilot CLI. Needs bash and git; the gh CLI is optional (squash-merge detection). Fetches from all remotes.
argument-hint: "[--dry-run] [--no-worktrees]"
allowed-tools: Bash
user-invocable: true
disable-model-invocation: true
metadata:
  short-description: Clean stale local branches safely
---

# Clean Gone

Delete local branches whose remote tracking is gone or merged, and remove their associated worktrees.

## Agent compatibility

Paths in this file are relative to the skill directory (the one holding this SKILL.md). The workflow is written for Claude Code; on other agents, or when a Claude feature is missing, use these fallbacks:

| Claude Code feature | Fallback |
| :-- | :-- |
| Argument substitution | If the "Parse from" line under Arguments shows no value or an unreplaced placeholder, take the flags from the user's request |
| Skill directory substitution | If the script path under Constraints is not an absolute path, run `bash <absolute skill directory>/scripts/clean-gone.sh` without changing directory. The script acts on the repository in the current working directory, so that must stay the user's repository, never the skill directory |
| Preprocessed context | If the values under Preprocessed context are unexpanded commands, ignore them: the script detects the remote, default branch and `gh` itself |
| `disable-model-invocation` | This skill deletes branches and worktrees and is meant to run only when the user invokes it by name. Codex enforces this through `agents/openai.yaml` (`allow_implicit_invocation: false`); where nothing enforces it (for example opencode), apply the confirmation gate below |
| AskUserQuestion, subagents, `context: fork` | Not used |

Confirmation gate on agents other than Claude Code: run the real cleanup directly only when the user invoked this skill by name (`/git-clean-gone` or `$git-clean-gone`) without `--dry-run` and without exclusions or conditions (such as "but keep feat/x"). In every other case, including plain requests such as "clean up stale branches", run with `--dry-run` first, show the preview, then end your turn and wait for the user's reply. Never run the real cleanup in the same turn as the preview; only an explicit yes in a later user message allows it. Approval is all-or-nothing: the script cannot skip individual branches, so if the user wants to keep any listed branch or worktree, stop and do not run the real cleanup. The real run fetches again, so after it, compare its `DELETED`/`REMOVED_WT` lines with the preview and call out every branch or worktree that was not in the preview. In Claude Code, invoking `/git-clean-gone` without `--dry-run` is that explicit request.

In Codex, `git fetch --prune` and `gh` need network access and the deletions write to `.git`, so run the script with escalation and a short reason from the start, for the `--dry-run` preview as well as the real run. A preview without network silently misses gone and squash-merged branches. If the output has a `fatal:` or `error:` line from `git fetch`, the fetch failed: report it and do not run the real cleanup.

## Arguments

Parse from `$ARGUMENTS`:

| Flag | Default | Purpose |
| :-- | :-- | :-- |
| (none) | — | Full cleanup: gone + merged branches + worktrees |
| `--dry-run` | off | Preview only, no changes |
| `--no-worktrees` | off | Branches only, skip worktree removal |

## Preprocessed context

- Default remote: !`git for-each-ref --format="%(upstream:remotename)" refs/heads/main 2>/dev/null || git remote | head -1 2>/dev/null || echo "origin"`
- Default branch: !`basename "$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null || echo refs/remotes/origin/main)"`
- gh CLI: !`command -v gh >/dev/null 2>&1 && echo "available" || echo "unavailable"`

## Constraints

- First action MUST be Bash — preamble text wastes a turn and delays the actual cleanup
- Never delete the current branch — skip and report in summary
- Never remove the main worktree — only feature/task worktrees
- Execute `"${CLAUDE_SKILL_DIR}/scripts/clean-gone.sh"` as a single Bash invocation
- Output summary directly as text (NOT via bash/printf)
- Agents other than Claude Code: follow the confirmation gate in [Agent compatibility](#agent-compatibility); a `--dry-run` preview always ends the turn

## Workflow

### Phase 1: Execute Cleanup Script

Execute `"${CLAUDE_SKILL_DIR}/scripts/clean-gone.sh"` immediately, passing through any flags from `$ARGUMENTS`. On agents other than Claude Code, apply the confirmation gate from [Agent compatibility](#agent-compatibility) first.

- No flags → full cleanup (gone + merged branches + worktrees)
- `--dry-run` → preview only, no changes
- `--no-worktrees` → gone branches only, no worktree removal or merge detection
- Invalid flag → script exits with error, show valid options (`--dry-run`, `--no-worktrees`), stop

### Phase 2: Output Summary

Parse script output line prefixes and render formatted summary directly as text.

**Line prefixes** (from script output):

| Prefix | Meaning |
| :-- | :-- |
| `DELETED:branch:reason` | Deleted branch |
| `REMOVED_WT:worktree:branch` | Removed worktree |
| `SKIPPED:branch:reason` | Skipped branch |
| `KEPT:branch:reason` | Kept branch |
| `KEPT_WT:worktree:branch:reason` | Kept worktree |

Dry-run uses `WOULD_DELETE`, `WOULD_REMOVE_WT`, `WOULD_SKIP`, `WOULD_KEEP`, `WOULD_KEEP_WT`.

**Summary format:**

```
**Cleanup Summary**

Deleted:
  🗑️ fix/old-feature (gone)
  🗂️ fix-old-feature-wt (worktree)

Skipped:
  ⚠️ feat/current-work (current branch)

Kept:
  🗂️ wt-name (worktree) - branch (N unmerged)
  ℹ️ feat/in-progress (14 unmerged)
```

Only include sections with items. Empty state: `✅ Repository already clean — no branches to process`

Dry-run header: `**Dry Run Preview**` with "Would delete/remove" phrasing.

## Cleanup Logic

- Uses pre-resolved remote name and default branch from preprocessed context
- Deletes branches marked `[gone]` (remote tracking deleted)
- Deletes branches fully merged via rebase/cherry-pick (`git cherry`)
- Deletes branches squash-merged via PR (`gh pr list --state merged`) when gh CLI is available
- Removes associated worktrees before branch deletion
- Skips main and current branch
- Falls back gracefully if gh CLI is unavailable (see preprocessed context)

## Edge Cases

- Invalid flags: report unknown flag, show valid options, stop
- No cleanable branches: report "Repository already clean"
- Current branch is gone/merged: skip deletion, warn in summary
- Uncommitted changes in worktree: force remove with `--force` flag
- No `gh` CLI (see preprocessed context): squash merges won't be detected, only `git cherry` used
- No remote configured: remote from preprocessed context used as fallback

## Example Invocations

<example>
Full cleanup:

```bash
/git-clean-gone
```
</example>

<example>
Preview what would be deleted:

```bash
/git-clean-gone --dry-run
```
</example>

<example>
Branches only, no worktree removal:

```bash
/git-clean-gone --no-worktrees
```
</example>

Files in this skill

  • SKILL.md3.2 KB
  • agents/openai.yaml253 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.