skills/code-quality/technical-debt-analyzer/SKILL.md
Analyzes a codebase to quantify and locate technical debt — where it lives, what it costs, and what order to pay it down in. Use when planning a refactoring sprint, when justifying engineering time to stakeholders, when the user asks where the codebase hurts most, or when onboarding to a legacy system.
npx skillsauth add santosomar/general-secure-coding-agent-skills technical-debt-analyzerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Technical debt is a cost metaphor: structure you'd build differently today, paid for in slower future changes. The analysis question is not "where is the bad code?" — it's "where does the bad code cost the most?"
debt_cost(file) = interest_rate(file) × principal(file)
A terrible file nobody touches has high principal, zero interest → zero cost. Pay down debt where the product is high.
| Signal | How to measure | What it tells you |
| ------------------------- | ------------------------------------------------------------------ | ------------------------------------ |
| Change frequency | git log --since=6.months --format= --name-only \| sort \| uniq -c | Interest rate |
| Churn (lines changed) | git log --since=6.months --numstat | Interest rate (finer-grained) |
| Complexity | Cyclomatic complexity, nesting depth, LOC per function | Principal |
| Smell density | → code-smell-detector findings per KLOC | Principal |
| Coupling | Fan-in (how many files import this) | Blast radius — changes here break many things |
| Bug concentration | git log --grep=fix --format= --name-only \| sort \| uniq -c | Where bugs actually happen — empirical interest |
| Test coverage | Coverage report | Cost of safe refactor — low coverage = high risk |
| Author count | git log --format=%an -- <file> \| sort -u \| wc -l | Knowledge fragmentation — 8 authors, nobody owns it |
| TODO/FIXME/HACK | rg 'TODO\|FIXME\|HACK\|XXX' | Self-reported debt — the team already knows |
Plot files on two axes: complexity (y) vs change frequency (x).
│ (cold+complex) (HOT+complex) ← pay down here
complexity │ low priority HIGH PRIORITY
│
│ (cold+simple) (hot+simple)
│ ignore healthy — leave alone
└──────────────────────────────────
change frequency
The upper-right quadrant is where every sprint loses time. That's the paydown target.
Input: Mid-size service, ~200 files. After gathering signals:
| File | Commits (6mo) | Cyclomatic | Bugs (6mo) | Coverage | Authors |
| ----------------------- | ------------- | ---------- | ---------- | -------- | ------- |
| billing/invoice.py | 34 | 58 | 7 | 31% | 6 |
| api/handlers.py | 41 | 22 | 2 | 78% | 4 |
| legacy/xml_export.py | 2 | 91 | 0 | 0% | 1 |
| utils/date.py | 19 | 8 | 1 | 95% | 3 |
Analysis:
billing/invoice.py: Top priority. High churn + high complexity + high bugs + low coverage = you're paying maximum interest on maximum principal, and you can't safely refactor it. Step 1 is coverage.api/handlers.py: High churn but moderate complexity and good coverage. This is healthy hot code — it changes because the product changes. Leave it.legacy/xml_export.py: Off-the-charts complexity, zero coverage — but 2 commits in 6 months and zero bugs. It's frozen. Principal is huge but interest is zero. Don't touch.utils/date.py: Boring. Fine.Output:
Debt hotspots
billing/invoice.py— 34 commits, cyclomatic 58, 7 bugs, 31% coverage. Every billing change takes 2× longer than it should. Seven bugs in six months is the highest concentration in the codebase. Paydown plan: (a) add characterization tests to reach 70% coverage — ~3 days; (b) extractInvoiceCalculatorfrom the 200-linecompute()— ~2 days; (c) splitInvoicegod class by state (draft vs. issued) — ~1 week. Step (a) is a prerequisite; do not skip.Explicitly not paying down
legacy/xml_export.py— complexity 91, but 2 commits in 6 months and zero bugs. Stable. Touching it is risk without reward.
Some debt is in people's heads, not in the AST:
Ask about these. They don't show up in git log.
## Hotspots (pay down)
<N>. <file> — <churn> commits, complexity <N>, <N> bugs, <N>% coverage
Interest: <what this costs per sprint — be concrete>
Principal: <what the refactor is, roughly how long>
Prerequisite: <coverage? knowledge? — anything blocking safe refactor>
## Explicitly deferred (high principal, low interest)
- <file> — <why it's safe to ignore>
## Non-code debt (from asking, not measuring)
- <knowledge / decision / dependency debt>
development
Extracts human-readable pseudocode from a verified formal artifact (Dafny, Lean, TLA+) while preserving the verified properties as annotations, so the proof-carrying logic can be reimplemented in a production language. Use when porting verified code to an unverified target, when documenting what a formal spec actually does, or when handing a verified algorithm to an implementer.
development
Translates natural-language or pseudocode descriptions of concurrent and distributed systems into TLA+ specifications ready for the TLC model checker. Identifies state variables, actions, type invariants, safety properties, and liveness properties from the description. Use when formalizing a protocol, when the user describes a distributed algorithm to verify, when designing a consensus or locking scheme, or when starting formal verification of a concurrent system.
testing
Reduces a TLA+ model so TLC can actually check it — shrinks constants, adds state constraints, abstracts data, or applies symmetry — when the state space is too large to enumerate. Use when TLC runs out of memory, when checking takes hours, or when a spec works at N=2 and you need confidence at larger scale.
development
TLA+-specific instance of model-guided repair — reads a TLC error trace, identifies the enabling condition that should have been false, strengthens the corresponding action, and maps the fix to source code. Use when TLC reports an invariant violation or deadlock and you have the code-to-TLA+ mapping from extraction.