agentleFS
prototypoprototypo/codequalityexplorer/skills/quality-report/SKILL.md

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

  • Other versions3 projects use a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    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.

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
  1. Very specific:

    If no supported language is found, tell the user and STOP.

    line 69
  2. Very specific:

    If a language is present but has no reference file in references/, name it in the report summary as detected-but-unsupported.

    line 70
  3. Very specific:

    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 …

    line 86
  4. Distinctive:

    If the user declines, use the reference file's fallback for that tool and mark the affected counts "estimated".

    line 89
  5. Very specific:

    Measure everything, not just violations: Run the tools per the reference files AND scripts/function_metrics.py <paths> (Python) or …

    line 92
  6. Distinctive:

    Judgment pass: Read every file that has a tool finding, plus up to 10 of the largest remaining source files.

    line 117
  7. Very specific:

    Write references/<lang>.md: tools, exact commands, output parsing, fallback for each missing tool, and how to produce the language's total …

    line 276
  8. Very specific:

    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 …

    line 281
  9. Very specific:

    Add a deliberately bad fixture under test-fixtures/<lang>/ and a test asserting the script finds each planted problem.

    line 305

“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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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

MetricThresholdSource
Cyclomatic complexity> 10tool
Function length> 50 linestool
Nesting depth> 4 levelstool
Argument count> 5tool
Code duplicationrepeated blocks ≥ 5 linestool + judgment
Dead code (uncalled functions)anytool
Error-handling smellsRust: unwrap()/expect() outside #[cfg(test)]; Python: bare except:; JS/TS: empty or swallowing catchtool
File size> 500 linestool
Comment qualityfor functions longer than 10 lines, comment/docstring must say WHAT, not HOWjudgment
Reusabilityduplicated logic that should be one shared functionjudgment

Status bands

Metric kindMetrics🟢🟡🔴
Numericcomplexity, function length, nesting, file sizeratio ≥ 95%ratio ≥ 80%ratio < 80%, or worst ≥ 5× threshold
Numeric, argsargument countratio ≥ 95%ratio ≥ 90%ratio < 90%, or worst ≥ 2.5× threshold (> 12 args)
Ratio, no worst valuecomment quality≥ 95%≥ 80%< 80%
Dead coderatio of used functions over all functions≥ 98%≥ 95%< 95%
Error smellsoccurrences 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%
Reusabilitysame 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

  1. Detect languages. In the target repo root, check for:
    • Python: pyproject.toml, setup.py, requirements.txt, or any *.py files.
    • Rust: Cargo.toml or any *.rs files.
    • JavaScript/TypeScript: package.json, tsconfig.json, or any *.js, *.jsx, *.mjs, *.cjs, *.ts, *.tsx files. If no supported language is found, tell the user and STOP. Write no report. If a language is present but has no reference file in references/, name it in the report summary as detected-but-unsupported.
  2. 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.
  3. 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 vulture
    • cargo install rust-code-analysis-cli
    • npm 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 install there 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".
  4. Measure everything, not just violations. Run the tools per the reference files AND scripts/function_metrics.py <paths> (Python) or scripts/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.

  5. 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.
  6. Write CODE_QUALITY.md in 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 a CODE_QUALITY.md already exists, carry forward its [!] blocked markers and their notes for findings that still apply; write everything else fresh as [ ].
  7. Tell the user: the report path, the top 3 findings in one line each, and that /quality-improve fixes 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.

  1. 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.
  2. 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.
  3. 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.
  4. Thresholds table: add the language's error-handling smell to the error-handling-smells row, so step 4 has something to classify against.
  5. Step 1: add the language's marker files AND its file extensions to the detection list.
  6. Step 2: add references/<lang>.md to the reference-file list.
  7. Step 3: add the install command for the language's tools.
  8. .gitignore: if that install command lands the toolchain inside this repo (npm install --prefix does; pip and cargo install are global and do not), ignore what it drops. Otherwise the next commit here carries the whole toolchain.
  9. 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.
  10. Step 5: add the language's suppression markers.
  11. Report template: add the metrics script to the comment-quality compliance paragraph.
  12. Add a deliberately bad fixture under test-fixtures/<lang>/ and a test asserting the script finds each planted problem.
  13. skills/quality-improve/SKILL.md: add how to fix the error-handling smell from item 4.
  14. .claude-plugin/plugin.json: name the language in the description.
  15. README.md: name the language in the one-line description, in the error-handling-smell list of the /quality-report paragraph, 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.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.