From asynkron-devtools
Identifies and explains churn hotspots and unstable code clusters in git repos. Groups by directory, filename stems (e.g. foo.go + foo_test.go), and co-changes; classifies as unstable, buggy, tightly-coupled, etc.
npx claudepluginhub asynkron/asynkron-skills --plugin asynkron-devtoolsThis skill uses the workspace's default tool permissions.
Identifies *clusters* of high-churn code and explains why they're problematic — not just a ranked file list. The user wants insight: which areas of the codebase are unstable, why, and what to do.
Analyzes git history to detect codebase hotspots (frequent changes/bug fixes), decay signals (accelerating churn), and inconsistencies (multiple authors/patterns). Use before refactoring or investigating recurring bugs.
Identifies riskiest codebase files using git churn analysis, complexity metrics, coupling, and lenskit risk scores for technical debt hotspots.
Analyzes git history to find code hotspots, temporal coupling between files, contributor knowledge distribution, and bus factor risks. Useful for queries on code ownership, frequent changes, or evolution.
Share bugs, ideas, or general feedback.
Identifies clusters of high-churn code and explains why they're problematic — not just a ranked file list. The user wants insight: which areas of the codebase are unstable, why, and what to do.
Trigger phrases: "hotmess", "hotspots", "what's churning", "unstable code", "where's the technical debt", "what's a mess in X", "/hotmess ". Always invoke for these — even if the user gives no time window or extension, fall back to sensible defaults (30 days, auto code detection).
Always invoke this skill's bundled analyzer (scripts/analyze.py, in this skill's base directory), which emits structured JSON with four signal sets. Do not reimplement git log parsing inline.
"<SKILL_DIR>/scripts/analyze.py" <path> --since "<expr>" [--ext .go,.ts] [--top N] [--html /tmp/hotmess.html] [--quiet]
<SKILL_DIR> is the "Base directory for this skill" path provided when the skill is invoked. Run from inside the target git repo (or pass an absolute path; git resolves it).
Defaults: --since "30 days ago", --top 30, auto-detected code extensions.
If the user asks for a visualization, diagram, picture, "show me", chart, or graph — also pass --html /tmp/hotmess.html and then open /tmp/hotmess.html. Use --quiet together with --html if you don't need the JSON in the same call. The HTML page contains a Mermaid module map (modules colored by classification, edges = cross-directory co-change), plus collapsible tables for stems and co-change pairs.
Requires Python 3.8+ (stdlib only) and git on PATH.
Period shorthand to translate before passing to --since:
7d → "7 days ago", 2w → "2 weeks ago", 1m → "1 month ago"2026-04-01) → pass through unchangedscope { path, since, ext, recent_window_days }
totals { commits, files, add, del }
files[] per file: commits, add, del, last, authors, recent_commits_7d, is_test
directories[] aggregated per parent dir (depth 1..3): commits, add, del, files
stems[] basename groups (foo.go + foo_test.go): members, commits, add, del, test_ratio
cochange[] pairs of files often changed together: a, b, together, a_total, b_total, jaccard
recent_commits_7d lets you see if churn is concentrated now vs. spread across the window. test_ratio is the share of stem-group commits that hit test files. jaccard is overlap (1.0 = always change together).
Read the JSON and identify clusters. A cluster is a coherent group of files — usually a directory, a stem, or a co-change pair/triangle. For each meaningful cluster, classify it using the heuristics below, and explain why it matters.
| Signal pattern | Likely classification | What it means |
|---|---|---|
| High commits, balanced add/del, multiple authors, sustained over window | Instabil / dåligt kravställd | Koden skrivs om i cykler — kraven eller designen är inte stabila |
High commits, mostly + lines, recent burst, 1-2 authors | Under aktiv utveckling | Pågående feature-arbete, förväntat — flagga bara om det varat länge |
| High commits, small commits (low avg lines), same author repeatedly | Buggig | Många små fixar — symptom på instabil logik eller dålig täckning |
Stem-grupp där test_ratio > 0.45 | Specifikation flyttar sig | Testerna ändras nästan lika mycket som koden — kraven är inte fastlagda |
Co-change-par med jaccard > 0.6 | Tät logisk koppling | Två filer som "alltid" ändras ihop — kanske dålig separation eller borde slås ihop |
| Hela mappen het (>30% av totala commits) | Hotspot-modul | Arkitekturproblem snarare än enskilda filer — hela ansvarsområdet är instabilt |
Recent burst (recent_commits_7d är majoriteten) i fil som inte är ny | Akut instabilitet | Något hände nyligen — incident, refaktor, eller problem |
Multiple signals stack — a cluster can be both "spec shifting" and "tightly coupled". Say so.
Don't dump the JSON. Don't list every file. Produce a short narrative report:
# Hotmess: <path> (<since>, <ext>)
<one-line summary: total commits, files, period — and the headline finding>
## Cluster 1: <name> — <classification>
**Files:** `a.go`, `b.go`, `c.go` (X commits combined)
**Signal:** <the specific numbers that triggered the classification — e.g. "test_ratio 0.51, jaccard with state.go 0.75">
**Why it's a problem:** <one or two sentences explaining the consequence>
**Suggested action:** <concrete next step — split, stabilise spec, add tests, refactor coupling, etc.>
## Cluster 2: ...
## Notable individual files
(only if a single file stands out and doesn't belong to a cluster — keep to 2-3 max)
## Co-change couplings worth knowing
(only the top 3-5 jaccard pairs that aren't already covered by clusters above)
Keep it concise — aim for 4-6 clusters max. Skip anything that's clearly normal activity. The goal is signal, not exhaustiveness.