Find the worktrees eating your disk. Remove only the ones Git can prove you no longer need.
- Dry-run means dry-run.
wtgcshows its working and changes nothing until you explicitly choose--yesor--interactive. - Conservative on purpose. Dirty, untracked, unmerged, locked, detached, primary, and ambiguous worktrees are kept.
- Scan more than one repository. Start at a common root and discover repositories with nested worktrees.
- The disk bill is itemised. See every worktree's status and size, plus the total space you could reclaim.
- Works in scripts. JSON output supports hooks and scheduled jobs without changing the cleanup rules.
One-worktree-per-task workflows are excellent at creating isolated checkouts and
terrible at reminding anyone to remove them. The audit that prompted wtgc
found 350+ registered worktrees across five repositories and more than 30 GB
tied up in directories whose branches had already landed.
Git already knows most of what is needed to clean this up; it just makes you
assemble the evidence yourself. wtgc does that boring part. It checks the
registered worktree, local default-branch ancestry, remote reachability, and
working-tree state before calling anything removable.
clean + merged locally + reachable remotely + not protected = eligible
Squash merges can be proven with explicit --provider github confirmation,
which binds the pull request to the exact branch SHA and mapped upstream.
For a live worktree, missing proof means it stays. False negatives waste disk;
false positives destroy work. Given that choice, wtgc leaves the worktree
alone. Live worktrees are removed through git worktree remove, never raw
rm -rf, and local branch deletion is a separate opt-in action.
Stale records are handled separately. If Git marks a missing worktree path as
prunable, wtgc may remove its registration with git worktree prune --expire=now; it does not delete a directory. The complete
safety contract documents every refusal and revalidation rule.
For unattended dry-run guidance, see the harness documentation.
Point wtgc at the directory containing your repositories:
wtgc clean --scan-root "$HOME/Projects"Running wtgc without arguments prints this usage and exits. Use the explicit
clean command when you want to start a scan; flags may also be supplied
without the command token for compatibility. The bare invocation never
recursively scans the directory where the shell happens to be running.
Every run is a dry-run unless you request a removal mode. It explains each decision without changing the filesystem. Abridged output:
PATH BRANCH CLASSIFICATION DIRTY ACTION SIZE RECLAIMED REASON
/Users/me/Projects/app-worktrees/42 feature/42 safe_to_remove clean would_remove 1.8 GiB 0 B clean branch tip is reachable from both the default branch and a remote-tracking ref
Summary:
dry run: true
repositories: 12
scanned: 38
safe: 4
removed: 0
potential reclaimable: 6.3 GiB
reclaimed: 0 B
When the preview looks right:
# Remove every worktree proven safe
wtgc clean --scan-root "$HOME/Projects" --yes
# Or confirm each action yourself
wtgc clean --scan-root "$HOME/Projects" --interactive
# Emit machine-readable inventory instead
wtgc clean --scan-root "$HOME/Projects" --jsonWorktree removal keeps the local branch. Add --delete-branch only when you
also intend to delete branches after their worktrees are safely removed.
Provider-confirmed squash candidates always retain their local branch, so an
interactive prompt states that outcome before removing the worktree.
Git commands have no deadline by default. For hooks and scheduled jobs, set
WTGC_GIT_TIMEOUT=2m (or another positive Go duration) to apply a deadline to
each Git command.
Install the latest stable release from the wtgc formula:
brew tap ben-ranford/tap
brew install wtgcFor development or an unreleased build, install directly with Go:
go install github.com/ben-ranford/wtgc/cmd/wtgc@latestRelease automation is configured to publish prebuilt archives for Linux, macOS,
and Windows on amd64 and arm64. Checksums and an SPDX SBOM will be published
beside them on GitHub Releases.
Stable releases also update the wtgc formula in
ben-ranford/tap.
GitHub records provenance as an artifact attestation. Verify a downloaded
archive with:
gh attestation verify PATH/TO/WTGC_ARCHIVE -R ben-ranford/wtgcSee GitHub's attestation verification guide for details.
Runtime requirements:
- Git
2.36+ - An unambiguous remote default branch, such as
origin/HEAD -> origin/main - Go
1.26.5+only when installing from source
- Why a worktree is kept or removed
- JSON inventory format
- Hooks and scheduled cleanup
- How wtgc is structured
Questions and feature ideas belong in GitHub Discussions. Concrete bugs and feature requests belong in issues.
If wtgc calls a worktree safe and you think it is wrong, that is the important
bug. Please report it with the Git state that produced the classification.
Contributions are welcome: start with CONTRIBUTING.md. Report suspected data-loss or command-execution vulnerabilities through the private process in SECURITY.md, not a public issue.
The support policy and Code of Conduct set expectations for help and participation.
wtgc was created by Ben Ranford and is
available under the MIT License.