gitling

module
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 27, 2026 License: MIT

README

gitling

CI

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:

  1. Repo vitals — branch, ahead/behind upstream, dirty files, stashes, branches.
  2. 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.
  3. 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.
  4. Hot files — the paths with the most commits against them in range.
  5. Top contributors — up to 5 authors by commit count in range, with bars.
  6. 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.

Directories

Path Synopsis
cmd
gitling command
Command gitling prints a compact, at-a-glance dashboard for the git repo in the current directory: repo vitals, an activity heatmap, top contributors, and codebase growth.
Command gitling prints a compact, at-a-glance dashboard for the git repo in the current directory: repo vitals, an activity heatmap, top contributors, and codebase growth.
internal
aggregate
Package aggregate turns raw commits into the per-panel metrics the dashboard needs, and holds the in-memory shape that the cache persists.
Package aggregate turns raw commits into the per-panel metrics the dashboard needs, and holds the in-memory shape that the cache persists.
cache
Package cache persists derived aggregates so repeat runs only process commits newer than the last one seen.
Package cache persists derived aggregates so repeat runs only process commits newer than the last one seen.
gitdata
Package gitdata is the git interaction layer for gitling.
Package gitdata is the git interaction layer for gitling.
render
Package render draws the dashboard to an io.Writer.
Package render draws the dashboard to an io.Writer.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL