We highly recommend completing the tour to get an overview of buf check lint.

Add a buf.yaml

To get started, add a buf.yaml file to the root of your repository that contains your Protobuf definitions.

This represents a buf.yaml file that sets the defaults for the build and for the lint checkers:

- .

Adjust your roots as necessary. This correlates to your --proto_paths.

See the lint configuration and build configuration documentation for more details.

Run linting

To run linting from the root of your repository:

$ buf check lint

This will:

  • Discover all Protobuf files per your configuration.
  • Copy the Protobuf files into memory.
  • Compile all Protobuf files.
  • Run the compilation result against the configured lint checkers.

If there are errors, they will be printed out in a file:line:column:message format by default. For example, from the tour:

$ buf check lint
google/appengine/v1/app_yaml.proto:53:5:Enum option "allow_alias" on enum "ErrorCode" must be false.
google/appengine/v1/app_yaml.proto:264:3:Enum option "allow_alias" on enum "SecurityLevel" must be false.
google/cloud/policytroubleshooter/v1/checker.proto:20:1:Import "google/cloud/policytroubleshooter/v1/explanations.proto" must not be public.
google/cloud/recommendationengine/v1beta1/catalog.proto:132:5:Enum option "allow_alias" on enum "StockState" must be false.
google/cloud/securitycenter/v1/securitycenter_service.proto:19:1:Import "google/cloud/securitycenter/v1/run_asset_discovery_response.proto" must not be public.
google/cloud/securitycenter/v1p1beta1/securitycenter_service.proto:20:1:Import "google/cloud/securitycenter/v1p1beta1/run_asset_discovery_response.proto" must not be public.
google/cloud/websecurityscanner/v1beta/scan_config_error.proto:35:5:Enum option "allow_alias" on enum "Code" must be false.
google/storage/v1/storage.proto:1902:5:Enum option "allow_alias" on enum "Values" must be false.

Output can also be printed as JSON. From the tour:

$ buf check lint --error-format=json
{"path":"google/appengine/v1/app_yaml.proto","start_line":53,"start_column":5,"end_line":53,"end_column":31,"type":"ENUM_NO_ALLOW_ALIAS","message":"Enum option \"allow_alias\" on enum \"ErrorCode\" must be false."}
{"path":"google/appengine/v1/app_yaml.proto","start_line":264,"start_column":3,"end_line":264,"end_column":29,"type":"ENUM_NO_ALLOW_ALIAS","message":"Enum option \"allow_alias\" on enum \"SecurityLevel\" must be false."}
{"path":"google/cloud/policytroubleshooter/v1/checker.proto","start_line":20,"start_column":1,"end_line":20,"end_column":73,"type":"IMPORT_NO_PUBLIC","message":"Import \"google/cloud/policytroubleshooter/v1/explanations.proto\" must not be public."}
{"path":"google/cloud/recommendationengine/v1beta1/catalog.proto","start_line":132,"start_column":5,"end_line":132,"end_column":31,"type":"ENUM_NO_ALLOW_ALIAS","message":"Enum option \"allow_alias\" on enum \"StockState\" must be false."}
{"path":"google/cloud/securitycenter/v1/securitycenter_service.proto","start_line":19,"start_column":1,"end_line":19,"end_column":83,"type":"IMPORT_NO_PUBLIC","message":"Import \"google/cloud/securitycenter/v1/run_asset_discovery_response.proto\" must not be public."}
{"path":"google/cloud/securitycenter/v1p1beta1/securitycenter_service.proto","start_line":20,"start_column":1,"end_line":20,"end_column":90,"type":"IMPORT_NO_PUBLIC","message":"Import \"google/cloud/securitycenter/v1p1beta1/run_asset_discovery_response.proto\" must not be public."}
{"path":"google/cloud/websecurityscanner/v1beta/scan_config_error.proto","start_line":35,"start_column":5,"end_line":35,"end_column":31,"type":"ENUM_NO_ALLOW_ALIAS","message":"Enum option \"allow_alias\" on enum \"Code\" must be false."}
{"path":"google/storage/v1/storage.proto","start_line":1902,"start_column":5,"end_line":1902,"end_column":31,"type":"ENUM_NO_ALLOW_ALIAS","message":"Enum option \"allow_alias\" on enum \"Values\" must be false."}

We can also output errors in a format you can then copy into your buf.yaml file. This allows you to ignore all existing lint errors and correct them over time. From the tour:

$ buf check lint --error-format=config-ignore-yaml
- google/appengine/v1/app_yaml.proto
- google/cloud/recommendationengine/v1beta1/catalog.proto
- google/cloud/websecurityscanner/v1beta/scan_config_error.proto
- google/storage/v1/storage.proto
- google/cloud/policytroubleshooter/v1/checker.proto
- google/cloud/securitycenter/v1/securitycenter_service.proto
- google/cloud/securitycenter/v1p1beta1/securitycenter_service.proto

Other Inputs

Buf can lint additional inputs instead of just your local Protobuf files. This is useful in a variety of scenarios, including enabling protoc output be used as buf input.

See the Input documentation for details on all available inputs.


# lint a pre-built image from buf image build -o image.bin
$ buf check lint --input image.bin
# lint a pre-built image passed to stdin - this is effectively the same as running buf check lint
$ buf image build -o - | buf check lint --input -
# lint output from protoc passed to stdin, assuming your only proto_path is "."
$ protoc -I . --include_source_info $(find . -name '*.proto') -o /dev/stdout | buf check lint --input -
# lint a remote git repository on the fly and override the config to be your local config file
$ buf check lint --input '' --input-config buf.yaml
# lint a remote tarball on the fly and override the config
$ buf check lint --input '' --input-config buf.yaml
# lint a remote zip archive on the fly and override the config
$ buf check lint --input '' --input-config buf.yaml

For remote locations that require authentication, see HTTPS Authentication and SSH Authentication for more details.

Suppress File Discovery

By default, Buf builds all files under configuration per the build config. You can instead manually specify the file paths to build and lint. This is an advanced feature intended to be used for editor or Bazel integration - it is better to let Buf discover all files under management and handle this for you in general.

$ buf check lint --file path/to/foo.proto --file path/to/bar.proto

Combine this with an in-line configuration override to make the only file I/O performed by Buf being the reading of your specified .proto files.

$ buf check lint --file path/to/foo.proto --file path/to/bar.proto --input-config '{"lint":{"use":["BASIC"]}}'

Ignore vendored Protobuf files

A lot of builds will have vendored Protobuf files that you want to ignore for linting. For example, you may build against googleapis for grpc-gateway. The following represents how to handle this situation:

# the proto/ directory contains your Protobuf definitions
# the googleapis/ directory contains the vendored Protobuf definitions from grpc-gateway
# note that per the documentation for roots, roots cannot overlap, so if you have this
# situation you will need a proto/ directory
- proto
- vendor/
# per the lint configuration docs, the paths for lint ignores have the root
# directory stripped so that this configuration works for both sources and images
# google/api and google/rpc are the directories within googleapis/ that we want to ignore
- google/api
- google/rpc


Buf ships a Docker image bufbuild/buf that allows you to use Buf as part of your Docker workflow. For example:

$ docker run \
--volume "$(pwd):/workspace" \
--workdir /workspace \
bufbuild/buf check lint