golangci-lint — Specification¶
Focus: Precise reference for the
golangci-lintdriver — synopsis, subcommands, flags, config schema, environment, exit codes, and behavioral guarantees.Sources: -
golangci-lint --help,golangci-lint <cmd> --help- Project docs: https://golangci-lint.run - Source: https://github.com/golangci/golangci-lint
This document tracks v1.59+ behavior with notes where v2 differs.
1. Synopsis¶
The default subject is the current Go module. path... accepts Go package patterns (./..., ./internal/api/...) or directories.
2. Top-level commands¶
| Command | Purpose |
|---|---|
run | Run enabled linters and report issues |
linters | List linters (enabled/disabled, by preset) |
config | Inspect or migrate .golangci.yml (path, verify, migrate in v2) |
cache | Cache management (status, clean) |
custom | Build a custom golangci-lint binary with extra linters (v2) |
version | Print version, Go version, build info |
completion | Shell completion script (bash, zsh, fish) |
help | Help for any command |
3. Key run flags¶
| Flag | Effect |
|---|---|
--enable=<l1,l2,...> / -E | Enable additional linters on top of config |
--disable=<l1,l2,...> / -D | Disable specific linters |
--enable-only=<l1,l2,...> | Run only these linters (overrides config) |
--disable-all | Disable all linters before applying --enable |
--presets=<bugs,style,...> | Enable all linters in named presets |
--fast | Run only fast linters (no type info / whole-program analysis) |
--new | Report only issues in lines changed in uncommitted diff |
--new-from-rev=<rev> | Report only issues new since <rev> (e.g., origin/main) |
--new-from-patch=<file> | Same, but compute "new" from a patch file |
--fix | Apply suggested fixes in place |
--out-format=<f1,f2:path,...> | Output format(s); see §6 |
--config=<path> / -c | Path to .golangci.yml (default: search up from CWD) |
--no-config | Ignore any discovered config file |
--timeout=<dur> | Per-run timeout (default 1m) |
--concurrency=<n> / -j | Worker concurrency (default NumCPU) |
--issues-exit-code=<n> | Exit code when issues are found (default 1; set 0 to make non-blocking) |
--max-issues-per-linter=<n> | Cap findings per linter (default 50) |
--max-same-issues=<n> | Cap repeated identical findings (default 3) |
--sort-results | Sort output deterministically |
--allow-parallel-runners | Allow multiple instances on the same machine |
-v | Verbose logging |
--print-resources-usage | Print RAM/CPU stats per linter |
4. .golangci.yml structure¶
Top-level keys (v1 schema; v2 reorganizes — see §9):
run: # execution
timeout: 5m
concurrency: 4
tests: true
build-tags: [integration]
go: "1.22"
linters: # which linters fire
disable-all: true
enable: [govet, staticcheck, errcheck]
presets: [bugs]
linters-settings: # per-linter configuration
gocyclo: { min-complexity: 15 }
revive:
rules:
- name: exported
issues: # filter the findings stream
exclude-dirs: [vendor, gen]
exclude-files: [".*\\.pb\\.go$"]
exclude-rules:
- path: _test\.go
linters: [errcheck, gosec]
exclude-use-default: true
max-issues-per-linter: 50
max-same-issues: 3
new-from-rev: "" # equivalent to --new-from-rev
severity: # map findings to severities
default-severity: error
rules:
- severity: warning
linters: [revive, gocritic]
output: # presentation
formats:
- format: colored-line-number
print-issued-lines: true
print-linter-name: true
sort-results: true
Top-level service: is used by the hosted golangci.com integration and is irrelevant for self-hosted CI.
5. Linter selection precedence¶
From lowest to highest priority:
- Default enabled set.
linters.disable-all/linters.enable-all.linters.presets.linters.enable/linters.disable.- Command-line
--disable-all,--enable,--disable. --enable-only(replaces everything above).
--enable-only is the kill switch: use it when you need to ignore all configuration and run exactly one linter.
6. Output formats¶
| Format | Use |
|---|---|
colored-line-number (default) | Human, terminal |
line-number | Human, no color (logs) |
tab | Human, tab-aligned |
json | Stable machine-readable, full issue records |
checkstyle | Jenkins, Bitbucket, etc. |
code-climate | GitLab Code Quality |
junit-xml | JUnit consumers |
github-actions | Inline PR annotations in GitHub Actions |
teamcity | TeamCity service messages |
sarif | SARIF for SAST tooling (v2) |
Multiple formats at once, each optionally to a path:
7. Exit codes¶
| Code | Meaning |
|---|---|
0 | No issues found (or --issues-exit-code=0) |
1 | Issues were found (default --issues-exit-code value) |
2 | Configuration or input error (bad flag, bad YAML, unknown linter) |
3 | Internal failure (linter crash, package load failure, timeout) |
7 | Validation error in the config file (v2 distinguishes from 2) |
Always check the exit code; do not parse stderr to determine success.
8. Environment variables¶
| Variable | Role |
|---|---|
GOLANGCI_LINT_CACHE | Cache directory (default ~/.cache/golangci-lint) |
GOCACHE | Go build cache (used during package load) |
GOPATH, GOMODCACHE | Module cache for dependency loading |
GOPROXY, GOSUMDB | Module download/verification policy |
GOFLAGS | Default flags for the embedded go invocations |
GOOS, GOARCH | Cross-compile target for analysis (matches build tags) |
CGO_ENABLED | Affects which files are loaded based on build constraints |
GOMAXPROCS | Caps concurrency in cgroup-limited environments |
GOLANGCI_LINT_VERBOSE | Verbose logging (equivalent to -v) |
9. v1 → v2 schema notes¶
| v1 | v2 |
|---|---|
linters.enable: [...] | linters.enable: [...] with linters.default: standard\|none\|all\|fast |
linters-settings: | linters.settings: |
issues.exclude-rules: | linters.exclusions.rules: |
issues.exclude-dirs: | linters.exclusions.paths: |
output.format (string) | output.formats: (map of name → options) |
service: | removed |
Migrate with golangci-lint migrate (in-place) or --dry-run.
10. Behavioral guarantees¶
- Single load. Packages are loaded once per run;
go/analysisanalyzers share the result. - Deterministic with a pinned version. Same version + same Go + same config + same source → same findings.
- Cache safety. Cache entries are keyed on tool/Go versions, enabled linter set, settings, and source hashes; stale entries are not returned.
- Faithful exit code. Returns non-zero when issues are found unless
--issues-exit-code=0. - Suggested fixes are atomic per file.
--fixwrites to a temp file and renames; partial writes do not occur.
11. Non-goals / limitations¶
- Not a security scanner on its own (use
gosecas one of its linters). - Not a code formatter (it can apply formatter linters' fixes, but pick one of
gofmt/gofumpt). - Not an IDE protocol; for editor integration use the upstream linters' LSPs or
golangci-lint's editor plugins. - Not a
go vetreplacement at the language level —go vetships with the Go toolchain and runs asgo testalways. - Not reproducible across versions; pin the version.
12. Related references¶
- Project site: https://golangci-lint.run
- Configuration reference: https://golangci-lint.run/usage/configuration/
- Linters list: https://golangci-lint.run/usage/linters/
- v2 migration guide: https://golangci-lint.run/product/migration-guide/
go/analysis: https://pkg.go.dev/golang.org/x/tools/go/analysis