Skip to main content

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 --proto to compile multiple entrypoints or --protoset to combine binary FileDescriptorSet files. Conflicting definitions of the same file are rejected.
  • Local schemas disable reflection by default. Add --use-reflection to resolve missing symbols from the server.
  • Local-only discovery does not contact the target, but still requires a target operand.
  • --protoset-out atomically exports the resolved schema and its dependencies.
  • Repeat --proto-path for 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.

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: decode google.rpc.Status and 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.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for protodial 1.0.1
File Size Uploaded Provenance
protodial-1.0.1.tar.gz 224.7 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for protodial 1.0.1
File Interpreter ABI Platform
protodial-1.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 390.1 kB

Release files / protodial-1.0.1.tar.gz

Download URL protodial-1.0.1.tar.gz
Size 224.7 kB
Tags Source
SHA-256 checksum
How to use checksums
647147901614e7a82df9d03cbd1e37ac78371027681251fb0fb9e325d3883f20
BLAKE2b-256 checksum
How to use checksums
02c2268990044c4654c6b0af101f457fb47103ae9be81c94f10fbf49d7a00ea1
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.1-py3-none-any.whl

Download URL protodial-1.0.1-py3-none-any.whl
Size 165.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7fa4a0dfacbd609316e5b1d12835b900552d54e2329825382ef909f4de066d83
BLAKE2b-256 checksum
How to use checksums
a5b695a9b8599ae773a1070b1546e7275b6d9d33124254bf7dfaf04818b2551b
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.1

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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page