repo-healthcheck · a CLI for people with too many repos

What every repo should have.

One command looks at every repo you can see — on GitHub, and now GitLab too — and tells you, worst first, exactly what's missing: a license, a protected branch, a README, a CI config. The stuff you meant to add and then forgot you didn't.

zsh — repo-healthcheck

The gaps you don't find until it's too late.

None of these show up until someone hits them — usually the day it matters most.

no license

The license trap

No LICENSE file means GitHub's legal default is "all rights reserved" — nobody, including future you, can safely reuse the code. And GitHub's own detector sometimes reports a perfectly real GPL license as NOASSERTION, hiding it entirely.

not protected

The one bad push

Without branch protection, a single accidental git push --force to main rewrites history with no way back. It happens on side projects precisely because nobody thought a side project needed protecting.

no CI, no tests

The repo you forgot

Forked eight months ago, still public, still listed under your name. No tests, no CI, no idea if it still runs — and no way to find that out without opening every repo one at a time.

The product, in three moves.

Run it once. It fetches everything the token can see, checks twelve things per repo, and hands you an interactive report — not a wall of JSON.

01 — THE SCORECARD

See the damage first

Total repos, how many have at least one gap, the average, and the single most common thing missing across the whole account — before you scroll to a single row.

Dashboard header showing 12 repos audited, 5 with gaps, 2.8 average gaps per repo, License as the most common gap
02 — THE STANDARD

Twelve checks, spelled out

Every check gets a two-letter code, a plain-English criterion, and a live missing-count — so "5/12 missing" always means something specific, never a mystery flag.

Checklist grid showing README, CLAUDE.md, License, Description, Topics, .gitignore, Tests, CI config, Contributors, Active, Branch protected, and pyproject.toml checks with their criteria and missing counts
03 — WORST FIRST

Click to filter, click to sort

Every checklist chip filters the table on click. Every column header sorts, and stacks as a tie-breaker. "Forks only" and a search box come free.

Interactive repo table sorted worst-first, with filter chips for each check and columns for branch protection, license type, contributors, forks, topics, and last push date

Try it yourself, with sample data →

What it actually checks

Every standard, in one place — the same list that drives the checklist chips above.

RMREADMEexists at the repo root
CMCLAUDE.mdproject context for Claude Code
LCLicensedetected, or a GNU license found by name
DSDescriptionthe About field is filled in
TPTopicsat least one topic is set
GI.gitignoreexists at the repo root
TSTeststests/ or test/ exists
CICI config.github/ or .gitlab-ci.yml
CNContributorssomeone besides the owner committed
ACActivepushed in the last 180 days
PRBranch protectedforce-push & deletion disallowed
PYpyproject.tomlPython repos only

One account moved to GitLab. It doesn't care.

Pass --gitlab and your GitLab projects land in the same table, same worst-first sort, same twelve checks — tagged so you always know which platform a repo lives on.

github

Every repo the token can see — your own, plus every org you belong to — in one call. --owner NAME narrows to one account's public repos.

gitlab

Same twelve checks against GitLab's API — .gitlab-ci.yml instead of .github/, protected branches via GitLab's own endpoint. Self-managed instances work too, via --gitlab-url.

Two minutes to your first report

$uv sync $uv run repo-healthcheck --dashboard report.html # or, to include GitLab: $export GITLAB_TOKEN=glpat-xxx $uv run repo-healthcheck --gitlab --dashboard report.html

Reads GITHUB_TOKEN if it's set, otherwise falls back to gh auth token — if you're already logged in via the gh CLI, there's nothing else to configure. Read-only: it never writes to a repo it audits.

What would yours find?

The account behind these screenshots had twelve repos and five gaps before it ever ran a single fix. Most accounts have more than twelve.