protodial
A Python command-line client for gRPC. Call methods, list services, inspect
protobuf definitions, and generate request templates using server reflection,
local .proto files, or descriptor sets. No generated client code is required.
Supports unary, client-streaming, server-streaming, and bidirectional RPCs. Requests and responses can use ProtoJSON, textproto, serialized protobuf, or raw bytes. Response payloads go to stdout; diagnostics go to stderr.
Installation
Requires Python 3.10 or newer. Install the checkout with uv:
uv tool install .
protodial --version
If the package is available on your package index, install version 1.0.0 with
uv tool install protodial==1.0.0 or python -m pip install protodial==1.0.0.
You can also run it as python -m protodial.
Quick start
Call a server with reflection enabled:
protodial -d '{"name":"Ada"}' \
grpc://localhost:50051/example.Greeter/SayHello
The hello example returns compact ProtoJSON:
{"message":"Hello, Ada!","requestId":"example-123"}
Use grpc:// for plaintext and grpcs:// for TLS. Bare targets and gRPC
resolver URIs use TLS by default. For resolver or Unix-socket targets, specify
--method separately:
protodial --plaintext --method example.Greeter/SayHello dns:///localhost:50051
protodial --plaintext --method example.Greeter/SayHello unix:///tmp/example.sock
When reflection is unavailable, provide a schema:
protodial --proto api.proto --proto-path protos -d @request.json \
grpcs://api.example.com:443/example.Greeter/SayHello
Invocation options precede the target. Discovery options follow list or
describe. Run protodial --help, protodial list --help, or
protodial describe --help for the full option reference.
Schema discovery
# List services, then methods on a service.
protodial list grpc://localhost:50051
protodial list grpc://localhost:50051 example.Greeter
# Inspect a service, method, message, or field.
protodial describe grpc://localhost:50051 example.Greeter
protodial describe grpc://localhost:50051/example.Greeter/SayHello
protodial describe grpc://localhost:50051 example.HelloRequest.name
# Generate a ProtoJSON request template.
protodial describe --template \
grpc://localhost:50051/example.Greeter/SayHello
Service names are sorted; methods retain declaration order. Reflection services
are hidden unless --show-reflection is set. Unique short or suffix names are
accepted; ambiguous names report the qualified candidates.
describe --template accepts a message or method. For methods, it uses the
request type. Templates include one repeated item and the first alternative
of each oneof. --template-depth limits nesting (default: 8).
Local schemas and descriptor sets
protodial list --proto api.proto --proto-path protos unused.example:443
protodial describe --protoset api.protoset \
unused.example:443 example.HelloRequest
protodial list --protoset-out schema.pb grpc://localhost:50051
- Repeat
--prototo compile multiple entrypoints or--protosetto combine binaryFileDescriptorSetfiles. Conflicting definitions of the same file are rejected. - Local schemas disable reflection by default. Add
--use-reflectionto resolve missing symbols from the server. - Local-only discovery does not contact the target, but still requires a target operand.
--protoset-outatomically exports the resolved schema and its dependencies.- Repeat
--proto-pathfor import roots. The default reusable schema directory is$XDG_DATA_HOME/protodial/protos, falling back to$HOME/.local/share/protodial/protos. It is not created automatically.
Invocation URL paths use /SERVICE/METHOD. Discovery URLs can contain
/SERVICE for list, or /SYMBOL or /SERVICE/METHOD for describe.
URL credentials, query strings, and fragments are not supported.
Request and response formats
Select encodings independently with --input-format and --output-format.
Both default to json.
| Format | Unary | Streaming |
|---|---|---|
json |
One ProtoJSON value | Whitespace-separated values; output is NDJSON |
text |
One textproto document | Documents separated by a line containing --- |
protobuf |
One serialized message | Four-byte unsigned big-endian length, then message bytes |
raw |
One top-level bytes field |
Input byte chunks; concatenated output bytes |
Protobuf file framing is a protodial convention, not gRPC wire framing.
ProtoJSON bytes fields use base64 strings.
-d / --data accepts a literal value, @path for a file, or - / @- for
stdin. Without --data, unary calls send one empty message and client streams
send no messages, regardless of format.
JSON client streams are parsed incrementally. NDJSON, multiline values, and consecutive whitespace-separated values are accepted. Responses are compact JSON values, one per line:
printf '%s\n' '{"value":1}' '{"value":2}' | \
protodial -d @- grpc://localhost:50051/example.Service/Upload
protodial -d '{"name":"Ada"}' \
grpc://localhost:50051/example.Greeter/SayHello | jq .
Use --allow-unknown-fields to ignore unknown JSON input fields,
--emit-defaults to include default-valued output fields, and
--max-input-buffer to limit buffered parser input.
Raw file input
Bind a file to a bytes field with --field:file; this selects raw input.
Use repeatable --field options for other top-level fields:
protodial --field filename=video.bin --field:file content=video.bin \
grpc://localhost:50051/example.Service/Upload
--field values are parsed as ProtoJSON values, or as strings if they are not
valid JSON. --field:file content=- reads bytes from stdin.
With --input-format raw or --output-format raw, the bytes field is inferred
if there is exactly one eligible field. Otherwise, select it with
--input-field or --output-field. Client-streaming raw input is split into
--chunk-size byte messages; --field values apply to every message.
Server streams flush each response as it arrives. Bidirectional calls send and
receive concurrently. Failed streams preserve partial stdout output and exit
nonzero. Ctrl-C and a closed output pipe cancel the active RPC. Interactive
prompting is not supported; use -d @- for streaming stdin.
Metadata and diagnostics
protodial -H 'authorization:Bearer token' --rpc-header 'x-request-id:1234' \
-i --show-trailers --show-status \
grpcs://api.example.com:443/example.Service/Call
-H / --header metadata is sent to reflection and the application RPC.
--reflect-header and --rpc-header add scope-specific metadata without
replacing duplicate keys. Values for keys ending in -bin must be base64.
--expand-headers expands $NAME and ${NAME} in values; $$ is a literal
dollar sign. Expansion does not invoke a shell.
Diagnostics never share stdout with response data:
-i/--include: response headers.--show-trailers: response trailers.--show-status: final status, message counts, and elapsed time.--format-error: decodegoogle.rpc.Statusand its detail messages.-v: response diagnostics, structured errors, and resolved method.-vv: also include connection, transport, schema, and RPC lifecycle events.
Human diagnostics use * for status, > for request metadata, and < for
response metadata. --color auto|always|never controls stderr color. Automatic
color requires a terminal and honors NO_COLOR and TERM=dumb.
For scripts, use NDJSON diagnostics rather than parsing human output:
protodial -vv --diagnostic-format json \
grpc://localhost:50051/example.Greeter/SayHello \
>responses.ndjson 2>diagnostics.ndjson
PROTODIAL_DIAGNOSTIC_FORMAT=human|json sets the default; the CLI option takes
precedence. See the diagnostic schema for the
protodial.diagnostic.v1 contract.
TLS and connection controls
TLS is enabled by default. Use --plaintext or a grpc:// URL to disable it.
| Option | Purpose |
|---|---|
--cacert FILE |
Trust a PEM CA bundle; repeatable |
--cert FILE --key FILE |
Present a client certificate and private key |
--key-password PASSWORD |
Decrypt an encrypted private key |
--servername NAME |
Set TLS SNI and the verified server identity |
--authority NAME |
Set HTTP/2 :authority |
-k / --insecure |
Disable TLS peer verification; unsafe |
--cert and --key are required together. Certificate options cannot be used
with --plaintext. A key password passed on the command line may be exposed
in shell history and the process list.
--insecure uses a local TLS relay and always emits a warning. On Unix, the
relay uses an owner-only temporary directory and a socket with mode 0600.
The loopback TCP fallback on platforms without Unix sockets rejects client
certificates to prevent other local processes from using that identity.
Neither mode protects against remote man-in-the-middle attacks.
--connect-timeout bounds the channel-readiness check before schema discovery
or invocation. -m / --max-time sets the RPC deadline in seconds.
--wait-for-ready lets an RPC wait for an available channel within that
deadline; local-schema calls with this flag skip the readiness preflight.
Reflection still requires the preflight.
--max-send-message-size and --max-recv-message-size set gRPC message limits.
--compression accepts none, gzip, or deflate. --keepalive-time sets the
HTTP/2 keepalive interval in seconds; aggressive intervals may be rejected by
servers. -A / --user-agent sets the primary gRPC user agent.
Exit codes
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Dependency, RPC, input, schema, or file error |
2 |
Invalid CLI usage |
130 |
Interrupted with Ctrl-C |
Docker
docker build -t protodial:1.0.0 .
docker run --rm protodial:1.0.0 --version
docker run --rm protodial:1.0.0 -d '{"name":"Ada"}' \
grpc://host.docker.internal:50051/example.Greeter/SayHello
On Docker Desktop, host.docker.internal addresses the host. On Linux, use
--network host with a localhost target when appropriate. Mount local schema,
request, and certificate files into the container; add -i when reading stdin.
Development
uv sync --dev
uv run protodial --help
uv run pytest
uv run ruff check .
uv run pyright
uv build
See examples for runnable servers and calls, and CHANGELOG.md for release notes. The CLI is the primary supported interface; this README does not define a stable Python library API.
Metadata
Release files for protodial 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| protodial-1.0.0.tar.gz | 225.4 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| protodial-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 391.4 kB
Release files / protodial-1.0.0.tar.gz
| Download URL | protodial-1.0.0.tar.gz |
|---|---|
| Size | 225.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5a1ae025132b1ee96dcbc5f42a6aaabdbe75b27d25d70159eadfd8b44e422678
|
|
BLAKE2b-256 checksum How to use checksums |
9b9c6153259504842e76fd0e24489e42d1eaea007752dd44bec461284faaa9ff
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / protodial-1.0.0-py3-none-any.whl
| Download URL | protodial-1.0.0-py3-none-any.whl |
|---|---|
| Size | 166.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e233bb868c6f8b19bf4db569e7a38a5b42cae950f6b0467d9558cc3518ec60cd
|
|
BLAKE2b-256 checksum How to use checksums |
dbd4be2646bbd3d7f11ebf6ffd5b5e66519ce61bcaeb9d563b78a8602d55cd52
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for protodial 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.