Configure linters
Trunk Code Quality's linter integrations are fully configurable. This means that you can easily tune existing linters or leverage our caching and hold-the-line solution with your own custom linters.
Here's an overview of the ways you can configure linters.
Config hierarchy
Linters can be configured at different places:
The source plugin repo usually
https://github.com/trunk-io/plugins.The repo-wide Trunk config file overrides the definitions in the plugin repos,
.trunk/trunk.yamlLocal, per-user configuration in
.trunk/user.yamlwhich is used for local overrides of.trunk/trunk.yamland doesn'tPer linter configuration in linter config files such as
eslint.config.jsor.prettierrc.
Plugin system
Trunk defines linter configuration in a plugin system. By default, it'll point to the Trunk plugin repo on GitHub. You can check if other custom plugin sources are specified in your trunk.yaml file for Shared configs.
version: 0.1
cli:
version: 1.22.2
# Trunk provides extensibility via plugins. (https://docs.trunk.io/cli/configuration/plugins)
plugins:
sources:
- id: trunk
ref: v1.6.1
uri: https://github.com/trunk-io/pluginsLinter definitions
Each linter implemented in the Plugin Repo has its own linter definition. Let's take clang-tidy as an example, which ships with the following default configuration:
definitions:
...
- name: clang-tidy
files: [c/c++-source]
type: llvm
commands:
- output: llvm
run: clang-tidy --export-fixes=- ${target}
success_codes: [0]
download: clang-tidy
direct_configs: [.clang-tidy]
disable_upstream: true
include_scanner_type: compile_command
environment:
- name: PATH
list: ["${linter}/bin"]
...Linter definition reference
You can find the default definitions for linters in the Plugin Repo and find references for these fields on the Linter Definitions page.
Overriding default linter definitions
You may find while using Trunk that you want to modify one of these defaults: perhaps you want clang-tidy to not run on the upstream, or maybe you want the node runtime to include another environment variable. In these cases, you can specify the field in your trunk.yaml to override the default value.
If you wanted to flip the value of disable_upstream to false, you could, in your own trunk.yaml, specify:
definitions:
...
- name: clang-tidy
disable_upstream: false
...Configure linter commands
Some linters have multiple commands, such as Ruff, which can run in different ways. By default, Ruff is configured to only run as a linter:
lint:
enabled:
- ruff@<version>:
commands: [lint]You can configure ruff to also run the format command by adding it to the commands tuple:
lint:
enabled:
- ruff@<version>:
commands: [lint, format]Configure linter platforms
Similarly, some linters are configured to run differently on different platforms or at different versions. When overriding a command definition, overrides are applied on the tuple [name, version, platforms].
For example, if you wanted to disable batching when running ktlint on Windows, you could consider its default configuration:
definitions:
...
- name: ktlint
...
commands:
- name: format
platforms: [windows]
run: java -jar ${linter}/ktlint.exe -F "${target}"
output: rewrite
cache_results: true
formatter: true
in_place: true
batch: true
success_codes: [0, 1]
- name: format
run: ktlint -F "${target}"
output: rewrite
cache_results: true
formatter: true
in_place: true
batch: true
success_codes: [0, 1]
...And override it as such:
definitions:
...
- name: ktlint
...
commands:
- name: format
platforms: [windows]
batch: false
...When executing linters, Trunk will execute the first matching command based on its compatible platforms and linter version. Note when overriding that new commands that don't match an existing tuple are prepended to the resulting commands list.
Alternatively, consider the default node runtime:
runtimes:
definitions:
- type: node
download: node
runtime_environment:
- name: HOME
value: ${home}
- name: PATH
list: ["${runtime}/bin"]
linter_environment:
- name: PATH
list: ["${linter}/node_modules/.bin"]
version: 16.14.2
version_commands:
- run: "node --version"
parse_regex: ${semver}If you want to add ${home}/my/special/node/path to PATH, you could specify the following:
runtimes:
- type: node
runtime_environment:
- name: HOME
value: ${home}
- name: PATH
list: ["${home}/my/special/node/path", "${runtime}/bin"]Blocking thresholds
All issue severities low-high are considered blocking by default. In cases where you might want to slowly try out a new linter, we provide a mechanism to set specific thresholds for each linter.
lint:
threshold:
- linters: [clang-tidy]
level: highEvery entry in threshold defines a set of linters and the severity threshold that is considered blocking. In this example, we're saying that only high lint issues should be considered blocking for clang-tidy.
linters
List of linters (e.g. [black, eslint]) or the special [ALL] tag
level
Default low. Threshold at which issues are considered blocking. One of: note, low, medium, high, or none (this last option will result in issues never blocking)
Trigger rules
Some linters do not operate on individual files. Instead, you must lint your entire repo at once. The way this is handled in Trunk is to set up a trigger rule. Most linters will not require the use of a trigger rule.
Trigger rules work on 3 principles:
Input(s) that trigger the linters. These can be files, directories, or extended globs.
Linter(s) to run when a triggered file is modified.
Targets(s) to pass to the linters (can be files or directories).
An example for ansible-lint:
lint:
enabled:
- [email protected]
triggers:
- linters:
- ansible-lint
paths:
- ansible # A directory
targets:
- ansible # A directoryTriggered linters will also be run when executing trunk check with --all so long as a file exists that matches one of the listed paths.
You may use . as a target to run on the entire repo instead of an isolated directory.
File size
By default, Trunk only lints files up to 4 MiB in size. To override this globally, specify a default_max_file_size in lint:
lint:
default_max_file_size: 1048576 # BytesTo override this for a specific linter, specify a max_file_size in its definition:
lint:
definitions:
- name: prettier
max_file_size: 2097152 # BytesTimeout
Each linter has a default timeout of 10 minutes. If its execution takes longer than this amount of time, Trunk Code Quality will terminate the process and return an error to the user.
To override the timeout for a specific linter, specify a run_timeout in its definition:
lint:
definitions:
- name: clang-tidy
run_timeout: 5mThe run_timeout value can be specified in seconds (s), minutes (m), or hours (h).
Local linter overrides
Trunk can also be managed by the .trunk/user.yaml file in your repository. This file is optional, but it allows individual developers to customize how they want trunk to run on their machines.
Simply configure .trunk/user.yaml as you would for .trunk/trunk.yaml. Be mindful that .trunk/user.yaml takes precedence over .trunk/trunk.yaml, so substantial modifications could violate hermeticity.
Per linter definitions
Trunk allows you to keep using your existing linter configs, and new linters recommended by Trunk will have their configs added in the .trunk/configs folder. These config files will be symlinked in during any trunk check run.
Moving linters
You can move existing linter config files into the .trunk/config folder. You can check which files are automatically symlinked by looking for the direct_configs of each plugin's definition. If there are config files not listed, you can add them by overriding the definition like this:
lint:
definitions:
- name: some_linter_name
direct_configs:
- .custom_config.fileLast updated

