CLI reference · Linters · Why flint? · Alternatives
Flint is a fast, simple lint runner that doesn't slow down your AI coding.
- Fast — native execution (no Docker), parallel, diff-aware (changed files only), opt-in (undeclared tools don't run), small binary cached by mise
- Local + CI aligned — one binary, one config model, local defaults tuned for day-to-day work and broader coverage in CI
- Sensible defaults —
flint initscaffolds a working setup quickly, and most repos can stick with the generated defaults - Opinionated config — Flint chooses canonical config filenames per linter,
while still letting you keep them in a directory such as
.github/config - AI-friendly — fix silently, surface only what needs review
- Separated ownership — dedicated linters and formatters own their file types to avoid overlapping rules and editor-config conflicts
- Predictable and updatable linter versions — lint behavior stays stable
until the repo intentionally updates pinned linter versions, for example via
Renovate updates to
mise.toml - Cross-platform — Linux, macOS, Windows
- Autofix —
--fixfixes what's fixable; reports what still needs review
Read the background and principles and alternatives/comparisons.
Tip
Legacy v1 (bash task scripts): see README-V1.md.
-
Install mise.
-
Add Flint to your repo:
mise use --pin aqua:grafana/flint
-
Optional: if you use Renovate, create your Renovate config before init. Flint can then patch it to include the Flint preset, which helps keep linter and Flint updates grouped with less PR noise.
-
Let Flint scaffold the setup:
mise exec -- flint initDuring
flint init, you can:- choose which linters to enable
- add the standard
miselint tasks - write
flint.tomlwhen needed - create
.github/workflows/lint.ymlwhen the repo does not already have one - add linting guidance to
AGENTS.mdorCLAUDE.md(or createAGENTS.md)
If you want non-interactive setup, run
mise exec -- flint init --yesand trim any generated linter pins afterward.For a real setup example, see grafana/docker-otel-lgtm's
mise.toml,flint.toml, and lint workflow. -
Optional: install a git hook that runs
flint run --fixbefore each commit:mise exec -- flint hook install
For normal local use, run:
mise run lint:fixFlint fixes what it can, tells you when everything is already good, and tells you what still needs review.
By default, Flint checks only changed files. Use --full to check every
matching file.
For more commands and flags, see the CLI reference.
Note
In rare cases (currently only renovate-deps) a failure may show up
only in CI. That is a deliberate performance optimization — see
adaptive runs. When it happens, flint prints the
command to reproduce locally (usually --full or the linter name).
| Name | Linter | Formatter |
|---|---|---|
| C# | — | dotnet-format |
| Go | golangci-lint |
gofmt |
| Java | — | google-java-format |
| JavaScript / TypeScript | biome |
biome-format |
| Kotlin | ktlint |
ktlint |
| Python | ruff |
ruff-format |
| Rust | cargo-clippy |
cargo-fmt |
| Name | Linter | Formatter |
|---|---|---|
| JSON | biome |
biome-format |
| Markdown | rumdl |
rumdl |
| Shell | shellcheck |
shfmt |
| TOML | — | taplo |
| XML | xmllint |
— |
| YAML | ryl |
ryl |
| Name | Check |
|---|---|
| Dockerfile | hadolint |
| GitHub Actions | actionlint |
| Name | Check | Description |
|---|---|---|
| EditorConfig | editorconfig-checker |
EditorConfig compliance |
| Flint setup | flint-setup |
Flint-managed setup and mise.toml layout |
| License headers | license-header |
Required file header text |
| Links | lychee |
Broken links |
| Renovate | renovate-deps |
Dependency update configuration |
| Spelling | typos |
Spelling in source and text files |
Flint activates checks from your repo's mise.toml: if a Flint-managed tool is
declared there, that check is active; if it is not declared, Flint skips it.
This project uses Semantic Versioning. Breaking changes will be documented in CHANGELOG.md and will result in a major version bump.
See RELEASING.md.