Skip to content

Adopting dscheck

Your first run will report a lot. That’s expected — you’re measuring drift that has been accumulating, not failing a test you were meant to pass. Here’s the path from that first number to a green build, usually within an hour.

Terminal window
npx dscheck-cli init

It looks for the token source you already have — a Tailwind @theme, a :root block, DTCG JSON, including inside monorepo packages — and proposes a config. On unfamiliar codebases it also detects scoped systems (a design system living under .my-app rather than :root) and runtime-injected variables (--radix-*, syntax-highlighter vars) that belong in allow. Nothing is written until you add --write.

Then see the damage:

Terminal window
npx dscheck-cli check .
  • Errors are values that are almost certainly wrong: a raw color when the identical token exists, or a var(--typo) that resolves to nothing.
  • Warnings are judgment calls — a 14px where your scale says 12px. Someone decided that once; dscheck is asking whether they meant to.

If the number is zero, be suspicious: run dscheck tokens to confirm a system was actually found, and dscheck check --explain-skips to see what wasn’t checked.

Terminal window
npx dscheck-cli fix .

Only provably-identical replacements are applied — a value that already equals a token becomes that token. 14px is never rounded to 12px. On a real marketing site this removed 60% of findings mechanically (162 → 64).

Terminal window
npx dscheck-cli baseline . # commit .dscheck-baseline.json

Now CI fails only on new drift. This is the step that makes adoption a one-day job instead of a cleanup project: the debt is recorded, visible, and can only shrink (baseline --update prunes what you’ve paid down but never raises a count).

Findings become ordinary editor squiggles and CI failures — see ESLint, stylelint, and CI. If agents write UI in this repo, add the guardrail hook too; that’s the difference between catching drift and preventing it.

Report it. False positives are the highest-priority bug class here — every confirmed one becomes a permanent regression fixture and a line on the release scoreboard. Until it’s fixed, ignore (files) and allow (names) in the config keep you moving without disabling a rule wholesale.