flint run [OPTIONS] [LINTERS...]
flint init
flint hook install
flint linters
flint version
Commands and flags follow golangci-lint conventions. Teams already using it do not need to re-learn the interface.
Flint is built to be quiet so AI agents (and humans) don't have to read pages of linter output to find the actionable bit:
- Clean run — no output. Same under
--fixwhen nothing needed fixing. --fix— silently fixes what it can, prints review-required output, and ends with a one-line summary of the non-clean checks and their state (fixed,review,partial). Fully-clean--fixruns print nothing.
Example --fix output:
[shellcheck]
In bad.sh line 2:
echo $1
^-- SC2086 (info): Double quote to prevent globbing and word splitting.
...
flint: fixed: cargo-fmt — commit before pushing | review: shellcheck
| Flag | Env var | Description |
|---|---|---|
--fix |
FLINT_FIX |
Fix what's fixable, report what still needs review. Exits 1 if anything was fixed (uncommitted) or needs review; 0 if already clean. Only 0 vs non-0 is stable for callers |
--allow-fixed |
FLINT_ALLOW_FIXED |
In --fix mode, exit 0 when all reported issues were fixed successfully. Still exits non-zero when any check is partial or needs review |
--full |
FLINT_FULL |
Lint all files instead of only changed files |
--verbose |
FLINT_VERBOSE |
Show all linter output, not just failures |
--short |
FLINT_SHORT |
Compact summary output — no per-check noise (human) or read-only AI review |
--new-from-rev REV |
FLINT_NEW_FROM_REV |
Show only new issues created after git revision REV (default: merge base with base branch) |
--to-ref REF |
FLINT_TO_REF |
Compare changed files to this ref (default: HEAD) |
--time |
FLINT_TIME |
Show how long each linter took to run |
All flint run flags above have env var equivalents.
| Context | Command | Why |
|---|---|---|
| Interactive development | flint run |
Full output so you can read the details |
| Human wanting a summary | flint run --short |
Compact output, no per-check noise |
| Pre-push hook (CC / agentic) | flint run --fix |
Fixes what it can silently, surfaces only what needs human review |
| CI | flint run |
Full output for humans reading CI logs |
By default, local flint run checks tracked files triggered by changes
relative to the merge base. In CI, flint run activates the full linter set
while still keeping diff-aware scoping where each linter supports it. Use
--full to check every matching tracked file explicitly.
Flint skips files marked linguist-generated in .gitattributes. Prefer that
over Flint-only settings.exclude entries when the file is generated, because
GitHub and other tools can reuse the same metadata.
Some changed-file runs intentionally expand one or more affected checks to all matching files. This establishes a baseline when lint coverage changes, while leaving unrelated checks scoped to changed files.
A check runs against all matching files when:
- the check is newly active because its tool was added to
mise.toml - the check's tool version changed in
mise.toml - the pinned Flint tool changed in
mise.toml, either releasedaqua:grafana/flintor a cargo-backed prerelease revision, which expands all active checks - the check's flint-managed config file changed, such as
.shellcheckrcor.yamllint.ymlinFLINT_CONFIG_DIR - another supported baseline config for the check changed, such as
.editorconfigforeditorconfig-checker flint.tomlchanged under[settings]flint.tomlchanged the check-specific config for a native check, such as[checks.links]or[checks.renovate-deps]
--full is still the explicit whole-repo mode. The automatic baseline behavior
only applies in changed-file mode, and only to checks whose lint coverage may
have changed. Config-file triggers are detected from the raw git change list, so
they still apply when the config path itself is excluded from ordinary lint file
selection.
Some linters are expensive enough that running them on every local
flint run would slow the inner loop. For those, flint run skips the
linter when none of the changed files could plausibly affect its result.
CI is unaffected — it always runs the full set.
Affected linters:
| Linter | Skipped locally when… |
|---|---|
renovate-deps |
No change to Renovate config, the snapshot, or any tracked file |
To force a local run of a skipped linter:
flint run --full— runs every active linterflint run <linter>— runs just that one
When Flint passes config paths explicitly, it supports one canonical config filename per linter. If an active linter has a known alternate upstream config file, Flint fails before running the linter instead of silently ignoring or partially auto-discovering that config.
Move the config to the Flint-managed filename under FLINT_CONFIG_DIR, or
remove the alternate file.
Note
Biome is the exception: its canonical config is root biome.jsonc, not a
file under FLINT_CONFIG_DIR.
--short output — failed checks partitioned by fixability, fixable ones
expressed as the exact command to run:
flint: 2 checks failed — flint run --fix rumdl cargo-fmt | review: shellcheck
--fix output — fixes what's fixable, then prints the full output of
any checks that still need review, followed by a summary line. The internal
outcome model distinguishes clean, fixed, review, and partial:
clean— the fixer ran and found nothing to changefixed— the fixer resolved the issue; commit before pushingreview— no fixer was applied; human review is requiredpartial— a fixer ran but the check still failed and needs review
Exit status remains intentionally coarse: 0 only when everything was already
clean, non-zero when anything still needs action. Callers should rely only on
0 vs non-0, not on specific non-zero codes:
[shellcheck]
In bad.sh line 2:
echo $1
^-- SC2086 (info): Double quote to prevent globbing and word splitting.
...
flint: fixed: cargo-fmt — commit before pushing | review: shellcheck
More --fix summary examples:
flint: fixed: gofmt — commit before pushing
flint: fixed: cargo-fmt — commit before pushing | review: shellcheck
flint: fixed: gofmt — commit before pushing | partial: cargo-clippy
flint: partial: cargo-clippy | review: shellcheck
flint: partial: cargo-clippy
flint: review: shellcheck
Pass one or more linter names to run only those:
flint run shellcheck shfmt # run only shellcheck and shfmt
flint run --fix rumdl # fix only Markdown issuesflint init pins Flint itself in mise.toml so every contributor uses the same
lint binary. For unreleased consumer validation, pass an explicit git revision:
flint init -y --flint-rev <git-rev>That writes a cargo-backed Flint pin. To return to the released Flint backend
after the release is cut, run flint init again without --flint-rev.
flint init is also the explicit way to reconcile a repo with the latest Flint
setup defaults. Routine lint runs use flint-setup and only fail when an
actionable setup migration applies to the repo.
To check setup drift without applying changes, run:
flint run flint-setupTo apply setup migrations and canonicalize mise.toml, run:
flint run --fix flint-setupflint linters shows every check with its status:
NAME BINARY STATUS SPEED PATTERNS
-------------------------------------------------------------------
shellcheck shellcheck installed fast *.sh *.bash *.bats
cargo-fmt cargo-fmt missing fast *.rs
renovate-deps renovate installed fast
...