A terminal-native, at-a-glance summary of a git repository: recent activity,
top contributors, and codebase growth. Run it once at the start of a session to
orient yourself — it's not a replacement for git log or a full TUI.
Six panels on one screen. They lay out in two columns on a terminal at least
100 columns wide and stack into one below that; --layout wide|stack forces
either shape.
brew install lcondliffe/tap/gitlingOr with Go:
go install github.com/lcondliffe/gitling/cmd/gitling@latestThat writes to $GOBIN, or $(go env GOPATH)/bin when GOBIN is unset — make
sure it's on your PATH. Prebuilt binaries are on the
latest release.
gitling # default dashboard (last 14 weeks)
gitling --since 30d # override the range for all sections (d, w, mo, y)
gitling graph --since 1y # focused activity drill-down
gitling churn --since 1y # file churn: all files, ranked by commit count
gitling contributors # all authors, ranked (--since sets the window)
gitling branches # branch overview: ahead/behind, last commit, author
gitling tidy # dry run: local branches that are safe to delete
gitling tidy --apply # actually delete them (prompts once)
gitling --recent 10 # list the last 10 commits (0 hides the panel)
gitling --layout stack # force one column; --layout wide forces two
gitling --prs=false # skip the open pull requests panel
gitling --json # structured dashboard data for scripts/integrations
gitling --date commit # bucket by commit date instead of author date
gitling --color=always # always, never, or auto (default; honors NO_COLOR)
gitling --config ~/gitling.json # use an explicit config file
gitling # in a directory of repos: one-line-per-repo overview
gitling --fetch # ...fetching each repo first for fresh ahead/behindEach drill-down is available as a subcommand or the matching --flag; naming
two different views is an error.
The dashboard shows a panel of open pull requests when it can get them, and
hides it entirely when it can't or when there are none. It never talks to a
forge API itself: it shells out to the platform's own CLI, so authentication is
whatever that CLI already has. Today that means GitHub via
gh; other platforms (GitLab's glab, Azure DevOps'
az repos) are one entry in internal/forge. With no CLI installed, no
network, or a remote gitling doesn't recognise, the panel just doesn't appear —
--prs=false skips the lookup altogether.
Run gitling in a directory that isn't a repo but whose immediate
subdirectories are (a ~/repo/* layout) and it renders a one-line-per-repo
overview instead of an error: current branch, ahead/behind upstream,
working-tree state, and the open PR count. Ahead/behind comes from the local
tracking refs — instant, but only as fresh as each repo's last fetch;
--fetch fetches every repo first (failures fall back to local refs). PR
counts follow the same rules as the dashboard panel and are skipped with
--prs=false. Only immediate children are scanned, and nothing is written.
gitling tidy is the one subcommand that changes anything. It finds the local
branches you're done with and, on request, deletes them:
gitling tidy # dry run over merged + upstream-gone branches
gitling tidy --apply # delete them, prompting once first
gitling tidy --merged # narrow to branches merged into the default branch
gitling tidy --gone # narrow to branches whose upstream was deleted
gitling tidy --stale # also include branches untouched for 90 days
gitling tidy --stale 180d # ...with a different threshold
gitling tidy --protect 'release/*' # never delete matching branches
gitling tidy --apply --yes # no prompt, for when you already know
gitling tidy --no-fetch # skip the pruning fetchTIDY · 4 of 9 branches
merged into origin/main -d
chore/tidy-readme 14d ago a1b2c3d
upstream gone (squash-merged) -D
feat/heatmap 1mo ago 9f8e7d6
fix/parse-numstat 3mo ago 4c5b6a7
4 branches to delete, 3 needing -D
dry run — pass --apply to delete
Which group a branch lands in decides how it gets deleted:
- merged — the tip is an ancestor of the default branch, so the work is
provably in. Deleted with
git branch -d, leaving git's own merge check as a second safety net under gitling's. - gone — the branch tracked a remote branch that no longer exists: the shape
a squash-merged pull request leaves behind. The commits landed under new
hashes, so git sees the branch as unmerged and only
-Dwill drop it. The forge deleting the remote branch is evidence it's safe, but circumstantial rather than proof — which is why the plan marks these-Drather than hiding the distinction. - stale — old, and neither merged nor gone. The only category where deleting
can lose work, so it's never selected unless you ask with
--stale.
--merged and --gone narrow the selection to what they name. --stale only
ever adds: asking to also clean up the old ones shouldn't quietly stop cleaning
up the safe ones.
"Merged" is measured against the remote default branch, so a branch merged
into your local main but never pushed is treated as unmerged and needs -D.
- Dry run by default. Nothing is deleted without
--apply, which prompts once (unless--yes) with the full plan on screen. Anything that isn't an explicity— a bare newline, no stdin at all — is a no. - The current and default branches are never deleted, nor anything matching
a
--protectglob or the config file'sprotectlist.--protectadds to that list rather than replacing it. - Every branch shows the commit it pointed at, before and after deletion, so
anything can be restored with
git branch <name> <hash>. - It fetches with
--prunefirst (skip with--no-fetch), because "upstream gone" is meaningless against stale remote-tracking refs. A failed fetch warns and continues — being offline shouldn't stop you tidying merged branches — but it says so, because the plan is then built on older information. - A branch git refuses to delete is reported and the rest still run.
gitling optionally reads defaults from
$XDG_CONFIG_HOME/gitling/config.json, falling back to
~/.config/gitling/config.json. Override with --config <path> or
GITLING_CONFIG. A missing file is fine; a malformed one is reported to
stderr.
{
"since": "30d",
"color": "auto",
"bucket": "week",
"recent": 5,
"layout": "auto",
"prs": true,
"protect": ["release/*", "wip/keep-me"]
}Command-line flags override the config file, which overrides the built-in
defaults. protect is the exception: --protect adds to the configured list
rather than replacing it, since a config saying "never delete release/*"
shouldn't be switched off by naming one more pattern.
go build ./cmd/gitlingPure Go standard library: go.mod has no requirements and there is no
go.sum. Needs git on PATH at runtime.

