← SkillSafe / Proto Gate

Your .proto, read the way a schema registry and protoc read it

Paste your .proto — and, for the compatibility lane, the previous revision of the same file beside it. The browser reads both for free: a real proto parser, the field-number rules protoc enforces, the enum zero value that quietly becomes every unset field's value, and a symbol-by-symbol diff of the two revisions. Then pick a lane.

Both examples ship with a saved result for every lane, so you can see a whole lane — findings, tables, the corrected schema and the rollout plan — without signing in and without spending a credit.

nothing pasted yet
Drag .proto files in, or Everything is read in your browser. Nothing uploads until you run a lane.
optional — only the compatibility lane needs it
Or drop the released file here
Schema review  

What the free reader does, before any model runs

It parses the file, it does not grep it

A real tokenizer and recursive-descent parser for proto2, proto3 and editions: nested messages, oneof, map, reserved ranges, enums with allow_alias, services, and rpcs with their stream modifiers. A half-edited file still parses on a best-effort basis, with the first bad line named.

Field numbers, which are the only identity the wire has

Duplicates. The 19000–19999 block protobuf keeps for itself, which protoc refuses outright. Numbers above 15 paying a second tag byte on every message while low numbers sit unused. A number that is both reserved and in use.

The enum zero value, spelled out

proto3 cannot tell an unset field from a zero one, so whatever sits at zero becomes the value every message that never set the field appears to carry. An enum whose zero is PENDING is an enum where every unset order is pending.

The diff, three ways

Paste the previous revision and every difference is classified for the wire, for canonical JSON and for generated source — separately, because they disagree. A rename is safe on the wire and breaking in JSON. A renumber is the exact reverse. Neither one fails to compile, and neither one raises an error at runtime: the field simply arrives unset.