🩺 CodePulse
Reveal a codebase's health from its git history.
Linters read your code. CodePulse reads your code's history — and that reveals things no linter can see: where bugs are born, what knowledge lives in one person's head, and which files are secretly glued together.
Because it works purely from git history, CodePulse works on any language, with zero dependencies beyond git and Python.
Demo
$ codepulse . --badge
Grade: B (83/100)
-2 bus factor (9 fichiers à auteur unique)
-15 pression hotspots en hausse
-green)
$ codepulse . --changed origin/main
🔴 Release risk: HIGH (100/100)
56 changed files · 2 high-risk
[100] crates/ui-egui/src/lib.rs (hotspot majeur)
[ 70] crates/layout/src/para.rs (zone active, auteur unique)
👥 Relecteurs suggérés: Valentin Klein (29/37 fichiers), Dmitrii Khlapov (22/37)
$ codepulse . --who crates/ui-egui/src/canvas.rs
crates/ui-egui/src/canvas.rs — 64 commits, 22 auteur(s), dernier changement 2026-10-12
45% 29 commits Valentin Klein
11% 7 commits Dmitrii Khlapov
A recordable
demo.tape(for VHS) generates an animateddocs/demo.gifof the above.
What it shows
| Signal | Question it answers |
|---|---|
| 🔥 Hotspots | Where do I refactor first? Files that are both complex and changed constantly — the birthplace of most bugs. |
| 👥 Bus factor | What breaks if someone leaves? Files actively maintained by a single person. |
| 🔗 Hidden coupling | What really depends on what? Files that almost always change together, even when the code doesn't show a link. |
| 🏆 Contributors | Who is active across the analyzed window. |
The result is a single self-contained HTML dashboard you can open anywhere or email to your team.
Install
pip install codepulse-cli # installs the `codepulse` command
Quick start
# From a git repository:
codepulse /path/to/repo --open
# Common options:
codepulse . --since "6 months ago" --top 30 -o health.html
Running from a source checkout instead? Use
python -m codepulsewithPYTHONPATH=src, orpip install -e ..
Options
| Flag | Meaning |
|---|---|
repo |
Path to a git repository (default: current directory) |
-o, --output |
Output HTML path (default: codepulse-report.html) |
--since |
Only commits after a date, e.g. "6 months ago" |
--max-count N |
Limit to the N most recent commits |
--top N |
Rows per table (default: 20) |
--open |
Open the report in a browser when done |
--who PATH |
Show who knows a file best (from history) and exit |
--badge |
Print a shields.io health-badge snippet and exit |
--ignore GLOB |
Exclude paths matching a glob (repeatable) |
Use in CI (the risk gate)
CodePulse can score only the files a change touches against the repo's risk map, then set an exit code so your pipeline can warn or block.
# Score what this branch changed vs main; fail the job on HIGH risk.
python -m codepulse . --changed origin/main --fail-on HIGH
# Machine-readable output for dashboards / PR comments:
python -m codepulse . --changed origin/main --format json
Output (JSON):
{
"level": "HIGH",
"score": 100,
"high_risk_count": 1,
"files": [
{ "path": "auth.py", "risk": 100, "commits": 6, "loc": 7,
"reasons": ["hotspot majeur", "auteur unique (Alice)"] }
]
}
GitHub Action (two lines)
Add CodePulse to any repository as a reusable Action — it scores each PR, posts
a sticky comment (updated in place, never spammed), and fails the check on
HIGH risk:
name: CodePulse
on: pull_request
permissions:
contents: read
pull-requests: write
jobs:
risk:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 } # full history is required
- uses: Mehouelley/codepulse@v0.1.0
with:
fail-on: HIGH # or MEDIUM / LOW / '' to never fail
The PR comment looks like:
🩺 CodePulse — Risque : 🔴 HIGH (100/100) 38 fichiers modifiés · 1 à risque élevé
👥 Relecteurs suggérés : Valentin Klein (29/37 fichiers), Dmitrii Khlapov (22/37)
Prefer a plain workflow with no external action? One ships in
.github/workflows/codepulse.yml — copy it in as-is.
Why DevOps cares: a release is roughly as risky as its riskiest file. Touching a well-known hotspot — or a file only one person understands — is exactly where change-failure-rate (a DORA metric) comes from. The gate makes that risk visible before merge, not after an incident.
How it works
- Parses
git log --numstatinto commits and file changes (no merges). - Accumulates per-file history: commit count, authors, size on disk.
- Derives the signals:
- Hotspot score =
commits × complexity, where complexity estimates decision points (branch keywords + boolean operators) — far better than raw line count at telling "big but simple" from "dense and risky". - Bus factor risk = files with ≥3 commits but exactly one author.
- Coupling degree =
commits-together / min(individual commits), ignoring bulk commits that touch many files at once.
- Hotspot score =
Inspired by the "code as a crime scene" approach to software analysis, made simple enough to run in one command.
Roadmap
- Risk gate: score a change set, JSON output, CI exit code
- Ignore globs / path filters for generated & data files
- Post the gate result as a sticky PR comment (GitHub Action)
- Trend over time (adaptive day/week/month buckets + hotspot-pressure verdict)
- Complexity-based hotspots (decision-point estimate instead of line count)
- Suggested PR reviewers from code ownership (in gate text/json/comment)
-
--who <file>— who knows this code best -
--badge— shareable A–F health badge for your README - Orphaned-code section — complex files nobody touches anymore
Development
pip install -e ".[dev]"
pytest
The suite covers the complexity estimator, git parsing, every analyzer, and an end-to-end run against a throwaway git repo. CI runs it on Python 3.10 and 3.12.
License
MIT
Metadata
Release files for codepulse-cli 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| codepulse_cli-0.1.2.tar.gz | 25.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| codepulse_cli-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 50.8 kB
Release files / codepulse_cli-0.1.2.tar.gz
| Download URL | codepulse_cli-0.1.2.tar.gz |
|---|---|
| Size | 25.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
933298a9c14bf0d9ba5542b713cd0bc5e3cf356beab04549b8d9dcc52a4562f4
|
|
BLAKE2b-256 checksum How to use checksums |
deae4f8461594fee8bae59f6599f80840b8664e537e204405623460ac0a1a0d3
|
| 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 Oct 12, 2026.
Transparency logRelease files / codepulse_cli-0.1.2-py3-none-any.whl
| Download URL | codepulse_cli-0.1.2-py3-none-any.whl |
|---|---|
| Size | 25.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a418b2149aff5dc25d7e8f740dce0f77e15e25c33f8bcfbb93a98d07428237f4
|
|
BLAKE2b-256 checksum How to use checksums |
cfc8e3a2628e83244952b7fa225a5d8500f8b78a91dd1bac802512a87e5a9275
|
| 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 Oct 12, 2026.
Transparency log