Monorepo linter

Linting a monorepo is a structural-validation problem, and most per-language linters punt on it. ESLint, Clippy, ruff, and golangci-lint all check the code inside a package; none of them check that your packages agree with each other. alint sits at the layer that sees the whole tree.

What alint catches that per-package linters miss

alint is not a replacement for Bazel, Nx, or Turborepo. Those orchestrate builds. alint enforces conventions. They coexist cleanly.

Real monorepos using alint

RepoShapeWhat alint adds
vercel/next.js Hybrid pnpm + Cargo dual-workspace Surfaces 3 of 19 npm packages without license fields and 4 of 63 crates with non-canonical licenses, drift no per-language linter catches because each only sees half the tree.
apache/arrow 6 languages in one tree 21 lint hooks across 14 tool repos and 0 of them see cross-language structural shape. alint fills that gap.
pnpm/pnpm 169-package pnpm-workspace Replaces 11 of 13 cross-package field invariants currently enforced by an in-tree 470-line meta-updater plugin, with no plugin install required.
pytorch/pytorch ~80k-file ML mega-monorepo Sits beneath lintrunner as the structural floor; ~86% of lintrunner's 57 adapters are structural and map cleanly onto alint rules.
nixos/nixpkgs 39,101 files, 20,678 package dirs Full 79-rule structural pass in 273 ms wall-clock, the empirical anchor for "fast at any size".
istio/istio Go modules + 9 Helm charts Helm-chart structural discipline that helm lint and golangci-lint don't reach: cross-chart field equality, release-note YAML shape, Dockerfile co-location.

Browse all 30 case studies → · See how alint compares to other repo-level linters →

Get started

The bundled monorepo@v1 ruleset covers the language-agnostic shape (every packages/* / crates/* / apps/* entry has a README.md; manifests where applicable). Layer ecosystem-specific overlays on top:

# .alint.yml
extends:
  - alint://bundled/monorepo@v1
  - alint://bundled/monorepo/cargo-workspace@v1   # if Cargo
  - alint://bundled/monorepo/pnpm-workspace@v1    # if pnpm
  - alint://bundled/monorepo/yarn-workspace@v1    # if yarn

# Pick up per-package .alint.yml files alongside the root.
nested_configs: true

nested_configs: true lets each package layer its own assertions on top of the root config without bloating it. This is the shovel-ready pattern for trees the size of nixpkgs.

One static binary, no Node/JVM/Docker runtime in your CI pipeline.