Skip to content

wtm prune

Remove finished worktrees (merged, closed PR or gone) in one pass

Batch-remove worktrees whose work is done, reparenting any surviving children onto their nearest surviving ancestor (like clean --reparent-children). Whether work is "done" is read from GitHub via the gh CLI — never guessed from local commits — so squash- and rebase-merges are detected correctly. By default prune considers every finished worktree: merged PR, closed PR, or upstream branch gone. The reason flags restrict to specific categories — --merged (PR merged), --closed (PR closed unmerged), --gone (remote branch deleted).

--merged and --closed require the GitHub CLI (gh) to be installed and authenticated; without it they match nothing and prune prints a notice — only --gone still applies. gone-detection first fetches the worktrees' branches from origin, dropping the remote-tracking refs of those deleted there (pass --no-fetch to skip). Only branches with a worktree are read, on git and on GitHub: the remote-tracking refs of the other branches are left as they are.

On a TTY, matches are shown for review (unsafe ones unchecked), then a prune confirmation, then — like clean — a dedicated confirmation to reparent surviving children onto their nearest surviving ancestor (or leave them orphaned). The main checkout and base branch are always protected; the current worktree is removed and the shell redirected to the base repo. Like clean, worktrees that are locked, dirty, have unpushed commits, or have an open PR are unsafe and need --force. Use --yes to skip the prompts (required with --output json); non-interactively, children are left orphaned unless --reparent-children is passed. --dry-run previews without changing anything.

Like clean, prune gives back the data the removed worktrees carved out of shared services (--keep-data withholds it); when such a service is down, the form asks whether to start it and drop the data now, or keep it until the service next starts. --yes keeps it; --drop-data drops it, starting the services that are down.

Each worktree goes through clean's whole sequence — jobs stopped, hooks, removal, then its data — before the next one starts. The first that fails stops the prune: the ones before it are gone with their data, it and the ones after keep theirs, and the report (and the failed field of --output json) names where it stopped.

wtm prune [flags]
# Review every finished worktree, then confirm
wtm prune
# Only show what would go
wtm prune --dry-run
# Every worktree whose PR was merged, no prompts
wtm prune --merged --yes --reparent-children
--closed Restrict to worktrees whose PR was closed without merging (needs gh)
--drop-data Drop the removed worktrees' data now, starting the shared services that are down to do it
--dry-run Preview what would be pruned without removing anything
--force Lift safety refusals (locked/dirty/unpushed/open-PR): also remove unsafe worktrees; still asks to confirm unless --yes
--gone Restrict to worktrees whose upstream branch was deleted on the remote
-h, --help help for prune
--keep-data Keep the namespaces the removed worktrees carved out of shared services
--merged Restrict to worktrees whose PR was merged on GitHub (needs gh)
--no-fetch Skip the fetch of the worktrees' branches that gone-detection performs; use already-fetched state
--output string Output format: text or json (default "text")
--reparent-children Reparent orphaned child worktrees onto their nearest surviving ancestor (no prompt)
-y, --yes Skip all prompts; keep every match without the selection picker (use --force for unsafe worktrees)
-q, --quiet Silence human output; errors and the exit code are unaffected, and --output json still emits its document
  • wtm - Orchestrate git worktrees and team dev workflows from the terminal