Rules and presets reference
Reference for RuleSetting, every preset field, the rules, presets, and codeFenceLanguages fields of an override, the order Kiira merges rule settings in, and the --rule flag.
Built-in rules
The list of built-in rules, with their scopes and default levels, lives on the Rules page. Plugin rules use the id <plugin>/<rule>.
RuleSetting
A rule's entry in rules, in a preset, or in an override:
import type { RuleSetting } from "kiira-core/plugin"export const levels: Record<string, RuleSetting> = { "language-tag": "off", "unused-symbols": "warn", "docs/max-length": ["error", { lines: 40 }],}A level is "off", "warn" (reports a warning), or "error" (reports an error). A [level, options] pair also passes options to a rule. The rule's meta.options.validate can reject them. A level without options keeps the options an earlier layer set.
An unknown rule id, an invalid level, or options a rule rejects fail when the config is resolved, and kiira check exits 2.
Presets
A preset is a named bundle of settings. Reference it by name (<plugin>/<preset>) in presets, or write it inline.
| Field | Type | What it does |
| --- | --- | --- |
| name | string | Required. |
| extends | string[] | Presets applied before this one, by name. Each preset is applied once, at its first use. A cycle is an error. |
| include | string[] \| (project) => string[] | Added to the top-level include. The function form is called with the project (cwd, packageJson, workspacePackages, isTracked) before files are discovered. |
| exclude | string[] | Added to the top-level exclude. |
| allowEmpty | boolean | When true and no file matches, Kiira skips the run, prints No files matched; nothing to check., and exits 0. Without it, an empty match is a normal run with zero files. |
| codeFenceLanguages | string[] | The fence identifiers to recognize. The last preset that sets it wins, unless you set markdown.codeFenceLanguages yourself. |
| rules | Record<string, RuleSetting> | Rule settings, applied in the order described in How settings merge. |
| typescript | (file, ctx) => result | A per-file TypeScript hook. Runs before the plugins' hooks. |
This preset builds on a preset named base, checks the docs folder of every workspace package, and is fine with finding none:
import { relative } from "node:path"import type { KiiraPreset } from "kiira-core/plugin"export const docs: KiiraPreset = { name: "docs", extends: ["base"], include: (project) => project.workspacePackages.map((pkg) => `${relative(project.cwd, pkg.dir).replaceAll("\\", "/")}/docs/**/*.md`), exclude: ["**/changelog.md"], allowEmpty: true, codeFenceLanguages: ["ts", "tsx", "typescript", "js", "jsx", "javascript"], rules: { group: "off" },}Globs use / separators. On Windows, relative() returns \, so the example changes it to /.
--entry and positional paths on the CLI replace the whole include set, presets included.
Overrides
An entry of overrides can also set, for the files its include matches:
rulesis applied after the top-levelrules.presetsis a list of presets whoserulesandcodeFenceLanguagesapply. Their other fields are ignored.codeFenceLanguagesreplaces the recognized fence identifiers. The last matching override wins.
import { defineConfig } from "kiira-core"export default defineConfig({ overrides: [ { include: ["docs/intent/**/*.md"], codeFenceLanguages: ["ts", "tsx", "typescript", "js", "jsx", "javascript"], rules: { group: "off" }, }, ],})How settings merge
Each layer is applied on top of the one before it:
- Each rule's built-in default level.
presets, in order, with each preset'sextendsapplied first.- Top-level
rules. The legacycheckUnusedSymbolsandcheckRelativeImportsoptions count as this layer, as aliases ofunused-symbolsandrelative-imports. An explicitrulesentry for the same rule wins. - Matching
overrides, in order. Within an override, itspresetsapply before itsrules. --ruleon the CLI.
--rule
Sets the level of one rule for one run, without editing your config. It is repeatable, and it beats every layer above, including per-file overrides.
kiira check --rule unused-symbols=warn --rule docs/no-todo=offA value that isn't <id>=<level>, or an id Kiira doesn't know, exits with code 2. See Flags.