A powerful documentation generator plugin for the Google Protocol Buffers compiler (protoc). Generate beautiful, interactive API documentation from your .proto files with full support for gRPC, grpc-gateway, validation rules, and custom annotations.
- Multiple Output Formats β HTML, JSON, and Markdown
- Interactive HTML β Search, tabs, copy buttons, syntax highlighting
- gRPC Support β Services, methods, streaming (server/client/bidirectional)
- REST API Support β Full grpc-gateway annotations (
google.api.http) - Validation Rules β protoc-gen-validate integration
- Field Behaviors β
google.api.field_behaviorsupport - Custom Annotations β Lightweight
doc.v1annotations for documentation - Auto-Generated Examples β Smart example generation based on field types and formats
- Markdown in Comments β Headers, lists, tables, code blocks
- Well-Known Types β Timestamp, Duration, FieldMask, Struct, and more
go install github.com/easyp-tech/protoc-gen-easydoc/cmd/protoc-gen-easydoc@latestgit clone https://github.com/easyp-tech/protoc-gen-easydoc.git
cd protoc-gen-easydoc
go build -o protoc-gen-easydoc ./cmd/protoc-gen-easydocGenerate HTML documentation (default):
protoc \
--easydoc_out=./docs \
-I . \
your_service.protoGenerate specific formats:
protoc \
--easydoc_out=./docs \
--easydoc_opt=formats=html|json|md \
-I . \
your_service.protoAdd to your easyp.yaml:
generate:
plugins:
- name: easydoc
out: docs
opts:
formats: "html|json|md"With source_relative paths (flat output):
generate:
plugins:
- name: easydoc
out: docs
opts:
formats: "html|json|md"
paths: "source_relative"Then run:
easyp generateDocument your services and methods using leading comments:
// UserService manages user accounts and authentication.
//
// ## Quick Start
//
// 1. Create a user: `POST /v1/users`
// 2. Authenticate: `POST /v1/auth/login`
// 3. Get profile: `GET /v1/users/{user_id}`
service UserService {
// GetUser retrieves a user by their unique identifier.
//
// Returns `NOT_FOUND` if the user does not exist.
rpc GetUser(GetUserRequest) returns (GetUserResponse) {
option (google.api.http) = {
get: "/v1/users/{user_id}"
};
}
}// User represents a registered user in the system.
message User {
// Unique identifier for the user.
string id = 1;
// User's email address, used for authentication.
string email = 2;
// Display name shown in the UI.
string display_name = 3;
}Comments support rich Markdown formatting:
// # Authentication
//
// All endpoints require a Bearer token:
//
// ```
// Authorization: Bearer <token>
// ```
//
// ## Rate Limits
//
// | Endpoint | Limit |
// |----------|-------|
// | GET | 1000/min |
// | POST | 100/min |
//
// - Free tier: 1000 requests/day
// - Pro tier: unlimitedPrefix comments with @exclude to hide them from documentation:
// @exclude
// This is an internal implementation detail.
message InternalMessage {
string id = 1; // @exclude internal field
}The plugin provides lightweight doc.v1 annotations for enhanced documentation without heavy dependencies:
import "doc/v1/doc.proto";
message CreateUserRequest {
// User's unique identifier.
string user_id = 1 [(doc.v1.field) = {
required: true
format: FORMAT_UUID
}];
// Email address for notifications.
string email = 2 [(doc.v1.field) = {
required: true
format: FORMAT_EMAIL
example: "john.doe@example.com"
}];
// User's age.
int32 age = 3 [(doc.v1.field) = {
min: 0
max: 150
}];
// Username (3-32 lowercase alphanumeric characters).
string username = 4 [(doc.v1.field) = {
required: true
min_length: 3
max_length: 32
pattern: "^[a-z][a-z0-9_-]*$"
}];
}| Option | Type | Description |
|---|---|---|
required |
bool | Mark field as required |
output_only |
bool | Field is read-only (set by server) |
immutable |
bool | Field can only be set on create |
format |
Format | Well-known format (see below) |
custom_format |
string | Custom format description |
example |
string | Example value (overrides auto-generation) |
min / max |
double | Numeric constraints |
min_length / max_length |
int32 | Length constraints |
pattern |
string | Regex pattern |
| Format | Example | Description |
|---|---|---|
FORMAT_UUID |
550e8400-e29b-41d4-a716-446655440000 |
UUID v4 |
FORMAT_EMAIL |
user@example.com |
Email address |
FORMAT_URI |
https://example.com/path |
URI/URL |
FORMAT_HOSTNAME |
example.com |
Hostname |
FORMAT_SLUG |
my-blog-post |
URL-friendly slug |
FORMAT_DATE |
1996-04-10 |
ISO 8601 date |
FORMAT_DATE_TIME |
1996-04-10T10:30:00Z |
ISO 8601 datetime |
FORMAT_TIME |
10:30:00 |
Time |
FORMAT_DURATION |
3600s |
Duration |
FORMAT_IPV4 |
192.168.1.1 |
IPv4 address |
FORMAT_IPV6 |
2001:db8::1 |
IPv6 address |
FORMAT_MAC |
00:1B:44:11:3A:B7 |
MAC address |
FORMAT_CIDR |
192.168.1.0/24 |
CIDR notation |
FORMAT_PHONE |
+14155552671 |
E.164 phone number |
FORMAT_CREDIT_CARD |
4111111111111111 |
Credit card number |
FORMAT_IBAN |
DE89370400440532013000 |
IBAN |
FORMAT_BIC |
COBADEFFXXX |
BIC/SWIFT code |
FORMAT_BYTE |
SGVsbG8gV29ybGQ= |
Base64 encoded |
FORMAT_HEX |
48656c6c6f |
Hexadecimal |
The plugin automatically extracts validation rules from protoc-gen-validate:
import "validate/validate.proto";
message CreatePetRequest {
string name = 1 [(validate.rules).string = {
min_len: 1
max_len: 100
}];
string email = 2 [(validate.rules).string.email = true];
int32 age = 3 [(validate.rules).int32 = {
gte: 0
lte: 30
}];
}Field behaviors are also supported:
import "google/api/field_behavior.proto";
message Pet {
string id = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
string name = 2 [(google.api.field_behavior) = REQUIRED];
}Full support for grpc-gateway annotations:
import "google/api/annotations.proto";
service PetService {
// Create a new pet.
rpc CreatePet(CreatePetRequest) returns (Pet) {
option (google.api.http) = {
post: "/v1/pets"
body: "pet"
};
}
// Update an existing pet.
rpc UpdatePet(UpdatePetRequest) returns (Pet) {
option (google.api.http) = {
patch: "/v1/pets/{pet_id}"
body: "pet"
additional_bindings {
put: "/v1/pets/{pet_id}"
body: "*"
}
};
}
// Search for pets.
rpc SearchPets(SearchPetsRequest) returns (SearchPetsResponse) {
option (google.api.http) = {
get: "/v1/pets:search"
};
}
}Document all streaming patterns:
service PetService {
// Server streaming: Watch for pet updates.
rpc WatchPets(WatchPetsRequest) returns (stream PetEvent);
// Client streaming: Batch create pets.
rpc BatchCreatePets(stream CreatePetRequest) returns (BatchCreatePetsResponse);
// Bidirectional streaming: Sync pets.
rpc SyncPets(stream PetSyncRequest) returns (stream PetSyncResponse);
}Interactive documentation with:
- π Full-text search
- π Protocol tabs (gRPC / HTTP)
- π Copy buttons for examples
- π¨ Syntax highlighting
- π± Responsive design
- π§ Collapsible navigation
Machine-readable output for integrations:
{
"file": "petstore.proto",
"package": "petstore.v1",
"services": [...],
"messages": [...],
"enums": [...]
}GitHub/GitLab-friendly documentation suitable for wikis and README files.
The examples/ directory contains comprehensive examples:
| File | Description |
|---|---|
petstore.proto |
Full-featured API with REST, gRPC, streaming, validation |
with_doc_annotations.proto |
Examples of doc.v1 annotations |
cd examples
protoc \
--easydoc_out=. \
--easydoc_opt=formats=html|json|md \
-I . \
-I /path/to/googleapis \
-I /path/to/protoc-gen-validate \
petstore.proto| Option | Default | Description |
|---|---|---|
formats |
html |
Output formats separated by | (pipe) |
paths |
(empty) | Output path mode: source_relative or empty for default |
Available formats: html, json, md
| Mode | Description | Example |
|---|---|---|
| (default) | Preserves input directory structure | api/v1/pet.proto β docs/api/v1/pet.html |
source_relative |
Outputs only filename, no directories | api/v1/pet.proto β docs/pet.html |
Default mode (preserves directory structure):
protoc \
--easydoc_out=./docs \
--easydoc_opt=formats=html|json|md \
-I . \
api/v1/*.protoSource-relative mode (flat output):
protoc \
--easydoc_out=./docs \
--easydoc_opt=paths=source_relative,formats=html|json|md \
-I . \
api/v1/*.protoExamples are automatically generated with the following priority:
- Explicit
doc.v1.field.exampleβ User-defined example doc.v1.field.formatβ Generated from format (UUID, email, etc.)validate.rulesβ Generated from validation rules- Default by type β Sensible defaults for scalar types
- β
Scalars:
string,int32,int64,uint32,uint64,float,double,bool,bytes - β Messages (nested and referenced)
- β Enums (top-level and nested)
- β
Maps:
map<K, V> - β Repeated fields
- β Oneofs
- β
Well-known types:
Timestamp,Duration,FieldMask,Struct,Empty,Any
- β Leading comments
- β Trailing comments
- β
@excludedirective - β Markdown formatting
- β Deprecation notices
- β Reserved fields/values
Apache License 2.0 β see LICENSE for details.
Inspired by protoc-gen-doc with enhanced features for modern API documentation needs.
Made with β€οΈ by easyp-tech