List and clean up Git worktrees.
Adds age and pull request state to git worktree list. Review cleanup before removal.
Install with Homebrew
brew install filipgutica/tap/wtree Homebrew installs Node.js. Optional: gh for PR state, fzf for wtree go. Install Homebrew if needed.
- Runs on
- macOS and Linux
- Needs
- Git and Node.js 20+
- Source
- filipgutica/wtree
Current wtree UI; demo repository and sample pull requests.
Browse
wtree — demo-api · 5 worktrees · 2 removable overall Rows 1–5 of 5 · s sort: age · p PR: all · filter: none · age: commit delete branches: off · 0 selected o open · ? help · q quit · Space select · Enter details · / filter · n new BRANCH AGE PR FLAGS PATH ▏ [-] main 2d - M@ ~/code/demo-api [-] spike/flink-cdc 8mo - * ~/code/demo…link-spike [ ] chore/bump-deps 5mo closed #4390 ~/code/demo…-bump-deps [ ] feat/usage-charts 3mo merged #4502 · [-] fix/token-refresh 4h open #4821 * · ╭──────────────────────────────────────────────────────────────────────────────╮ │ main 2d old │ │ path ~/code/demo-api │ │ PR none │ │ state clean · unpushed unknown │ │ remove blocked: main worktree; you are inside it │ │ head 0671a0fbdd8378fe8a2beedbe63440e0a7abfe4d │ │ │ ╰──────────────────────────────────────────────────────────────────────────────╯ [-] protected · M main · @ current · * dirty · path: · default blocked: main worktree; you are inside it · main — ~/code/demo-api
wtree ui Shortcuts sit above the table, with focused worktree details below it. [-] marks a worktree that cannot be removed.
Select
wtree — demo-api · 5 worktrees · 2 removable overall Rows 1–5 of 5 · s sort: age · p PR: all · filter: none · age: commit delete branches: off · 2 selected o open · ? help · q quit · d review 2 · Space select · Enter details · / filter BRANCH AGE PR FLAGS PATH [-] main 2d - M@ ~/code/demo-api [-] spike/flink-cdc 8mo - * ~/code/demo…link-spike [x] chore/bump-deps 5mo closed #4390 ~/code/demo…-bump-deps ▏ [x] feat/usage-charts 3mo merged #4502 · [-] fix/token-refresh 4h open #4821 * · ╭──────────────────────────────────────────────────────────────────────────────╮ │ feat/usage-charts 3mo old │ │ path ~/.wtree/demo-api/feat/usage-charts │ │ PR merged #4502 · Usage charts │ │ state clean · unpushed unknown │ │ remove available after review │ │ head c6d048ec51635e797cb1e0b211a28c18f14a3b18 │ │ │ ╰──────────────────────────────────────────────────────────────────────────────╯ [x] selected · M main · @ current · * dirty · path: · default selected ~/.wtree/demo-api/feat/usage-charts
SpaceSpace selects a removable row. The selection count stays above the table, alongside d to review it.
Review
wtree — confirmation
y remove 2 Esc cancel b branches
DELETE WORKTREES — also delete branches: NO
will remove: 2
REMOVE ~/.wtree/demo-api/feat/usage-charts (3mo, merged)
REMOVE ~/code/demo-api-bump-deps (5mo, closed)
skipped: 0dThe plan lists what will go. Nothing is removed until you press y. b also deletes the branches.
List
BRANCH AGE PR FLAGS PATH main 2d - M@ ~/code/demo-api spike/flink-cdc 8mo - * ~/code/demo-api-flink-spike chore/bump-deps 5mo closed #4390 ~/code/demo-api-bump-deps feat/usage-charts 3mo merged #4502 · fix/token-refresh 4h open #4821 * · flags: M main @ current * dirty ↑ unpushed L locked P prunable d detached ✓ in default branch path: · in ~/.wtree/<repo>/<branch> 2 worktrees have merged/closed PRs — run wtree clean --done
wtreeThe same data as a plain table. It ends with a hint when there is something to clean up.
Dry run
remove (2): BRANCH AGE PR PATH - chore/bump-deps 5mo closed ~/code/demo-api-bump-deps - feat/usage-charts 3mo merged ~/.wtree/demo-api/feat/usage-charts dry run. drop --dry-run to remove them.
wtree clean --done --dry-runPrints the cleanup plan for merged and closed pull requests. A dry run removes nothing.
Commands
Uses the current repository.
wtreeList: main first, then oldest.
wtree uiBrowse, filter, select, and remove worktrees.
wtree clean --done --dry-runPreview worktree removal for merged or closed PRs.
wtree new feat/exampleCreate a branch's worktree or print its existing path.
wtree goPick a worktree or branch; print its path.
wtree --sizeMeasure disk usage with
du; off by default.wtree --jsonList as JSON.
Keys in wtree ui
? shows all shortcuts.
- Space
Select; blocked worktrees explain why they refuse.
- Enter
Full branch and path.
- /
Filter by branch or path.
- d
Review selected removals, then confirm.
- o
Exit; print the focused worktree's path.
- n
Create a branch's worktree.
Change directory
The wt wrapper changes your shell's directory.
eval "$(wtree shell-init zsh)"Add to
~/.zshrc; usebashfor~/.bashrc.wt goPick and change directory. Also:
wt new,wt path,wt ui.
Good to know
Cleanup: review the plan, then confirm. --yes skips confirmation; --dry-run never removes. Branch deletion requires --delete-branch.
Protected: main and current worktrees are never removed. Dirty, unpushed, or locked worktrees require --force.
Unknown PR state stops filtered cleanup. Missing, signed-out, or offline gh makes wtree clean --done fail, rather than report no matches.
Without a terminal: clean, rm, and prune print the plan and exit 2 unless given --dry-run or --yes. wtree ui exits 2.