A key component of maintaining a consistent Protobuf schema is utilizing a linter to enforce a common set of rules. This is a good practice whether you're building a personal project, maintaining a large set of Protobuf definitions across a major organization, or anything in-between. It's especially important for users and organizations that continually onboard new engineers without a wealth of experience in Protobuf schema design to make sure that APIs remain consistent and follow patterns that allow easy maintainability, but is useful even if you have years of Protobuf experience as a forcing function on your API decisions.

Buf provides lint functionality through buf check lint, which runs a set of lint checkers across your entire Protobuf schema. By default, Buf uses a carefully curated set of lint checkers designed to guarantee consistency and maintainability across a Protobuf schema of any size and any purpose, but without being so opinionated as to restrict organizations from making the design decisions they need to make for their individual APIs.

Buf is designed to be extremely simple to use, while providing functionality for advanced use cases. Features of Buf's linter include:

  • Automatic file discovery. By default, Buf will build your .proto files by walking your file tree and building them per your build configuration. This means you no longer need to manually specify your --proto_paths and files every time you run the tool. However, Buf does allow manual file specification through command-line flags if you want no file discovery to occur, for example in Bazel setups.

  • Selectable configuration of the exact lint checkers you want, including categorization of lint checkers into logical categories. While we recommend using the DEFAULT set of lint checkers, Buf allows you to easily understand and select the exact set of checkers your organization needs.

  • Selectable error output. By default, Buf outputs file:line:col:message information for every lint error, with the file path carefully outputted to match the input location, including if absolute paths are used. JSON output that includes the end line and end column of the lint error is also available, and JUnit output is coming soon.

  • Editor integration. The default error output is easily parseable by any editor, making the feedback loop for lint errors very short. Currently, we provide Vim integration, but will extend this in the future to include other editors such as Emacs, VS Code, and Intellij IDEs.

  • Lint anything from anywhere. Buf allows you to not only lint a Protobuf schema stored as .proto files, but allows you to lint from many different Inputs:

    • Tar or zip archives containing .proto files, both local and remote.
    • Git repository branches or tags containing .proto files, both local and remote.
    • Pre-built Images or FileDescriptorSets from protoc, from both local and remote (http/https) locations.
  • Speed. Buf's internal Protobuf compiler utilizes all available cores to compile your Protobuf schema, while still maintaining deterministic output. Additionally files are copied into memory before processing. As an unscientific example, Buf can compile all 2,311 .proto files in googleapis in about 0.8s on a four-core machine, as opposed to about 4.3s for protoc on the same machine. While both are very fast, this allows for instantaneous feedback, which is especially useful with Editor integration. Buf's speed is directly proportional to the input size, so linting a single file only takes a few milliseconds.