gitling

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.
Install
With Homebrew:
brew install lcondliffe/tap/gitling
Or with Go:
go install github.com/lcondliffe/gitling/cmd/gitling@latest
go install writes the binary to $GOBIN, or to $(go env GOPATH)/bin when
GOBIN is unset. Make sure that directory is on your PATH:
export PATH="$(go env GOPATH)/bin:$PATH"
For zsh, add that line to ~/.zshrc so gitling is available in new
terminals too.
Or grab a prebuilt binary for your platform from the
latest release and put
it on your PATH.
Output
Six boxed panels, single screen. On a terminal at least 100 columns wide they
lay out in two columns; below that, or when the width can't be detected (piped
or redirected output), they stack into one. --layout wide|stack forces either
shape, and --layout auto (the default) picks per terminal:
╭─ REPO ──────────────────────────────────────────────────────────────────────╮
│ ● main ↑0 ↓0 5 dirty 0 stashes 23 branches │
╰─────────────────────────────────────────────────────────────────────────────╯
╭─ ACTIVITY · last 14 weeks ─────────────╮ ╭─ TOP CONTRIBUTORS ───────────────╮
│ · · · · · · · · · · · · · · □ │ │ Ada Lovelace ██████████ 33 │
│ · · · · · · · · · · · █ · · │ │ Alan Turing ██ 7 │
│ 41 commits in range · streak: 1 days │ ╰──────────────────────────────────╯
╰────────────────────────────────────────╯ ╭─ CODEBASE GROWTH · 6mo ──────────╮
╭─ HOT FILES ────────────────────────────╮ │ 6,722 LOC ▲ 18% │
│ 22 README.md │ │ ▁▃▅▇███ │
╰────────────────────────────────────────╯ ╰──────────────────────────────────╯
╭─ RECENT · 5 commits ────────────────────────────────────────────────────────╮
│ 2440dfe #18 fix: make release publishing rerunnable Ada Lovelace 1d ago│
╰─────────────────────────────────────────────────────────────────────────────╯
The panels:
- Repo vitals — branch, ahead/behind upstream, dirty files, stashes, branches.
- Activity heatmap — GitHub-style contribution grid (default last 14 weeks),
5-step intensity, today's cell marked with a hollow square. Total commits and
current streak below.
- Recent — the last 5 commits on HEAD (
--recent <n>, 0 hides the panel),
with the pull-request number when the commit message carries one, the author,
and how long ago it landed. Merge commits are included, so PR-merge and
squash-merge workflows both show what shipped. Unlike the other panels this
one ignores --since: "what landed last" is only useful unfiltered.
- Hot files — the paths with the most commits against them in range.
- Top contributors — up to 5 authors by commit count in range, with bars.
- Codebase growth — total LOC, 6-month percent change, and a trend
sparkline.
Usage
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 --graph --bucket week --since 1y
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 --recent 10 # list the last 10 commits (0 hides the panel)
gitling --layout stack # force one column; --layout wide forces two
gitling --json # structured dashboard data for scripts/integrations
gitling --no-color # plain output, no ANSI escape codes
gitling --date commit # bucket by commit date instead of author date
gitling --color=always # force color even when stdout isn't a terminal
gitling --config ~/gitling.json # use an explicit config file
Color
--color takes always, never, or auto (the default). auto honors the
NO_COLOR convention and auto-disables color when
stdout isn't a terminal; always forces color on even when piping into a
pager or a screenshot/SVG renderer; never forces it off. --no-color is
kept as a back-compat alias for --color=never and always wins if both are
given.
Config file
gitling optionally reads defaults from a JSON config file at
$XDG_CONFIG_HOME/gitling/config.json, falling back to
~/.config/gitling/config.json when XDG_CONFIG_HOME is unset. Override the
path with --config <path> or the GITLING_CONFIG environment variable. The
file is entirely optional — a missing file is not an error, but a malformed
one is reported to stderr.
Supported keys, all optional:
{
"since": "30d",
"color": "auto",
"bucket": "week",
"recent": 5,
"layout": "auto"
}
Precedence: command-line flags always override the config file, which
overrides gitling's built-in defaults. Panel toggles aren't yet
config-driven; that's left as future work.
How it works
- gitdata shells out to
git log --numstat and a handful of cheap
plumbing commands. Each commit carries both its author date and commit date.
The recent-commits panel is a separate, bounded git log -n <n> (merges
included) read live on each run rather than served from the cache — it is
cheap, and it must reflect the tip exactly.
- aggregate rolls commits up into per-day buckets (counts, line deltas,
per-author and per-file tallies), keyed by either the author date (default)
or the commit date, per
--date. Range queries sum the days in range, so
changing --since never invalidates the cache.
- cache persists the rollup as a gob file under
.git/gitling-cache/,
keyed by the last HEAD seen. Author-date and commit-date runs use separate
cache files, so switching --date never serves a stale, wrongly-bucketed
rollup. Each run only walks commits newer than the last, making repeat runs
effectively instant. An opt-in sqlite-backed cache is also available for
very large repos — see below.
- render draws everything with 256-color ANSI chosen to read on both light
and dark backgrounds, or emits the same model as indented JSON when
--json
is set. Each panel renders its body into a buffer at the width it has been
given; a small box/column compositor then frames those bodies and, when the
terminal is wide enough, places them side by side. All the width arithmetic
measures visible columns, skipping ANSI escapes, so color never shifts the
layout.
The layers are cleanly separated: the git backend (shell-out by default, with
an opt-in pure-Go go-git backend — see below) and the cache (gob by default,
swappable for sqlite — see below) are each swappable without touching the
others.
Build
go build ./cmd/gitling
Pure Go standard library — no external dependencies.
Optional go-git backend
The git interaction layer (internal/gitdata) sits behind a small Backend
interface. By default it's implemented by shelling out to the git binary,
which keeps the default build dependency-free. An alternative pure-Go
implementation using go-git is available
behind the gogit build tag:
go build -tags gogit ./cmd/gitling
This trades the dependency-free default for not needing git on PATH.
It's opt-in and not the default because, on this project's benchmarks,
shell-out is still faster for the commit-log walk that dominates gitling's
runtime; see internal/gitdata/bench_test.go /
internal/gitdata/bench_gogit_test.go. A GITLING_BACKEND=shell environment
variable can force shell-out even in a gogit-tagged binary; it has no
effect on the default build.
Known divergences from shell-out are documented on gogitRepo in
internal/gitdata/gogit.go (notably: author identity is not
mailmap-resolved, and stash count is always reported as 0 since go-git has
no porcelain equivalent of git stash list).
Optional sqlite cache backend
The default cache backend is the zero-dependency gob file described above.
For very large repos (or to enable future partial/range queries against the
cache) an alternative sqlite-backed store is available behind a build tag:
go build -tags sqlite ./cmd/gitling
This uses modernc.org/sqlite, a
pure-Go, cgo-free database/sql driver, so the tagged build still
cross-compiles without a C toolchain (important for the release workflow).
The dependency is listed in go.mod/go.sum but is only compiled in when
building with -tags sqlite; the default build remains dependency-free.
The sqlite store writes to .git/gitling-cache/aggregates.db using a
normalized schema: one row per calendar day (days, mirroring the in-memory
per-day buckets) plus a meta table for the schema version and last-seen
HEAD hash. It implements the same cache.Backend interface as the gob store,
so gitling behaves identically either way — only the on-disk format
changes.
Releases
Tagging a commit vX.Y.Z triggers the release workflow, which cross-compiles
binaries (linux/darwin/windows, amd64/arm64), attaches them with a
checksums.txt, and publishes a GitHub Release with auto-generated notes:
git tag v0.1.0
git push origin v0.1.0
Status
v0.2. The drill-down subcommands have landed — each available as a
subcommand or the matching --flag (naming two different views errors):
graph — focused activity view with day/week/month buckets.
churn — every file touched in range, ranked by commit count.
contributors — all authors ranked (beyond the dashboard's top 5).
branches — per-branch ahead/behind vs upstream (or the default branch),
last-commit age, and tip author.