Install
$ agentstack add skill-marcoskichel-empire-worktree-cleanup ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Worktree Cleanup
Scan for stale worktrees and orphaned branches, then let the user decide what to clean up. This is the batch housekeeping counterpart to /empire-git:worktree-close (which handles one worktree at a time).
User input: $ARGUMENTS
If --dry-run is in the arguments, report what would be cleaned up without making any changes.
If --days N is in the arguments (e.g. --days 14), use N as the staleness threshold. Otherwise default to 7 days. Note: worktree-list uses a softer 3-day threshold (informational warning); cleanup uses 7 days because removal is the action and the longer window reduces false positives.
Step 1 — Inventory worktrees
git worktree list --porcelain
For each worktree (excluding the main working tree), gather:
- Branch name
- Path on disk — verify the directory still exists
- Last commit date:
``bash git -C "" log -1 --format="%ct" 2>/dev/null ``
- Dirty/clean status:
``bash git -C "" status --porcelain 2>/dev/null | wc -l | tr -d ' ' ``
Classify each worktree:
| Status | Criteria | | ----------- | ------------------------------------------------------------------------------ | | Stale | Last commit more than --days (default 7) ago and clean (no uncommitted work) | | Missing | Directory no longer exists on disk (stale git metadata) | | Active | Recent commits or has uncommitted changes |
Step 2 — Find stale local branches
First, prune remote-tracking references so git knows which remote branches are gone:
git fetch --prune
Determine which branches must never be flagged as orphans:
# The repo's default branch (main, master, develop, trunk, …) — detected, not assumed
DEFAULT_BRANCH=$(git symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null | sed 's|^origin/||')
# Fallback 1: check well-known branch names
[ -z "$DEFAULT_BRANCH" ] && DEFAULT_BRANCH=$(git for-each-ref --format='%(refname:short)' refs/heads/main refs/heads/master refs/heads/trunk refs/heads/develop | head -n1)
# Fallback 2: use current HEAD (guaranteed as long as we are in a git repo)
[ -z "$DEFAULT_BRANCH" ] && DEFAULT_BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null)
# Fallback 3: pick the most-recently-committed local branch
[ -z "$DEFAULT_BRANCH" ] && DEFAULT_BRANCH=$(git for-each-ref --sort=-committerdate --format='%(refname:short)' refs/heads | head -n1)
# Guard: if DEFAULT_BRANCH is still empty we cannot safely run merged checks
if [ -z "$DEFAULT_BRANCH" ]; then
echo "Warning: could not determine default branch — merged-check classification will be skipped."
fi
# The branch currently checked out in the main working tree
CURRENT_BRANCH=$(git -C "$(git rev-parse --show-toplevel)" branch --show-current)
# Branches checked out in any worktree (these are "in use" — git won't let you delete them anyway)
git worktree list --porcelain | awk '/^branch / { sub("refs/heads/", "", $2); print $2 }'
Then list candidate local branches, excluding the default branch, the current branch, and any branch that has a worktree:
git branch --format='%(refname:short)'
Filter that list in your head (or with grep -v) against $DEFAULT_BRANCH, $CURRENT_BRANCH, and the worktree branches above. Do not hardcode main|master — many repos use develop, trunk, or custom default branches, and the user may currently be checked out on a branch that isn't the default.
For each remaining local branch, check:
- Is it merged into the default branch?
``bash git branch --merged "$DEFAULT_BRANCH" | grep -w "" ``
- Was its remote deleted? (common after merging a PR on GitHub)
``bash git branch -vv --format='%(refname:short) %(upstream:track)' | grep '\[gone\]' ` The [gone]` marker means the branch once tracked a remote that no longer exists — a strong signal the PR was merged and the remote branch deleted.
- Does it have an open PR? (if
ghis available)
``bash gh pr list --head "" --state open --json number 2>/dev/null ``
Classify:
| Status | Criteria | | ------------------- | --------------------------------------------------------------------------------- | | Remote deleted | Tracked a remote that's gone (PR likely merged and branch deleted on GitHub) | | Merged orphan | Merged into $DEFAULT_BRANCH, no worktree, no remote — safe to delete | | Unmerged orphan | Not merged into $DEFAULT_BRANCH, no worktree, no remote — may be abandoned work | | Has open PR | Skip — still in use |
Step 3 — Present findings
Show a summary grouped by action:
Worktree Cleanup Report
═══════════════════════
Stale worktrees (no commits in 7+ days, clean):
feat/old-experiment .claude/worktrees/feat-old-experiment-1a2b3c4d 12d ago
fix/typo-header .claude/worktrees/fix-typo-header-5e6f7a8b 8d ago
Missing worktrees (directory gone, metadata remains):
feat/deleted-thing (path no longer exists)
Branches with deleted remote (PR likely merged on GitHub):
feat/auth-refactor remote gone — safe to delete locally
fix/login-bug remote gone — safe to delete locally
Orphaned branches (no worktree, no remote):
feat/abandoned-idea merged into $DEFAULT_BRANCH — safe to delete
fix/half-done NOT merged — review before deleting
Active worktrees (no action needed):
feat/current-work .claude/worktrees/feat-current-work-9c0d1e2f 2h ago
If --dry-run, stop here.
Step 4 — Let the user choose
Present cleanup options as a checklist — the user picks what to clean up:
- Prune missing worktrees — run
git worktree pruneto clear stale metadata - Close stale worktrees — remove worktree directories for stale entries
- Delete branches with deleted remote —
git branch -dfor each (their PRs were merged) - Delete merged orphan branches —
git branch -dfor each - Skip unmerged orphans — list them but don't touch (inform the user of
git branch -Dif they want to force)
Ask which of these the user wants to proceed with. Don't auto-execute anything — the user confirms first.
Step 5 — Execute
For each action the user approved:
# Prune stale metadata
git worktree prune
# Close stale worktrees
git worktree remove ""
# Delete merged orphan branches
git branch -d ""
Print a summary of what was done:
Cleanup complete:
2 stale worktrees removed
1 missing worktree pruned
3 merged orphan branches deleted
1 unmerged orphan branch kept (fix/half-done)
After the cleanup actions complete, prune the session registry so it forgets any worktree directories that were removed:
bash "${CLAUDE_PLUGIN_ROOT}/scripts/worktree-registry.sh" prune
If the call fails, print a warning and continue — registry hygiene is best-effort.
Guiding principles
This is a housekeeping tool, not a destructive one. The default posture is conservative — show what could be cleaned up, let the user decide. The --dry-run flag makes it completely safe to explore.
Merged branches are safe to delete. Their commits live in the target branch. Unmerged branches might contain work the user forgot about — flag them but don't delete without explicit confirmation.
Use git worktree remove, not rm -rf. And use git branch -d (safe delete), not -D. If something refuses to delete, that's useful information — surface it.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: marcoskichel
- Source: marcoskichel/empire
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.