Coupling heatmap generator — visualize co-change risk in any git repo
Project description
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file churnmap-1.0.0.tar.gz.
File metadata
- Download URL: churnmap-1.0.0.tar.gz
- Upload date:
- Size: 18.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a2b6de8d7cbd8b758cf1eca7c3881b2f04e68fd715420d72a0d3ed33de29ce40
|
|
| MD5 |
af259a94d8de334bf906f0e2bde9ef1b
|
|
| BLAKE2b-256 |
360f62c8f1084254c6f37b1dc598b9d212989ba499e6d1237cbfef5d79e02dd7
|
Provenance
The following attestation bundles were made for churnmap-1.0.0.tar.gz:
Publisher:
release.yml on Meru143/churnmap
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
churnmap-1.0.0.tar.gz -
Subject digest:
a2b6de8d7cbd8b758cf1eca7c3881b2f04e68fd715420d72a0d3ed33de29ce40 - Sigstore transparency entry: 1655603122
- Sigstore integration time:
-
Permalink:
Meru143/churnmap@7481dee30012c3d20c3dfd8ad91be3dd43ec7564 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Meru143
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7481dee30012c3d20c3dfd8ad91be3dd43ec7564 -
Trigger Event:
push
-
Statement type:
File details
Details for the file churnmap-1.0.0-py3-none-any.whl.
File metadata
- Download URL: churnmap-1.0.0-py3-none-any.whl
- Upload date:
- Size: 16.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6e61ec5f589247eb1216da4b7759d99f9e50cef0f644325313b198e37b59b89
|
|
| MD5 |
f94ac5cce876e2a11da543163ca00cc2
|
|
| BLAKE2b-256 |
2792dd2ab9804f327cc776a4a1f3c96f73b8d725e3cbd3401fe82253e3de7133
|
Provenance
The following attestation bundles were made for churnmap-1.0.0-py3-none-any.whl:
Publisher:
release.yml on Meru143/churnmap
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
churnmap-1.0.0-py3-none-any.whl -
Subject digest:
a6e61ec5f589247eb1216da4b7759d99f9e50cef0f644325313b198e37b59b89 - Sigstore transparency entry: 1655603437
- Sigstore integration time:
-
Permalink:
Meru143/churnmap@7481dee30012c3d20c3dfd8ad91be3dd43ec7564 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Meru143
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7481dee30012c3d20c3dfd8ad91be3dd43ec7564 -
Trigger Event:
push
-
Statement type: