quality-report
Skill2 starsChanged 46 days agoMITView on GitHub
Use when the user asks for a code quality report, code metrics, complexity analysis, or invokes /quality-report - measures complexity, function length, nesting, argument counts, duplication, dead code, error-handling smells, comment quality, and reusability, then writes a ranked CODE_QUALITY.md
- Installs packages
3 other projects use a version of this.
Adopted by
Most recently taken up by
- pierrebelin/claude-code-toolkittheir own version, first seen Oct 21, 2026
- teachskillofskills-ai/DigitalMarketingPro-techshutheir own version, first seen Oct 11, 2026
- indranilbanerjee/digital-marketing-protheir own version, first seen Feb 12, 2026
Other versions3 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 3
- indranilbanerjee/digital-marketing-pro★ 934same name
- pierrebelin/claude-code-toolkit★ 7same name
- teachskillofskills-ai/DigitalMarketingPro-techshu★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository2 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- quality-improveSkill
The file
We split this skill into the rules it gives an agent
9 rules. 0 are common, 2 are distinctive, and 7 are very specific to this project.
0
Common
Most of the 3 edited versions we read keep these.
2
Distinctive
This author's own choices. Worth a look.
7
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 69
If no supported language is found, tell the user and STOP.
- Very specific: line 70
If a language is present but has no reference file in references/, name it in the report summary as detected-but-unsupported.
- Very specific: line 86
NEVER in the target repo: npm install there runs that repo's own dependency install scripts, and the tools must then be invoked by absolute …
- Distinctive: line 89
If the user declines, use the reference file's fallback for that tool and mark the affected counts "estimated".
- Very specific: line 92
Measure everything, not just violations: Run the tools per the reference files AND scripts/function_metrics.py <paths> (Python) or …
- Distinctive: line 117
Judgment pass: Read every file that has a tool finding, plus up to 10 of the largest remaining source files.
- Very specific: line 276
Write references/<lang>.md: tools, exact commands, output parsing, fallback for each missing tool, and how to produce the language's total …
- Very specific: line 281
If any of those commands hands a tool its own config file, ship that config under scripts/, beside the skill, so the tool and its parser …
- Very specific: line 305
Add a deliberately bad fixture under test-fixtures/<lang>/ and a test asserting the script finds each planted problem.
“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Quality Report
Measure the target code base and write a ranked report to CODE_QUALITY.md
in the repo root. This skill changes NO code. It only reads and reports.
Thresholds
| Metric | Threshold | Source |
| Cyclomatic complexity | > 10 | tool |
| Function length | > 50 lines | tool |
| Nesting depth | > 4 levels | tool |
| Argument count | > 5 | tool |
| Code duplication | repeated blocks ≥ 5 lines | tool + judgment |
| Dead code (uncalled functions) | any | tool |
| Error-handling smells | Rust: unwrap()/expect() outside #[cfg(test)]; Python: bare except:; JS/TS: empty or swallowing catch | tool |
| File size | > 500 lines | tool |
| Comment quality | for functions longer than 10 lines, comment/docstring must say WHAT, not HOW | judgment |
| Reusability | duplicated logic that should be one shared function | judgment |
Status bands
| Metric kind | Metrics | 🟢 | 🟡 | 🔴 |
| Numeric | complexity, function length, nesting, file size | ratio ≥ 95% | ratio ≥ 80% | ratio < 80%, or worst ≥ 5× threshold |
| Numeric, args | argument count | ratio ≥ 95% | ratio ≥ 90% | ratio < 90%, or worst ≥ 2.5× threshold (> 12 args) |
| Ratio, no worst value | comment quality | ≥ 95% | ≥ 80% | < 80% |
| Dead code | ratio of used functions over all functions | ≥ 98% | ≥ 95% | < 95% |
| Error smells | occurrences per 1,000 lines (total lines = sum of file sizes) | ≤ 0.5 | ≤ 2 | > 2 |
| Duplication | % of lines duplicated (JS/TS: jscpd statistics.total.percentage; Python/Rust: estimated from the step-5 sample, marked "estimated") | < 3% | < 5% | ≥ 5% |
| Reusability | same Status and reason as duplication (same copies) |
"Ratio" = share of functions (files, for file size) that pass the
threshold — the same number already in the Compliance/Distribution
columns. A per-item 🟡 (within 10% below the threshold) counts as passing
in that ratio; only a per-item 🔴 fails it. Check order: 🔴 first (row
reads 🔴 if the ratio is below its band's floor — 80% for complexity,
function length, nesting and file size, 90% for argument count — or if
the worst value is ≥ 5× the threshold (≥ 2.5× for argument count),
whichever fires), then 🟢 (ratio ≥ 95%), then 🟡 (ratio ≥ the band's
floor). Each Status cell carries a short reason, e.g. 🔴 worst 5.2×
limit, 🟡 88% pass, 🟢 0.2 / 1k lines.
Worked example, 200 functions measured for complexity (threshold 10): one
function at complexity 25 gives a compliance ratio of 199/200 = 99.5%, and
worst (25) is only 2.5× the threshold — well under the 5× 🔴 trigger — so
the ratio governs → 🟢 99.5% pass. One function at complexity 50 (5× the
threshold) among the same 200 still gives a ratio of 199/200 = 99.5%, but
the worst-value 🔴 condition now fires → 🔴 worst 5× limit. Thirty
functions at complexity 11 (worst 1.1×, well under 5×) give a compliance
ratio of 170/200 = 85% — between the 80% and 95% bands → 🟡 85% pass.
For argument count (threshold > 5, its own row): 15 of 200 functions at 6
args give a compliance ratio of 185/200 = 92.5% — between that row's 90%
and 95% bands → 🟡 92.5% pass.
Steps
- Detect languages. In the target repo root, check for:
- Python:
pyproject.toml,setup.py,requirements.txt, or any*.pyfiles. - Rust:
Cargo.tomlor any*.rsfiles. - JavaScript/TypeScript:
package.json,tsconfig.json, or any*.js,*.jsx,*.mjs,*.cjs,*.ts,*.tsxfiles. If no supported language is found, tell the user and STOP. Write no report. If a language is present but has no reference file inreferences/, name it in the report summary as detected-but-unsupported.
- Python:
- Load the reference file for each detected language:
references/python.md,references/rust.md,references/javascript.md. Follow its tool commands. For every tool that is not installed, record it in the "Tools missing" list. - Offer to install missing tools. For each tool from step 2 that is
missing, tell the user the exact install command and ask whether to
install it now:
pip install radon ruff vulturecargo install rust-code-analysis-clinpm install --prefix "<skill dir>" --no-save --ignore-scripts eslint@9 typescript@6 typescript-eslint@8 jscpd@5— installs beside the skill, NEVER in the target repo:npm installthere runs that repo's own dependency install scripts, and the tools must then be invoked by absolute path so the repo cannot substitute its own binaries. If the user declines, use the reference file's fallback for that tool and mark the affected counts "estimated".
Measure everything, not just violations. Run the tools per the reference files AND
scripts/function_metrics.py <paths>(Python) orscripts/function_metrics.mjs <paths>(JavaScript/TypeScript) to get per-function length, nesting, argument count, and comment-presence values for the whole code base.For every metric with a numeric value — complexity, length, nesting, argument count, file size — also record the distribution: the compliance RATIO, the worst value, the median, and the standard deviation. A bare count of violations is not enough; see "Counts lie when the denominator moves" below. Classify each function/file 🟢/🟡/🔴 against the thresholds table using the 10% rule: 🟡 = measured value within 10% below the threshold (e.g. complexity exactly 10, length 46–50, nesting exactly 4, args exactly 5, file size 451–500). Each dead-code, error-handling-smell, duplication, reusability, and comment-quality ITEM is 🟢 or 🔴 only, with no per-item 🟡 — but the row's Status uses the Status bands above and can still read 🟡. Every threshold violation still becomes a finding exactly as before.
Also record: total lines (the sum of file sizes, the denominator for the error-smells density), the dead-function count over all functions (the denominator for the dead-code ratio), and the duplicated-lines % (from jscpd for JS/TS, estimated from the step 5 sample for Python/Rust). These feed the Status bands above.
- Judgment pass. Read every file that has a tool finding, plus up to 10
of the largest remaining source files. Comment presence counts
(from step 4) come from the script/tool for every function; only
comment quality (WHAT vs HOW) is judged here, on this sample. Judge:
- Comment quality: for each function longer than 10 lines, does its docstring/comment state WHAT the function does? A comment narrating the implementation steps ("loop over X, then append to Y") is a HOW comment: flag it. A missing docstring on a public function longer than 10 lines: flag it.
- Reusability: blocks of ≥ 5 similar lines appearing in 2+ places, or 2+ functions with near-identical bodies. Flag as one finding naming all copies and the shared function that should replace them.
- Suppressed problems (Python
# noqa, Rust#[allow(...)], JS/TS// eslint-disable,// @ts-ignore,// @ts-expect-error) still count: report them, note the suppression.
- Write
CODE_QUALITY.mdin the target repo root using the template below. Rank findings worst first: order by (how far past the threshold, how many readers the file likely has — entry points and public APIs first). Give each finding an id Q1, Q2, ... in rank order. If aCODE_QUALITY.mdalready exists, carry forward its[!]blocked markers and their notes for findings that still apply; write everything else fresh as[ ]. - Tell the user: the report path, the top 3 findings in one line each, and
that
/quality-improvefixes them one at a time.
Report template
# Code Quality Report
Generated: <YYYY-MM-DD> by quality-report v0.4.1
## Summary
- Languages analyzed: <list>
- Files analyzed: <n>
- Tools used: <name and version, one per line>
- Tools missing: <name — metric estimated by reading code; or "none">
- Findings: <n> open
## Metrics
| Metric | Threshold | Status | Compliance | Source |
|---|---|---|---|---|
| Cyclomatic complexity | > 10 | 🟢 95% pass | 🟢 39 · 🟡 2 · 🔴 2 | tool |
Fill one row per metric from the thresholds table above. Status follows
the Status bands table above, not just the worst item in the row; each
cell also carries a short reason (see the reason examples in the Status
bands section above). Compliance counts functions for function metrics
(complexity, length, nesting, args, comment quality), files for file size,
occurrences for error-handling smells, and duplicate-block groups for
reusability. Binary metrics show the number their Status band is judged
on, not a bare violation count: dead code shows the ratio of used
functions over all functions (e.g. `🟢 98% (412/420)`), error-handling
smells show occurrences per 1,000 lines (e.g. `🟡 1.2 / 1k lines`), and
duplication shows the duplicated-lines % (e.g. `🟢 1.8% (estimated)` for
Python/Rust, `🟢 1.8%` for JS/TS).
Comment counts are parsed from every function in the code base; comment
*quality* and the other judgment metrics (reusability, suppressed
problems) are judged on a sample only — the files with findings, plus up
to 10 of the largest remaining source files. "estimated" in the Source
column marks a count made by reading code instead of by a tool.
Comment-quality compliance is denominated over functions longer than 10
lines only; each function is 🟢 or 🔴 only (no per-item 🟡) — does it have a
WHAT-comment or not — but the row's Status uses the Status bands above and
can still read 🟡. The presence count comes from the `has_doc` field of
`function_metrics.py`/`function_metrics.mjs` for every such function in the
code base; comment *quality* (WHAT vs HOW) is judged only on the step 5
sample, per the disclaimer above.
## Distribution
| Metric | Compliance | Worst | Median | Std dev |
|---|---|---|---|---|
| Cyclomatic complexity | 95% (41/43) | 14 | 3 | 2.1 |
| Function length | ... | | | |
| Nesting depth | ... | | | |
| Argument count | ... | | | |
| File size | ... | | | |
One row per numeric metric. **Compliance is the ratio, and it is the
headline number** — the count of violations is the denominator's shadow,
not a result.
### Counts lie when the denominator moves
Fixing these findings CHANGES THE DENOMINATOR, almost always upward:
extracting a helper adds a function, splitting a module adds a file. So a
raw count of violations can rise while the code base genuinely improves,
and a reader who watches only the count concludes the work made things
worse.
A real example, from splitting three oversized files in one code base:
| | before | after |
|---|---|---|
| files | 25 | 40 |
| files over the limit | 12 | 15 |
| **compliance** | **52%** | **62%** |
| largest file | 9,888 | 5,721 |
| mean | 1,493 | 975 |
| standard deviation | 2,492 | 1,535 |
| share of all code in an oversized file | 94% | 84% |
The count rose by three and every other measure improved. Judged by count
alone, the honest conclusion would have been "don't split files" — which
rewards leaving a monolith alone, the exact opposite of the point.
So when reporting progress against an earlier run:
- **Lead with the compliance ratio**, never the raw count.
- **Quote the worst value.** One function at complexity 171 matters more
than forty at 11, and only the worst value shows that.
- **Quote the standard deviation.** Falling variance means the outliers
are being pulled in, which is what this whole exercise is for.
- If a count rose, say plainly whether the denominator rose too, and by
how much. A count that rose while the ratio improved is progress and
should be written up as progress.
## Findings (worst first)
### [ ] 🔴 Q1: <metric> — <file>:<line> `<function>`
- Measured: <value> (threshold <value>)
- Recommendation: <one or two plain sentences saying what change to make>
### [ ] 🔴 Q2: ...
## Marginal (🟡) — close to the limit, no action required
- Cyclomatic complexity 10 (limit 10) — src/foo.py:12 `bar`
## Top recommendations
1. <the 3–5 changes with the biggest payoff, each one sentence>Status markers on findings: [ ] open, [x] fixed, [!] blocked. The
marker always comes first, with the emoji after it — quality-improve
parses [ ]/[x]/[!] by position, so never move the marker. The
quality-improve skill updates these; this skill writes them all as [ ].
The Marginal section lists every 🟡 function/file that has no threshold
violation, one line each, with no Q id and no [ ] marker — so
quality-improve never picks these up. A function's 🟡 listing is decided
solely by its own metric measurement, regardless of whether that same
function also appears in a judgment finding (e.g. duplication) elsewhere
in the report.
Adding a language
Adding JavaScript/TypeScript needed every edit below. Skip one and the language is half-wired.
- Write
references/<lang>.md: tools, exact commands, output parsing, fallback for each missing tool, and how to produce the language's total lines, a dead-function count over all functions, and a duplicated-lines % (tool, or estimated from the step-5 sample) — step 4's Status bands need all three for every language. - If any of those commands hands a tool its own config file, ship that
config under
scripts/, beside the skill, so the tool and its parser resolve from the skill's own install and never from the scanned repo. Without it the reference documents a command pointing at a file nobody wrote. - Unless a tool already reports every function in the language, write
scripts/function_metrics.<ext>that does — step 4's compliance counts need a denominator covering the whole code base, not just violations. - Thresholds table: add the language's error-handling smell to the error-handling-smells row, so step 4 has something to classify against.
- Step 1: add the language's marker files AND its file extensions to the detection list.
- Step 2: add
references/<lang>.mdto the reference-file list. - Step 3: add the install command for the language's tools.
.gitignore: if that install command lands the toolchain inside this repo (npm install --prefixdoes;pipandcargo installare global and do not), ignore what it drops. Otherwise the next commit here carries the whole toolchain.- Step 4: add the run command for the metrics script from item 3. Omit this and the script exists but is never invoked, so the denominator it was written for is still missing.
- Step 5: add the language's suppression markers.
- Report template: add the metrics script to the comment-quality compliance paragraph.
- Add a deliberately bad fixture under
test-fixtures/<lang>/and a test asserting the script finds each planted problem. skills/quality-improve/SKILL.md: add how to fix the error-handling smell from item 4..claude-plugin/plugin.json: name the language in the description.README.md: name the language in the one-line description, in the error-handling-smell list of the/quality-reportparagraph, in the tools sentence, and in the fixtures paragraph and its self-check command; add a paragraph for the metrics script from item 3 and for any install caveat from item 7; and keep README's own shorter "Adding a language" summary from contradicting this list. Nothing else a user reads before installing says the language is supported.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

