Clean up stale git branches safely.
deadbranch helps you identify and remove old, unused git branches that clutter your repository. It's designed to be safe by default — protecting important branches and requiring explicit confirmation before any deletion.

main, master, develop, staging, or productionwip/* and draft/* branchescurl -sSf https://raw.githubusercontent.com/armgabrielyan/deadbranch/main/install.sh | sh
brew install armgabrielyan/tap/deadbranch
# Install globally
npm install -g deadbranch
# Or run directly
npx deadbranch list
cargo install deadbranch
Download pre-built binaries from the GitHub Releases page.
| Platform | Architecture | Download |
|---|---|---|
| Linux | x86_64 (glibc) | deadbranch-VERSION-x86_64-unknown-linux-gnu.tar.gz |
| Linux | x86_64 (musl/static) | deadbranch-VERSION-x86_64-unknown-linux-musl.tar.gz |
| Linux | ARM64 | deadbranch-VERSION-aarch64-unknown-linux-gnu.tar.gz |
| macOS | Intel | deadbranch-VERSION-x86_64-apple-darwin.tar.gz |
| macOS | Apple Silicon | deadbranch-VERSION-aarch64-apple-darwin.tar.gz |
| Windows | x86_64 | deadbranch-VERSION-x86_64-pc-windows-msvc.zip |
git clone https://github.com/armgabrielyan/deadbranch
cd deadbranch
cargo build --release
# Binary will be at target/release/deadbranch
deadbranch can generate tab-completion scripts for bash, zsh, and fish.
mkdir -p ~/.local/share/bash-completion/completions
deadbranch completions bash > ~/.local/share/bash-completion/completions/deadbranch
Requires bash-completion 2.x to be active. On macOS without Homebrew's bash, source the file manually in ~/.bash_profile:
source ~/.local/share/bash-completion/completions/deadbranch
mkdir -p ~/.zfunc
deadbranch completions zsh > ~/.zfunc/_deadbranch
Then add the following to your ~/.zshrc before the compinit call (or add it if you don't have one):
fpath=(~/.zfunc $fpath)
autoload -Uz compinit && compinit
Reload your shell or run exec zsh to activate.
mkdir -p ~/.config/fish/completions
deadbranch completions fish > ~/.config/fish/completions/deadbranch.fish
Fish auto-loads completions from this directory — no extra configuration needed.
# List all stale branches (older than 30 days)
deadbranch list
# List branches older than 60 days
deadbranch list --days 60
# Preview what would be deleted
deadbranch clean --dry-run
# Delete merged stale branches (with confirmation)
deadbranch clean
# Delete only local branches
deadbranch clean --local
# Show branch health overview
deadbranch stats

deadbranch list [OPTIONS]
| Option | Description |
|---|---|
-d, --days <N> |
Only show branches older than N days (default: 30) |
--local |
Only show local branches |
--remote |
Only show remote branches |
--merged |
Only show merged branches |
Example output:
ℹ Using 'main' as the default branch for merge detection
Local Branches:
┌────┬──────────────────────┬─────────┬────────┬───────┬──────────────┬──────────────┐
│ # │ Branch │ Age │ Status │ Type │ Last Commit │ Author │
├────┼──────────────────────┼─────────┼────────┼───────┼──────────────┼──────────────┤
│ 1 │ feature/old-api │ 154d │ merged │ local │ 2024-09-01 │ Jane Doe │
│ 2 │ bugfix/header-issue │ 89d │ merged │ local │ 2024-11-03 │ John Smith │
└────┴──────────────────────┴─────────┴────────┴───────┴──────────────┴──────────────┘
Remote Branches:
┌────┬─────────────────────────────────┬─────────┬────────┬────────┬──────────────┬──────────────┐
│ # │ Branch │ Age │ Status │ Type │ Last Commit │ Author │
├────┼─────────────────────────────────┼─────────┼────────┼────────┼──────────────┼──────────────┤
│ 1 │ origin/feature/deprecated │ 203d │ merged │ remote │ 2024-07-15 │ Jane Doe │
└────┴─────────────────────────────────┴─────────┴────────┴────────┴──────────────┴──────────────┘

deadbranch clean [OPTIONS]
| Option | Description |
|---|---|
-d, --days <N> |
Only delete branches older than N days (default: 30) |
--merged |
Only delete merged branches (this is the default) |
--force |
Force delete unmerged branches (dangerous!) |
--dry-run |
Show what would be deleted without doing it |
--local |
Only delete local branches |
--remote |
Only delete remote branches |
-y, --yes |
Skip confirmation prompts (useful for scripts) |
Safety features:
- Only deletes merged branches by default
- Requires --force to delete unmerged branches
- Shows confirmation prompt before deletion
- Extra confirmation for remote branches
- Creates backup file with branch SHAs
Example:
$ deadbranch clean
Local Branches to Delete:
┌────┬──────────────────────┬─────────┬────────┬───────┬──────────────┬──────────────┐
│ # │ Branch │ Age │ Status │ Type │ Last Commit │ Author │
├────┼──────────────────────┼─────────┼────────┼───────┼──────────────┼──────────────┤
│ 1 │ feature/old-api │ 154d │ merged │ local │ 2024-09-01 │ Jane Doe │
│ 2 │ bugfix/header-issue │ 89d │ merged │ local │ 2024-11-03 │ John Smith │
└────┴──────────────────────┴─────────┴────────┴───────┴──────────────┴──────────────┘
Delete 2 local branches? [y/N] y
Deleting local branches...
✓ feature/old-api
✓ bugfix/header-issue
✓ Deleted 2 local branches
↪ Backup: ~/.deadbranch/backups/my-repo/backup-20250201-143022.txt

Open a full-screen TUI for browsing, filtering, and selecting branches to delete:
deadbranch clean -i [OPTIONS]
| Option | Description |
|---|---|
-i, --interactive |
Open interactive TUI for branch selection |
-d, --days <N> |
Pre-filter to branches older than N days |
--merged |
Start with merged-only filter active |
--force |
Unlock unmerged branches for selection |
--local |
Start with local-only filter active |
--remote |
Start with remote-only filter active |
Key bindings:
| Key | Action |
|---|---|
j/↓, k/↑ |
Navigate down/up |
gg, G |
Jump to top/bottom |
Ctrl+d/Ctrl+u |
Half-page down/up |
Ctrl+f/Ctrl+b |
Full-page down/up |
| Mouse scroll | Scroll up/down |
Space |
Toggle selection |
V |
Visual range select (Vim-style) |
a |
Select all merged |
A |
Select all (requires --force) |
n |
Deselect all |
i |
Invert selection |
d |
Delete selected |
/ |
Fuzzy search by branch name |
s |
Cycle sort (age → branch → status → type → date → author) |
S |
Reverse sort direction |
m |
Toggle merged-only filter |
l |
Toggle local-only filter |
R |
Toggle remote-only filter |
? |
Help |
q/Esc |
Quit |
TUI features:
gg/G jump, Ctrl+d/Ctrl+u page scrolling, relative line numbersV to anchor, move cursor to extend range, Space to toggle/ opens search with matched characters highlightedyes for risky ones (unmerged/remote)Note: -i cannot be combined with -y (skip confirmation) or --dry-run.
Preview deletions without making any changes:
$ deadbranch clean --dry-run
Local Branches to Delete:
┌────┬──────────────────────┬─────────┬────────┬───────┬──────────────┬──────────────┐
│ # │ Branch │ Age │ Status │ Type │ Last Commit │ Author │
├────┼──────────────────────┼─────────┼────────┼───────┼──────────────┼──────────────┤
│ 1 │ feature/old-api │ 154d │ merged │ local │ 2024-09-01 │ Jane Doe │
└────┴──────────────────────┴─────────┴────────┴───────┴──────────────┴──────────────┘
[DRY RUN] Commands that would be executed:
git branch -d feature/old-api
No branches were actually deleted.

deadbranch stores its configuration in ~/.deadbranch/config.toml.
# Show current configuration
deadbranch config show
# Set default age threshold
deadbranch config set days 45
# Set default branch for merge detection
deadbranch config set default-branch main
# Set protected branches
deadbranch config set protected-branches main master develop
# Set exclude patterns
deadbranch config set exclude-patterns "wip/*" "draft/*" "temp/*"
# Open config in your editor
deadbranch config edit
# Reset to defaults
deadbranch config reset
Default configuration:
[general]
default_days = 30
[branches]
protected = ["main", "master", "develop", "staging", "production"]
exclude_patterns = ["wip/*", "draft/*", "*/wip", "*/draft"]
| Key | Aliases | Description |
|---|---|---|
days |
default-days, general.default-days |
Default age threshold in days |
default-branch |
branches.default-branch |
Branch used for merge detection (auto-detected if unset) |
protected-branches |
branches.protected |
Branches that are never deleted |
exclude-patterns |
branches.exclude-patterns |
Glob patterns for branches to skip |

Every deadbranch clean run automatically creates a backup. Use deadbranch backup to manage those backups.
# Show a summary of all repositories with backups
deadbranch backup list
# Show backups for the current repository
deadbranch backup list --current
# Show backups for a specific repository
deadbranch backup list --repo my-repo
# Restore from the most recent backup
deadbranch backup restore feature/old-api
# Restore from a specific backup file
deadbranch backup restore feature/old-api --from backup-20250201-143022.txt
# Restore with a different name
deadbranch backup restore feature/old-api --as feature/recovered
# Overwrite an existing branch
deadbranch backup restore feature/old-api --force
# Show storage usage per repository and overall
deadbranch backup stats
```bash
d
$ claude mcp add deadbranch \
-- python -m otcore.mcp_server <graph>