Audit your local git branches — spot stale, merged, and forgotten branches in a single table
You open a repo you haven't touched in a month. Run git branch. Get this:
chore/bump-deps
feat/auth-refactor
feat/dark-mode
feat/old-experiment
* main
release/v2.1
wip/that-thing-from-last-quarter
Which of these are merged? Which are three months old and blocked on a review that never happened?
git branch -v adds a commit hash and message — it doesn't answer the question you actually care about.
Branch sprawl is invisible until it isn't. You delete the wrong one, lose two days of work, or ship a stale branch to review because you forgot it diverged 47 commits ago.
cuscus runs one command and prints a table that answers all of it at once:
$ cuscus
BRANCH AGE AHEAD BEHIND STATUS
------------------------ -------- ----- ------ -------
* main just now 0 0 CURRENT
feat/auth-refactor 3d ago 2 0 FRESH
feat/dark-mode 6d ago 5 1 FRESH
release/v2.1 18d ago 0 4 STALE
feat/old-experiment 1mo ago 1 19 STALE
chore/bump-deps 2mo ago 0 0 MERGED
wip/that-thing 3mo ago 3 0 STALE
Named after the cuscus — a marsupial that clings tightly to tree branches. Fitting for a tool that clings to your git tree and refuses to let branches get away from you.
$ cd ~/code/big-monorepo
$ cuscus
BRANCH AGE AHEAD BEHIND STATUS
--------------------------- --------- ----- ------ -------
* main just now 0 0 CURRENT
feat/auth-refactor 3d ago 2 0 FRESH
feat/dark-mode 6d ago 5 1 FRESH
release/v2.1 18d ago 0 4 STALE
feat/old-experiment 1mo ago 1 19 STALE
chore/bump-deps 2mo ago 0 0 MERGED
wip/that-thing 3mo ago 3 0 STALE
$ cuscus --clean | sh # only after you've reviewed
Deleted branch chore/bump-deps (was a1b2c3d).
Deleted branch release/v2.1 (was e4f5g6h).
go install github.com/iamkorun/cuscus/cmd/cuscus@latest
cd your-repo/
cuscusgo install github.com/iamkorun/cuscus/cmd/cuscus@latestRequires Go 1.21+. The binary lands in $(go env GOPATH)/bin.
Download a binary for your platform from the Releases page. No runtime required — single static binary.
| Platform | Architecture | File |
|---|---|---|
| Linux | x86_64 | cuscus_linux_amd64.tar.gz |
| macOS | Apple Silicon | cuscus_darwin_arm64.tar.gz |
| macOS | Intel | cuscus_darwin_amd64.tar.gz |
| Windows | x86_64 | cuscus_windows_amd64.zip |
# Coming soon
brew install iamkorun/tap/cuscuscuscusBRANCH AGE AHEAD BEHIND STATUS
------------------------ -------- ----- ------ -------
* main just now 0 0 CURRENT
feat/auth-refactor 3d ago 2 0 FRESH
release/v2.1 18d ago 0 4 STALE
chore/bump-deps 2mo ago 0 0 MERGED
- CURRENT — the branch you are on right now
- FRESH — active, within the stale threshold
- STALE — no commits within the threshold (default: 14 days)
- MERGED — fully merged into the base branch
cuscus --days 30Marks branches with no activity in the last 30 days as STALE instead of the default 14.
cuscus --base developAhead/behind counts and merged detection use develop instead of auto-detected main/master.
cuscus --cleangit branch -d chore/bump-deps
git branch -D release/v2.1 # STALE — force delete
git branch -D feat/old-experiment # STALE — force delete
⚠️ Warning:--cleanuses-D(force delete) for STALE branches.STALE branches are not fully merged into your base branch. Running the output of
--cleanthroughshwill permanently delete unmerged commits for any STALE branch listed.Always review the output of
cuscus --cleanbefore piping it:# Review first: cuscus --clean # Then pipe only if you are sure: cuscus --clean | shcuscus itself never deletes anything. It only prints commands. You decide what runs.
cuscus --json | jq '.[] | select(.status == "STALE") | .branch.name'"release/v2.1"
"feat/old-experiment"
"wip/that-thing"cuscus -C /path/to/other-repo| Flag | Short | Default | Description |
|---|---|---|---|
--days N |
-d |
14 |
Stale threshold in days |
--base BRANCH |
-b |
auto | Base branch for ahead/behind and merged detection |
--clean |
false |
Print git branch -d/-D commands for merged/stale branches |
|
--json |
false |
Machine-readable JSON output (no ANSI codes) | |
--dir PATH |
-C |
. |
Run against a specific repo directory |
--verbose |
-v |
false |
Extra output (e.g. detected base branch) |
--quiet |
-q |
false |
Suppress non-essential output |
--version |
Print version and exit | ||
--help |
-h |
Print help |
- One-glance table — branch name, age, ahead/behind your base, and health status in a single view
- Auto base detection — finds
main,master, or your origin's HEAD without configuration - Safe cleanup —
--cleanprints shell commands, never executes them; you pipe only when ready - JSON output — pipe to
jqfor scripting, CI gates, or custom dashboards - Color-aware — auto-disables ANSI when piped or when
NO_COLORis set - Zero config — run from any git repo, no setup required
- Single static binary — no runtime, no dependencies, no Python/Node bootstrap
cuscus is designed to be scriptable.
| Code | Meaning |
|---|---|
0 |
Success — even if there are stale or merged branches |
1 |
Error — not in a git repo, invalid flags, or git failure |
The presence of stale branches is not an error: it's the answer to a question you asked. If you want CI to fail when stale branches accumulate, parse the JSON:
# Fail if any branch is older than 30 days
if cuscus --days 30 --json | jq -e '. | any(.status == "STALE")' >/dev/null; then
echo "::error::Stale branches detected"
exit 1
fi| Need | git branch -v |
git for-each-ref |
cuscus |
|---|---|---|---|
| List branches | yes | yes | yes |
| Last-commit age in human form | no | manual format | yes |
| Ahead/behind vs base | no | no | yes |
| Merged-into-base detection | no | no | yes |
| Color-coded health status | no | no | yes |
| Bulk-delete commands (review first) | no | no | --clean |
| Machine-readable output for scripts | no | yes (raw) | --json |
The cuscus is a marsupial native to the forests of Papua New Guinea and northern Australia. It spends its entire life in the tree canopy, gripping branches with its prehensile tail and curved claws — never losing track of where it is in the tree.
That's the tool: something that clings to your git tree, accounts for every branch, and notices when one has been dead on the vine for too long.
Contributions are welcome. Please open an issue first to discuss the change.
git clone https://github.com/iamkorun/cuscus.git
cd cuscus
go test ./...