Dendrochronology
Every repo is a tree. Cut yours open.
One ring per month of your repository’s life, width from that month’s churn, knots where the long branches merged. Reads the commit graph. Never opens a file. Nothing leaves this machine.
curl/curlOld-growth timber. 321 monthly rings, and two knots in the whole log.first ring December 1999 · 321 rings · 1,587 hands
ReactiveX/RxSwiftTwelve hands in the sapwood. The outer rings are thin.first ring February 2015 · 134 rings · 447 hands
twbs/bootstrapForty-eight knots in fifteen years. Every long branch left a mark.first ring April 2011 · 184 rings · 1,671 hands
elixir-lang/elixir22,412 commits and thirteen knots. A language that merges fast.first ring January 2011 · 188 rings · 1,663 hands
OpenZeppelin/openzeppelin-contracts514 hands, 21 knots. Money runs on this and it is reviewed like it.first ring August 2016 · 121 rings · 514 hands
psf/requestsForty-seven knots on 6,489 commits. A small library merged the long way.first ring February 2011 · 187 rings · 803 hands
nvm-sh/nvmHalf the lifetime churn is the test folder. 439 hands on a shell script.first ring April 2010 · 196 rings · 439 hands
sinatra/sinatraNineteen years of rings, and nine hands still on the bark.first ring September 2007 · 227 rings · 545 hands
astral-sh/tyA sapling. 66 weekly rings, no knot yet, and one very loud season.first ring May 2025 · 66 rings · 54 hands
square/retrofitThe website wedge is 45% of the churn. The library is the smaller half.first ring September 2010 · 191 rings · 220 hands
Reference-LAPACK/lapack215 rings and 48 knots. Fortran from 2008 that scientific computing still links against.first ring October 2008 · 215 rings · 204 hands
chalk/chalkThin and pale. 377 commits in 156 months - a library that is finished.first ring August 2013 · 156 rings · 71 hands
facebook/reactKnotty. 27 long branches absorbed, 4 revert scars still open to the bark.first ring May 2013 · 160 rings · 2,085 hands
serilog/serilog156 hands over 162 rings. Narrow, even, unhurried.first ring February 2013 · 162 rings · 156 hands
envoyproxy/data-plane-api3,425 commits and 4 hands left in the sapwood. The contract every Envoy on earth reads from.first ring May 2017 · 105 rings · 94 hands
lowRISC/ibex126 hands built this silicon core. 13 are still on the bark.first ring April 2015 · 136 rings · 126 hands
neovim/neovimSame ink as curl and nothing alike: 48 knots, 282 hands still on the bark.first ring January 2014 · 152 rings · 1,617 hands
zulip/zulipNothing here reaches 40%. Python, prose and TypeScript, all at once.first ring August 2012 · 169 rings · 1,440 hands
spf13/cobra345 hands for 1,106 commits. Almost everybody passed through once.first ring September 2013 · 155 rings · 345 hands
BurntSushi/ripgrepStraight grain. 127 rings, not one knot, not one scar.first ring February 2016 · 127 rings · 497 handsnpx busfactor ringsPrivate repo? Run it yourself. Offline, no signup, nothing uploaded.- Offline
- No signup
- Commit metadata only
- Byte-identical output
Read a stranger’s trunk
- 1Pith. The first commit. It drifts toward whichever subsystem took the work.
- 2Ring. One period. Width is that period's churn, log-scaled against the busiest one.
- 3Wedge. A top-level directory. Arc = its share of lifetime churn, largest at 12 o'clock.
- 4Sealed pocket. A directory that stopped and is gone from HEAD.
- 5Knot. A branch that lived 30 days or more and carried 3+ commits, then merged.
- 6Scar. A period where reverts crossed 5% of its commits.
- 7Bark. Thickness = distinct authors of the last 12 periods. Counted, never named.
Seventeen inks. Your language mix picks one.
Most-touched family wins.
- MadderCSS, Sass, HTML and templates
- MiniumFortran, COBOL, Ada, Pascal, VB6
- OxideC, C++, Objective-C, shaders, assembly
- MarigoldPython, notebooks, R, Julia, SQL
- WeldVerilog, VHDL, SystemVerilog, KiCad
- VeronaHaskell, Elixir, Erlang, OCaml, Lisp
- VerdigrisJava, Kotlin, Scala, Clojure
- CyanotypeJavaScript, TypeScript, Vue, Svelte
- CeruleanProtobuf, GraphQL, Thrift, grammars
- CelestineSwift, Dart, GDScript, QML
- IndigoSolidity, Vyper, Move, Cairo
- PrussianShell, Make, Terraform, Nix, Docker
- UltramarineRust, Go, Zig, Nim, D
- AmethystC#, F#, VB.NET
- TyrianRuby, PHP, Perl, Lua
- SlateMarkdown, docs, YAML and JSON config
- OpalNo family over 40% of touches
What every mark counts
| Mark | Git fact | How it is counted |
|---|---|---|
| One ring | One period of the repo's life | commit author dates, UTC |
| Ring width | Lines added + removed that period, log-scaled against the busiest period | git log --numstat |
| Tight band | A quiet period | same |
| Wide flush | A rewrite or a big push | same |
| Dark ring edge | Latewood: darker where the period was busier | same |
| Wedge | A top-level directory; arc = its share of lifetime churn, largest at 12 o'clock going clockwise | numstat path prefixes |
| Bright grain | That directory dominated that period's churn | per-period churn share |
| Knot | A merged branch that lived >= 30 days with >= 3 commits, sitting in the subsystem it touched most | merge parents, walked |
| Scar | A period where reverts were >= 5% of commits and >= 3 of them | commit subjects starting with revert or reverted |
| Sealed pocket | A top-level directory that stopped and is gone from HEAD | git ls-tree HEAD |
| Off-centre pith | The trunk leans toward wherever the work moved | dominant wedge per period, accumulated |
| Lighter outer wood | Sapwood: the last 12 periods | ring index |
| Bark thickness | Distinct author emails in the sapwood window | hashed locally, counted, never named |
| Ink | The language family whose files were touched most often | numstat rows by file extension |
- Ring period: one week under 548 days of history, one quarter over 10957 days, one month between.
- Wedges: top 12 top-level paths by lifetime churn; anything under 0.5% folds into one.
- Knots: branch age >= 30 days and >= 3 commits; the 48 largest are drawn.
- Scars: reverts >= 5% of a period's commits and >= 3 of them.
- Ink: the family your files were touched in most often, unless none reaches 40% - then Opal.
- Dates are UTC. Author dates outside the log's committer span are clamped into it.
- Same repo, same HEAD, byte-identical SVG.
- Hands are distinct author emails, hashed locally and counted. No person is ever named on the artefact.
What you get
- SVG
- PNG
- Wallpaper plates
- A1 + A2 PDF, 3mm bleed
- Dark + light
- JSON model
npx busfactor rings --print --wallpapers --light