Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Prune Merged Worktrees

ASecurity

Remove local git worktrees (and their branches) whose associated pull request was merged, verifying merge state against GitHub instead of git ancestry. Use when the user says /prune-merged-worktrees, "prune worktrees", "clean up merged worktrees", "remove worktrees for merged PRs", or wants stale worktree cleanup after merges.

10 stars
0 votes
0 copies
0 views
Added 10/6/2026
code-qualitygogit

Works with

cli

Security Analysis

A100/100

Scanned 10/6/2026

$npx -y skills add tomzx/agents --skill prune-merged-worktrees --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Prune Merged Worktrees?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Prune Merged Worktrees
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tomzx-prune-merged-worktrees/badge)](https://www.skillsdirectory.com/skills/tomzx-prune-merged-worktrees)

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

Download with Pro
Files
SKILL.md
---
name: prune-merged-worktrees
description: Remove local git worktrees (and their branches) whose associated pull request was merged, verifying merge state against GitHub instead of git ancestry. Use when the user says /prune-merged-worktrees, "prune worktrees", "clean up merged worktrees", "remove worktrees for merged PRs", or wants stale worktree cleanup after merges.
argument-hint: "[repo-path] [--dry-run] [--force]"
---

# Prune Merged Worktrees

Finds local git worktrees whose branch's remote was deleted, verifies through GitHub that the branch's pull request was actually merged, then removes the worktree and the local branch after user confirmation.
Verification goes through the forge because squash and rebase merges (the `/merge-pr` default) land the work under a new SHA, so `git branch -d`, `git merge-base --is-ancestor`, and `git rev-list main..<branch>` all classify fully shipped branches as unmerged.

## Prerequisites

- Current working directory is a checkout of the target repository, or a repo path is passed as `$1`
- `git worktree` available
- `ghx` (preferred) or `gh` CLI authenticated with access to the repository
- The skill never removes the main checkout, a bare entry, or the worktree containing the current directory

## Arguments and Flags

- `$1` (optional): path to the repository checkout (default: current directory)
- `--dry-run`: print the classification table and exit without removing anything
- `--force`: allow removing worktrees with uncommitted changes; without it, dirty worktrees are reported and skipped

## Steps

### 1. List worktrees and candidates

```
git -C <repo> worktree list --porcelain
```

Skip the main checkout (the first entry) and any worktree containing the current directory.
For each remaining worktree, read its branch from the `branch` line.

### 2. Fetch and find stale branches

```
git -C <repo> fetch --prune origin
git -C <repo> branch -vv
```

A worktree is a candidate only when its branch's upstream is `gone` (the remote branch was deleted, typically by the merge).
Worktrees whose upstream still exists (open PRs, shared branches) are kept.
Worktrees on branches with no upstream at all were never pushed, so there is no PR to verify: report them as skipped.

### 3. Verify merge state against GitHub

For each candidate branch, list merged PRs from that head. `ghx pr list` does not expose `headRefOid`, so use `gh`:

```
gh pr list --state merged --head <branch> --json number,headRefOid,mergedAt
```

Compare the newest merged PR's `headRefOid` with the local tip (`git rev-parse <branch>`) and classify:

- **Merged (verified)**: a merged PR exists and its head SHA equals the local tip, so nothing was added to the branch after the merge. Safe to remove.
- **At risk**: no merged PR for that head, or the local tip differs from the PR head (commits after the merge). Keep the worktree and report why.
- **Unverifiable**: `gh` is unavailable or unauthenticated. Treat every candidate as at risk, say that verification was impossible, and stop before any deletion.

Gone upstream alone never proves the work shipped: a branch can be deleted on the remote while still holding unmerged commits.

### 4. Check each verified worktree for dirty state

```
git -C <worktree-path> status --porcelain
```

Classify each merged worktree as clean (removable) or dirty (removable only with `--force` or explicit approval).

### 5. Present the plan and confirm

| Worktree | Branch | PR | State | Action |
|---|---|---|---|---|
| `<path>` | `<branch>` | #42 | clean, merged | remove |
| `<path>` | `<branch>` | #17 | dirty, 3 changes | remove with `--force`, or skip |
| `<path>` | `<branch>` | none, or tip differs from PR head | at risk | keep |

Call out the at-risk rows explicitly so the decision is made with the merge state in view.
On `--dry-run`, print the table and stop.
Otherwise wait for the user's confirmation before deleting anything.

### 6. Remove confirmed worktrees and branches

```
git -C <repo> worktree remove <path>
git -C <repo> branch -D <branch>
git -C <repo> tag -d "prs/<pr-number>/review" 2>/dev/null || true
```

Add `--force` to `worktree remove` only for dirty worktrees the user explicitly approved.
Use `-D` and not `-d`: a squash or rebase merge makes `-d` refuse to delete a fully shipped branch.
The tag deletion cleans up the review checkpoint left by validate-pr, verify-pr, and review-pr (see `sdlc/references/shared.md`, Review checkpoint tags), which matters when the PR was merged from another machine or through the UI.
Then prune orphaned worktree metadata:

```
git -C <repo> worktree prune -v
```

### 7. Report

Summarize what was removed, what was kept and why, and anything skipped.

## Output Format

```
Pruned N worktrees in <repo>:

| Worktree | Branch | PR | Result |
|---|---|---|---|
| <path> | <branch> | #42 | removed (clean, merged) |
| <path> | <branch> | #17 | removed (dirty, force approved) |
| <path> | <branch> | at risk | kept (tip differs from PR #9 head) |
| <path> | <branch> | none | skipped (never pushed) |

Branches deleted: <branch>, <branch>
Review tags deleted: prs/42/review
```

If everything was already clean, report "nothing to prune" with the count of worktrees inspected.

## Example Usage

**Scenario 1: Routine cleanup after a batch of merges**
```
/prune-merged-worktrees
```
Three worktrees exist, two branches are `gone` upstream, both have merged PRs whose head SHAs match the local tips, both worktrees are clean. Present the table, get confirmation, remove both worktrees, delete both branches with `-D`, delete the `prs/<n>/review` tags, run `git worktree prune -v`.

**Scenario 2: Dirty worktree on a merged branch**
```
/prune-merged-worktrees --force
```
PR #17 is merged but the worktree holds 3 uncommitted files. With `--force` the worktree is removed after the user confirms the summary table; without `--force` it would be reported and skipped.

**Scenario 3: Squash-merged branch that git thinks is unmerged**
```
/prune-merged-worktrees
```
`git branch -d` would refuse and `git rev-list main..<branch>` shows commits, because the squash merge created a new SHA. `gh pr list --state merged --head <branch>` finds merged PR #23 with `headRefOid` equal to the local tip, so the branch is classified merged (verified) and pruned.

**Scenario 4: Commits added after the merge**
```
/prune-merged-worktrees
```
PR #9 is merged, but the local tip differs from the PR head: someone committed to the branch after the merge. The worktree is classified at risk, kept, and surfaced in the report for a human decision.

## Useful Commands Reference

| Command | Description |
|---|---|
| `git worktree list --porcelain` | List worktrees with their branches |
| `git fetch --prune origin` | Refresh remote refs and drop deleted branches |
| `gh pr list --state merged --head <branch> --json number,headRefOid,mergedAt` | Find merged PRs for a head branch |
| `git worktree remove <path>` | Remove a worktree (`--force` for dirty ones) |
| `git branch -D <branch>` | Delete a local branch whose merge was squashed |
| `git tag -d "prs/<pr-number>/review"` | Delete the review checkpoint tag after merging |
| `git worktree prune -v` | Remove orphaned worktree metadata |

Attribution

tomzxtomzx
View sourceSee grades on GitHubMore from tomzx →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

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 (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Caveman Review

Ultra-compressed code review comments. Cuts noise from PR feedback while preserving the actionable signal. Each comment is one line: location, problem, fix. Use when user says "review this PR", "code review", "review the diff", "/review", or invokes /caveman-review. Auto-triggers when reviewing pull requests.

1100021 votes

Caveman Commit

Ultra-compressed commit message generator. Cuts noise from commit messages while preserving intent and reasoning. Conventional Commits format. Subject ≤50 chars, body only when "why" isn't obvious. Use when user says "write a commit", "commit message", "generate commit", "/commit", or invokes /caveman-commit. Auto-triggers when staging changes.

1100021 votes

Verification Loop

一个全面的 Claude Code 会话验证系统。

2456590 votes

Django Verification

Verification loop for Django projects: migrations, linting, tests with coverage, security scans, and deployment readiness checks before release or PR.

2456590 votes

Springboot Verification

Verification loop for Spring Boot projects: build, static analysis, tests with coverage, security scans, and diff review before release or PR.

2456590 votes
View all in code-quality →