crap
Skill1 starsChanged 3 months agoMITView on GitHub
Score Python functions by CRAP (cyclomatic complexity combined with test coverage) and gate on a threshold, scoped to the functions a diff touches. Use when cleaning up agent-written code before a PR, when a contract Verifier needs a complexity/coverage gate, when asked which functions are too complex or too untested, or when running a "cleaner" stage.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- lancy69/skillstheir own version, first seen Nov 1, 2026
- jonmumm/skillstheir own version, first seen Oct 21, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- jonmumm/skills★ 2same name
- lancy69/skills★ 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 repository39 other files it gives its agents.
- arch-mapSkill
- ask-meSkill
- autodevSkill
- codebase-designSkill
- code-reviewSkill
- context-barSkill
- contractSkill
- copilot-reviewSkill
- deep-research-consolidateSkill
- deep-research-promptSkill
- domain-modelingSkill
- drop-reviewSkill
- fleet-reviewSkill
- framing-decisionsSkill
- grillingSkill
- grill-meSkill
- grill-with-docsSkill
- handoffSkill
- herdrSkill
- implementSkill
- mergedSkill
- meta-analysisSkill
- mutation-testSkill
- obsidian-vaultSkill
- paper-outlineSkill
- probeSkill
- prSkill
- setup-matt-pocock-skillsSkill
- show-meSkill
- slack-askSkill
- slack-notifySkill
- sparSkill
- sync-matt-pocock-skillsSkill
- tddSkill
- to-specSkill
- triageSkill
- writing-for-agentsSkill
- writing-git-commitsSkill
- writing-great-skillsSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 1 is distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 54
Run it. For each FAIL row, read the cc and cov columns:
- Very specific: line 55
covlow: write tests for the untested paths. - Distinctive: line 60
Never pass the gate by:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
CRAP
CRAP (Change Risk Anti-Patterns) scores one function as cc² · (1 − cov)³ + cc, where cc is
its cyclomatic complexity and cov is the fraction of it the tests exercise. Two properties make it
a good gate for agent code:
- At full coverage the score equals
cc. Tests cannot rescue a function with too many paths; only splitting it can. - An untested function scores
cc² + cc. Even a modest one fails, so the fix is a test.
The default threshold is 6. Uncle Bob keeps human code at 4 or below and lets agents go to 6; raise it per repo only with a reason written down, never to get a red run green.
Run it
Produce a coverage.py JSON report, with branch coverage, from the repo root, in the repo's own activated environment:
pytest <tests> --cov=<package> --cov-branch --cov-report= coverage json -o "$TMPDIR/cov.json"Score the functions the change touched:
~/.claude/skills/crap/bin/crap --coverage "$TMPDIR/cov.json" --diff <base>--diff <base>compares the working tree against<base>, usually the branch's merge-base with main; untracked new files count as changed in full. Without--diffit scores every function in every.pyfile under the root (git-tracked and unignored ones in a repo), including files the report lacks. That is useful for a survey, but never gate a legacy repo on it: on ARC one file has 35 of 81 functions above 6.
| Exit | Meaning |
| 0 | every scored function ≤ threshold |
| 1 | at least one above it: the rows marked FAIL |
| 2 | bad input: unreadable report, bad diff base, unparsable file |
Other flags: --threshold N, --json, --top N, --exclude GLOB (test files are excluded by
default), and trailing paths to limit the scope.
The cleaner loop
As a contract Verifier, the command plus exits 0 is the whole check. The loop:
- Run it. For each
FAILrow, read theccandcovcolumns:covlow: write tests for the untested paths.ccabove the threshold: split the function, or move its branching into a lookup or into smaller named helpers. More tests will not move the score.
- Regenerate coverage and rerun until it exits 0.
Never pass the gate by:
- deleting or weakening tests,
- adding
# pragma: no cover, - excluding the file,
- raising the threshold.
Each of those makes the gate report clean while the code stays the same. If a function genuinely cannot be split, stop and report it with its score rather than pass by any of those routes.
Because a deterministic check decides acceptance, the loop does not need a strong model: a free-tier one can run it.
Limits
- Python only.
- Coverage is statement plus branch coverage from coverage.py, not the basis-path coverage of the original CRAP paper. Functions missing from the report are scored as uncovered and counted in the summary line.
ccis McCabe complexity from the AST: one point for eachif/elif, loop,except, ternary, extra boolean operand, comprehensionfor/if, and refutablecase.- Nested functions are scored separately from their parent. A lambda counts toward the function
that contains it; one at module or class level is scored on its own as
<lambda>, always as uncovered: its line runs when it is defined, so the report cannot tell whether the body ever did. Abovecc2 that fails the gate whatever the tests do; make it adef.
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.

