| Crates.io | granc |
| lib.rs | granc |
| version | 0.5.0 |
| created_at | 2026-01-20 17:28:31.07567+00 |
| updated_at | 2026-01-24 19:00:15.268859+00 |
| description | A dynamic gRPC CLI tool written in Rust (gRPC + Cranc, Crab in Catalan) |
| homepage | https://github.com/JasterV/granc |
| repository | https://github.com/JasterV/granc |
| max_upload_size | |
| id | 2057069 |
| size | 48,268 |
⚠️ Status: Experimental
This project is currently in a highly experimental phase. It is a working prototype intended for testing and development purposes. APIs, command-line arguments, and internal logic are subject to breaking changes. Please use with caution.
Granc (gRPC + Cranc, Crab in Catalan) is a lightweight, dynamic gRPC CLI tool written in Rust.
It allows you to make gRPC calls to any server using simple JSON payloads, without needing to compile the specific Protobuf files into the client. By loading a FileDescriptorSet at runtime, granc acts as a bridge between human-readable JSON and binary Protobuf wire format.
It is heavily inspired by tools like grpcurl but built to leverage the safety and performance of the Rust ecosystem (Tonic + Prost).
prost-reflect..bin or .pb).cargo install --locked granc
Granc needs to know the schema of the service you are calling. It can obtain this in two ways:
FileDescriptorSet (.bin) generated by protoc.If your server does not support reflection, you must generate a descriptor file:
# Generate descriptor.bin including all imports
protoc \
--include_imports \
--descriptor_set_out=descriptor.bin \
--proto_path=. \
my_service.proto
Note: The
--include_importsflag is crucial. It ensures that types defined in imported files (likegoogle/protobuf/timestamp.proto) are available for reflection.
Syntax:
granc <URL> <COMMAND> [ARGS]
| Argument | Description | Required |
|---|---|---|
<URL> |
Server address (e.g., http://[::1]:50051). Must be the first argument. |
Yes |
call (Make Requests)Performs a gRPC call using a JSON body.
granc http://localhost:50051 call <ENDPOINT> --body <JSON> [OPTIONS]
| Argument/Flag | Description | Required |
|---|---|---|
<ENDPOINT> |
Fully qualified method name (e.g., my.package.Service/Method). |
Yes |
--body |
The request body in JSON format. Object {} for unary, Array [] for streaming. |
Yes |
--header, -H |
Custom header key:value. Can be used multiple times. |
No |
--file-descriptor-set |
Path to the binary FileDescriptorSet (.bin) if not using reflection. |
No |
{ ... }.[ { ... }, { ... } ].If you omit the --file-descriptor-set flag, Granc will automatically attempt to connect to the server's reflection service to download the necessary schemas.
granc http://localhost:50051 call --body '{"name": "Ferris"}' helloworld.Greeter/SayHello
This requires the server to have the grpc.reflection.v1 service enabled.
list (Service Discovery) (Server reflection required)Lists all services exposed by the server.
granc http://localhost:50051 list
describe (Introspection) (Server reflection required)Inspects services, messages or enums and prints their Protobuf definition.
Describe Service:
Describe in detail all methods of a service.
granc http://localhost:50051 describe my.package.Greeter
Describe Message:
Shows the fields of a specific message type.
granc http://localhost:50051 describe my.package.HelloRequest
The core logic of Granc is decoupled into a separate library crate, granc-core.
If you want to build your own tools using the dynamic gRPC engine (e.g., for custom integration testing, proxies, or automation tools), you can depend on granc-core directly.
granc-core README for examples on how to use the GrancClient programmatically.granc-core**1. Service 'x' not found**
.proto file. If it has package my.app; and service API {}, the full name is my.app.API.**2. Method 'y' not found in service 'x'**
GetUser vs getUser).**3. h2 protocol error**
Contributions are welcome! Please run the Makefile checks before submitting a PR:
cargo make ci # Checks formatting, lints, and runs tests
Licensed under either of:
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.