git + telemetry. Your own developer-efficiency report, built from git history — on your machine, for your eyes.
gitmetry turns your git history into a private performance review you run on yourself — 11 dimensions mapped to the DORA, SPACE and CodeScene frameworks, then narrated by an LLM into a readable report with 🟢/🟡/🔴 verdicts and trends.
No cloud. No account. No dashboard for your manager. It's read-only over git (git archive / git show) — it never touches your working tree, and your data never leaves your laptop. The whole generator is a single zero-dependency stdlib Python file.
Think of it as Git Wrapped for your engineering habits, but with a method behind it: instead of vanity stats, you get throughput, rework rate, function complexity, defect hotspots, change coupling, work rhythm and bus-factor — the things that actually tell you whether the code you write lasts.
Almost every tool in this space — LinearB, Swarmia, Haystack, Code Climate Velocity, Waydev — is a team dashboard for managers: cloud-hosted, paid, and pointed at developers. gitmetry is the opposite.
| Team analytics SaaS | gitmetry | |
|---|---|---|
| Audience | managers, leads | you, about your own work |
| Where data lives | their cloud | your machine, read-only over git |
| Cost / setup | paid, integrations | one Python file, git only |
| Metrics | often vanity KPIs | DORA / SPACE / CodeScene-backed |
| Output | live dashboards | an LLM-narrated report you keep |
Good for: a personal retro, prep for a 1:1 or performance review, sanity-checking your own habits, or just curiosity about how you actually work.
A two-phase workflow:
gitmetryscans your local repo(s) and emits raw data — markdown tables and/or JSON.- An LLM (or you) turns that into a readable, interpreted report with flags and trends. See
examples/sample-report.mdfor the target — here's a taste:
## 🟢 Summary
Stable volume, small batches and declining rework — a healthy profile.
Watch one knowledge concentration.
| Dimension | Verdict | Trend |
|-------------------------------|------------------|------------------------|
| First-pass quality (rework) | 🟢 better | 31 % → 24 % |
| Defect/complexity hotspots | 🟡 one dominant | Controller/Order.php |
| Ownership / bus factor | 🟡 concentration | 41 solo files |
⚠️ Metrics are proxies, not truth. Most trustworthy: commit throughput, rework %, function CCN, ownership. Indicative only (skewed by generated code / commit discipline): raw line sums. gitmetry leans on trends, not absolute numbers.
The generator is a single stdlib Python 3 script — no install required:
git clone https://github.com/vzoha/gitmetry
cd gitmetry
./gitmetry.py # last 24 months of the repo in the CWD, markdown to stdoutOr install it as a gitmetry command with pipx:
pipx install git+https://github.com/vzoha/gitmetry
gitmetry --versionThen hand the output to your LLM of choice (Claude Code, etc.) with the prompt "interpret this gitmetry raw data into a report" — the conventions live in CLAUDE.md and the structure in the section below.
# last 24 months of the repo in the current directory, markdown to stdout
gitmetry
# explicit window + save both md and json
gitmetry --since 2021-06 --until 2026-06 --format both --out report.md
# a JS/TS codebase for the deep-analysis layers
gitmetry --main-ext ts --paths src
# + slow code-health trend (scc snapshots, runs for minutes)
gitmetry --since 2021-06 --health-trend --format both --out report.mdBy default gitmetry analyzes the git repo in the current directory. Point --root at a parent folder to analyze several repos at once (throughput / rework / sustainability are cross-project; the deep layers run on one --main-repo).
| Option | Default | Description |
|---|---|---|
--root |
. |
folder holding the repos (*/.git); may itself be a repo |
--main-repo |
the only repo found | repo (under --root) for deep analysis (layers 5,6,7,8,9,11) |
--author |
git config user.name |
regex for git --author (case-insensitive) |
--main-ext |
php |
primary language extension for the deep layers (php, js, ts, py, go, rb…) |
--since / --until |
last 24 months | YYYY-MM or YYYY-MM-DD |
--paths |
. |
paths within the main repo passed to lizard/scc |
--format |
md |
md | json | both |
--out |
stdout | output file (both → .md + .json) |
--health-trend |
off | scc complexity snapshots over time (slow) |
--quarterly |
off | also emit a per-quarter overview table (on top of yearly) |
--rework-days |
14 |
rework window: churn on code anyone touched within N days |
--off-hours |
8-19 |
working hours START-END; commits outside count as off-hours |
--big-batch |
400 |
churn (add+del) above which a commit counts toward big % |
--coupling-min-shared |
5 |
min co-changes for a file pair to show in change coupling |
--include-docs |
off | also count non-code files in line metrics |
--no-exclude |
off | don't exclude test/generated code |
The script has no config files and no hardcoded paths beyond the option defaults. Copy it anywhere and point the options at your repos.
Note: the deep-analysis layers (5 defect hotspots, 6 functional changes, 7 complexity hotspots, 8 change coupling, 9 code-health) operate on a single primary language selected via
--main-ext(defaultphp). The cross-project / language-agnostic layers are throughput, rework, test co-change, corrective, sustainability and ownership.
So you don't retype --author / --root / --main-repo / --main-ext every run (and never commit them to a shared repo), put your defaults in a JSON file:
cp .gitmetry.example.json .gitmetry.json # then edit it{ "author": "you", "root": "~/code", "main_repo": "my-app", "main_ext": "ts", "paths": ["src"] }The tunable thresholds (rework_days, off_hours, big_batch, coupling_min_shared) can live here too. gitmetry loads the first file it finds — $GITMETRY_CONFIG, then ./.gitmetry.json, then $XDG_CONFIG_HOME/gitmetry/config.json — and uses it as defaults; any flag you pass on the command line still overrides it. .gitmetry.json and CLAUDE.local.md are gitignored, so your settings stay local.
Don't commit your generated reports — they contain your real author name and private file paths. Keep them outside the repo (e.g.
~/reports/) or in a local./reports/folder, which is already gitignored (along withgitmetry-*.md/gitmetry-*.json). Using gitmetry on a private fork? Drop those lines from.gitignoreto version your reports.
Only git is required. The two analysis tools below are optional — if a tool is missing, gitmetry just skips its layer and the rest of the report still runs, so you can start with nothing extra installed.
| Tool | Powers | Required? |
|---|---|---|
git |
everything | yes |
lizard |
layer 2 — function CCN | optional |
scc |
layers 6 & 10 — complexity hotspots & code-health trend | optional |
tar |
--health-trend only (usually preinstalled) |
optional |
Install lizard (Python, cross-platform):
pipx install lizard # or: pip install --user lizard
pip install -e ".[analysis]" # already covered by the project's "analysis" extraInstall scc (a Go binary — pick one):
brew install scc # macOS / Linux (Homebrew)
go install github.com/boyter/scc/v3@latest # any Go toolchain → ~/go/bin
scoop install scc # Windows (Scoop)Or grab a prebuilt binary from the scc releases and put it on your PATH. gitmetry also looks in ~/bin/scc, so this works too:
mkdir -p ~/bin && mv scc ~/bin/ && chmod +x ~/bin/sccDon't copy the raw tables wholesale — distill a story from them. Target structure (see examples/sample-report.md):
- Header — author, window, repo count, main repo, commit count; a line on the standards; a warning that metrics are proxies, not truth (most trustworthy: throughput, rework %, CCN, ownership; indicative only: line sums, corr %).
- 🟢/🟡/🔴 Summary — one headline sentence, then a
Dimension | Verdict | Trendtable flagging each of the 11 dimensions, then 2–3 sentences on what to watch. - Yearly overview — distil the tool's pre-aggregated
rollup(window totals + per-year, optionally per-quarter) rather than re-deriving it: commits, median batch, big %, rework %, corr %, hotfixes, reverts, avg CCN,Δcx, severe fns, off-hours %, weekend %, active days, test co-change %. Partial years are pre-marked with*. - Per dimension (1–11) — each gets a short Legend: + Assessment: with a flag and concrete files/numbers.
- Footer — note that it was generated from
gitmetry(read-only over git) + where the raw data lives.
Flags: 🟢 healthy/improving · 🟡 watch · 🔴 problem. Be concrete (file names, numbers, "X → Y" trends). Trend > absolute number.
Grouped into four themes — Activity (1) · First-pass quality (2–5) · Code structure (6–9) · People (10–11):
Activity
- Throughput — commits/month cross-project + batch-size distribution (med/p90 churn, big %) and commits per active day. SPACE Activity.
First-pass quality
- Rework rate — churn on code anyone touched within
--rework-days(default 14). CodeScene / MS relative churn. - Test co-change — of your commits touching production code, the share that also touch a test file — a message-independent first-pass-quality habit.
- Corrective vs value-add — Feature/Refactoring vs Fix vs Hotfix, with reverts surfaced separately (subset of Fix); hotfix = DORA Change-Failure proxy.
- Defect hotspots — files in your Fix/Hotfix commits × complexity.
Code structure / complexity
- Functional changes — CCN of the functions you actually touched plus
Δcx, the net function-complexity your commits add vs remove (file totals after − before parent; negative = you simplified). lizard, main repo. - Complexity hotspots — change frequency × complexity (
score = touches × cx). CodeScene. - Change coupling — files changed together in one commit (temporal coupling).
- Code-health trend — complexity/kLOC over time via git-archive snapshots (
--health-trend).
Sustainability & people
- Sustainability — when you commit (off-hours/weekend rhythm; off-hours window via
--off-hours). SPACE well-being. - Ownership / bus factor — authorship share per file across full history, both churn-weighted and recency-weighted (1y half-life), plus who touched it last (solo ≥80 % = risk).
On top of the per-dimension monthly tables, gitmetry emits pre-aggregated overviews — window totals plus a per-year table (--quarterly adds a per-quarter one) — so yearly figures and YoY deltas come straight from raw counts, not from re-averaging the rounded monthly rows.
⚠️ Line metrics (added/deleted) are skewed by generated code (AI tests, docs, lock files). Most trustworthy signals: commit throughput, rework rate, function CCN, ownership.
Corrective/value-add (layer 4) and defect hotspots (layer 5) classify commits by their subject prefix: Feature/Refactoring/feat/refactor/perf → value, Fix/revert → fix, Hotfix → hotfix, Chore/Docs/test/build/ci/style → other. Reverts (git's auto-generated Revert "…" or a revert: prefix) stay in the fix bucket but are also counted separately, so the report can flag undo churn on its own. Conventional-Commits scope and the breaking marker are stripped first (feat(api)!: → feat), so both the golemos convention and full Conventional Commits classify correctly. Any unknown prefix (or a subject with no Type: prefix) falls to other. If your repo uses a different convention, those two layers will under-count; the other eight don't depend on commit messages.
pip install -e ".[dev]" # pytest + ruff
ruff check . # lint
pytest # run the unit tests (tests/)The tests cover the pure, git-free helpers (commit-type classification, multi-language test-file detection, percentile math, path filtering, date arithmetic) plus an integration suite that builds a throwaway repo. CI runs ruff + pytest on Python 3.9 / 3.11 / 3.12 — see .github/workflows/ci.yml.
MIT © 2026 Vojtěch Žoha