← back to gallery

Lockfile Census

Every lockfile on GitHub, counted every 6 hours — see which package manager is actually winning.

dev-toolspackage-managersnpmuvpnpmbuncargogithubmetricslive-data
Open product ↗

lockfile-census

Live, public market-share dashboard for every package manager on GitHub. One screen. No auth. No mock data. Refreshed every six hours from the GitHub Code Search API.

lockfile-census answers the recurring engineering-Slack debate —
"should we move to pnpm? to bun? to uv? is yarn dead yet?" — with a count.
Not a survey, not an opinion piece, just the number of public GitHub repos
that contain each lockfile, snapshotted every 6 hours and plotted over time.

Why it exists

May 2026 has been a brutal month for package-manager politics:

lockfile-census is the alternative: a transparent, append-only counter
that anyone can audit.

What it shows

Data sources

All public. Refresh frequencies are honest — they match what node-cron
actually runs.

| Source | URL pattern | Frequency |
|---|---|---|
| GitHub Code Search API | https://api.github.com/search/code?q=filename:<lockfile>&per_page=1 | every 6 hours (0 /6 ) |
| GitHub Repos API | https://api.github.com/repos/<owner>/<name> | once daily, top-repo enrichment (0 2 *) |

Setting GITHUB_TOKEN is required — Code Search is auth-only for the
total_count we depend on. Without it, every cell renders and the
fetch log loudly says missing GITHUB_TOKEN. The dashboard never falls
back to fake counts.

Hard rules

Tracked lockfiles

| id | filename | ecosystem | display name |
|---|---|---|---|
| npm | package-lock.json | js | npm |
| pnpm | pnpm-lock.yaml | js | pnpm |
| yarn | yarn.lock | js | Yarn |
| bun | bun.lock | js | Bun (text) |
| bun_b | bun.lockb | js | Bun (binary) |
| deno | deno.lock | js | Deno |
| uv | uv.lock | py | uv |
| poetry | poetry.lock | py | Poetry |
| pipenv | Pipfile.lock | py | Pipenv |
| pdm | pdm.lock | py | PDM |
| pixi | pixi.lock | py | Pixi |
| conda | conda-lock.yml | py | conda-lock |
| cargo | Cargo.lock | rust | Cargo |
| go | go.sum | go | Go modules |
| gemfile | Gemfile.lock | ruby | Bundler |
| composer | composer.lock | php | Composer |
| mix | mix.lock | elixir | Mix |
| gradle | gradle.lockfile | jvm | Gradle |
| maven | pom.xml | jvm | Maven (proxy) |
| dotnet | packages.lock.json | dotnet | NuGet |
| flake | flake.lock | nix | Nix flakes |
| pubspec | pubspec.lock | dart | pub |
| sbt | build.sbt | jvm | sbt (proxy) |
| nimble | nimble.lock | nim | nimble |
| swift | Package.resolved | swift | Swift PM |

Running locally

npm install
cp .env.example .env
# put a real GitHub PAT in .env (any classic or fine-grained token works)
node server.js
# → listening on http://0.0.0.0:4761/lockfile-census/

The first snapshot fires about 5 seconds after boot so the dashboard is
populated immediately. Subsequent snapshots run on the cron schedule.

Endpoints

All public, all read-only except /refresh, which manually fires a
snapshot (still no auth).

| Method | Path | Notes |
|---|---|---|
| GET | /lockfile-census/ | Static SPA |
| GET | /lockfile-census/health | {status, snapshots, last_snapshot_at} |
| GET | /lockfile-census/api/lockfiles | Canonical list of trackable lockfiles |
| GET | /lockfile-census/api/latest | Latest non-null count per lockfile; ?ecosystem= filter |
| GET | /lockfile-census/api/history | ?lockfile=<id>&days=30 or all-series shape |
| GET | /lockfile-census/api/movers | Growers + fallers over the last 7 days |
| GET | /lockfile-census/api/share | ?ecosystem=py — share breakdown for that ecosystem |
| GET | /lockfile-census/api/top-repos | ?lockfile=<id> — top 5 repos by stars |
| GET | /lockfile-census/api/fetch-log | Last 100 fetch_log rows |
| POST | /lockfile-census/refresh | Manual snapshot kick (also accepts GET) |

JSON envelope: { "ok": true, "data": ..., "as_of": "ISO-8601" }.

Tech stack

File layout

lockfile-census/
├── server.js
├── db.js
├── package.json
├── .env.example
├── .gitignore
├── README.md
├── CLAUDE.md
├── SPEC.md
├── DEPLOY_MANIFEST.json
├── fetchers/
│   ├── github-code-search.js
│   └── github-top-repos.js
├── routes/
│   ├── api.js
│   └── refresh.js
├── data/                   # created at runtime
└── public/
    ├── index.html
    ├── app.js
    └── style.css

License

MIT.

Built by the Cowork R&D pipeline (Claude Opus 4.7).