churnmap
Coupling heatmap generator — visualize co-change risk in any git repo.
churnmap is a dead-simple CLI that analyzes any git repository's co-change history and generates a two-tab interactive HTML report — a coupling heatmap and a D3 force graph — plus a machine-readable JSON file. It is the open-source CodeScene replacement for local, ad-hoc coupling audits.
One command, two files. No signup, no external service, no Kubernetes.
Install
pip install churnmap
Or with uv:
uv tool install churnmap
Usage
# Analyze the current directory
churnmap
# Analyze a specific repo with custom settings
churnmap \
--repo /path/to/repo \
--output-dir ./my-report \
--lookback-days 180 \
--min-occurrences 5 \
--heatmap-limit 30 \
--format both \
--open
Output is written to ./coupling-report/:
coupling-report/
├── index.html # Two-tab interactive report (Heatmap + Force Graph + Table)
└── report.json # Machine-readable JSON with meta + pairs envelope
Flags
| Flag | Type | Default | Description |
|---|---|---|---|
--repo |
Path |
. |
Path to git repository root |
--output-dir |
Path |
./coupling-report |
Output directory for report files |
--lookback-days |
int |
90 |
Days of git history to analyze |
--min-occurrences |
int |
3 |
Minimum co-change count to include a pair |
--heatmap-limit |
int |
50 |
Max files in heatmap (top by max coupling score) |
--top-files |
int |
100 |
Max pairs in HTML table |
--format |
str |
both |
Output format: both, html, json |
--exclude |
list[str] |
[] |
Glob patterns to exclude (repeatable) |
--low-threshold |
float |
0.3 |
Score below this is 🟢 Low |
--high-threshold |
float |
0.7 |
Score above this is 🔴 High |
--open |
bool |
False |
Open HTML report in browser after generation |
--version |
flag | — | Print version and exit |
Output
index.html— self-contained, three-tab D3-powered report. Heatmap tab shows top-N files by max coupling score with color-coded cells. Force Graph tab shows file relationships with node size = churn and edge thickness = coupling score. Table tab lists top pairs.report.json— envelope withmeta(repo name, generation date, lookback days, total commits analyzed, churnmap version) andpairs(all coupling pairs abovemin_occurrences, sorted by score descending).
Config file
Drop a .churnmap.yml in your repo root to set defaults:
lookback_days: 90
min_occurrences: 3
heatmap_limit: 50
top_files: 100
format: both
low_threshold: 0.3
high_threshold: 0.7
open: false
exclude:
- "docs/**"
- "*.md"
- "migrations/**"
CLI flags override config file values.
How it works
coupling-coreparses the git history, builds a co-change matrix, normalizes scores into the 0–1 range, and returns aRepoAnalysis.DataPreparerturns the analysis into a heatmap matrix, force-graph nodes/links, and a table-pairs list.HtmlRendererrenders a Jinja2 template containing embedded JSON data and D3.js (loaded from CDN).JsonWriteremits the machine-readable envelope.OutputWritercreates the output directory and writes both files.
Report screenshot
┌──────────────────────────────────────────────────────────────┐
│ ChurnMap — Meru143/churnmap │
│ Total pairs: 42 • Max score: 0.91 • Commits: 342 │
│ │
│ [ Heatmap ] [ Force Graph ] [ Table ] │
│ ───────── │
│ │
│ src/ src/ src/ ... │
│ a.py b.py c.py │
│ a.py ▓▓ ░░ ▒▒ │
│ b.py ░░ ▓▓ ▓▓ │
│ c.py ▒▒ ▓▓ ▓▓ │
│ │
└──────────────────────────────────────────────────────────────┘
Used alongside
- couplingguard — PR-time coupling warning as a GitHub Action. Same
coupling-coreengine, complementary surface.
License
Metadata
Release files for churnmap 1.0.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 | |
|---|---|---|---|
| churnmap-1.0.0.tar.gz | 18.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| churnmap-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 35.0 kB
Release files / churnmap-1.0.0.tar.gz
| Download URL | churnmap-1.0.0.tar.gz |
|---|---|
| Size | 18.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a2b6de8d7cbd8b758cf1eca7c3881b2f04e68fd715420d72a0d3ed33de29ce40
|
|
BLAKE2b-256 checksum How to use checksums |
360f62c8f1084254c6f37b1dc598b9d212989ba499e6d1237cbfef5d79e02dd7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 May 28, 2026.
Transparency logRelease files / churnmap-1.0.0-py3-none-any.whl
| Download URL | churnmap-1.0.0-py3-none-any.whl |
|---|---|
| Size | 16.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a6e61ec5f589247eb1216da4b7759d99f9e50cef0f644325313b198e37b59b89
|
|
BLAKE2b-256 checksum How to use checksums |
2792dd2ab9804f327cc776a4a1f3c96f73b8d725e3cbd3401fe82253e3de7133
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 May 28, 2026.
Transparency log