Migrate from Prototool#
Prototool was Uber’s Protobuf tool covering compilation, linting, breaking-change detection, formatting, gRPC calls, and plugin execution. Uber archived the project in 2020.
This guide is a lookup reference for repositories that still carry a prototool.yaml or shell scripts wrapping prototool.
Each section maps a Prototool surface to its current Buf CLI equivalent.
For installation, see the Buf CLI installation guide; for a hands-on intro, see the CLI quickstart.
Configuration mapping#
prototool.yaml field |
buf.yaml (v2) field |
Notes |
|---|---|---|
excludes |
modules[].excludes |
Per-module exclude paths. |
lint.group |
lint.use |
Buf takes a list of categories or rule IDs, not a single named group. |
lint.ignores |
lint.ignore_only |
Per-rule path ignores. Use lint.ignore to skip a path for every rule. |
lint.rules |
lint.use and lint.except |
Buf splits add/remove between two keys. |
break.include_beta |
breaking.ignore_unstable_packages |
Approximate inverse: Buf ignores all unstable suffix forms (alpha, beta, v1alpha1, and so on), not only beta. |
generate |
buf.gen.yaml |
Code generation moved to its own config file. |
For the full set of lint keys (including enum_zero_value_suffix, service_suffix, and the rpc_allow_* options), see the usage guide.
Command mapping#
| Prototool | Buf CLI | Notes |
|---|---|---|
prototool compile |
buf build |
|
prototool format |
buf format |
|
prototool generate |
buf generate |
Configure plugins in buf.gen.yaml. |
prototool lint |
buf lint |
--json becomes --error-format=json. |
prototool lint --list-linters |
buf config ls-lint-rules |
|
prototool lint --list-all-linters |
buf config ls-lint-rules --all |
Lists every rule across configurations, not just the ones currently configured. |
prototool break check --git-branch main |
buf breaking --against '.git#branch=main' |
For tags: '.git#tag=v1.0.0'. See the inputs reference for the full Git input grammar. |
prototool break check --descriptor-set-path lock.binpb |
buf breaking --against lock.binpb |
|
prototool config init |
buf config init |
|
prototool descriptor-set |
buf build --exclude-imports --exclude-source-info -o - |
Writes a binary Buf image to stdout. Add --as-file-descriptor-set to drop the extra Buf metadata; replace -o - with a file path to write to disk. |
prototool files |
buf ls-files |
|
prototool grpc |
buf curl |
|
prototool version |
buf --version |
No direct equivalent#
These Prototool surfaces don’t have a Buf counterpart:
prototool all. Run the individual Buf commands you need (buf build,buf lint,buf format,buf breaking).prototool create. Buf doesn’t generate.prototemplates.prototool cache. Buf doesn’t shell out toprotocand has no compiler cache; see the internal compiler.prototool x inspect. For schema inspection, runbuf build -o -#format=json | jqto read a compiled image as JSON.prototool.yamlkeysprotoc,create,lint.file_header,lint.java_package_prefix, andbreak.allow_beta_deps. Buf doesn’t download or invokeprotoc, doesn’t lint specific file option values (see What we left out), and doesn’t enforce package dependency restrictions.
Lint rule mapping#
google#
There’s no exact Buf equivalent for the google lint group.
The closest baseline is BASIC with the lower_snake_case rules removed; for finer control, compose a lint.use list from the rules catalog.
uber1, uber2#
Both lint groups are supersets of Buf’s STANDARD category, with different suffix conventions.
This Buf config is the closest equivalent:
The one place this breaks down is uber1’s nested enum prefix.
uber1 expects the enclosing message name to appear in nested enum value names:
// uber1: valid
// Buf's ENUM_VALUE_PREFIX rule rejects this
message Foo {
enum Bar {
FOO_BAR_INVALID = 0;
FOO_BAR_ONE = 1;
}
}
Buf and uber2 both expect the prefix to use only the enum’s own name:
Protobuf’s C++ scoping rules allow nested enums in different messages to share value names, so the shorter prefix is sufficient.
Breaking change detection#
buf breaking is fully configurable.
Pick which categories to apply, and override individual rules per directory or file.
See breaking rules for the four built-in categories: FILE, PACKAGE, WIRE, and WIRE_JSON.
If you want to keep your existing protoc invocation and run Buf’s lint or breaking-change checks against the FileDescriptorSet it produces, use protoc-gen-buf-lint and protoc-gen-buf-breaking.
Docker#
The Buf CLI is published at bufbuild/buf.
The image’s ENTRYPOINT is buf, so omit buf from the docker run invocation:
$ docker pull bufbuild/buf:1.70.0
$ docker run --rm --volume "$(pwd):/workspace" --workdir "/workspace" \
bufbuild/buf:1.70.0 lint
Pin to a specific tag in CI so behavior stays reproducible across runs.