gitmole
A toolkit for digging into any cloned git repository: who works on it, where the risk is, how old the code is, whether the repo itself is healthy, and whether anything sensitive was ever committed.
Free. Any Stack. Local. Offline. Deterministic. Fast.
- Free. MIT licence, no paid tier, no account, no token. A local clone needs no credentials, and a public
owner/repois cloned with plain git. Yourghlogin is only used for private repositories and forowner/*, and only when you ask for them. The tools it runs are open source too. - Any stack. It reads what every repository has: the git log, git blame and the files themselves.
- Local & Offline. Everything runs against a clone on your machine. Nothing is uploaded, nothing phones home; the vulnerability database is a copy you download once.
- Deterministic. No AI at runtime. Every finding is a plain rule over counts you can recompute by hand. The JSON export carries each finding's rule and the numbers it fired on. The same clone gives the same report every time.
- Fast. A 4,400-commit repository takes under thirty seconds.
Install
# macOS, or Linux with Homebrew: gitmole and the five tools it runs
brew tap antvinni/gitmole https://github.com/antvinni/gitmole
brew trust antvinni/gitmole
brew install gitmole
# anywhere else: scc, git-sizer, betterleaks, jscpd and osv-scanner on your PATH, then
pipx install gitmole
Linux package names, the release binaries, --plots and the pip caveats:
docs/install.md.
Usage
gitmole . # the clone you are in
gitmole /path/to/clone # any local clone
gitmole owner/repo # clones into a temp dir first, with gh or plain git
gitmole 'owner/*' # every non-archived repo of a user or org, one summary table
gitmole . --markdown report.md # the same report as a Markdown document
gitmole . --json report.json # every table, the watch list and the findings
gitmole . --fail-on warning # exit 3 if any finding is a warning or worse
gitmole . --risk main --risk-threshold 10 # exit 3 if the files changed since main hold over 10% of the risk
gitmole . --since 2y --full # the current team, every row and column
gitmole --clean # list what gitmole left behind, delete on a yes
A CI job that runs gitmole . --fail-on critical --markdown - >> "$GITHUB_STEP_SUMMARY"
blocks on secrets in source files and still posts the report. Every option:
docs/cli.md.
What you get
The opening of the report for react, 21,703 commits since 2013, at a pinned commit:
╭─ react ──────────────────────────────────────────────────────────────────────────────────────────╮
│ 21703 commits · 2013-05-28 → 2026-09-16 · 1843 identities · branch main │
│ 681,078 lines in 4781 files · JavaScript, TypeScript, Rust, CSS │
│ most commits on Wed at 15:00 · 14% of commits are fixes · 1% of commits are reverts · 19% │
│ of surviving code from 2026 │
│ 1 critical, 6 warnings, 9 notes │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
◎ Watch list
file why
──────────────────────────────────────────────────────────────────────────────────────────────────
packages/react-server/src/ReactFlightServer.js changed 319 times · fixed once in six months ·
visitAsyncNodeImpl() complexity 46
packages/react-server/src/ReactFizzServer.js changed 297 times · fixed twice in six months ·
retryNode() complexity 41
packages/react-reconciler/src/ReactFiberWorkLoo changed 312 times · fixed 4 times in six months
p.js · flushSpawnedWork() complexity 48
packages/react-reconciler/src/ReactFiberCommitW changed 284 times · fixed 28 times ·
ork.js commitLayoutEffectOnFiber() complexity 72
packages/react-reconciler/src/ReactFiberBeginWo changed 361 times · fixed once in six months ·
rk.js beginWork() complexity 52
ranked by revisions × lines of code; the reasons say what else counts against each file
6 months ago this list would have named 11 of the 46 files fixed since (a random 15 of the 1802
files that had changed more than once would name 0.3; the 15 most changed would name 7)
The watch list is the point: the five source files most likely to need a fix
next, the reasons in words, and a backtest that says how the same list, drawn
six months earlier, would have done against the fixes that followed. The list
ranks by revisions × lines of code: measured at six cut-offs on three
repositories
(validation),
that named more of the files fixed next than churn alone, size alone or a
weighted product of fixes, complexity and ownership. Between the header and that
list the full report puts its findings, 16 for react (1 critical, 6 warnings, 9
notes); below it, tables for people, the knowledge map, the timeline, change
coupling, complex functions and repo health; --full adds the hotspots table
behind the list, size, activity and code age. Every section is explained in
docs/output.md.
Reports on repositories you know, each at a pinned commit with a fixed reference date, published as gitmole wrote them; the repo-health numbers come from git-sizer over the whole clone, so a fresh clone can differ there:
| Repository | Commits | Lines | Watch list backtest |
|---|---|---|---|
| curl | 39,758 | 247,179 | named 15 of the 238 files fixed in the next six months; a random pick would name 4.9, the 15 most changed 15 |
| django | 34,933 | 431,749 | named 15 of the 213 files fixed in the next six months; a random pick would name 3.1, the 15 most changed 13 |
| react | 21,703 | 681,078 | named 11 of the 46 files fixed in the next six months; a random pick would name 0.3, the 15 most changed 7 |
The tool set
One tool per question; together they cover what a single command can tell you about a clone.
| Question | Tool | Install |
|---|---|---|
| What is this repo, at a glance; who commits, when, how much churn | gitmole itself, from the git log | built in |
| How big is the codebase, per language | scc | brew |
| Is the repo itself healthy (huge blobs, deep trees) | git-sizer | brew |
| Where is the risk: hotspots, coupling, ownership | gitmole's own change analysis over git log --numstat |
built in |
| How old is the surviving code, per year and author | gitmole's own blame pass (one git blame per file at HEAD) |
built in |
| Code-age and survival plots over time | git-of-theseus | pip, opt-in with --plots |
| Per-function complexity, length, parameters | lizard | pip, installed with gitmole; tracked code files only |
| Which blocks of code appear more than once | jscpd | brew |
| Have secrets ever been committed | betterleaks | brew |
| Do the dependencies have known vulnerabilities | osv-scanner, offline against a local copy of the OSV database | brew, plus a one-time database download |
Why these and not others: docs/tools.md.
Docs
- Install: macOS, Linux, pipx, the check, pinned releases.
- Command line: every option, portfolio mode, exports and CI gates, big repositories.
- The report and the output files: what each section and each file means.
- Example reports: curl, django and react at pinned commits, regenerated by
bin/render-examples. - Validation: the watch list against other ways of ranking the same files at six cut-offs on three repositories.
- Why these tools: the rationale, what was left out, licences.
- Development: setup, tests, releases, code layout.
- Contributing: bugs, ideas, pull requests, security reports.
Safety
- Everything is offline except the optional clone step, which uses your existing gh auth. None of the tools send data anywhere; osv-scanner runs against a local copy of its database that you download once, and gitmole never downloads it for you.
- Remote targets are cloned into a fresh temp directory that is removed when
the run ends. Local clones are only read. The secrets scan reads every
branch; everything else describes the branch that is checked out.
gitmole --cleanlists every directory gitmole created and deletes them after a y/N question. - Secret values never reach the output directory. betterleaks reports to gitmole in memory, and gitmole stores a short keyed hash in place of the value, the matched text and the commit message. The key is random, made for that one report and never saved.
License
MIT. gitmole runs the tools it wraps as separate processes and bundles none of them; their licences are listed in docs/tools.md.
Release files for gitmole 0.9.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gitmole-0.9.0.tar.gz | 193.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gitmole-0.9.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 300.2 kB
Release files / gitmole-0.9.0.tar.gz
| Download URL | gitmole-0.9.0.tar.gz |
|---|---|
| Size | 193.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
64082b6b6f76be28cd9fc5baa7cad54b0db4f91d157929cd164e228625a0f6d4
|
|
BLAKE2b-256 checksum How to use checksums |
243e98a3cda7c5c0d06f0689eb9183ec293c2801d596c74177b6caab2875cc62
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.
Transparency logRelease files / gitmole-0.9.0-py3-none-any.whl
| Download URL | gitmole-0.9.0-py3-none-any.whl |
|---|---|
| Size | 106.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c949e9aa61187361db391f938658896d98a93f7a6f8a520a3b78c6b3fc46cbb8
|
|
BLAKE2b-256 checksum How to use checksums |
00f855300acc6d3a510fb22647690b696d58586a7664e02d8391e4e91bfdecfe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 17, 2026.
Transparency log