A pragmatic tool for measuring whether a codebase is too complex for its task.
pip install prometheus-analyzer
# Analyze a GitHub repo directly
prometheus https://github.com/pallets/flask
# Or use short form
prometheus pallets/flask
# Analyze local codebase
prometheus /path/to/your/code
# Outputs: prometheus_pallets_flask.html, prometheus_pallets_flask.json| Tool | Named After | Purpose |
|---|---|---|
| prometheus.py | Titan who gave fire to humanity | Combined orchestrator — 2D fitness quadrant |
| shield_analyzer.py (Aegis) | Shield of Zeus/Athena | Resilience pattern detector |
| entropy_analyzer.py | Shannon | Complexity metrics |
| hubris.py | Greek for "excessive pride" | Resilience theater detector — finds cargo-cult patterns |
| olympus.py | Home of the gods | Multi-repository comparison tool |
flowchart TB
IN["prometheus <repo or path>"]
FETCH{Local or URL?}
CLONE[git clone to tmp]
subgraph ANALYZE[Analyzer modules]
direction TB
ENT[entropy_analyzer<br/>Shannon + Halstead]
AEGIS[shield_analyzer Aegis<br/>resilience patterns]
HUB[hubris<br/>cargo-cult detector]
TASK[Task metrics<br/>tests, endpoints, FPs]
end
COMBINE["prometheus.py<br/>fitness quadrant"]
RATIOS[Fitness ratios<br/>complexity / feature]
OUT1[HTML report]
OUT2[JSON report]
OLY["olympus<br/>multi-repo compare"]
IN --> FETCH
FETCH -->|URL| CLONE --> ANALYZE
FETCH -->|Local| ANALYZE
ENT --> COMBINE
AEGIS --> COMBINE
HUB --> COMBINE
TASK --> COMBINE
COMBINE --> RATIOS --> OUT1
RATIOS --> OUT2
OUT2 --> OLY
classDef in fill:#e3f2fd,stroke:#1565c0;
classDef an fill:#fff3e0,stroke:#e65100;
classDef out fill:#c8e6c9,stroke:#1b5e20;
class IN,FETCH,CLONE in;
class ENT,AEGIS,HUB,TASK,COMBINE,RATIOS an;
class OUT1,OUT2,OLY out;
This tool implements a pragmatic proof that simpler systems are more reliable:
- Channel capacity limits how much information can be transmitted error-free
- Code is an information channel between intent and execution
- Higher complexity → more bits → higher error probability
- Maintaining information requires energy:
E = kT ln(2)per bit - Complex systems require more energy to maintain
- Complex systems have more failure modes and decay faster
- System reliability:
R = r₁ × r₂ × ... × rₙ - Each component with reliability
r < 1reduces total reliability - More components = exponentially lower reliability
- The complexity of an object is the length of its shortest description
- Simpler descriptions are more compressible
- High compression ratio → redundancy → potential simplification
- Cyclomatic Complexity: Number of independent paths through code
- Cognitive Complexity: Weighted by nesting depth (SonarQube-style)
- Halstead Metrics: Volume, difficulty, effort, estimated bugs
- Maintainability Index: Composite score (0-100)
- Token Entropy: Shannon entropy of token distribution
- Compression Ratio:
original_size / gzip_size - Nesting Depth: Maximum control flow nesting
- Coupling: Import count and dependencies
- Test file count and test case count
- Assertion density
- API endpoint count
- Function point estimate
- Complexity per Feature: Is the code over-engineered?
- LOC per Function Point: Industry standard ~50
- Bits per Feature: Information-theoretic complexity density
- Redundancy Ratio: How much could be DRY'd out?
pip install radon lizard# Full URL
python prometheus.py https://github.com/django/django
# Short form (owner/repo)
python prometheus.py fastapi/fastapi
# Keep the cloned repo after analysis
python prometheus.py pallets/flask --keep# Full analysis with HTML quadrant chart
python prometheus.py /your/codebase
# Just resilience (Aegis)
python shield_analyzer.py /your/codebase
# Just complexity (Shannon metrics)
python entropy_analyzer.py /your/codebaseFiles are automatically named after the repo:
prometheus_<owner>_<repo>.html— Visual quadrant reportprometheus_<owner>_<repo>.json— Machine-readable data
Override with:
python prometheus.py owner/repo --html custom.html -o custom.json| Metric | Good | Medium | Poor |
|---|---|---|---|
| Cyclomatic Complexity (avg) | < 5 | 5-10 | > 10 |
| Maintainability Index | > 65 | 40-65 | < 40 |
| LOC per Function Point | < 50 | 50-150 | > 150 |
| Token Entropy | 4-6 | 6-8 | < 4 or > 8 |
- LOW: Complexity well-matched to task. Reliable.
- MEDIUM: Trending toward excess. Monitor.
- HIGH: Over-complex. Elevated error rates expected.
- CRITICAL: Significantly over-engineered. Refactor before adding features.
# Basic installation
pip install prometheus-analyzer
# With security scanning (bandit)
pip install prometheus-analyzer[security]
# Full suite with all optional dependencies
pip install prometheus-analyzer[full]After installation, use the commands:
prometheus pallets/flask
olympus -f repos.txt -o comparison.html
hubris pallets/flask --html hubris_report.htmlgit clone https://github.com/yourusername/prometheus.git
cd prometheus
pip install -e .If installing manually without the package:
# Minimal (Prometheus only)
pip install radon lizard
# Full Suite
pip install radon lizard banditThis tool doesn't claim to measure "truth" — it measures fitness.
Per the pragmatist framework:
- We don't ask "is this codebase correct?"
- We ask "will this codebase reliably do its job?"
Physics and information theory tell us: simpler systems win.
- Task complexity estimation is heuristic (based on tests, endpoints, imports)
- Some metrics only available for Python (uses
radon) - Doesn't measure semantic complexity (bad names, confusing logic)
- Can't detect "essential" vs "accidental" complexity
To add new languages or metrics:
- Add extension mapping in
Extractor.LANGUAGE_EXTENSIONS - Implement
_analyze_<language>()method - Integrate additional static analysis tools
Hubris analyzes codebases for cargo-cult resilience patterns — code that looks like it handles failures but doesn't actually work.
| Quadrant | Description |
|---|---|
| SIMPLE | Few patterns, low complexity — appropriate for simple tasks |
| BATTLE_HARDENED | Many patterns, correctly implemented — production-ready |
| OVERENGINEERED | Too many patterns for the task — unnecessary complexity |
| CARGO_CULT | Many patterns, poorly implemented — false sense of security |
- Retry without backoff: Retries that hammer services without delay
- Missing timeouts: Network calls without timeout configuration
- Empty exception handlers:
except: passand similar anti-patterns - Circuit breakers without metrics: Breakers that can't report state
- Library soup: Too many resilience libraries without coherent strategy
hubris.py # Main orchestrator
├── models.py # Data classes (HubrisReport, etc.)
├── patterns.py # Regex patterns for detection
├── detectors.py # Detection logic (RetryDetector, TimeoutDetector, etc.)
├── fp_filter.py # False positive filtering
├── design_patterns.py # Design pattern anti-pattern detection
└── report.py # HTML report generation
# Analyze a codebase
python hubris.py /path/to/code
# Generate HTML report
python hubris.py /path/to/code --html report.html
# Export JSON
python hubris.py /path/to/code -o report.json"Complexity is the enemy of reliability."
This tool exists because:
- Simpler systems have fewer failure modes (physics)
- Simpler systems are easier to understand (cognition)
- Simpler systems are cheaper to maintain (economics)
- We can measure simplicity (information theory)
Therefore: we can measure expected reliability.
That's the pragmatic proof.
Built to answer: "Can you provide something I can measure?"