Protocol Buffers (.proto) Formatter

Paste a .proto schema with messages, enums and gRPC services and get it consistently indented. clang-format runs as WebAssembly in the page, so internal API definitions are never uploaded.

Input

Settings

History

Load from URL

How .proto files are formatted

The engine is clang-format (WASM, proto mode). clang-format is best known for C and C++, but it has a dedicated Protocol Buffers mode — the same one used by many Google and gRPC repositories and by editor plugins that format .proto files on save.

In proto mode it:

  • puts each field, enum value, option and rpc on its own line
  • indents nested messages, enums and oneof groups
  • normalises spacing around = in field numbers and options
  • formats rpc Method(Request) returns (stream Response) signatures consistently
  • re-wraps long field options and comments at the line width

It works for proto2 and proto3 files and for edition-based schemas, since the layout rules do not depend on the syntax version.

A tidy schema matters more for protobuf than for most formats because the .proto file is the contract between services. Field numbers that line up one per line make it easy to spot a reused number or a gap left by a deleted field, which is exactly what reviewers need to check before a change ships to clients that cannot be updated at the same time.

The Style option, indent and width

Style chooses clang-format’s base preset: Google (the default), LLVM, Chromium, Mozilla, WebKit, Microsoft or GNU. For protobuf files the presets mostly differ in small things, such as whether a very short message like message Empty { string id = 1; } may stay on one line and whether spaces appear inside the brackets of field options ([json_name = "x"] versus [ json_name = "x" ]). Google is the right choice for most gRPC projects because Google’s own style guide for protos is written against it.

Whatever preset you pick, the toolbar’s indent replaces the preset’s IndentWidth, and the line-width control sets ColumnLimit. Choosing tabs switches to tab indentation.

Shortcuts: Ctrl/Cmd+Enter formats, Ctrl/Cmd+Shift+C copies, Ctrl/Cmd+K opens the command palette. There is no minified form of a schema, so Ctrl/Cmd+Shift+M is not used here.

It formats; it does not compile

This is the most important thing to know: clang-format is a layout tool. It tokenises the file and reprints it, but it does not check that the schema is valid. A missing semicolon, a duplicate field number or an unknown type will not produce an error. Instead the output looks subtly wrong — two statements merged on one line, or a stray brace at the left margin — and that is your cue to look closer.

To validate a schema, run protoc or buf lint, which also catch style issues such as field names that are not lower_snake_case and enum values without a type prefix.

Comments, including the // documentation comments above messages and RPCs, are kept and re-wrapped only if they exceed the width. Import order is left as written. Use the JSON formatter to read the JSON encoding of a message.

Examples

oneof, field options and reserved, LLVM style

The LLVM preset keeps the one-field message on a single line and adds spaces inside the option brackets.

Input
syntax="proto3";package billing.v1;
message Payment{string id=1;oneof method{Card card=2;BankTransfer bank=3;}int64 amount_cents=4 [json_name="amountCents"];reserved 5,6;reserved "legacy_ref";}
message Card{string last4=1;int32 exp_month=2;int32 exp_year=3;}
message BankTransfer{string iban=1;}
Output
syntax = "proto3";
package billing.v1;
message Payment {
  string id = 1;
  oneof method {
    Card card = 2;
    BankTransfer bank = 3;
  }
  int64 amount_cents = 4 [ json_name = "amountCents" ];
  reserved 5, 6;
  reserved "legacy_ref";
}
message Card {
  string last4 = 1;
  int32 exp_month = 2;
  int32 exp_year = 3;
}
message BankTransfer { string iban = 1; }
Open this example in the tool

gRPC service with comments

Comments stay above the RPC they document, and the option block inside an rpc is expanded.

Input
// Inventory service
service Inventory{
// Streams stock updates for one warehouse.
rpc WatchStock(WatchStockRequest)returns(stream StockEvent){option deprecated=false;}
rpc Adjust(AdjustRequest)returns(AdjustResponse);}
Output
// Inventory service
service Inventory {
  // Streams stock updates for one warehouse.
  rpc WatchStock(WatchStockRequest) returns (stream StockEvent) {
    option deprecated = false;
  }
  rpc Adjust(AdjustRequest) returns (AdjustResponse);
}
Open this example in the tool

Enum and map fields, Google style

Each enum value and field gets a line; the map type keeps its compact form.

Input
syntax="proto3";
enum Status{STATUS_UNSPECIFIED=0;STATUS_ACTIVE=1;STATUS_SUSPENDED=2;}
message Account{string id=1;Status status=2;map<string,string> labels=3;repeated string emails=4;}
Output
syntax = "proto3";
enum Status {
  STATUS_UNSPECIFIED = 0;
  STATUS_ACTIVE = 1;
  STATUS_SUSPENDED = 2;
}
message Account {
  string id = 1;
  Status status = 2;
  map<string, string> labels = 3;
  repeated string emails = 4;
}
Open this example in the tool

Common errors and how to fix them

ErrorCauseFix
Two statements appear on one line in the outputA semicolon is missing, for example after syntax = "proto3". clang-format does not report it; it simply joins the lines.Add the semicolon and format again. Run protoc or buf lint to catch this class of mistake reliably.
A closing brace is printed at the start of a line after the last messageThe braces are unbalanced: there is one } more than {.Remove the surplus brace. The formatter does not flag it because it never validates the grammar.
A message ends without its closing brace in the outputA } is missing, so everything after it is treated as part of the same message.Close the message where it should end; check nested messages and enums first.
Field options gain or lose spaces inside the bracketsThis is a style difference, not an error: some presets put spaces inside [ ].Switch the Style option to Google if you want [json_name = "x"] without inner spaces.

Frequently asked questions

Which style should I choose for gRPC projects?

Google. It is the default here and matches the style used in most published .proto files and in the protobuf documentation.

Why was my invalid .proto not rejected?

clang-format only rearranges tokens and never checks the protobuf grammar. Use protoc or buf lint to validate a schema.

Does it work with proto2 and editions?

Yes. The layout rules are the same for proto2, proto3 and edition-based files.

Will it reorder fields or renumber them?

No. Field order, field numbers and import order are left exactly as written; only whitespace and line breaks change.

Related tools