Lint
oxlint with type-aware and Panda-aware rules.
What
Linting runs on oxlint, with three layers of rules:
- Built-in (
correctness,suspicious, React, a11y, Next, imports). - Type-aware, through tsgolint, which is built on the same TypeScript 7 we use.
- Panda-aware, through
@pandacss/eslint-plugin, loaded as an oxlint JS plugin fromoxlint-panda.mjsat the repo root.
Formatting is oxfmt. Both run in bun run check.
Why
Types stop a wrong value. The Panda rules explain it: "12px is not a token, the
matching token is 3". They also catch mistakes that compile fine but produce no
CSS, like ":hover" without &, which Panda ignores silently.
The same rules can later run on agent-generated code with JSON output, as one more grader that already knows the design system.
Try it
Create a file with deliberate mistakes:
// packages/ds/src/scratch.tsx
import { css } from "styled-system/css";
export const bad = css({
bg: "#ff0000",
color: "neutral.0",
px: "12px",
marginLeft: "2",
":hover": { bg: "accent.emphasized" },
});bun run linterror prefer-token Use a colors token instead of the hardcoded value "#ff0000".
error no-primitive-token Use a semantic colors token instead of the primitive token "neutral.0".
error prefer-token Hardcoded spacing value "12px". Matching tokens: 3.
warning no-physical-properties Use the logical property "marginInlineStart" instead of "marginLeft".
error no-invalid-nesting Nested selector ":hover" has no "&", so Panda ignores it.Delete the file afterwards. With the oxc VS Code extension (recommended in
.vscode/extensions.json) the same messages appear inline while you type.
Two of those rules are about meaning, not syntax. prefer-token says "use a token".
no-primitive-token says "use the semantic one": neutral.0 is a valid token, but a
component should say accent.fg or bg.surface, so that it follows the theme. A value
that is valid and still wrong is the kind of mistake the benchmark is built to count.
Extend it
- Turn a rule on or off in
.oxlintrc.json, underrules. Panda rules are prefixed@pandacss/. The full list is in the plugin README:node_modules/@pandacss/eslint-plugin/README.md. no-primitive-tokenis configured forcolorsonly: those are the tokens that have a semantic layer. Add a category to itscategorieswhen another one gets semantic tokens.- Widen
prefer-token. It checkscolors,spacing,fontSizesandradiitoday. Add a category to itscategoriesarray to cover more. - Lint another Panda config. The plugin binds one config per run.
oxlint-panda.mjssetscwdtopackages/dsbecause Panda resolves itsincludeglobs from the working directory, not from the config path. - Auto-fix on save is configured in
.vscode/settings.json(source.fixAll.oxc).
Known gaps
- oxlint JS plugins are alpha. If a Panda rule misbehaves, check the plugin version before blaming the rule.
- tsgolint is tied to the exact TypeScript version. Upgrade
typescriptandoxlint-tsgolinttogether. - The plugin declares
eslintas a peer dependency. Bun installs it; nothing uses it.