Configuration reference
Every key in .clean-code-tracker.json, the local override file, VS Code settings, CLI flags, and which one wins
CleanLens can be configured in four places:
| Where | Scope | Who uses it |
|---|---|---|
.clean-code-tracker.json | Project; commit it to share with the team | Extension + CLI |
.clean-code-tracker.local.json | Personal; git-ignored | Extension + CLI (not with --preset) |
VS Code settings (cleanlens.*) | User or workspace | Extension only |
| CLI flags | One run | CLI only |
This document lists every option. For which values to choose, see 11 — Customization guide.
1. .clean-code-tracker.json
Lives in the repository root. Create it with CleanLens: Initialize Project
or by hand. If it is missing, the javascript preset is used and a warning is shown.
Full example (every key)
{
"version": 1,
"rules": {
"maxFunctionLines": { "enabled": true, "severity": "medium", "limit": 40 },
"maxFileLines": { "enabled": true, "severity": "medium", "limit": 400 },
"maxParameters": { "enabled": true, "severity": "medium", "limit": 5 },
"maxComplexity": { "enabled": true, "severity": "high", "limit": 10 },
"maxNestingDepth": { "enabled": true, "severity": "high", "limit": 4 },
"detectDuplicateCode": { "enabled": true, "severity": "medium", "options": { "minLines": 6 } },
"detectUnusedCode": { "enabled": true, "severity": "low" },
"requireClearVariableNames": { "enabled": true, "severity": "low" },
"requireErrorHandling": { "enabled": true, "severity": "medium" },
"forbidEmptyCatchBlocks": { "enabled": true, "severity": "high" },
"forbidHardcodedSecrets": { "enabled": true, "severity": "critical" },
"forbidDebugStatements": { "enabled": true, "severity": "low" },
"requireSingleResponsibility": { "enabled": true, "severity": "medium", "options": { "maxMethods": 10 } },
"requireDocumentationForComplexCode": { "enabled": true, "severity": "low", "options": { "complexityThreshold": 15 } }
},
"exclude": ["node_modules/**", "dist/**", "*.min.js", "scripts/**"],
"excludeGenerated": true,
"excludeMigrations": true,
"excludeLockFiles": true,
"mergeSameNameAuthors": true,
"developers": [
{ "displayName": "Musa Alahmed", "emails": ["musa@work.com", "musa.personal@gmail.com"] }
],
"analysis": {
"maxCommits": 500,
"since": "2026-01-01"
},
"scoring": {
"categoryScales": { "duplication": 15, "structure": 45, "hygiene": 38 },
"weights": { "duplication": 0.3, "structure": 0.45, "hygiene": 0.25 },
"minLinesForRanking": 1000
}
}Keys
| Key | Type | Default | Description |
|---|---|---|---|
version | 1 | — (required) | Schema version. Must be exactly 1. |
rules | object | — (required) | One entry per rule id. Unknown ids are an error. A rule that is absent is disabled. See 06. |
rules.<id>.enabled | boolean | — (required) | Turns the rule on/off. |
rules.<id>.severity | low/medium/high/critical | — (required) | Weight 1/3/5/8; also the diagnostic level in the editor. |
rules.<id>.limit | number > 0 | per rule | Threshold for numeric rules. |
rules.<id>.options | { [k]: number | boolean } | per rule | minLines, maxMethods, complexityThreshold. |
exclude | string[] | [] | Extra glob patterns. Added to the built-in list, never replacing it. See 05 — glob syntax. |
excludeGenerated | boolean | true | Skip linguist-generated files and files whose first 5 lines say "generated" / "do not edit". |
excludeMigrations | boolean | true | Exclude **/migrations/**. |
excludeLockFiles | boolean | true | Exclude package-lock.json, yarn.lock, pnpm-lock.yaml. |
mergeSameNameAuthors | boolean | true | Automatically merge identities that look like the same person. See 04. |
developers | { displayName, emails[] }[] | [] | Force emails into one developer with a fixed display name. |
analysis.maxCommits | number ≥ 0 | 500 | Replay the newest N non-merge commits. 0 = the whole history. |
analysis.since | string | none | Replay only commits after this date. Any git log --since value. |
scoring.categoryScales | { duplication?, structure?, hygiene? } | 15 / 45 / 38 | Density at which a sub-score drops to ~37. Larger = more lenient. |
scoring.weights | { duplication?, structure?, hygiene? } | 0.30 / 0.45 / 0.25 | Share of each sub-score in the final score. Should sum to 1. |
scoring.minLinesForRanking | number | 1000 | Analyzed lines needed to be ranked. |
scoring.severityWeights | { low?, medium?, high?, critical? } | 1 / 3 / 5 / 8 | Accepted, but does not currently affect scores (see 08). Use rule severity instead. |
Partial objects are fine for scoring.*: missing keys keep their defaults.
Validation
The file is validated when it is loaded (configValidator.ts). Any error stops
the analysis with a list of every problem, for example:
.clean-code-tracker.json is invalid:
- Rule "maxComplexity": "severity" must be one of critical | high | medium | low.
- Unknown rule: "maxLineLength". Supported rules: maxFunctionLines, …What is checked: version === 1; rules is an object of known ids, each with a
boolean enabled, a valid severity, a positive limit if present, and
number/boolean options; exclude is a string array; the four flags are
booleans; developers has the right shape; scoring and analysis are
objects; analysis.maxCommits is a non-negative number; analysis.since is a
string.
The file must be strict JSON (no comments, no trailing commas).
2. .clean-code-tracker.local.json
A personal override, git-ignored by this repository's own .gitignore (add it
to yours too). Only two keys are read:
| Key | Behavior |
|---|---|
rules | Each entry is shallow-merged into the project rule: { ...project, ...local } |
exclude | Appended to the project list |
Example — silence two rules for yourself, and skip a scratch folder:
{
"rules": {
"forbidDebugStatements": { "enabled": false },
"maxComplexity": { "limit": 15 }
},
"exclude": ["playground/**"]
}Notes:
- The local file is not validated. A typo in a rule id adds an unknown rule that nothing reads. Double-check spelling.
- Other keys (
scoring,analysis,developers, …) are ignored. - A local override changes the config hash, so it also invalidates your cache.
- Local overrides make your numbers differ from your teammates'. Use them for experiments, not for official reports.
3. VS Code settings
Set them in Settings → Extensions → CleanLens, or in settings.json
(user or .vscode/settings.json for the workspace).
| Setting | Type | Default | Maps to |
|---|---|---|---|
cleanlens.liveDiagnostics | boolean | true | Re-check open files as you type |
cleanlens.exclude | string[] | [] | Appended to exclude |
cleanlens.excludeGenerated | boolean | true | excludeGenerated |
cleanlens.excludeMigrations | boolean | true | excludeMigrations |
cleanlens.excludeLockFiles | boolean | true | excludeLockFiles |
cleanlens.mergeSameNameAuthors | boolean | true | mergeSameNameAuthors |
cleanlens.analysis.maxCommits | number | 500 | analysis.maxCommits |
cleanlens.analysis.since | string | "" | analysis.since (empty = not set) |
cleanlens.scoring.minLinesForRanking | number | 1000 | scoring.minLinesForRanking |
cleanlens.cache.enabled | boolean | true | Use the per-commit cache |
cleanCodeTracker.liveDiagnostics | boolean | true | Deprecated alias of cleanlens.liveDiagnostics; read only if explicitly set |
Example workspace settings.json:
{
"cleanlens.analysis.maxCommits": 0,
"cleanlens.exclude": ["scripts/**", "**/fixtures/**"],
"cleanlens.scoring.minLinesForRanking": 500
}4. CLI flags
| Flag | Effect |
|---|---|
[path] | Repository to analyze (default: current directory) |
--preset <name> | Use a preset (javascript/react/python/django) instead of both config files |
--max-commits <n> | Overrides analysis.maxCommits |
--full-history | Same as --max-commits 0 |
--since <date> | Overrides analysis.since |
--no-cache | Disable the cache |
--json, --markdown, --violations, --fail-on <sev> | Output and exit code; see 13 — CLI |
5. Precedence — which value wins
In the CLI
built-in defaults
◀ .clean-code-tracker.json (or --preset, which replaces both files)
◀ .clean-code-tracker.local.json (rules + exclude only; skipped with --preset)
◀ --max-commits / --full-history / --sinceIn the VS Code extension
built-in defaults
◀ .clean-code-tracker.json
◀ .clean-code-tracker.local.json (rules + exclude only)
◀ VS Code settingsQuick matrix
| Option | Config file | Local file | VS Code setting | CLI flag |
|---|---|---|---|---|
| rules | ✅ | ✅ (merged) | — | --preset replaces |
| exclude | ✅ | ✅ (appended) | ✅ (appended) | — |
| excludeGenerated / Migrations / LockFiles | ✅ (CLI) | — | ✅ (wins) | — |
| mergeSameNameAuthors | ✅ (CLI) | — | ✅ (wins) | — |
| developers | ✅ | — | — | — |
| analysis.maxCommits | ✅ (CLI) | — | ✅ (wins) | ✅ (wins) |
| analysis.since | ✅ | — | ✅ if non-empty | ✅ (wins) |
| scoring.categoryScales / weights | ✅ | — | — | — |
| scoring.minLinesForRanking | ✅ (CLI) | — | ✅ (wins) | — |
| cache | — | — | ✅ | --no-cache |
| live diagnostics | — | — | ✅ | — |
6. Other files CleanLens reads
| File | Used for |
|---|---|
.gitignore (root only) | Added to the exclude list (best effort, no negations) |
.gitattributes (root only) | linguist-generated paths are excluded |
.mailmap | Applied by Git itself to author names/emails |
manage.py, pyproject.toml, requirements.txt, setup.py, package.json | Preset suggestion in Initialize Project |
7. Presets
| Preset | Rules | Extra excludes (on top of the base list) |
|---|---|---|
javascript | base rules | — |
react | base rules | *.stories.*, storybook-static/**, **/__tests__/**, *.test.*, *.spec.* |
python | base rules | __pycache__/**, *.pyc, .mypy_cache/**, .pytest_cache/**, **/tests/**, test_*.py, conftest.py |
django | base rules, maxFileLines.limit = 500 | the Python list + **/migrations/**, manage.py |
Base exclude list in every preset: node_modules/**, .venv/**, venv/**,
migrations/**, dist/**, build/**, coverage/**, staticfiles/**,
*.min.js, *.generated.*.