reproto

Reconstructs .proto source files from compiled protobuf descriptor sets (.pb files produced by protoc --descriptor_set_out).

What it does

reproto takes one or more binary or text-format descriptor sets and regenerates the original .proto files with correct syntax, field types, and options. It supports proto2, proto3, and editions syntax.

Key features:

Installation

NixOS / nix-shell

reproto depends on prototext_codec, a compiled Rust extension that is built as part of the prototools Nix derivation.

User shellreproto and reproto-instantiate-schema on PATH, man page and completions activated:

git clone https://github.com/douzebis/prototools
cd prototools
nix-shell          # enters shell.nix → user-shell

Development shell — adds pyright, pytest, and source-tree wiring for working on reproto itself:

nix-shell dev-shell.nix

Quick start

Decompile a descriptor set

Compile a .proto to a descriptor, then reconstruct it:

protoc --descriptor_set_out=my.pb --include_imports my.proto
reproto --use-variant descriptor -O out/ my.pb
cat out/my.proto

--use-variant descriptor supplies descriptor.proto from the built-in variant bundle, so no separate descriptor .pb is needed.

For selective output — emit only Person and its dependencies:

reproto --use-variant descriptor -O out/ --seed desc:.tutorial.Person my.pb

Build a schema DB for prototext list-schemas

reproto --build-schema-db=my.desc my.pb
prototext --descriptor-set my.desc list-schemas unknown.pb

--build-schema-db writes my.desc (the merged FileDescriptorSet), my/hopcroft.rkyv (compiled scoring graph), and my/index.rkyv (lazy-loading index). No -O is required when only the DB is needed.

reproto-instantiate-schema

Generates pseudo-random binary protobuf instances from a .desc FileDescriptorSet. Useful for populating test corpora and sanity-checking that a schema is well-formed.

reproto-instantiate-schema --descriptor-set my.desc --seed 42 -O out/ \
    google.type.PostalAddress google.protobuf.Timestamp

Options:

OptionDescription
--descriptor-set FILE.desc FileDescriptorSet to load
-O DIRRoot directory for output .pb files
--seed INTPRNG seed (default: 0)
--max-depth INTMaximum recursion depth for nested messages (default: 4)
--max-repeated INTMaximum elements for repeated fields (default: 3)
-q / --quietSuppress per-file progress messages

Non-Nix users: reproto-instantiate-schema is the nix-shell alias for python -m reproto.instantiate_cli.

CLI reference

reproto [OPTIONS] PB_FILES...
OptionDescription
-I PATHSearch path for loading imported .pb files
-O DIR, --output-root DIROutput directory for reconstructed .proto files
--use-variant NAMEActivate a descriptor variant (e.g. descriptor, all)
--seed FQDNRestrict output to nodes reachable from FQDN
--prune FQDNExclude FQDN and its children from output
--build-schema-db FILEBuild .desc + scoring graph + index (no -O needed)
--emit-scoring-yamlWrite per-file scoring-graph YAML alongside .proto output
--emit-descriptorInclude descriptor.proto in output
--dry-runRun all phases but skip writing files
--debugVerbose per-phase logging
--versionPrint version and exit

Running the tests

From the repository root inside the development shell:

nix-shell dev-shell.nix
python -m pytest reproto/src/reproto/tests/ -x -q