lintmax-go

command module
v0.20.30 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 10, 2026 License: MIT Imports: 6 Imported by: 0

README

lintmax-go

Maximum-strictness Go quality gate. One command, always-latest, never stale.

The Go counterpart to lintmax (TypeScript). Designed for coding agents, not humans.

Why

Go's compiler is already stricter than tsc on some axes (unused vars/imports are hard errors). lintmax-go closes the rest of the gap and pushes past it: every linter golangci-lint bundles, maxed internal configs, plus the tools golangci deliberately doesn't wrap — nil-safety, whole-program dead code, vulnerability scanning.

Never stale

No linter version is ever pinned. Every tool is fetched @latest on each run, and the embedded golangci config uses default: all — so the moment golangci ships a new linter, your build runs it. You are always on the bleeding edge; you fix-forward, you never accumulate lint debt.

This extends to your own dependencies. A realtime staleness scan checks go.mod deps and GitHub-Action pins against upstream the instant a newer release publishes (tolerance 0; opt into a buffer via LINTMAX_STALENESS_TOLERANCE_DAYS). A stale direct dep — or a stale used indirect one — hard-fails the gate; graph-only modules the build never compiles are ignored. Indirect deps that are MVS-capped (a transitive can't exceed what its requiring module pins) are reported as a non-blocking advisory rather than failing on the unfixable. Set LINTMAX_SKIP_STALENESS=1 to disable.

Install

go install github.com/1qh/lintmax-go@latest   # Go users

brew tap 1qh/tap                              # macOS / Linux
brew install lintmax-go

# or prebuilt binary (no Go, no brew):
curl -fsSL https://raw.githubusercontent.com/1qh/lintmax-go/main/install.sh | sh

Use

Exactly four commands — the lean agent-first surface:

lintmax-go fix      # format + autofix + full gate (every scanner) — the default action
lintmax-go check    # verify only, no writes (CI mode) — same exhaustive scanner set
lintmax-go version  # print version
lintmax-go rules    # list every enabled linter under the maxed config

Prints ok on a single line on success, exit 0 = clean. Tool output is shown only on failure (verbose). The ok is the explicit success signal an agent needs to confirm the gate ran and passed; a clean run that is cached prints ok (cached).

Self-evolving (automatic, never a command)

The tool maintains itself — you never type a maintenance command. Every gate run, internally:

  • Linter @latest refresh — every child tool is reinstalled @latest on a refresh cadence (fast local loop caches the last green run for <24h; CI always forces @latest).
  • Self-update — in CI the running binary refreshes itself to @latest before gating.
  • Green-tree-hash cache — a clean check is skipped when the working tree hash is unchanged (ok (cached)).
  • Staleness scango.mod deps + GitHub-Action pins are checked against upstream every run.

What runs

Layer Tool Catches
comments + compact native (go/scanner + go/ast) deletes all comments except directives; removes blank lines inside function bodies
format gofumpt → gci → golines strict format, deterministic imports, line length 123
lint golangci-lint default: all ~115 linters, all internal checks maxed, error-or-off
nil-safety nilaway nil panics (the TS-strict-null gap)
dead code deadcode whole-program unreachable funcs
tests go test -race -shuffle=on data races, test-order coupling
deep govulncheck + osv-scanner reachability + lockfile CVEs

Parity with lintmax

Mirrors lintmax (TypeScript): every rule error or off (never warn), default: all (auto-inherits new linters), comment deletion + compaction, 2-wide indent (.editorconfig tab_width=2), line width 123.

Two hard limits Go's gofmt imposes that lintmax doesn't hit (cannot be overridden without abandoning gofmt):

  • Tabs, not spaces — gofmt mandates tabs; tab_width=2 makes them render identically to lintmax's 2-space.
  • Top-level blank lines — gofmt forces a blank after package, around imports, and between top-level declarations. Blank lines inside function bodies are removed (true "no empty lines between statements"); the top-level ones are gofmt law.

Earned disables

The disable list starts empty. Each entry is earned by a concrete conflict found on real code, never anticipated — feature-forced (comment-strip/compact removing what a rule demands) or lintmax-parity (matching lintmax's own OFF-list). See internal/config/golangci.yml for the documented reason on each.

Configless by default

The bundled config is generic only and runs with zero per-project config — no consumer file is read, no override is merged. It carries no project/ecosystem opinion (import paths, in-house ban patterns, first-party struct scope); those live in the consuming project's own enforcement layer, never in lintmax. exhaustruct ships disabled (with no include it would flag every third-party T{}); forbidigo ships generic stdlib-discipline bans only (log.*, bare fmt.Print*, context.Background in tests).

Strictness policy

  • default: all — opt out of nothing by default; new linters auto-enabled.
  • Only physical conflicts disabled (nlreturn vs wsl_v5) — every other linter and rule stays on.
  • Maxed internal checks: staticcheck all categories, gocritic all checks, revive all rules, gosec low/low, errcheck type-assertions + blank.
  • golangci's silent default exclusions are off — nothing is hidden.
  • Every suppression requires //nolint:rule // reason (nolintlint enforces it).

License

MIT

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
internal
run

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL