[Go to site: main page, start]

Skip to content

Linting Protobuf files#

buf lint checks .proto files against style and structural rules, configured in the lint section of buf.yaml. With no configuration, it applies the STANDARD rule set, Buf’s recommended baseline for new Protobuf development.

weather/weather.proto
syntax = "proto3";

package weather;
buf.yaml
version: v2
lint:
  use:
    - STANDARD
$ buf lint
weather/weather.proto:3:1:Package name "weather" should be suffixed with a correctly formed version, such as "weather.v1".

Adding the version suffix (package weather.v1;) clears the error. For a step-by-step walkthrough on a workspace that fails several rules at once, see the quickstart.

When to run it#

Two integration points cover most of the workflow:

  • During development: the editor integration surfaces the same lint errors in your IDE as you type, and buf lint catches anything you’ve missed before you commit.
  • In code review: a CI/CD job (often a GitHub Action) runs the same rules against every pull request.

For organization-wide enforcement, publish modules to the BSR and use schema checks to enforce lint, breaking-change, uniqueness, and policy rules at buf push time. Local linting keeps authors fast; BSR checks keep consumers protected.

Rules and categories#

The built-in rules are organized into five categories. Three are arranged by strictness, each a superset of the one below it; the other two are independent.

The strictness hierarchy:

  • MINIMAL: fundamental Protobuf hygiene, like requiring a package, matching file paths to package names, no import cycles, and one package per directory. Failing these tends to cause real problems with downstream Protobuf tooling.
  • BASIC: everything in MINIMAL plus widely accepted Protobuf style, including PascalCase messages and enums, lower_snake_case fields and packages, UPPER_SNAKE_CASE enum values, and no public imports.
  • STANDARD: everything in BASIC plus Buf’s recommended additions, including package version suffixes, service-name suffixes, RPC request and response name conventions, Protovalidate correctness, and zero-value enum naming. This is the default when no lint section is configured.

Anything passing STANDARD also passes BASIC and MINIMAL.

The two non-hierarchical categories:

  • COMMENTS: requires leading comments on enums, messages, fields, oneofs, services, RPCs, and enum values. Each schema element is a separate rule, so you can require comments on services without also requiring them on every field.
  • UNARY_RPC: forbids client-streaming and server-streaming RPCs. Useful when your transport (Twirp, for instance) doesn’t support streaming or your team has decided against it.

For the full rule list, including which rules can be selected individually outside their category, see rules and categories.

Custom rules via plugins#

Buf plugins extend the linter with rules of your own. A plugin is a binary that follows the Buf check plugin API; install it on your $PATH, declare it under plugins in buf.yaml, and reference its rules or categories in lint.use alongside the built-ins. Built-in rules and plugin rules combine in a single lint.use list.

For configuration details and worked examples, see plugin rules.

Further reading#