A fast Rust CLI that scores source files by hotspot risk — combining lines of code, cyclomatic complexity, git churn, and gzip density into a single actionable ranking.
score = LoC × churn × complexity
Files ranked highest are large, frequently changed, and full of branches — the true hotspots where refactoring effort pays off most.
cargo install --git https://github.com/janhesters/churnex# Scan current directory (defaults to .ts, .tsx, .js, .jsx)
churnex .
# Explicit extensions and options
churnex src/ --ext ts,tsx,js,jsx
churnex . --days 90 # churn window (default: 90)
churnex . --top 20 # limit output (default: 20)
churnex . --min-loc 50 # exclude small files
churnex . --json # machine-readable output
churnex . --no-churn # skip git, score = LoC × complexity
# Specific files
churnex file1.ts file2.tsx file3.ts
# Pipe from git (PR workflow)
git diff --name-only main..HEAD -- '*.ts' '*.tsx' | churnex --stdin
# CI gates (exit code 1 on threshold violation)
churnex . --max-complexity 25
churnex . --max-score 50000 Score LoC Churn Cx Density File
─────────────────────────────────────────────────────────
284160 480 12 37 62.3% src/routes/dashboard.tsx
98304 256 8 48 41.2% src/utils/parser.ts
45000 300 5 30 78.1% src/components/Form.tsx
[
{
"file": "src/routes/dashboard.tsx",
"score": 284160,
"loc": 480,
"churn": 12,
"complexity": 37,
"density": 62.3
}
]| Metric | In Score | Description |
|---|---|---|
| LoC | Yes | Total lines (SLOC) — more code = more surface area for bugs |
| Churn | Yes | Commits touching the file in the --days window — instability predicts defects |
| Complexity | Yes | Cyclomatic complexity — branches (if, for, switch, &&, ||, etc.) |
| Density | No | Gzip compression ratio — low % = repetitive/copy-pasted code worth deduplicating |
- File discovery — walks directories respecting
.gitignore(via theignorecrate) - Metrics — parses each file with rust-code-analysis (tree-sitter) for LoC and cyclomatic complexity, compresses with
flate2for density - Churn — counts commits per file via
git2(libgit2 bindings, no subprocess) - Scoring —
LoC × churn × complexity, sorted descending - Parallelism — all file analysis runs in parallel via
rayon
MIT