Linting
Configuration
Configure lint behavior in Acton.toml
Use the [lint] section for global linter behavior, and [lint.rules] for rule levels.
[lint] Settings
| Field | Type | Default | Description |
|---|---|---|---|
exclude | string[] | [] | Glob patterns used to hide lint diagnostics for matching files. |
max-warnings | integer | unlimited | Warning threshold. If warnings are greater than this value, acton check exits with non-zero code. |
output-format | string | plain | Default output format for acton check: plain, json, sarif, github, or gitlab. |
Example:
[lint]
exclude = ["contracts/generated/*.tolk", "contracts/legacy.tolk"]
max-warnings = 0
output-format = "sarif"Behavior notes:
- In project-wide mode (
acton checkwithout target), contracts matchingexcludeare skipped as roots. - Project-wide discovery still walks only
.tolkfiles and skips built-in directories such as.git,.github,.idea,.acton,node_modules,target,tolk-stdlib,.codex, and.claude. - Non-
.tolkcontract entries such as precompiled.boccontracts are never lint roots. - If you pass an explicit target (
acton check <contract-name>oracton check <file.tolk>), that root target is still analyzed. - Excluded dependency files can still be parsed/resolved, but their lint diagnostics are filtered out.
- In project-wide runs, excluded contract roots are skipped entirely, so their compiler errors and lint diagnostics are not reported.
- Compiler errors are still shown for roots that are actually checked, including explicit targets.
- Exclude matching is checked against both project-root-relative and absolute paths.
[lint.rules] Global Rule Levels
Set rule levels for the entire project:
[lint.rules]
unused-variable = "deny"
mutable-variable-can-be-immutable = "warn"Supported levels:
| Level | Effect |
|---|---|
allow | Disable the rule |
warn | Report as warning |
deny | Report as error |
Per-Contract Overrides
Override rule levels for a specific contract:
[contracts.Counter]
display-name = "Counter"
src = "contracts/Counter.tolk"
[lint.rules]
unused-variable = "deny"
[lint.rules.Counter]
unused-variable = "allow"The subsection name (Counter above) must match [contracts.NAME].
Inline Suppressions
You can suppress diagnostics for the next line with an inline comment:
// check-disable-next-line <rule-name>[, <rule-name>...]Examples:
// check-disable-next-line unused-variable
val x = 1;
// check-disable-next-line unused-variable, write-only-variable
var tmp = 10;
tmp = 20;
// check-disable-next-line all
val legacy = oldLogic();Notes:
- Suppression applies only to the immediately following line.
- The suppression comment must use
//and be placed directly above the target line. - Use lint rule names (for example
unused-variable) or diagnostic names such ascompiler-error/parse-error, not diagnostic codes (for exampleE002orC001). - Matching is keyed from the diagnostic's primary location, so the suppression must sit directly above the line that receives the primary annotation.
- Unknown rule names in the suppression list are ignored.
allsuppresses all diagnostics for the next line.- Suppressions also apply to compiler/parser diagnostics when the diagnostic name matches (
compiler-error,parse-error).
Temporary rule narrowing with --enable-only
Use --enable-only for one-off focused runs:
acton check --enable-only E003,E028Semantics:
- selectors are resolved after config is loaded
- selected rules keep their configured
warn/denyseverity - if a selected rule was configured as
allow, the explicit selection re-enables it at the default severity - every unselected rule is forced to
allowfor that invocation
Selectors must resolve to exactly one rule. Full rule codes such as E003
are the safest form.
Last updated on