Skip to content

Repository files navigation

Statline

GitHub team statistics in your terminal.

Statline (gh statline) is a terminal dashboard for the numbers behind your team's pull-request workflow — who's opening, merging, reviewing, approving, and commenting, across the repos your team actually works in.

Statline demo: team stats table, charts dashboard, and trends view

(All names in the demo are generated by the built-in seed command — no real data.)

Features

  • Team stats — one sortable stat line per member: PRs opened and merged, reviews given (approved / commented / changes requested), comments given vs received, median cycle time (open → merge), median time to first review, and median PR size.
  • Charts — a 3×3 dashboard that always fits one screen: PR throughput, review outcomes, cycle-time trend, who-reviews-whom matrix, first-review latency, PR sizes, open-PR aging, and an activity punch card, topped by stat tiles comparing the window to the previous one (▲/▼ deltas appear once the cache covers both). Any card expands to a scrollable fullscreen view; the review matrix pans with its name labels pinned.
  • Trends — where the numbers are heading: a card per headline metric showing its 12-week trajectory with week-over-week deltas, plus a movers card for the members whose recent volume rose or fell the most ("reviews 2 → 8, up 4 weeks running"). Cards expand to fullscreen — count metrics break down into per-member weekly sparklines, movers drop the top-3 cap. Weekly buckets are fixed regardless of the time window, and the series only reaches as far back as the cache honestly covers.
  • Person drill-down — headline stats, daily activity sparkline, and a per-repo breakdown for any teammate.
  • Time windows — cycle 7/14/30/90-day presets with w, or pick a custom date range with r.
  • Teams your way — a setup wizard imports a GitHub org team (members + assigned repos) into a local config you can edit freely: add contractors, hide alumni, track repos the team isn't formally assigned. Multiple team profiles, switchable in-app with t.
  • Local cache — incremental sync into SQLite (pure Go, no CGO): instant startup, offline browsing, no re-fetching what you already have. A headless gh statline sync keeps the cache warm from cron.
  • Markdown exporty copies the current view as a Markdown table for standups, retros, and 1:1 notes.
  • Keyboard-first (vim keys + arrows) with clickable tabs and rows, wheel scrolling, and an adaptive light/dark Charm-style theme.

Install

As a GitHub CLI extension (recommended):

gh extension install byte2pixel/gh-statline
gh statline

Standalone binaries are attached to each release (download, rename to gh-statline, put it on your PATH), or build from source with go install github.com/byte2pixel/gh-statline@latest.

Auth & scopes

Statline reuses your GitHub CLI credentials (gh auth login), falling back to GITHUB_TOKEN. It needs the repo and read:org scopes.

Usage

gh statline              # open the TUI (first run launches the setup wizard)
gh statline init         # add another team profile
gh statline sync         # refresh the cache without the TUI (cron-friendly)
gh statline sync --team platform --backfill 180

Keys

Key Action
1 / 2 / 3 / tab Team stats / charts / trends
enter / esc Drill into member / back
j/k, arrows Move selection
h/l, / Change sort column
- Flip sort direction
f / enter Expand the focused card (charts, trends)
j/k · h/l Scroll / pan a fullscreen card
pgup/pgdn, d/u, g/G Page / half-page / jump in a fullscreen card
w Cycle time window
r Custom date range
t Switch team
s Sync now
y Copy view as Markdown
? Full help
q Quit

Configuration

Lives at ~/.config/gh-statline/config.yml (Windows: %AppData%\gh-statline\config.yml) — wizard-written, human-editable:

default_team: platform
exclude_bots: ["*[bot]", "dependabot*", "renovate*", "copilot*"]
teams:
  - name: platform
    org: acme
    gh_team_slug: platform-eng   # provenance of the import; optional
    # no_sync: true              # local-only profile; sync never touches GitHub
    members:
      - {login: alice}
      - {login: bob, hidden: true}   # kept in cache, hidden from views
    repos:
      - {owner: acme, name: api}
      - {owner: acme, name: web}
sync: {backfill_days: 120, page_size: 25, concurrency: 3}
ui: {window: 30d, sort: prs_merged}   # updated as you use the app; see below

exclude_bots globs (*, ?, case-insensitive, brackets literal) match reviewer and commenter logins in addition to GitHub's own bot flag. copilot* is in the defaults because Copilot code review reviews as copilot-pull-request-reviewer, which has no [bot] suffix, so no other glob catches it. A Copilot review lands within minutes of the PR opening, and without the glob it would count as the first review whenever the synced bot flag missed it. Defaults only fill in when the key is absent from the file, so a config written by an older version keeps its old list. Add new globs by hand.

sync tunes the GitHub walk: backfill_days is how far back a fresh cache reaches, page_size is PRs per request (1–100), and concurrency is how many repos sync in parallel, capped at 10. GitHub's secondary rate limits trigger on concurrent requests from one token, so more workers than that earn a block, not a faster sync.

Statline remembers how you left it: switching teams (t) updates default_team, and changing the time window (w) or the sort column (/) updates ui, so the next launch reopens the same view. Custom date ranges (r) and --team <name> are one-shot and never persist. These in-app changes rewrite the file, so YAML comments don't survive a session — keep notes elsewhere if you hand-edit.

The SQLite cache lives in the user cache dir and is safe to delete — it just re-syncs.

Metric definitions

  • Counts are attributed to the person acting: reviews to the reviewer, comments to their author. Commenting on your own PR never counts.
  • Review-thread replies arrive as GitHub "commented" reviews; v0.1 counts them as such (a known inflation of the commented bucket).
  • Reviews GitHub has since marked dismissed still count as reviews given, in their own column: the review happened, and a later push invalidating an approval shouldn't erase the reviewer's work.
  • Time to first review ignores bots and the PR author.
  • Hidden members and bots are excluded as actors from every number, including the charts: what the team table shows and what the charts total are the same set of people. Their activity towards a visible member still counts, so hiding a teammate never rewrites someone else's stat line.
  • Medians use the lower-middle value; a means no data in the window.
  • Percent changes (tiles, trends, movers) are rounded to the nearest whole percent, with one shared definition. A change from a zero base has no percentage and is labelled new; in the movers ranking, new activity sorts ahead of every percentage change, by volume.
  • The review matrix only counts reviews on PRs authored by humans: reviews on bot-authored PRs are excluded, and the (others) column (reviews on non-member PRs) doesn't influence the heat-map scale.
  • The updatedAt-ordered incremental walk cannot see PRs untouched since before the backfill horizon (default 120 days) — deepen with sync --backfill N. Fetched data is never deleted, so local coverage grows the longer you use statline; the tile deltas turn on per window once the cache provably covers the previous period.

Development

go build ./...   # pure Go, no C toolchain needed
go test ./...
go run .
go run . seed    # dev helper: seeds a deterministic local-only "demo" team
                 # (38 members, 120d of history) to inspect charts at scale

To render views headlessly (sizes, scroll states, seeded data), use the dump harness: STATLINE_DUMP=1 go test ./internal/tui/app -run TestDumpView -v — see dump_test.go for the STATLINE_DUMP_VIEW/_PRE/_POST options.

The README demo GIF is scripted with VHS against seeded data — vhs/demo.tape has the Docker one-liner to regenerate it after UI changes.

Built with Bubble Tea v2, Lip Gloss, Bubbles, ntcharts, BubbleZone, Harmonica, go-gh, and modernc.org/sqlite.

License

MIT

About

Statline, your GitHub team-stats TUI

Topics

Resources

Contributing

Security policy

Stars

5 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages