Codebase Health Checker
Runs a comprehensive health check on your codebase: dead code, circular dependencies, outdated packages, security vulnerabilities, and technical debt.
Codebase Health Checker
Audit your codebase for technical debt, code smells, dependency risks, test coverage gaps, and maintainability issues with actionable improvement recommendations.
When to Use This Template
Choose Codebase Health Checker when:
- You want a comprehensive audit of code quality across an entire project
- You are inheriting a codebase and need to assess its state quickly
- You need to prioritize technical debt reduction with objective metrics
- Sprint planning requires data on which areas of the code need attention
Consider alternatives when:
- You need real-time code quality gates (use SonarQube or CodeClimate in CI)
- You want automated code formatting only (use Prettier or Black)
- You need security vulnerability scanning (use Snyk or Dependabot)
Quick Start
# .claude/skills/codebase-health-checker.yml name: codebase-health-checker description: Audit codebase for quality, debt, and maintainability prompt: | Perform a comprehensive health check on this codebase. Analyze: 1. Code complexity (cyclomatic complexity, function length) 2. Dependency health (outdated, deprecated, vulnerable) 3. Test coverage and quality 4. Code duplication 5. Dead code and unused exports 6. Documentation coverage 7. Consistency (naming, patterns, file structure) Output a health report card with scores and prioritized action items.
Example invocation:
claude "Run a health check on the src/ directory and prioritize fixes"
Sample health report:
Codebase Health Report ā src/
āāāāāāāāāāāāāāāāāāāāāāāāāāāā
Overall Score: 72/100 (Fair)
Category Scores:
Complexity: āāāāāāāāāā 78/100
Dependencies: āāāāāāāāāā 62/100
Test Coverage: āāāāāāāāāā 68/100
Duplication: āāāāāāāāāā 85/100
Dead Code: āāāāāāāāāā 80/100
Documentation: āāāāāāāāāā 52/100
Consistency: āāāāāāāāāā 76/100
Top 5 Action Items:
1. [HIGH] 12 dependencies are 2+ major versions behind
2. [HIGH] src/services/payment.ts has cyclomatic complexity of 47
3. [MED] Test coverage for src/utils/ is 34% (target: 80%)
4. [MED] 23 exported functions are never imported
5. [LOW] Inconsistent naming: mix of camelCase and snake_case
Core Concepts
Health Dimensions
| Dimension | What It Measures | Healthy Threshold |
|---|---|---|
| Complexity | Cyclomatic complexity per function | < 10 per function |
| Dependencies | Outdated, deprecated, or vulnerable deps | 0 critical, < 5 outdated |
| Test Coverage | Line and branch coverage | > 80% lines, > 70% branches |
| Duplication | Repeated code blocks | < 3% duplicated lines |
| Dead Code | Unused exports, unreachable paths | 0 unused exports |
| Documentation | JSDoc/docstring coverage on exports | > 60% public APIs documented |
| Consistency | Naming, patterns, file organization | < 5 inconsistencies |
Automated Analysis Scripts
// Complexity analysis const { analyzeComplexity } = require('./analyzers'); function checkComplexity(srcDir) { const results = []; const files = glob.sync(`${srcDir}/**/*.{ts,tsx,js,jsx}`); for (const file of files) { const ast = parse(readFileSync(file, 'utf8')); const functions = extractFunctions(ast); for (const fn of functions) { const complexity = calculateCyclomaticComplexity(fn.node); if (complexity > 10) { results.push({ file, function: fn.name, complexity, lines: fn.endLine - fn.startLine, severity: complexity > 20 ? 'high' : 'medium', suggestion: complexity > 20 ? 'Extract into smaller functions with single responsibilities' : 'Consider simplifying conditional logic' }); } } } return results.sort((a, b) => b.complexity - a.complexity); }
# Dependency health check npx npm-check-updates --format group # Group by major/minor/patch npx depcheck # Find unused dependencies npm audit --json # Security vulnerabilities
Scoring Algorithm
interface HealthScore { category: string; score: number; // 0-100 weight: number; // Relative importance findings: Finding[]; trend: 'improving' | 'stable' | 'declining'; } function calculateOverallScore(scores: HealthScore[]): number { const totalWeight = scores.reduce((sum, s) => sum + s.weight, 0); const weightedSum = scores.reduce((sum, s) => sum + s.score * s.weight, 0); return Math.round(weightedSum / totalWeight); } // Default weights const weights = { complexity: 20, dependencies: 20, testCoverage: 20, duplication: 10, deadCode: 10, documentation: 10, consistency: 10 };
Configuration
| Option | Type | Default | Description |
|---|---|---|---|
scanPaths | string[] | ["src"] | Directories to analyze |
excludePaths | string[] | ["node_modules", "dist"] | Directories to skip |
complexityThreshold | number | 10 | Max acceptable cyclomatic complexity |
coverageTarget | number | 80 | Target test coverage percentage |
duplicationThreshold | number | 3 | Max acceptable duplication percentage |
checkDependencies | boolean | true | Run dependency health analysis |
outputFormat | string | "markdown" | Report format: markdown, json, html |
Best Practices
-
Run health checks on a schedule, not just once ā Set up a weekly or per-sprint health check to track trends over time. A single snapshot tells you the current state; a trend line tells you whether the codebase is improving or degrading. Store historical scores for comparison.
-
Focus on high-complexity, high-churn files ā Files that are both complex (high cyclomatic complexity) and frequently changed (high git commit count) are the highest-risk targets. Use
git log --format='%H' -- filename | wc -lto measure churn and cross-reference with complexity scores. -
Track dead code before it accumulates ā Run unused export detection as part of CI. Every unused export was once "might need it later" code that now confuses new developers and inflates bundle sizes. Delete unused code confidently since git preserves history.
-
Set team-agreed thresholds, not arbitrary ones ā Default thresholds are starting points. A data pipeline with inherently complex transformations may reasonably have complexity of 15, while a CRUD API should stay under 8. Agree on per-module thresholds that reflect actual requirements.
-
Prioritize fixes by blast radius ā A utility function used in 50 files with poor type safety has a larger blast radius than a complex function used in one place. Weight action items by the number of dependents and the severity of the issue.
Common Issues
False positives on complexity for switch statements ā A function with a 20-case switch statement (e.g., mapping status codes to messages) gets flagged as highly complex, but it is simple and readable. Exclude pure mapping functions from complexity analysis, or use a lookup object instead of a switch to reduce the measured complexity.
Dependency scanner flags transitive vulnerabilities you cannot fix ā npm audit reports a critical vulnerability in a sub-dependency three levels deep, but the direct dependency has not released a fix. Document the risk in your security exceptions file, check if the vulnerable code path is actually reachable in your usage, and set up Dependabot to alert when the fix is released.
Test coverage percentage is misleading ā 90% line coverage does not mean the code is well tested. Lines can be "covered" by tests that never assert on the output. Supplement line coverage with branch coverage and mutation testing (using tools like Stryker) to ensure tests actually verify behavior, not just execute code paths.
Reviews
No reviews yet. Be the first to review this template!
Similar Templates
Full-Stack Code Reviewer
Comprehensive code review skill that checks for security vulnerabilities, performance issues, accessibility, and best practices across frontend and backend code.
Test Suite Generator
Generates comprehensive test suites with unit tests, integration tests, and edge cases. Supports Jest, Vitest, Pytest, and Go testing.
Pro Architecture Workspace
Battle-tested skill for architectural, decision, making, framework. Includes structured workflows, validation checks, and reusable patterns for development.