Skip to main content
rules_lint, built and maintained by Aspect, integrates linting and formatting as first-class concepts under Bazel.

Why rules_lint

  • No changes needed to rulesets. Works with the Bazel rules you already use.
  • No changes needed to BUILD files. No lint wrapper macros, and lint doesn’t appear in bazel query output. Users simply lint their existing *_library targets.
  • Incremental. Lint checks (including producing fixes) run as normal Bazel actions, so they support Remote Execution and their outputs land in the Remote Cache.
  • Lint changes only. It’s fine if your repository has a lot of existing issues; you don’t need to fix or suppress them all to start linting new changes. We call this the “Water Leak Principle”: always fix the leak before mopping the spill.
  • Formats files Bazel doesn’t know about. Formatting runs directly on the file tree, so there’s no need to create targets for your shell scripts just to format them.
  • Honors your existing configuration files. The same config the tools use outside Bazel (for example, in your editor) applies under Bazel.

Supported tools

Formatters and linters ship for dozens of languages, including:
LanguageFormatterLinter(s)
JavaScript / TypeScriptPrettierESLint
Pythonruffruff, flake8, pylint, bandit, ty
C / C++clang-formatclang-tidy, cppcheck
Gogofmt / gofumpt
Javagoogle-java-formatPMD, Checkstyle, Spotbugs
Kotlinktfmtktlint
Rustrustfmtclippy
Shellshfmtshellcheck
StarlarkBuildifierBuildifier
Protocol Buffersbufbuf lint
Markdown, YAML, JSON, HTML, CSSPrettier and friendsVale, yamllint, Stylelint
See the full table in the repository; new tools are added frequently.

Running under the Aspect CLI

The aspect lint and aspect format tasks are the easiest way to run rules_lint: hold-the-line linting that only fails on violations you introduced, and formatting for just the files changed in your PR. Results can be surfaced by Marvin as status checks, review comments, and suggested fixes on GitHub and GitLab, or as failing tests.

API reference

Per-linter configuration references live alongside each language: