jhump/protoreflect: Dynamic Protobuf Descriptors and gRPC Clients in Go
Reflection (Rich Descriptors) for Go Protocol Buffers
At a glance
- What is it?
- jhump/protoreflect is a Go library for descriptor construction, schema resolution, source information, and generic gRPC calls. It is most useful when an application must work with protobuf schemas that are not compiled into Go types.
- Who is it for?
- Adopt jhump/protoreflect when your Go application needs to inspect, modify, print, resolve, or invoke protobuf and gRPC schemas at runtime without generated Go service code. Do not add it when a small set of statically generated messages already covers the application and schema inspection is unnecessary.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 27 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.
Star history
- jhump/protoreflect1,491 ★ · +0
| Repository | 2026-10-16 | 2026-11-07 |
|---|---|---|
| jhump/protoreflect | 1.5k | 1.5k |
0 Stars in the last 22 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Why jhump/protoreflect exists above generated Go protobuf code
jhump/protoreflect addresses a specific gap between generated protobuf code and tools that do not know their message types when the binary is built. The Go protobuf runtime already offers `protoreflect.Descriptor` and dynamic messages such as `dynamicpb`, but applications still need higher-level ways to construct descriptors, resolve schema elements, recover source information, print schemas, and call gRPC methods described at runtime. This repository builds on those runtime APIs and supplies additional packages for those tasks.
The intended users are Go developers building schema-aware tools, dynamic RPC clients, descriptor processors, and services that receive protobuf definitions rather than compiling every message into a Go struct. It can also help during code generation because `protobuilder` can create or modify rich descriptors and `protoprint` can render them as `.proto` source.
The distinction matters. This is not a replacement protobuf compiler or runtime. Its module depends on `google.golang.org/protobuf`, `google.golang.org/grpc`, and `github.com/bufbuild/protocompile`. The library operates around the schema representation and reflection facilities that those projects provide.
Descriptor construction, rendering, and resolution in jhump/protoreflect
The `protobuilder` package is the central construction path. The README explains that the standard approach requires building a valid tree of descriptor protocol buffers and then linking it with `protodesc`. That tree includes relationships among files, messages, fields, services, and other schema elements, and the package is intended to simplify the process. It also converts existing rich descriptors into builders, which allows an application to modify a schema without reconstructing every descriptor manually.
The reverse operation belongs to `protoprint`. It prints descriptors as `.proto` source, making it the inverse of a parser or compiler such as `protocompile`. A program can obtain a descriptor, alter it through a builder, print the result, and use that output in a generation pipeline. The README describes this combination as a way to generate protobuf source programmatically.
Resolution is handled separately by `protoresolve`. Its named interfaces represent several resolver categories, while `Resolver` acts as a union of descriptor and type resolver interfaces. Descriptor resolvers return descriptor instances. Type resolvers return types, often backed by `dynamicpb`. This model extends the registry concepts in the Go protobuf runtime and gives callers a common interface when schema lookup may involve both static descriptor data and dynamic types.
The `protomessage` and `protodescs` packages cover generic `proto.Message` handling and miscellaneous descriptor operations. These are supporting APIs rather than a single application framework.
Dynamic gRPC calls without generated service stubs
The `dynamicpb` package in the Go protobuf runtime can represent arbitrary messages through a message descriptor and a field-value map. jhump/protoreflect applies a similar idea to RPC services. Its `grpcdynamic` package supplies a dynamic stub that issues RPC methods from method descriptors instead of generated client interfaces.
That design changes where the schema enters the program. A conventional generated client binds RPC calls to Go code produced from a known service definition. A `grpcdynamic` caller can work with a service and method descriptor acquired at runtime, then invoke the operation through the dynamic stub. This fits tools that inspect unknown APIs, administrative clients, compatibility utilities, and systems that receive protobuf or gRPC schemas separately from their executable.
The repository also includes `grpcreflect`, described in the README as a client for the gRPC reflection service. The README excerpt ends before documenting a complete call sequence. The exact server setup, authentication options, transport configuration, and error behavior therefore should be checked in the package documentation rather than inferred from the repository overview.
A key dependency remains the gRPC service's schema. Reflection or descriptor loading must supply enough information to identify the target method, define its request and response types, and select the correct message construction path.
Recovering comments and source locations with sourceinfo
Generated Go protobuf types do not retain the original protobuf source-code information. The README describes this data as including filenames, line and column positions, and comments associated with messages, enums, services, and methods. Losing those details matters for dynamic RPC clients because a caller may know that an RPC exists without receiving its documentation from generated Go structs.
The `sourceinfo` package retrieves descriptors for generated types when that information has been captured through the included `protoc-gen-gosrcinfo` plugin. During Go code generation, this plugin supplies an additional path for preserving source details that the ordinary generated Go representation omits. The `sourceinfo` APIs then make those details available to descriptor consumers.
The companion `sourceloc` package works with `protoreflect.SourceLocation` and `protoreflect.SourcePath`. This separates source-position handling from the mechanism that restores source information. A tool that only needs to navigate source paths can use the location helpers without assuming that comments and positions were preserved during generation.
This feature has a clear boundary. Installing or importing `sourceinfo` alone does not recreate comments that were never embedded. The generation process must use the documented plugin, and the output must retain the captured data. The README does not describe a fallback for generated artifacts that lack it.
Installing jhump/protoreflect v2 and making the first import
The module path for v2 is `github.com/jhump/protoreflect/v2`, and `go.mod` declares `go 1.26.0`. The README does not give a consumer installation command or version requirement beyond the module declarations in the repository. It also directs v1 users to the v2 beta release notes to understand changes.
For a checkout of this repository, the Makefile defines an install target that installs all packages in the module. This is a developer-oriented command, not the adoption step for an external application.
The Makefile runs `go install ./...`, with a space between the command and the package pattern. The README shows the first package import in this form:
import "github.com/jhump/protoreflect/v2/protoprint"That import selects the package that prints descriptors as `.proto` source. The README also lists imports for `protobuilder`, `protoresolve`, `protomessage`, `protodescs`, `sourceinfo`, `sourceloc`, `grpcdynamic`, and `grpcreflect`. A first real implementation should import only the package needed for that task rather than treating the repository as one monolithic API.
Before building an external application, confirm the local Go version against the module's declared `go 1.26.0` directive and read the migration notes linked for v2 users.
Operational limits, maintenance signals, and the plain protobuf alternative
The strongest limitation is schema dependence. Dynamic clients can avoid generated service code, but they cannot invoke an RPC without a valid description of the service and its messages. Source comments have another prerequisite: ordinary Go generation does not preserve them, so `protoc-gen-gosrcinfo` must be part of generation. Projects that have fixed protobuf schemas, straightforward service methods, and ordinary generated Go structs may find the standard Go protobuf runtime and generated gRPC clients simpler.
A concrete alternative is to use only `google.golang.org/protobuf` with generated types and `google.golang.org/grpc` with generated clients. That approach binds schemas and methods at build time and avoids runtime descriptor manipulation. jhump/protoreflect is the better fit when unknown or changing schemas are central to the application. Another relevant alternative is `github.com/bufbuild/protocompile`, which the README identifies as a parser or compiler. `protoprint` is presented as its inverse, so these activities can complement each other rather than serve as exact substitutes.
The repository is not archived. Its last push was on 2026-10-11, and the release list includes `v2.0.0` on 2026-10-10 and `v1.19.0` on 2026-10-05. Those facts indicate recent project activity, but the README still explicitly sends existing v1 users to migration notes. Upgrading therefore carries an API review cost, especially for applications that depend on multiple packages.
The project uses the Apache-2.0 license. That identifies the repository's declared licensing terms, while downstream distribution and modification decisions still need to be checked against the actual `LICENSE` file and applicable organizational requirements.
Editorial conclusion
Adopt jhump/protoreflect when your Go application needs to inspect, modify, print, resolve, or invoke protobuf and gRPC schemas at runtime without generated Go service code. Do not add it when a small set of statically generated messages already covers the application and schema inspection is unnecessary. For version 2, verify first that the build environment provides Go 1.26.0, then inspect migration notes for v2 and the package APIs you plan to use. If source comments or original file positions are required, also verify whether generation includes the documented protoc-gen-gosrcinfo plugin.
Frequently asked questions
What Go version does jhump/protoreflect v2 require?
The repository's `go.mod` declares `go 1.26.0`.
Can jhump/protoreflect call gRPC methods without generated Go service code?
Yes. The `grpcdynamic` package provides a dynamic stub that issues RPC methods using method descriptors rather than generated client interfaces.
How does jhump/protoreflect preserve protobuf comments and source positions?
The repository documents the `protoc-gen-gosrcinfo` plugin and the `sourceinfo` package for retrieving generated-type descriptors that include source code information.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jhump-protoreflect)Star history chart for your README
[](https://hysenlabs.com/projects/jhump-protoreflect)Was this useful?