Skip to content

Rule Configuration

Lint rules are configured in chant.config.ts under the lint key.

export default {
lint: {
rules: {
"EVL001": "error",
"COR004": "warning",
"COR008": "off",
},
},
} satisfies ChantConfig;
SeverityEffect
"error"Fails the lint run (non-zero exit code)
"warning"Reported but does not fail
"info"Informational notice
"off"Disables the rule entirely

Use extends to inherit rule configurations:

export default {
lint: {
extends: ["@intentius/chant/lint/presets/strict"],
rules: {
"COR004": "off", // override preset
},
},
} satisfies ChantConfig;

Presets are resolved recursively. Local rules override inherited ones.

This is a different, narrower thing from extends above. Core’s extends bundles (strict, relaxed) set AST rule severities. lint.presets is a lexicon’s own bundle of which of its post-synth check ids get reported at all, the way tflint-ruleset-terraform ships recommended (13 of its 20 language rules) and all (all 20). A lexicon that ships presets exposes them through its plugin’s lintPresets(). See Presets, lintPresets() for the lexicon-authoring side.

export default {
lexicons: ["terraform"],
lint: {
presets: { terraform: "recommended" },
},
} satisfies ChantConfig;

The key is the lexicon’s name (plugin.name, e.g. "terraform", not a serializer name), and the value is a preset name that lexicon’s lintPresets() defines. Naming a preset the lexicon doesn’t define, or omitting the entry for a lexicon that ships presets at all, falls back to "recommended", the safe default, matching tflint’s own precedent of shipping a curated subset rather than everything.

A rule the active preset excludes is not the same as rules: { ID: "off" }. It never runs the severity-override pass in the first place, so it is counted separately. chant build reports “N post-synth finding(s) not reported: excluded by the active lint.presets preset,” distinct from the lint.rules-suppressed count. An explicit rules entry for that id always wins over the preset and reports it anyway, the same precedence tflint documents (rule config over preset over disabled_by_default). So you can opt one report-only rule back in under recommended without switching the whole lexicon to all:

export default {
lexicons: ["terraform"],
lint: {
presets: { terraform: "recommended" },
rules: { "TF011": "warning" }, // re-enabled even though it's report-only
},
} satisfies ChantConfig;

A lexicon that ships no lintPresets() at all is unaffected by lint.presets. Every one of its findings reports regardless, exactly as before this existed.

Apply different rule settings to specific file patterns:

export default {
lint: {
rules: { "COR004": "warning" },
overrides: [
{
files: ["src/legacy/**/*.ts"],
rules: { "COR004": "off" },
},
],
},
} satisfies ChantConfig;

Some rules accept an options object as the second element of a tuple:

rules: {
"COR009": ["warning", { max: 12 }],
}

rules applies to a post-synth check id (a lexicon’s WAW019, WK8005, …) and a project policy’s own id (ORG-COST-CENTER) exactly the same way it applies to COR004 or EVL001 above — same key, same severities, "off" suppresses it entirely:

export default {
lexicons: ["aws"],
lint: {
rules: { "WAW019": "off" }, // this project's scenario needs an open SSH ingress
},
} satisfies ChantConfig;

This is the whole surface for suppressing a post-synth or policy finding. Two things that work for COR/EVL/COMP rules do not apply here:

  • File-specific overrides — a post-synth check runs over the whole synthesized output, not one file, so there is no file path to match a glob against.
  • chant-disable source comments — a post-synth diagnostic’s only locator (entity) names a resource in the synthesized output (a CloudFormation logical id, a Kubernetes metadata.name), not a source file or line, and several checks never set it at all. There is no reliable anchor to put a directive at, so a project-wide rules: { ID: "off" } is the only suppression path.

A suppressed post-synth/policy finding is not silently dropped: chant build prints a count (N post-synth finding(s) suppressed via lint.rules) so the suppression stays visible.

The chant audit failure-severity floor (chant #2113)

Section titled “The chant audit failure-severity floor (chant #2113)”

rules/severity above decides what a rule reports by default. --fail-on on chant audit is a separate lever. It decides what makes the exit code non-zero, the job tflint’s --minimum-failure-severity does. It takes one of four values.

--fail-onExit 1 when…
none (default)never (read-only)
merge-worthyany merge-worthy finding exists
warningany error- or warning-severity finding exists
errorany error-severity finding exists

error is the floor a rule can ship under before it is trusted to fail a pipeline. Land it at severity: "warning" (or configure it to "warning" via rules above), run --fail-on error in CI, and the new rule is visible in every report without breaking a single build. Nobody’s pipeline is pinned to a --fail-on value the new rule would trip. Promote it to "error" later, in the rule’s own default or via rules: { ID: "error" }, once you’re confident. The exact same --fail-on error pipeline then starts enforcing it, with no separate opt-in step.

Terminal window
chant audit . --fail-on error

See the chant audit reference for the full exit-code table.