The buf.gen.yaml file defines a local plugin template, and is used by the buf generate command to generate code for the language(s) of your choice. This file is often used with a module (or another input), and is typically placed next to your buf.work.yaml file:

.
├── buf.gen.yaml
├── buf.work.yaml
├── acme
│   └── pet
│       └── v1
│           └── pet.proto
├── buf.lock
└── buf.yaml

An example of the buf.gen.yaml file used to generate Go/gRPC stubs is shown below:

buf.gen.yaml
version: v1
plugins:
  - plugin: go
    out: gen/proto/go
    opt: paths=source_relative
  - plugin: buf.build/grpc/go:v1.2.0
    out: gen/proto/go
    opt:
      - paths=source_relative
      - require_unimplemented_servers=false

version

The version key is required, and defines the current configuration version. The only accepted values are v1beta1 and v1.

plugins

Each entry in the buf.gen.yaml plugins key is a protoc plugin configuration, which is a program that generates code by interacting with the compiled representation of your module.

plugin

plugin is required.

Local Plugins:

To execute a locally installed plugin, specify the plugin name via the plugin field. All protoc plugins begin with the protoc-gen- prefix.

By default, a protoc-gen-<name> program is expected to be on your PATH so that it can be discovered and executed by buf. This can be overridden with the path option shown below.

Remote Plugins:

The plugin field can specify a remotely executed plugin (<remote>/<owner>/<plugin-name>:<plugin-version> or <remote>/<owner>/<plugin-name>). If a remotely executed plugin omits the <plugin-version>, the latest version will be used. If a <plugin-version> is specified, the optional revision can be specified to pin an exact revision of a plugin version.

out

The out of a plugin is required, and controls where the generated files are deposited for a given plugin. Although absolute paths are supported, this configuration is traditionally a relative output directory that depends on where buf generate is run. For example, running buf generate from the root of the tree shown above would result in a new gen/proto/go directory within the same root:

buf generate
tree
.
├── acme
│   └── pet
│       └── v1
│           └── pet.proto
├── gen
│   └── proto
│       └── go
│           └── ...
├── buf.gen.yaml
├── buf.lock
└── buf.yaml

opt

The opt of a plugin is optional, and specifies one or more protoc plugin options for each plugin independently. In the buf.gen.yaml example above, this is relevant for both protoc-gen-go and protoc-gen-go-grpc. As you can see, you can provide options as either a single string or a list of strings.

path

The path of a plugin is optional, and overrides the default location and explicitly specify where to locate the protoc plugin. For example, if another custom plugin called protoc-gen-foo is not located on your PATH, but is found at bin/proto/protoc-gen-foo, you can refer to it like this:

buf.gen.yaml
version: v1
plugins:
  - plugin: foo
    out: gen/foo
    path: bin/proto/protoc-gen-foo

The path can include some arguments. If the path has more than one element, the first is the plugin binary and the others are optional additional arguments to pass to the binary. For example, you can run the version of protoc-gen-go that matches the google.golang.org/protobuf specified by go.mod by:

buf.gen.yaml
version: v1
plugins:
  - name: go
    path: ["go", "run", "google.golang.org/protobuf/cmd/protoc-gen-go"]
    out: gen/proto
    opt: paths=source_relative

This field only works with local plugins.

revision

The revision is optional and may be used along with the plugin field to pin an exact version of a remote plugin. In most cases, it is recommended to omit the revision, in which case the latest revision of the plugin will be used (automatically pulling in the latest bug fixes).

Below is an example of using the revision to target an exact version of a plugin:

buf.gen.yaml
version: v1
plugins:
  - plugin: buf.build/protocolbuffers/go:v1.28.1
    revision: 1
    out: gen/proto/go
    opt: paths=source_relative

strategy

Your strategy of a plugin is optional, and specifies the generation strategy for buf generate to use. For example, we can add a strategy to one of the plugins in the configuration shown above like this:

buf.gen.yaml
version: v1
plugins:
  - plugin: go
    out: gen/proto/go
    opt: paths=source_relative
  - plugin: go-grpc
    out: gen/proto/go
    opt:
      - paths=source_relative
      - require_unimplemented_servers=false
    strategy: directory

There are two options:

  1. directory (default for local plugins)

This results in buf splitting the input files by directory and making separate plugin invocations in parallel. That's roughly the concurrent equivalent of this operation:

$ for dir in $(find . -name '*.proto' -print0 | xargs -0 -n1 dirname | sort | uniq); do
  protoc -I . $(find "${dir}" -name '*.proto')
done

Almost every protoc plugin either requires this, so this is the recommended strategy. The directory strategy is used by default if omitted for local plugins. Remote plugins use all for every invocation.

  1. all

This results in buf making a single plugin invocation with all input files, which is roughly equivalent to this:

$ protoc -I . $(find . -name '*.proto')

This is needed for certain plugins that expect all files to be given at once. It is also used for remote plugin generation to improve code generation performance.

protoc_path

The protoc_path of a plugin is optional and only applies to the code generators that are built-in to protoc. Normally, a plugin is a separate executable whose binary name is like protoc-gen-<name>. But for a handful of plugins, the executable used is protoc itself. The following plugins result in invoking protoc instead of a dedicated plugin binary:

  1. cpp
  2. csharp
  3. java
  4. js (before v21)
  5. kotlin (after v3.17)
  6. objc
  7. php
  8. pyi
  9. python
  10. ruby

Normally for the above plugins, buf will execute the protoc binary that is found in your $PATH. But this configuration option lets you point to a specific binary. This is particularly useful if you need to support a specific version of protoc, which could differ from the version in $PATH. For example, you can run a specific version of protoc instead of the protoc installed in $PATH by:

buf.gen.yaml
version: v1
plugins:
  - plugin: go
    revision: 1
    out: gen/proto/go
    protoc_path: /path/to/specific/version/bin/protoc

managed

The managed key is used to configure managed mode and is an advanced feature. A complete example of the managed configuration with the protoc-gen-go plugin is shown below:

buf.gen.yaml
version: v1
managed:
  enabled: true
  cc_enable_arenas: false
  java_multiple_files: false
  java_package_prefix: com
  java_string_check_utf8: false
  optimize_for: CODE_SIZE
  go_package_prefix:
    default: github.com/acme/weather/private/gen/proto/go
    except:
      - buf.build/googleapis/googleapis
    override:
      buf.build/acme/weather: github.com/acme/weather/gen/proto/go
  override:
    JAVA_PACKAGE:
      acme/weather/v1/weather.proto: "org"
plugins:
  - plugin: go
    out: gen/proto/go
    opt: paths=source_relative

enabled

The enabled key is required if any other managed keys are set. Setting enabled equal to true enables managed mode according to default behavior.

cc_enable_arenas

The cc_enable_arenas key is optional, and controls what the cc_enable_arenas value is set to in all of the files contained within the generation target input. The only accepted values are false and true.

java_multiple_files

The java_multiple_files key is optional, and controls what the java_multiple_files value is set to in all of the files contained within the generation target input. The only accepted values are false and true.

java_package_prefix

The java_package_prefix key is optional, and controls what the java_package prefix value is set to in all of the files contained within the generation target input. By default, the value is com.

java_string_check_utf8

The java_string_check_utf8 key is optional, and controls what the java_string_check_utf8 value is set to in all of the files contained within the generation target input. The only accepted values are false and true.

optimize_for

The optimize_for key is optional, and controls what the optimize_for value is set to in all of the files contained within the generation target input. The only accepted values are SPEED, CODE_SIZE and LITE_RUNTIME. If omitted, the default value, SPEED, is used.

go_package_prefix

The go_package_prefix key is optional, and controls what the go_package value is set to in all the files contained within the generation target input.

default

The default key is required if the go_package_prefix key is set. The default value is used as a prefix for the go_package value set in each of the files. The default value must be a relative filepath that must not jump context from the current directory, that is they must be subdirectories relative to the current working directory. As an example, ../external is invalid.

In the configuration example shown above, the github.com/acme/weather/gen/proto/go prefix is joined with the given Protobuf file's relative path from the module root. In the buf.build/acme/weather module's case, the acme/weather/v1/weather.proto file would have this go_package set:

acme/weather/v1/weather.proto
syntax = "proto3";

package acme.weather.v1;

option go_package = "github.com/acme/weather/gen/proto/go/acme/weather/v1;weatherv1";

If the Protobuf file's package declaration conforms to the PACKAGE_VERSION_SUFFIX lint rule, the final two path elements are concatenated and included after the ; element in the go_package result. The above example generates a Go package with a package declaration equal to weatherv1, which enables you to import Go definitions from a variety of generated packages that would otherwise collide (a lot of Protobuf packages contain the v1 suffix).

except

The except key is optional, and removes certain modules from the go_package file option override behavior. The except values must be valid module names.

There are situations where you may want to enable managed mode for the go_package option in most of your Protobuf files, but not necessarily for all of your Protobuf files. This is particularly relevant for the buf.build/googleapis/googleapis module, which points its go_package value to an external repository. Popular libraries, such as grpc-go depend on these go_package values, so it's important that managed mode does not overwrite them.

override

The override key is optional, and overrides the go_package file option value used for specific modules. The override keys must be valid module names. Additionally, the corresponding override values must be a valid Go import path and must not jump context from the current directory. As an example, ../external is invalid.

This setting is used for workspace environments, where you have a module that imports from another module in the same workspace, and you need to generate the Go code for each module in different directories. This is particularly relevant for repositories that decouple their private API definitions from their public API definitions (as is the case for buf).

override

This is a list of per-file overrides for each modifier. In the example provided above, an override for acme/weather/v1/weather.proto is set for the java_package_prefix modifier to be org instead of com. This sets org as the package prefix for only the specific acme/weather/v1/weather.proto file and not for the rest of the module.