deadbranch
March 14, 2026 Β· View on GitHub
Clean up stale git branches safely.
Table of Contents
- Demo
- Features
- Installation
- Shell Completions
- Quick Start
- Usage
- Safety Features
- Restoring Deleted Branches
- Pattern Matching
- Requirements
- Roadmap
- License
- Contributing
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.
Demo

β¨ Features
- π List stale branches β Find branches older than N days (default: 30)
- π Safe deletion β Only deletes merged branches by default
- π‘οΈ Protected branches β Never touches
main,master,develop,staging, orproduction - π§ WIP detection β Automatically excludes
wip/*anddraft/*branches - πΎ Backup creation β Saves deleted branch SHAs for easy restoration
- ποΈ Dry-run mode β Preview what would be deleted without making changes
- π Local & remote β Works with both local and remote branches
- π₯οΈ Interactive TUI mode β Full-screen TUI with Vim navigation, fuzzy search, visual range selection, and 6-column sorting
π¦ Installation
β‘ Quick Install (macOS/Linux)
curl -sSf https://raw.githubusercontent.com/armgabrielyan/deadbranch/main/install.sh | sh
πΊ Homebrew (macOS/Linux)
brew install armgabrielyan/tap/deadbranch
π¦ npm/npx
# Install globally
npm install -g deadbranch
# Or run directly
npx deadbranch list
π¦ Cargo (from source)
cargo install deadbranch
β¬οΈ Manual Download
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 |
π¨ Build from Source
git clone https://github.com/armgabrielyan/deadbranch
cd deadbranch
cargo build --release
# Binary will be at target/release/deadbranch
π Shell Completions
deadbranch can generate tab-completion scripts for bash, zsh, and fish.
Bash
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
Zsh
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.
Fish
mkdir -p ~/.config/fish/completions
deadbranch completions fish > ~/.config/fish/completions/deadbranch.fish
Fish auto-loads completions from this directory β no extra configuration needed.
π Quick Start
# 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
π οΈ Usage
π List Stale Branches

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 β
ββββββ΄ββββββββββββββββββββββββββββββββββ΄ββββββββββ΄βββββββββ΄βββββββββ΄βββββββββββββββ΄βββββββββββββββ
ποΈ Delete Stale Branches

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
--forceto 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
π₯οΈ Interactive Mode

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:
- Vim-style navigation β
gg/Gjump,Ctrl+d/Ctrl+upage scrolling, relative line numbers - Visual range selection β Press
Vto anchor, move cursor to extend range,Spaceto toggle - Fuzzy search β
/opens search with matched characters highlighted - Age coloring β Green (<30d), yellow (31β90d), red (>90d)
- Sections β Merged and unmerged branches are visually grouped with section headers
- Snap dissolution β Thanos-style particle animation on deletion with a live progress gauge; branches are deleted in the background while the animation plays
- Smart confirmation β Simple confirm for safe deletions, typed
yesfor risky ones (unmerged/remote)
Note: -i cannot be combined with -y (skip confirmation) or --dry-run.
π Dry Run Mode
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.
βοΈ Configuration

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"]
Config keys
| 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 |
πΎ Backup Management

Every deadbranch clean run automatically creates a backup. Use deadbranch backup to manage those backups.
List 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 a deleted branch
# 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
Backup statistics
# Show storage usage per repository and overall
deadbranch backup stats
Clean up old backups
# Keep the 10 most recent backups for the current repo (default)
deadbranch backup clean --current
# Keep only the 3 most recent backups
deadbranch backup clean --current --keep 3
# Preview what would be removed
deadbranch backup clean --current --dry-run
# Skip confirmation prompt
deadbranch backup clean --current --yes
# Clean backups for a specific repository by name
deadbranch backup clean --repo my-repo
π Branch Statistics

Get a health overview of all branches in your repository:
deadbranch stats [OPTIONS]
| Option | Description |
|---|---|
-d, --days <N> | Age threshold for "stale" classification (default: from config or 30) |
Example output:
βΉ Using 'main' as the default branch for merge detection
Repository Statistics:
ββββββββββββββββββ¬ββββββββ¬ββββββββ¬βββββββββ
β Category β Total β Local β Remote β
ββββββββββββββββββΌββββββββΌββββββββΌβββββββββ€
β All branches β 12 β 7 β 5 β
β Merged β 8 β 5 β 3 β
β Unmerged β 4 β 2 β 2 β
β Stale (>30d) β 6 β 4 β 2 β
β Safe to delete β 5 β 3 β 2 β
ββββββββββββββββββ΄ββββββββ΄ββββββββ΄βββββββββ
Age Distribution:
βββββββββββββββ¬ββββββββ¬βββββββββ
β Age Range β Count β Status β
βββββββββββββββΌββββββββΌβββββββββ€
β < 7 days β 2 β fresh β
β 7β30 days β 4 β fresh β
β 30β90 days β 3 β stale β
β > 90 days β 3 β stale β
βββββββββββββββ΄ββββββββ΄βββββββββ
π‘ Run 'deadbranch clean' to remove 5 safe-to-delete branches
Stats cover all visible branches (respecting protected and exclude patterns) regardless of age, so --days only shifts the stale/safe-to-delete threshold β it doesn't hide branches.
π‘οΈ Safety Features
deadbranch is designed to prevent accidental data loss:
| Feature | Description |
|---|---|
| Merged-only default | Only deletes branches already merged to main/master |
| Protected branches | Never deletes main, master, develop, staging, production |
| Current branch | Never deletes the branch you're currently on |
| WIP detection | Excludes branches matching wip/*, draft/*, etc. |
| Confirmation prompts | Always asks before deleting |
| Remote warning | Extra confirmation for remote deletions |
| Backup files | Saves SHA of every deleted branch for restoration |
| Dry-run mode | Preview changes without risk |
β»οΈ Restoring Deleted Branches
Every deletion creates a backup file at ~/.deadbranch/backups/<repo>/backup-<timestamp>.txt.
The backup contains git commands to restore each branch:
# From the backup file:
git branch feature/old-api abc1234def5678
git branch bugfix/header-issue 987654fedcba
You can restore branches manually by running those commands, or use the deadbranch backup restore command.
π€ Pattern Matching
Exclude patterns support glob-style wildcards:
| Pattern | Matches |
|---|---|
wip/* | wip/experiment, wip/test |
*/draft | feature/draft, bugfix/draft |
feature/*/temp | feature/foo/temp, feature/bar/temp |
*test* | test, testing, my-test-branch |
π Requirements
- Git (installed and accessible in PATH)
- A git repository (run from within a repo)
πΊοΈ Roadmap
- π₯οΈ Interactive TUI mode
- π€
--only-mineflag for personal branches - π GitHub/GitLab PR detection
- π Multiple output formats (JSON, CSV)
- π Per-repo configuration
β Star History
π License
MIT License β see LICENSE for details.
π€ Contributing
Contributions are welcome! See CONTRIBUTING.md for development setup, commit message conventions, testing requirements, and how to submit a pull request.