Reference
Baseline.
How it works
The baseline is a JSON file, committed with your code, holding a violation count per file per rule. When applied, a run hides violations up to the recorded count and reports everything else normally.
The alternative — switching rules to off until the backlog clears — also stops them protecting the code you write tomorrow. A baseline keeps the gate on new code while the existing violations wait.
Create one
01npx ngcompass baseline create01❯ Running a full analysis for the baseline...02❯ Baseline written: .ngcompass/baseline.json03 6 violations recorded across 3 files (2 rules scanned)Commit .ngcompass/baseline.json. It describes the state of the code next to it, so it belongs in version control and should move in the same pull request as any change that alters it.
Apply it
01# Uses baseline.path from config02npx ngcompass analyze --baseline03
04# Explicit file05npx ngcompass analyze --baseline .ngcompass/baseline.json06
07# Ignore a baseline that config enables08npx ngcompass analyze --no-baselineHidden violations stay in the summary line, so a green run still reports the size of the backlog:
01❯ src/fresh.component.ts:4:2202
03 ❯ 4 | template: '<ul><li *ngFor="let x of items">{{ x }}</li></ul>',04 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^05
06× 1 violation (1 error, 0 warnings) FAILED · 6 hidden by baselineThe HTML report shows the same count as a Hidden by baseline stat. If the baseline is enabled and the file is missing, the run fails with a message pointing at baseline create rather than analyzing without it.
The file
01{02 "version": 1,03 "entries": {04 "src/legacy.component.ts": {05 "template-prefer-control-flow": 206 },07 "src/widget.component.ts": {08 "template-prefer-control-flow": 209 }10 }11}Counts, not fingerprints — no line numbers, no message hashes, no copies of your source. Reformatting a file or moving code within it does not invalidate an entry. Files and rules are written sorted and zero counts are dropped, so diffs stay readable.
The trade-off is precision: a file recorded at 2 hides any 2 violations of that rule, not specifically the 2 that were there when you recorded it. Prune regularly and the window stays small.
As the code changes
A new violation is addedReported, and the run exits non-zero as usual. A file recorded with 2 violations of a rule hides 2 — the third is reported, with a note that the file exceeded its recorded count.
A baselined violation is fixedThe entry is now stale. onStale decides whether that is ignored, warned about, or an error. Pruning writes the lower count back.
A file is renamed or movedIts entry follows the file when exactly one baselined path and one new path share a filename. Ambiguous cases are not guessed at — those violations are reported as new.
A file is deletedIts entry is dropped on the next prune.
A run scans a subsetOnly the files and rules covered by the run are considered. Running with --rule or against part of the tree leaves every other entry untouched rather than treating it as fixed.
Keeping it shrinking
Fixing baselined code surfaces on the next run:
01❯ 2 baselined violations have been fixed - run 'ngcompass baseline prune' to tighten the baseline02❯ No new violations found · PASS · 4 hidden by baseline01npx ngcompass baseline prunePruning writes the lower counts back, so fixed violations cannot silently return under an old allowance.
Commands
baseline createRuns a full uncached analysis and records what it finds. Fails if a baseline already exists, unless --force is passed.
baseline showPrints what the baseline currently hides, grouped by rule and ranked by count. Reads the file only — no analysis runs.
baseline pruneRe-counts what this run scanned, follows renamed files, and drops entries for files that no longer exist. This is what shrinks a baseline.
baseline updateRe-counts what this run scanned and writes those counts, keeping entries for files it did not scan. Unlike prune, it will raise counts — use it when you are deliberately accepting new debt.
Flags accepted by the subcommands:
--path <path>Baseline file to read or write. Defaults to baseline.path from config.
-p, --profile <name>Run under a named profile, so the baseline covers the rules CI enforces.
--rule <id>create, updateRecord or refresh one rule, leaving other entries untouched.
--forcecreateOverwrite an existing baseline file.
--top <n>showFiles listed under each rule. Default 3.
--skip-type-checkSkip type-aware rules while recording. The baseline then covers only the rules that ran.
Configuration
01export default defineConfig({02 extends: 'ngcompass:recommended',03
04 baseline: {05 enabled: true,06 path: '.ngcompass/baseline.json',07 onStale: 'warn', // 'ignore' | 'warn' | 'error'08 },09});enabledbooleandefault falseApply the baseline on every analyze run. Leave it false and pass --baseline when you only want it in CI.
pathstringdefault .ngcompass/baseline.jsonBaseline file location, relative to the project root. Override per run with --baseline <path>.
onStale"ignore" | "warn" | "error"default "warn"What to do when the baseline records more violations than the run found — meaning debt was fixed and the file is now looser than reality. error makes that a failing build.
ngcompass config health reports baseline-file-missing when the baseline is enabled but absent, and flags a large maxWarnings budget sitting alongside an active baseline — the baseline already absorbs existing warnings, so a wide budget on top only hides regressions.
In CI
01- name: Install dependencies02 run: npm ci03
04- name: Run ngcompass05 run: npx ngcompass analyze --baseline --profile ciThe baseline is applied after analysis, as a filter on results. It is not part of any cache key, so toggling it does not invalidate the incremental cache, and filtered results are never written back to it.
Because the file is sorted and count-only, a pull request that grows the baseline shows up as raised numbers in the diff. Reviewing that is what keeps it from becoming a dumping ground.