By Arjun Mehta
Codebase Health: The CLI Commands Every PM Should Know About
PMs usually don't interact with code directly. But PMs should understand what their codebase looks like.
You don't need to learn the code itself. You just need to understand its health.
This guide introduces simple CLI commands that give you visibility into codebase health. You can run these commands without being an expert engineer.
Why Codebase Health Matters
A healthy codebase is:
- Easy to understand
- Easy to modify
- Easy to test
- Easy to deploy
An unhealthy codebase is:
- Hard to understand
- Hard to modify
- Hard to test
- Slow to deploy
Codebase health directly impacts feature velocity. You should understand it.
Metrics That Matter
Metric 1: Lines of Code
How big is the codebase?
find . -name "*.py" -type f | xargs wc -l | tail -1
For a Python project, this counts total lines of Python code.
What it means:
- < 10,000 lines: Small project, easy to understand
- 10,000 - 100,000 lines: Medium project, manageable
- 100,000 - 1,000,000 lines: Large project, complexity building
-
1,000,000 lines: Very large project, significant complexity
Warning sign: Sudden jumps in lines of code (100K to 500K in one quarter) indicate either major features or technical debt accumulation.
Metric 2: Number of Files
How many files does the project have?
find . -name "*.py" -type f | wc -l
What it means:
- Fewer files = simpler organization
- More files = harder to navigate
- Very large number of small files = poor module organization
Metric 3: Duplicate Code
How much code is duplicated?
# Requires duplication detection tool (pylint, etc.)
pylint --duplicate-code-check
What it means:
-
10% duplication: High, refactor needed
- 5-10% duplication: Moderate, some refactoring
- < 5% duplication: Good
Why it matters: Duplicated code is a maintenance nightmare. Change it in one place, miss it in another, and bugs emerge.
Metric 4: Test Coverage
What percentage of code is tested?
coverage run -m pytest && coverage report
What it means:
-
80% coverage: Good
- 50-80% coverage: Adequate, but gaps
- < 50% coverage: Poor, risky changes
Interpretation: Coverage isn't everything. 100% coverage of bad tests is worthless. But < 50% coverage is a red flag.
Metric 5: Cyclomatic Complexity
How complex is the code?
# Requires complexity analysis tool
radon cc -s .
What it means:
- < 5: Simple, easy to understand
- 5-10: Moderate, manageable
- 10-20: High, hard to understand
-
20: Very high, refactor needed
Why it matters: Complex code is hard to modify and full of bugs.
Metric 6: Dependency Count
How many dependencies does the project have?
# For Python
pip list | wc -l
# For Node
npm list --depth=0 | wc -l
What it means:
-
100 dependencies: Too many, bloated
- 20-50 dependencies: Reasonable
- < 20 dependencies: Minimal
Why it matters: More dependencies = more maintenance, more security vulnerabilities, more compatibility issues.
Metric 7: Code Age
How old is the code?
# Find files not modified in the last year
find . -name "*.py" -type f -mtime +365
What it means:
- Large amount of old code: Either stable (good) or abandoned (bad)
- Everything modified recently: Good, actively maintained
Interpretation: Context matters. Stable core code that doesn't change often is fine. But dead code should be removed.
Creating a Health Dashboard
Instead of running commands manually, create a script:
#!/bin/bash
echo "=== Codebase Health ==="
echo ""
echo "Lines of Code:"
find . -name "*.py" -type f | xargs wc -l | tail -1
echo ""
echo "Number of Files:"
find . -name "*.py" -type f | wc -l
echo ""
echo "Test Coverage:"
coverage run -m pytest && coverage report --omit=tests
echo ""
echo "Complexity Issues:"
radon cc -s . | grep -E "(HIGH | VERY HIGH)"
Run this monthly and track changes.
Interpreting the Numbers
Healthy Codebase
- Lines of code: Stable or growing slowly
- Test coverage: > 80%
- Complexity: Most functions < 10
- Duplication: < 5%
- Dependencies: Stable
Warning Signs
- Lines of code doubling every quarter (more than feature growth)
- Test coverage dropping
- More complex functions (high cyclomatic complexity)
- Increasing duplication
- Dependency count increasing rapidly
Crisis Signs
- Lines of code 10x in one quarter (major refactoring or technical debt)
- Test coverage near 0%
- Average complexity > 20
-
20% duplication
- 100+ new dependencies
How to Use This Information
If Code is Healthy
Keep the team moving. Continue current practices.
If Code Shows Warning Signs
Start allocating time for refactoring:
- "We're seeing duplication increase. Let's allocate 1 sprint to reduce it."
- "Test coverage is dropping. Let's prioritize test writing."
- "Dependencies are growing. Let's audit unused ones."
If Code is in Crisis
Allocate significant time for recovery:
- "Complexity is out of control. We need 3 sprints to refactor."
- "Test coverage is near 0%. We need to pause feature work and write tests."
- "Duplication is 30%. Major refactoring is needed."
Communicating to Leadership
When showing codebase metrics:
Healthy codebase: "Our code is well-maintained. Test coverage is 85%, complexity is low, and we have minimal duplication. This supports fast feature development."
Warning signs: "Our test coverage is dropping (from 85% to 75%) and complexity is increasing. If we don't address this, feature velocity will slow down in 2-3 months. I recommend allocating 1 sprint to refactoring."
Crisis: "Our codebase is in poor health. Test coverage is 20%, complexity is very high, and duplication is 30%. This is limiting our velocity. We need to pause feature work and invest 3 sprints in refactoring."
Tools to Use
Python:
radon: Complexity analysiscoverage: Test coveragepylint: Code quality
JavaScript:
eslint: Code qualityjest: Test coveragecomplexity-report: Complexity analysis
Go:
go fmt: Code qualitygo test -cover: Test coveragego vet: Bug detection
Most tools have CI/CD integration, so metrics are tracked automatically.
Getting Started
- Run baseline metrics - Where is the codebase now?
- Create a dashboard - Track metrics monthly
- Set targets - What's healthy for your project?
- Monitor trends - Are metrics improving or degrading?
- Act on warnings - If metrics degrade, invest in fixing them
You don't need to be a developer to understand codebase health. These simple metrics tell you everything you need to know.
Frequently Asked Questions
Q: Which metric is most important? A: Test coverage. If your tests are comprehensive, other metrics matter less. Poor test coverage is a red flag regardless of other metrics.
Q: How often should we measure? A: Monthly. This gives you a trend. Measuring more frequently is noise. Measuring less frequently misses important changes.
Q: What's a healthy target for each metric? A: Coverage > 80%, complexity < 10 average, duplication < 5%, lines of code stable. But these depend on your project. Set your own targets.