06

Rules reference

Every one of the 14 rules in depth: exact detection logic, options, false-positive notes

6 min read6 sections

CleanLens has 14 rules. Each one is configured in .clean-code-tracker.json under rules.<ruleId>:

json
"maxFunctionLines": { "enabled": true, "severity": "medium", "limit": 40 }
FieldTypeMeaning
enabledboolean, requiredThe rule runs only if this is true.
severitylow | medium | high | critical, requiredSets the violation's weight and its editor diagnostic level.
limitpositive number, optionalThreshold for numeric rules.
optionsobject of numbers/booleans, optionalRule-specific extra settings.

Summary

Rule idTitleCategoryDefault severityDefault limit / optionsJS/TSPython
maxFunctionLinesLong functionstructuremediumlimit 40✅✅
maxFileLinesLarge filestructuremediumlimit 400 (Django 500)✅✅
maxParametersToo many parametersstructuremediumlimit 5✅✅
maxComplexityHigh complexitystructurehighlimit 10✅≈
maxNestingDepthDeep nestingstructurehighlimit 4✅≈
detectDuplicateCodeDuplicate codeduplicationmediumoptions.minLines 6✅✅
detectUnusedCodeUnused codehygienelow—✅imports only
requireClearVariableNamesUnclear namehygienelow—✅✅
requireErrorHandlingMissing error handlinghygienemedium—awaitrisky calls
forbidEmptyCatchBlocksEmpty catch blockhygienehigh—✅✅
forbidHardcodedSecretsHardcoded secrethygienecritical—✅✅
forbidDebugStatementsDebug statementhygienelow—✅✅
requireSingleResponsibilityMultiple responsibilitiesstructuremediumoptions.maxMethods 10✅✅
requireDocumentationForComplexCodeComplex code without docsstructurelowoptions.complexityThreshold 15✅✅

≈ = approximate (heuristic, see below).

The defaults come from BASE_RULES in src/configuration/presets.ts. If a rule has no limit/option in the config, the analyzer uses the same default value.


Structure rules

maxFunctionLines — Long function

  • Reports a function whose span (first line to last line, inclusive) is greater than limit.
  • JS/TS: every function-like node, including arrow functions and methods. Nested functions are measured separately; the outer function's span includes them.
  • Python: def / async def from the header to the last indented line.
  • Location: the whole function (start → end line). Carries the function name.

maxFileLines — Large file

  • Reports a file with more lines than limit. One violation per file, on line 1.
  • Counts all lines, including blanks and comments.

maxParameters — Too many parameters

  • Reports a function that declares more than limit parameters.
  • Python ignores self, cls, *args and **kwargs.
  • JS/TS counts every declared parameter; a destructured object counts as one.

maxComplexity — High complexity

  • Reports a function whose cyclomatic complexity is greater than limit.
  • JS/TS: 1 + each if, ?:, loop, catch, non-empty case, &&, ||, ??. Nested functions are not included.
  • Python (approximate): 1 + each body line starting with if/elif/for/ while/except/case + each and/or. Nested functions are included.

maxNestingDepth — Deep nesting

  • Reports a control statement nested deeper than limit.
  • JS/TS: depth increases for if, for, for…in, for…of, while, do, switch. An else if does not add a level. Every statement past the limit is reported.
  • Python (approximate): depth = indentation ÷ 4 on if/elif/else/for/while/ with/try/except lines. The count includes the enclosing def/class levels, so Python code reaches the limit sooner than equivalent JS. Consider a higher limit for Python projects.

requireSingleResponsibility — Multiple responsibilities

Two triggers:

  • A class with more than options.maxMethods methods (JS/TS: methods, getters, setters; Python: defs one level inside the class).
  • A function that is both longer than 1.5 × maxFunctionLines.limit and more complex than 1.5 × maxComplexity.limit. This trigger reads the other two rules' limits, so changing them changes this rule too.

This is a heuristic. See the false-positive notes below.

requireDocumentationForComplexCode — Complex code without docs

  • Reports a function with complexity ≥ options.complexityThreshold and no documentation.
  • JS/TS: documentation = a JSDoc block (/** … */) attached to the function. A plain // comment does not count.
  • Python: documentation = a docstring on the first body line.

Duplication rule

detectDuplicateCode — Duplicate code

  • Reports a block of at least options.minLines significant lines (default 6, minimum 3) that is identical, after whitespace normalization, to a block seen earlier.
  • Lines shorter than 12 characters, brace-only lines, comments and import/export lines are ignored, so boilerplate does not trigger it.
  • One violation per duplicated block; the message says where the original is.
  • The HEAD scan detects clones across files; the commit walk detects clones within a file. See 05 — Analyzers.

Hygiene rules

detectUnusedCode — Unused code

  • JS/TS: reports an import, a module-level non-exported variable, or a non-exported function declaration whose name appears only once in the file. There is no type information and no cross-file analysis, so only obvious cases are found. Names starting with _ are ignored.
  • Python: reports unused imports only (the name appears once in the file). from x import * is ignored.

requireClearVariableNames — Unclear name

  • Variables (JS/TS): 1–2 character names not on the allow list, vague words with a number (data1, tmp2, obj3), and short letters with digits (abc1).
  • Parameters and function/class names (both languages): only vague words with a number and letters+digits. Conventional short names (e, x, cb, i) are allowed.
  • Allowed: _-prefixed names and technical names (utf8, sha256, ipv6, oauth2, i18n, h1, …).

requireErrorHandling — Missing error handling

  • JS/TS: an await that is not inside a try block (in the same function) and not part of a .catch(…) / .then(…) chain.
  • Python: a line calling open(, requests.*(, urllib, json.load(s)(, socket., subprocess., os.remove(, shutil., int(, float( that is not inside a try: block of the same function.
  • Code often handles errors at a higher level (a framework, a caller), so this rule is the most likely to be noisy.

forbidEmptyCatchBlocks — Empty catch block

  • JS/TS: a catch clause with no statements. A catch that contains only a comment counts as empty.
  • Python: an except …: whose body is only pass or ....

forbidHardcodedSecrets — Hardcoded secret

  • Checks string values assigned to variables, object properties and assignments (JS/TS), and assignments or any string on a line (Python).
  • Reports known token formats (AWS, GitHub, Slack, JWT, sk-…, private keys), or a credential-looking value assigned to a secret-looking name. Placeholders such as changeme, your_api_key, <token>, ${VAR}, example are ignored.
  • Severity is critical by default: one secret weighs as much as eight low findings.

forbidDebugStatements — Debug statement

  • JS/TS: console.log/debug/info/trace/dir/table(…) and debugger. console.error and console.warn are allowed.
  • Python: a line starting with print(, and any breakpoint().

False positives and how to handle them

RuleTypical false positiveSuggested handling
requireErrorHandlingErrors handled by a framework or a callerLower to low, or disable
requireSingleResponsibilityLarge but cohesive classes (e.g. a Django ModelAdmin, a React class component)Raise maxMethods
requireDocumentationForComplexCodeTeams that document with // commentsRaise complexityThreshold, or disable
maxNestingDepth (Python)Methods start at depth 2Raise limit to 5–6 for Python
forbidDebugStatementsCLIs and scripts where print/console.log is the outputExclude the script folders, or disable
detectUnusedCodeNames used only via re-export or string lookupPrefix with _, or lower to low
forbidHardcodedSecretsTest fixtures with fake tokensExclude the fixtures folder

There are no inline suppression comments. Adjust the rule, or exclude the path. Recipes are in 11 — Customization guide.

Rule changes and caching

Any change to rules changes the analysis config hash, which invalidates the per-commit cache. The next run re-analyzes everything with the new rules. See 09 — Caching & performance.