12. Linting
tcm lints with oxlint, with nothing to install or configure. It runs:
- on scratch files: in VS Code as diagnostics (source
oxlint) as you type, and intcm check; - on what you save:
tcm addandtcm updateshow the findings in the definitions being saved, and a rule set to"error"stops the save; - on the codebase:
tcm lint [namespace].
tcm check and saving look only at code that's new or changed. A definition in a cycle with one you changed is
saved with it and re-hashed, but its code is as it was, so it isn't linted.
$ tcm lint
ui.Pic #uds7r4nm
2:10 warning Missing `alt` attribute. jsx-a11y(alt-text)
return <img src={src} />;
Must have `alt` prop, either with meaningful text, or an empty string for decorative images.
no errors, 1 warning(s) in 12 definition(s) (11 cached)
Positions are in the definition as tcm view shows it. tcm lint exits with 1 when there are errors.
12.1 Cached by hash
A definition's findings depend only on its text as tcm view shows it, the linter's version and the configuration,
so they're cached by those: linting a whole codebase lints what's new. (The text, not just the hash: a comment
that turns a rule off, or a local renamed _unused, changes what's found without changing the hash.) Definitions
that refer to each other run as one module, and each is linted as tcm view shows it, the others imported; what
only comes of that (assigning to a let they share, as to an import) isn't reported. Changing the configuration or oxlint's version (a new tcm's, or
another chosen for the codebase with tcm upgrade oxlint@<range>) lints everything again. oxlint comes with tcm, at
the version tcm was tested with, so there's nothing to install. --fresh re-lints regardless.
Findings travel with tcm push and tcm pull, as test results do (sync), so a clone or another
machine doesn't lint again what was linted elsewhere with the same linter and configuration.
12.2 What's checked
oxlint's correctness rules, as warnings, plus its plugins for what the code uses:
- any
typescript,unicorn,oxc- JSX
react,jsx-a11y- tests
vitest- Node builtins (
node:fs, …) node
12.3 lint.config
A definition at lint.config configures it. Its value is oxlint configuration: rules, categories,
plugins (oxlint's built-in ones) and settings.
// tcm: namespace lint
import noOnlyTests from "eslint-plugin-no-only-tests";
export const config = {
jsPlugins: [noOnlyTests],
categories: { suspicious: "warn" },
rules: { "no-debugger": "error", "no-only-tests/no-only-tests": "error" },
};
Plugins are imports. The packages lint.config imports are its JS plugins (ESLint-compatible ones;
oxlint's JS plugins). List them under jsPlugins, so the
import counts as used. Like any import they're provided, pinned and upgraded by tcm. Since the configuration
is a definition, changing it is an update, and its history is the codebase's.