CLI reference

May 27, 2026 · View on GitHub

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.

Output

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 --fix when 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 --fix runs 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

flint run flags

FlagEnv varDescription
--fixFLINT_FIXFix 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-fixedFLINT_ALLOW_FIXEDIn --fix mode, exit 0 when all reported issues were fixed successfully. Still exits non-zero when any check is partial or needs review
--fullFLINT_FULLLint all files instead of only changed files
--verboseFLINT_VERBOSEShow all linter output, not just failures
--shortFLINT_SHORTCompact summary output — no per-check noise (human) or read-only AI review
--new-from-rev REVFLINT_NEW_FROM_REVShow only new issues created after git revision REV (default: merge base with base branch)
--to-ref REFFLINT_TO_REFCompare changed files to this ref (default: HEAD)
--timeFLINT_TIMEShow how long each linter took to run

All flint run flags above have env var equivalents.

Intended use by context

ContextCommandWhy
Interactive developmentflint runFull output so you can read the details
Human wanting a summaryflint run --shortCompact output, no per-check noise
Pre-push hook (CC / agentic)flint run --fixFixes what it can silently, surfaces only what needs human review
CIflint runFull output for humans reading CI logs

Changed-file and baseline runs

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 released aqua:grafana/flint or a cargo-backed prerelease revision, which expands all active checks
  • the check's flint-managed config file changed, such as .shellcheckrc or .yamllint.yml in FLINT_CONFIG_DIR
  • another supported baseline config for the check changed, such as .editorconfig for editorconfig-checker
  • flint.toml changed under [settings]
  • flint.toml changed 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.

Adaptive runs

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:

LinterSkipped locally when…
renovate-depsNo 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 linter
  • flint run <linter> — runs just that one

Canonical config filenames

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 change
  • fixed — the fixer resolved the issue; commit before pushing
  • review — no fixer was applied; human review is required
  • partial — 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 issues

flint init

flint 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-setup

To apply setup migrations and canonicalize mise.toml, run:

flint run --fix flint-setup

flint linters

flint 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
...