cyclomatic-complexity
Skill0 starsChanged 3 months agoMITView on GitHub
This skill should be used when the user asks "how complex is this function", "count the branches", "find overly complex functions", "set a complexity threshold", "reduce cyclomatic complexity", or asks to interpret a complexity report from radon, ESLint, gocyclo, PMD, or lizard. Also applies when a function "has too many if statements" and needs simplifying.
1 other project uses a version of this.
Adopted by
Most recently taken up by
- saurabhkumar8112/cyclomatic-complexity-skilltheir own version, first seen Aug 26, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- saurabhkumar8112/cyclomatic-complexity-skill★ 391same 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 repository29 other files it gives its agents.
- algorithmic-complexity-attacksSkill
- cache-stampedeSkill
- clocks-and-timeSkill
- code-hotspotsSkill
- connascenceSkill
- connection-poolingSkill
- consistent-hashingSkill
- coordinated-omissionSkill
- database-queuesSkill
- dependency-confusionSkill
- expand-contractSkill
- floating-pointSkill
- hyrums-lawSkill
- index-designSkill
- isolation-anomaliesSkill
- keyset-paginationSkill
- metamorphic-testingSkill
- module-depthSkill
- mutation-testingSkill
- mvcc-and-bloatSkill
- parse-dont-validateSkill
- query-plansSkill
- queueing-and-utilizationSkill
- retry-amplificationSkill
- start-hereSkill
- tail-latencySkill
- unicode-pitfallsSkill
- universal-scalability-lawSkill
- write-amplificationSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 3 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 12
Start at 1. Add 1 for each decision point.
- Very specific: line 93
Polymorphism: When the same switch on a type appears in several functions, move each branch onto the type.
- Distinctive: line 97
Define errors out of existence: Every failure mode removed from a callee deletes a branch from every call site.
- Distinctive: line 114
Use cyclomatic complexity to estimate test count, cognitive complexity to judge readability.
≈ “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
Cyclomatic complexity
Cyclomatic complexity counts the independent paths through a function. It estimates two things: the minimum number of test cases needed for branch coverage, and how much a reader must hold in mind at once.
Counting rule
Start at 1. Add 1 for each decision point.
| Add 1 for | Notes |
if, else if | else adds nothing, it is the fall-through path |
for, while, do-while | each loop |
case in a switch | each case label. The switch and default add nothing |
catch / except | each handler. try and finally add nothing |
&&, ||, ?? | each short-circuit operator |
ternary ? : | one each |
?. optional chaining | one each, though some tools skip it |
| pattern-match arm with a condition | each arm |
Nothing else counts. Assignments, calls, returns, and straight-line statements are free.
Worked example
def classify(user, order): # 1 base
if user is None: # 2
return "anonymous"
if order.total > 100 and user.is_member: # 3 if, 4 and
return "vip"
for item in order.items: # 5
if item.flagged: # 6
return "review"
return "standard"Complexity 6, so 6 test cases for full branch coverage.
Interpreting the score
| Score | Band | Action |
| 1-5 | Simple | None |
| 6-10 | Moderate | Acceptable, monitor |
| 11-20 | Complex | Refactor when next touching it |
| 21-50 | High risk | Refactor now, hard to test fully |
| 50+ | Untestable | Redesign |
Gate CI at 10 per function if a single threshold is needed. Apply it consistently rather than debating case by case.
Two constraints on interpretation:
- The metric is per function, never per file. A large file of simple functions is fine.
- Parsers, state machines, and generated code score high legitimately. Exclude them rather than distorting code to satisfy a linter.
Reducing it
Removing decision points lowers complexity. Moving them elsewhere does not. Splitting a complexity-20 function into two complexity-10 functions helps only when each half is independently understandable.
Guard clauses. Flatten nesting by returning early. The count is unchanged but nesting depth and cognitive load drop sharply.
function pay(user) {
if (!user) return null;
if (!user.active) return null;
if (user.balance <= 0) return null;
return charge(user);
}Table lookup. Replace an if/else chain that maps values to results. This genuinely removes branches.
// complexity 5
function rate(tier) {
if (tier === "free") return 0;
if (tier === "pro") return 10;
if (tier === "team") return 25;
return 100;
}
// complexity 1
const RATES = { free: 0, pro: 10, team: 25 };
const rate = (tier) => RATES[tier] ?? 100;Extract a named predicate. Move a compound condition into its own function. The operators still cost 1 each but now live in a small, separately testable unit.
Polymorphism. When the same switch on a type appears in several functions, move each branch onto the type.
Split by responsibility. A function that validates, transforms, and persists is three functions. This is the only refactor that reliably lowers the total complexity a reader absorbs at once.
Define errors out of existence. Every failure mode removed from a callee deletes a branch from every call site.
Tooling
| Language | Tool | Command |
| Python | radon | radon cc -s -n C path/ |
| JS/TS | ESLint | "complexity": ["error", 10] |
| Go | gocyclo | gocyclo -over 10 . |
| Java | PMD | CyclomaticComplexity rule |
| C/C++ and many others | lizard | lizard -C 10 path/ |
| Multi-language | SonarQube | reports cyclomatic and cognitive complexity |
Cognitive complexity
Cyclomatic complexity scores ten flat if statements the same as ten nested ones. Cognitive complexity (SonarSource, 2017) adds a nesting penalty and does not charge for a switch.
Use cyclomatic complexity to estimate test count, cognitive complexity to judge readability. When a tool reports both, gate CI on cyclomatic and use cognitive as the refactoring signal.
Limits
The score says nothing about naming, coupling, duplication, or correctness. A complexity-3 function can be entirely wrong. Treat a high score as a candidate for review, not a verdict.
To decide which complex code is worth fixing, cross the score with change frequency using code-hotspots. To explain why a change is hard rather than why a function is hard to test, use connascence.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
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.

