Wraps the buf CLI for protobuf PR gating: `buf build` (compile .proto), `buf lint` (STANDARD rules: snake_case fields, Service suffix), `buf breaking --against {ref}` (detect wire/codegen breakage vs a git/BSR baseline), and `buf format`. Use as the CI proto-lint + breaking-change gate, or to debug a breaking failure by rule ID (e.g. FIELD_NO_DELETE_UNLESS_NUMBER_RESERVED) and pick the FILE/PACKAGE/WIRE_JSON/WIRE ruleset per consumer. This is the detection TOOL that enforces the rules and carries the catalog of what is breaking and why (field-number reservation, wire-safe vs wire-incompatible changes, oneof/map constraints, the four buf categories) in references/versioning-strategy.md; for cross-service schema contract testing use protobuf-compat-checking - not this.
72
90%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Full rule-ID tables for buf's four breaking categories, plus worked proto-evolution diffs. Sources: buf.build/docs/breaking/rules and protobuf.dev/programming-guides/proto3/.
| Rule | Detects |
|---|---|
ENUM_NO_DELETE | Removed enum |
MESSAGE_NO_DELETE | Removed message |
SERVICE_NO_DELETE | Removed service |
FILE_NO_DELETE | Removed file |
FIELD_SAME_NAME | Renamed field |
FIELD_SAME_TYPE | Type change |
FIELD_SAME_CARDINALITY | singular <-> repeated |
| Rule | Detects |
|---|---|
PACKAGE_NO_DELETE | Removed package |
PACKAGE_ENUM_NO_DELETE | Enum deletion across files in package |
PACKAGE_MESSAGE_NO_DELETE | Message deletion across files |
| Rule | Detects |
|---|---|
ENUM_VALUE_NO_DELETE_UNLESS_NUMBER_RESERVED | Deleted enum value without reserve |
FIELD_NO_DELETE_UNLESS_NUMBER_RESERVED | Deleted field without reserve |
FIELD_SAME_JSON_NAME | JSON field name change |
| Rule | Detects |
|---|---|
FIELD_WIRE_COMPATIBLE_TYPE | Type change incompatible at wire level (allows int32->int64 etc.) |
FIELD_WIRE_COMPATIBLE_CARDINALITY | Cardinality change incompatible at wire |
Safe (always):
message User {
string name = 1;
+ string nickname = 2;
}Add new, deprecate + reserve old:
message User {
string name = 1;
- string nickname = 2;
+ string display_name = 3;
+ reserved 2;
+ reserved "nickname";
}Consumers must migrate from nickname to display_name. The wire format reads
either; the codegen forces consumers to update.
int32 to int64Wire-compatible per protobuf3 docs:
message Counter {
- int32 count = 1;
+ int64 count = 1;
}Old clients writing int32 still parse correctly. Old clients reading new int64 data truncate silently if the value exceeds int32 range.
ALWAYS BREAKING. Don't.
message Event {
oneof body {
string text = 1;
bytes binary = 2;
+ string emoji = 3; // BREAKS old parsers
}
}Mitigation: add the new variant as a non-oneof field; promote later in a separate proto file/package.