Multi-language code quality scanner — complexity, duplication, security, and smells
Project description
qlint
Multi-language code quality scanner. Walks any codebase and produces JSON, HTML, and Markdown reports covering complexity, duplication, security, code smells, and predictive risk (which files are most likely to cause your next outage).
Install
# from PyPI
pip install qlint
# from source
git clone https://github.com/ropean/qlint.git
cd qlint
pip install -e .
Usage
qlint /path/to/repo # JSON + HTML + Markdown; auto-opens HTML
qlint /path/to/repo --format md # Markdown only
qlint /path/to/repo --format json,md # JSON + Markdown, no HTML, no auto-open
qlint /path/to/repo --no-open
qlint /path/to/repo --json-only # print JSON to stdout, no files
qlint /path/to/repo -v # verbose per-file output
qlint # interactive: prompts for path
qlint /path/to/repo --risk # predictive risk report (top 5 chunked narrative)
qlint /path/to/repo --risk --risk-window 30
qlint /path/to/repo --risk-md /tmp/risk.md # standalone markdown risk report
Reports are written to ~/Downloads/qlint-reports/<repo>/ as report.json, report.html, and report.md. HTML auto-opens only when an HTML report is produced. --risk alone prints to the console and writes nothing.
Options
| Flag | Description |
|---|---|
--format, -f |
Comma-separated formats: json, html, md (default: all three) |
--output, -o |
Custom JSON output path (implies json) |
--html |
Custom HTML output path (implies html) |
--md |
Custom Markdown output path (implies md) |
--risk |
Print predictive risk report (top 5 files most likely to break) |
--risk-window |
Days of git history to consider as "recent" (default 90) |
--risk-md |
Write standalone risk Markdown report to PATH |
--json-only |
Skip files, print JSON to stdout |
--no-open |
Do not auto-open HTML report |
--verbose, -v |
Show per-file progress |
--version |
Show version |
Analysis Features
| Feature | What it detects |
|---|---|
| Complexity | Cyclomatic complexity per function, flags > 10 |
| Duplication | Duplicate 6-line blocks across files |
| Security | Hardcoded secrets, dangerous functions (eval, exec, …) |
| Code Smells | Long functions, deep nesting, long parameter lists |
| Predictive Risk | Recency-weighted: recent_churn × complexity × (1 + 2·bug_fix_ratio) × (1 + 0.15·authors) / 100. Each top file gets a risk_level (critical/high/medium/low), structured signals, and human-readable reasons. |
Predictive Risk
qlint --risk highlights the files most likely to cause your next outage by combining:
- Static signals — complexity, smells, security issues
- Git signals (recent window) — churn, commit frequency, bug-fix ratio, author count
Bug-fix detection scans commit subjects for fix|bug|hotfix|patch|revert (case-insensitive). Files with a high share of recent bug-fix commits get amplified scores — past fix density is a strong predictor of future fixes.
Risk levels are bucketed: critical (≥50), high (≥20), medium (≥5), low (<5).
Languages
Python, JavaScript, TypeScript, Java, Go, Ruby, Rust, C, C++, C#, PHP, Swift, Kotlin, Scala, Shell, HTML, CSS, SQL, YAML, JSON, and more.
JSON Output
{
"scanId": "...",
"timestamp": "...",
"repository": { "path": "...", "totalFiles": 42, "totalLines": 8500, "languages": {} },
"files": [
{
"path": "src/main.py",
"language": "Python",
"metrics": { "loc": 120, "code": 95, "comments": 10, "blank": 15, "functions": 8, "classes": 2, "complexity": 4.2 },
"smells": [],
"security_issues": [],
"git_risk": {
"commits": 12, "churn": 340, "authors": 2,
"risk_score": 25.5, "risk_level": "high",
"signals": { "...": "see gitRisk.top_risk_files for the full shape" },
"reasons": ["active churn (340 lines / window)"]
}
}
],
"qualityScore": 87,
"grade": "B",
"gitRisk": {
"available": true,
"window_days": 90,
"top_risk_files": [
{
"file": "src/main.py",
"risk_score": 25.5,
"risk_level": "high",
"reasons": ["active churn (340 lines / window)"],
"signals": {
"complexity": 4.2,
"recent_commits": 5,
"recent_churn": 340,
"all_time_commits": 12,
"all_time_churn": 600,
"authors": 2,
"bug_fix_ratio": 0.4,
"smells": 1,
"security_issues": 0
}
}
]
}
}
Claude Code skill — qlint-refactor
The .claude/skills/qlint-refactor/ directory ships a Claude Code skill that turns the scanner into a feedback signal: it picks the riskiest file, proposes a behavior-preserving refactor, re-scans, and verifies the score dropped.
Loop:
- Baseline via
scripts/risk_top.py(top-N risk JSON) - Locate the worst function in the top-1 file
- Propose a minimal refactor (extract function, flatten conditionals, lookup tables)
- Apply, then
scripts/verify.py FILE --baseline N.NN→improved/unchanged/regressed - Roll back on no-improve; max 3 attempts per file; exit when all top-5 are
risk_score < 50
Activates on prompts like "list top risk files", "explain why this file is risky", "refactor the risky code", "reduce risk score", "run the risk loop".
Development
make install # pip install -e ".[dev]"
make lint # ruff check
make format # ruff format
make build # python3 -m build
Requirements
- Python 3.11+
gitin PATH (for predictive risk; optional —--riskdegrades gracefully on non-git dirs)
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file qlint-0.3.0.tar.gz.
File metadata
- Download URL: qlint-0.3.0.tar.gz
- Upload date:
- Size: 32.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b4d26e5e9b5acda094caef29dfe59746b3bcae79809142f518584ff5487c17bb
|
|
| MD5 |
12097b024ca465e2a1c9ecfaeb150f36
|
|
| BLAKE2b-256 |
65cc8ddd036efcb29339b3ba70ec0f2344c717f9b595b8fc26fdaa50229d239f
|
File details
Details for the file qlint-0.3.0-py3-none-any.whl.
File metadata
- Download URL: qlint-0.3.0-py3-none-any.whl
- Upload date:
- Size: 36.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ddeb9a69989455cbb47aac82213babf26348cb092b5aae9860b9a8064b5cc64a
|
|
| MD5 |
b3e7f18ea016da93aaf67f7d8901c018
|
|
| BLAKE2b-256 |
a504afdb9b4afc90485157336b0d891df2d5c4c92c39d7dfd179236eccca675f
|