Toolchains, runtimes and recipes
polylint’s built-in engines ship as components pinned to the poly version. Two other mechanisms run tools that are not components: host tools and recipes. Both run as subprocesses, and both are where a run can depend on the machine. This page says exactly where.
Host tools
Section titled “Host tools”A language’s canonical CLI, run per file over stdin and stdout when it is on PATH. Each is an
engine, configured as [engines.<id>].
| Engine id | Language | Default |
|---|---|---|
rustfmt |
Rust | on when installed |
gofmt |
Go | on when installed |
shellcheck |
Shell (lint) | on when installed |
zigfmt |
Zig | opt-in |
google-java-format |
Java | opt-in |
ktfmt |
Kotlin | opt-in |
swift-format |
Swift | opt-in |
dartfmt |
Dart | opt-in |
gleamfmt |
Gleam | opt-in |
styler |
R (via Rscript) |
opt-in |
[engines.zigfmt]enabled = true
[engines.gofmt]enabled = false # use the tree-sitter tier for Go instead- Absent or disabled — the language falls through to tree-sitter formatting with a notice. A missing host tool is never an error.
- Cache — each tool’s own
--versionoutput is part of the cache key, so upgrading the tool invalidates its cached results. - Batching —
batch = truehands a tool many files per invocation, with output identical to the per-file path;rustfmt,swift-formatandstylercannot be batched. - Shell formatting is not a host tool. It comes from the
shcomponent (shfmt as a Go sidecar). The hostshfmtis used only by the bundled build or with[components] disable = ["sh"];[engines.shfmt] enabled = falseleaves shell unformatted.
Recipes
Section titled “Recipes”A recipe is a built-in integration for an ecosystem tool. Enable one with [tools.<name>]:
[tools.golangci-lint]enabled = trueversion = "2.15.0" # a release listed in the cataloginstall = "auto" # download it when it is missingRecipe tools run batched (once per Go module, Helm chart or buf.yaml module where that is the
tool’s unit), and their reports are parsed into per-line findings with rule codes and URLs. The
full behavior is on the tool catalog page.
| Tool | Covers | Download (install = "auto") |
Needs on the host |
|---|---|---|---|
golangci-lint |
Go lint and format | yes | Go toolchain (it type-checks the module) |
buf |
Protobuf | yes | — |
actionlint |
GitHub Actions workflows | yes | — |
gau |
GitHub Actions uses: pins |
no | install gh-actions-updater |
hadolint |
Dockerfile | yes | — |
helm, helm-template |
Helm charts | yes | — |
tflint |
Terraform | yes | — |
tofu |
HCL / Terraform format | yes | — |
terraform |
HCL / Terraform format | no | install terraform |
buildifier |
Starlark / Bazel | yes | — |
checkstyle |
Java lint | yes (a jar) | a JRE (java) |
palantir-java-format |
Java format | yes (native image) | — |
npm-groovy-lint |
Groovy | no | Node, npm install --global npm-groovy-lint |
pyproject-fmt |
pyproject.toml |
no | Python, uv tool install pyproject-fmt |
- Downloads are available on macOS and Linux (arm64 and x86_64; the
checkstylejar is platform-independent). On Windows, install the tool yourself. - Verification — a download is checked against its SHA-256 before use. A
versionpolylint cannot provision makes the tool unavailable with a message; polylint never runs a different version fromPATHinstead. - Missing tool — without
install = "auto", a missing recipe tool is a warning naming the command that installs it. - Takes over its language — an enabled recipe formatter that covers a whole language
(
golangci-lintfor Go,tofufor HCL) replaces the built-in formatter for it. If that tool is missing, its files are reported as skipped rather than formatted by something else.
Catalog tools
Section titled “Catalog tools”Any of the 348 tools in the embedded mdsf catalog can be
enabled the same way. Without a recipe, a catalog tool is probed on PATH, run per file, and gives
a file-level verdict (no line, no rule code). See the tool catalog.
Reproducible runs
Section titled “Reproducible runs”Components are pinned to the poly version. Everything else on this page depends on the machine, so pin it where results must match across machines:
- Fix the poly version in CI:
required_versioninpoly.tomlwith the GitHub Action’sversion: from-config, orversion:/POLY_VERSIONdirectly. - Pin host toolchains (
rustfmt,gofmt,shellcheck) in CI, for example withmiseor the language’s setup action — or disable them and accept tree-sitter formatting everywhere. - Give every downloaded recipe tool a
version. - Install the runtimes recipe tools need (
java,node,python) at pinned versions. - Run
poly lint --deny-skipsso a tool that went missing fails the job instead of quietly checking less.
poly doctor prints which poly is running and the configuration in effect — the first thing to
compare when two machines disagree.