RepoPilotOpen in app →

fullstorydev/grpcurl

Like cURL, but for gRPC: Command-line tool for interacting with gRPC servers

Healthy

Healthy across all four use cases

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 3mo ago
  • 33+ active contributors
  • Distributed ownership (top contributor 45% of recent commits)
Show all 7 evidence items →
  • MIT licensed
  • CI configured
  • Tests present
  • Slowing — last commit 3mo ago

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/fullstorydev/grpcurl)](https://repopilot.app/r/fullstorydev/grpcurl)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/fullstorydev/grpcurl on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: fullstorydev/grpcurl

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/fullstorydev/grpcurl shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across all four use cases

  • Last commit 3mo ago
  • 33+ active contributors
  • Distributed ownership (top contributor 45% of recent commits)
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Slowing — last commit 3mo ago

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live fullstorydev/grpcurl repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/fullstorydev/grpcurl.

What it runs against: a local clone of fullstorydev/grpcurl — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in fullstorydev/grpcurl | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 130 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>fullstorydev/grpcurl</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of fullstorydev/grpcurl. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/fullstorydev/grpcurl.git
#   cd grpcurl
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of fullstorydev/grpcurl and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "fullstorydev/grpcurl(\\.git)?\\b" \\
  && ok "origin remote is fullstorydev/grpcurl" \\
  || miss "origin remote is not fullstorydev/grpcurl (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "cmd/grpcurl/grpcurl.go" \\
  && ok "cmd/grpcurl/grpcurl.go" \\
  || miss "missing critical file: cmd/grpcurl/grpcurl.go"
test -f "grpcurl.go" \\
  && ok "grpcurl.go" \\
  || miss "missing critical file: grpcurl.go"
test -f "invoke.go" \\
  && ok "invoke.go" \\
  || miss "missing critical file: invoke.go"
test -f "desc_source.go" \\
  && ok "desc_source.go" \\
  || miss "missing critical file: desc_source.go"
test -f "format.go" \\
  && ok "format.go" \\
  || miss "missing critical file: format.go"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 130 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~100d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/fullstorydev/grpcurl"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

grpcurl is a command-line tool that functions like cURL but for gRPC servers, allowing you to invoke RPC methods from the shell by converting JSON request data into protocol buffer binary encoding. It supports all gRPC method types (unary, server streaming, client streaming, bidirectional streaming) and can discover service schemas via server reflection, proto source files, or precompiled protoset descriptor files. Single-package architecture with cmd/grpcurl/grpcurl.go as the CLI entry point and library code at root level (grpcurl.go, format.go, desc_source.go) providing reusable primitives. Test infrastructure in internal/testing/ includes two runnable demo services (bankdemo and testserver) and test proto files (test.proto, example.proto). The Dockerfile and shell scripts support cross-platform builds and testing.

👥Who it's for

Backend engineers and DevOps practitioners who need to test, debug, and interact with gRPC services from the command line without writing client code; QA teams validating gRPC APIs; and developers building gRPC infrastructure tools who want to reuse the grpcurl library (github.com/fullstorydev/grpcurl) for dynamic RPC invocation.

🌱Maturity & risk

Production-ready and actively maintained. The project has comprehensive test coverage (evident from _test.go files throughout), CircleCI/GitHub Actions CI setup, Docker support, and is distributed via multiple channels (GitHub releases, Snap, goreleaser). Go version constraint to 1.24.0+ indicates recent active development with no signs of abandonment.

Low risk overall. Dependencies are well-established gRPC/protobuf ecosystem packages (google.golang.org/grpc, github.com/jhump/protoreflect, protobuf). Single maintainer risk exists (fullstorydev org) but the tool is widely adopted and stable. No concerning breaking-change patterns visible in the file structure; proto definitions in internal/testing/ suggest good backward compatibility testing.

Active areas of work

The repo shows active Go ecosystem maintenance: recent toolchain bump to go1.24.1, dependency updates via dependabot.yml, and CI improvements (codesee-arch-diagram workflow). The internal/testing/ directory with two feature-complete demo servers (bank and support chat services) suggests ongoing investment in test coverage quality.

🚀Get running

git clone https://github.com/fullstorydev/grpcurl.git
cd grpcurl
go build -o grpcurl ./cmd/grpcurl
./grpcurl -h

Daily commands:

# Build the CLI tool
make build

# Or build directly
go build -o grpcurl ./cmd/grpcurl

# Test against the built-in demo server
cd internal/testing/cmd/testserver && go run testserver.go &
grpcurl -plaintext localhost:7777 list

# Test the full suite
go test ./...

🗺️Map of the codebase

  • cmd/grpcurl/grpcurl.go — Main CLI entry point that parses arguments, sets up gRPC connections, and orchestrates the entire tool's execution flow.
  • grpcurl.go — Core package exposing InvokeRPC and primary APIs that all callers use to execute gRPC method invocations.
  • invoke.go — Handles the actual gRPC unary/streaming RPC invocation logic, message marshaling, and response handling.
  • desc_source.go — Abstracts descriptor sources (reflection, protoset files) so the tool can discover service schemas dynamically or statically.
  • format.go — Converts protobuf messages to/from JSON, handling formatting options and encoding logic that bridges binary gRPC and human-readable output.
  • go.mod — Declares dependencies on grpc, protobuf, and protoreflect libraries that enable all gRPC and schema introspection functionality.

🧩Components & responsibilities

  • CLI Parser (grpcurl.go) (Go flag package, TLS config, gRPC dial options) — Parses command-line flags, builds descriptor sources, constructs gRPC dial options, and orchestrates invocation.
    • Failure mode: Invalid flags or malformed arguments cause early exit with usage message; wrong host/port fails at connection time.
  • Descriptor Source (desc_source.go)

🛠️How to make changes

Add a new output format handler

  1. Define a new formatter function matching the signature used in format.go for JSON marshaling (format.go)
  2. Add a flag option in the CLI to select this format, typically via a string flag like -format=yaml (cmd/grpcurl/grpcurl.go)
  3. Call your new formatter in the message-writing paths within invoke.go where responses are encoded (invoke.go)
  4. Add tests in format_test.go to validate encoding and decoding of sample messages (format_test.go)

Support a new descriptor source type

  1. Implement the DescriptorSource interface defined in desc_source.go (FindService, ListServices, etc.) (desc_source.go)
  2. Add a CLI flag in grpcurl.go to specify this new source (e.g., -descriptor-dir=/path) (cmd/grpcurl/grpcurl.go)
  3. Wire the flag into descriptor source construction logic in the main CLI execution (cmd/grpcurl/grpcurl.go)
  4. Add integration tests in desc_source_test.go validating discovery and method lookup (desc_source_test.go)

Add a new gRPC method invocation mode (e.g., timeout-aware streaming)

  1. Extend the InvokeRPC function signature in grpcurl.go to accept new parameters or context options (grpcurl.go)
  2. Implement the core invocation logic in invoke.go, handling your new mode in the RPC execution path (invoke.go)
  3. Add CLI flags in grpcurl.go to expose the new mode to users (cmd/grpcurl/grpcurl.go)
  4. Test with internal/testing/test_server.go or bankdemo to validate the new behavior (internal/testing/test_server.go)

Add metadata/header injection support

  1. Parse header flags in the CLI argument handler (cmd/grpcurl/grpcurl.go)
  2. Pass headers into InvokeRPC via a new parameter or context metadata (grpcurl.go)
  3. Inject headers into the gRPC context before invoking methods in invoke.go (invoke.go)
  4. Test header propagation with grpcurl_test.go and bankdemo integration tests (grpcurl_test.go)

🔧Why these technologies

  • gRPC & Protocol Buffers — grpcurl's entire purpose is to interact with gRPC services; protobuf is the native wire format.
  • gRPC reflection API — Enables dynamic schema discovery without requiring .proto files; key feature for exploring unknown services.
  • jhump/protoreflect — High-level protobuf descriptor manipulation library; avoids low-level protobuf descriptor API complexity.
  • Go CLI with flag package — Lightweight, portable command-line tool with minimal external dependencies; fits curl-like usage pattern.
  • TLS support — Production gRPC services almost always use TLS; essential for real-world interactions.

⚖️Trade-offs already made

  • JSON as the input/output format rather than binary or text proto

    • Why: JSON is human-readable, script-friendly, and matches curl's paradigm; bridges the gap between gRPC's binary nature and user interaction.
    • Consequence: Must maintain JSON ↔ protobuf converters; potential precision loss for some types (e.g., large integers, custom types).
  • Support both reflection and static protoset files

    • Why: Reflection requires server support (may be disabled in production); static files provide fallback for locked-down environments.
    • Consequence: Two code paths for descriptor discovery; added complexity in descriptor source abstraction.
  • Single-threaded, synchronous CLI rather than async/concurrent calls

    • Why: Simpler UX and implementation; matches curl's sequential execution model.
    • Consequence: Cannot parallelize multiple RPC calls in one invocation; users must run grpcurl multiple times for concurrent requests.
  • Stateless CLI tool rather than persistent REPL

    • Why: Simpler design, easier integration with scripts and CI/CD, no session management overhead.
    • Consequence: Each invocation re-establishes connection and re-discovers schema; slightly slower for rapid testing (but caching via file descriptors mitigates).

🚫Non-goals (don't propose these)

  • Does not provide authentication beyond TLS client certificates; delegated to gRPC interceptors or server-side config.
  • Not a gRPC proxy or gateway; pure client tool for testing/exploration.
  • Does not generate or modify .proto files; focused on consumption and invocation.
  • No GUI or interactive REPL; CLI-only for scriptability.
  • Does not handle gRPC load-balancing or service discovery; requires explicit host:port.

🪤Traps & gotchas

Proto compilation dependencies: Tests rely on protoc being available (see download_protoc.sh)—some tests may fail if proto code generation hasn't run. TLS cert paths: internal/testing/tls/ contains hardcoded test certificates; mTLS tests assume specific cert locations. Test server ports: bankdemo and testserver use fixed ports (7777 implied by test patterns); port conflicts will break integration tests. Reflection protocol version: code assumes grpc-reflection v1; older servers with v0 reflection may not work. Go version constraint: go1.24.0 minimum is strict; no fallback for older Go versions.

🏗️Architecture

💡Concepts to learn

  • gRPC Server Reflection — Core feature allowing grpcurl to discover RPC methods and message schemas at runtime from live servers without needing proto files; enables truly cURL-like zero-config invocation
  • Protocol Buffers (Protobuf) Messages & Services — The serialization format and RPC definition language that grpcurl converts from/to JSON; understanding .proto syntax and descriptor messages is essential to using and modifying grpcurl
  • gRPC Streaming (Unary, Server, Client, Bidirectional) — grpcurl must handle four distinct RPC patterns with different request/response semantics; this complexity is hidden in InvokeRPC and format.go but is critical to understanding what grpcurl supports
  • Protobuf FileDescriptor & Message Descriptors — grpcurl uses descriptor protos to introspect and validate message structure at runtime; desc_source.go and format.go heavily rely on these reflection objects from google.golang.org/protobuf
  • JSON-Proto Marshaling / Unmarshaling — The core value-add of grpcurl is converting human-friendly JSON input to binary protobuf for gRPC calls and back to JSON for output; format.go and jsonpb_test_proto/ show the complexity of this transformation
  • TLS / mTLS (Mutual TLS) for gRPC — grpcurl must support both plaintext and encrypted connections, including client certificate authentication; cmd/grpcurl/grpcurl.go handles credential setup, and internal/testing/tls/ provides test certs
  • Protoset Files (Binary Descriptor Bundles) — An alternative to .proto sources for providing schema to grpcurl; a protoset is a serialized FileDescriptorSet that avoids needing protoc at runtime, handled in desc_source.go
  • grpc/grpc — The upstream gRPC project that defines the protocol, reflection spec, and go-grpc library that grpcurl depends on
  • jhump/protoreflect — The reflection and descriptor manipulation library that powers grpcurl's ability to introspect proto schemas without generated code
  • protocolbuffers/protobuf — The protobuf compiler and runtime that underpins all proto file parsing and message encoding/decoding in grpcurl
  • evalphobia/grpcurl-cli — An alternative gRPC CLI tool with a different feature set; comparison point for grpcurl design decisions
  • fullstorydev/grpcui — Sister project from the same org providing a web UI for gRPC interaction; grpcui likely reuses some grpcurl library primitives for dynamic invocation

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive integration tests for TLS/mTLS scenarios in cmd/grpcurl

The repo has extensive TLS certificate fixtures in internal/testing/tls/ (ca.crt, client.crt, server.crt, expired.crt, wrong-ca.crt, etc.) but cmd/grpcurl/grpcurl.go lacks dedicated test coverage for TLS flag combinations. This is critical for a tool that users rely on for secure gRPC communication. New contributor can write tests covering: valid mTLS, expired certs, wrong CA, cert validation failures, and cert chains.

  • [ ] Review cmd/grpcurl/grpcurl.go to identify TLS-related flag handling (e.g., -cacert, -cert, -key)
  • [ ] Create cmd/grpcurl/grpcurl_tls_test.go with subtests for each TLS scenario using fixtures from internal/testing/tls/
  • [ ] Test both positive cases (successful mTLS) and negative cases (expired cert rejection, wrong CA rejection)
  • [ ] Verify tests run against internal/testing/cmd/testserver with TLS enabled

Add unit tests for the format.go module covering edge cases

format.go handles message formatting (JSON output, text formatting) which is core to grpcurl's functionality, but format_test.go appears minimal. This is a high-impact area since output formatting bugs directly affect user experience. Tests should cover edge cases like null values, nested messages, unknown field types, and unicode handling.

  • [ ] Examine format.go to identify all exported functions and their complexity
  • [ ] Expand format_test.go with table-driven tests for: nil messages, deeply nested structures, custom field types from internal/testing/jsonpb_test_proto/test_objects.proto
  • [ ] Add tests for JSON marshaling edge cases: empty messages, repeated fields, oneof fields, well-known types (Timestamp, Duration, etc.)
  • [ ] Test both default and -json-name formatting modes

Add GitHub Actions workflow for testing gRPC streaming scenarios across platform matrices

The repo has .circleci/config.yml but the .github/workflows/ directory only contains codesee-arch-diagram.yml. There's no GitHub Actions CI coverage for matrix testing (Go 1.24+ on Linux/macOS/Windows). The internal/testing/cmd/bankdemo includes a chat service with streaming endpoints, but there's no dedicated CI verification that streaming RPC invocation works correctly across platforms.

  • [ ] Create .github/workflows/streaming-tests.yml that runs on multiple Go versions (1.24.x, 1.25.x) and OS matrices (ubuntu-latest, macos-latest, windows-latest)
  • [ ] Add steps to build internal/testing/cmd/bankdemo and internal/testing/cmd/testserver
  • [ ] Run grpcurl against bankdemo's chat service to verify unary, client-streaming, server-streaming, and bidirectional streaming work
  • [ ] Compare test results with .circleci/config.yml to avoid redundancy, or document why GitHub Actions provides unique coverage

🌿Good first issues

  • Add JSON validation tests in format_test.go: currently missing edge cases for malformed JSON input, null values in required fields, and deeply nested proto messages. Start by reviewing existing test patterns in format_test.go and expand coverage.
  • Implement help/documentation for the -metadata flag family (seems referenced in cmd/grpcurl/grpcurl.go but lacks dedicated tests): add integration tests in grpcurl_test.go that verify metadata headers are correctly sent to servers.
  • Create a comprehensive example or documentation update for bidirectional streaming with the interactive terminal: internal/testing/cmd/bankdemo/chat.go implements chat streaming but no grpcurl invocation example exists in README or docs.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • c54eac2 — Bump github.com/jhump/protoreflect from 1.17.0 to 1.18.0 (#545) (dependabot[bot])
  • 6caf0e7 — update lead version to Go 1.25 (#543) (dragonsinth)
  • 1ad1dc1 — refactor: use strings.Builder to improve performance (#537) (rifeplight)
  • f575e91 — refactor: use slices.Contains to simplify code (#536) (vastonus)
  • ed672b2 — Bump google.golang.org/protobuf from 1.36.8 to 1.36.10 (#535) (dependabot[bot])
  • eab6c91 — add arm build for snap (#534) (PietroPasotti)
  • 60e53f3 — Bump google.golang.org/protobuf from 1.36.7 to 1.36.8 (#527) (dependabot[bot])
  • f093930 — Bump google.golang.org/protobuf from 1.36.6 to 1.36.7 (#525) (dependabot[bot])
  • 7ad93a4 — test: Update TLS error checks for Go 1.25 compatibility (#522) (mikelolasagasti)
  • 7155fb6 — Bump golang.org/x/oauth2 from 0.14.0 to 0.27.0 in the go_modules group (#520) (dependabot[bot])

🔒Security observations

The grpcurl codebase demonstrates generally good security practices with no critical vulnerabilities detected. The project uses up-to-date Go versions (1.24.1), includes HTTPS/TLS testing infrastructure, and follows secure Docker build practices with multi-stage builds and non-root user execution. However, there are notable issues: (1) An incomplete Dockerfile that prevents the final image from being functional, (2) The inclusion of test private keys in version control (though clearly marked as test artifacts), and (3) A deprecated protobuf dependency that should be phased out. The dependency versions are reasonably current with no known high-severity CVEs identified. Recommended priority: Fix the Dockerfile immediately as it prevents the application from working, then address the deprecated dependency, and finally consider best practices for test credential management.

  • Medium · Incomplete Docker Multi-Stage Build — Dockerfile (final FROM scratch stage). The Dockerfile's final stage appears to be incomplete. The COPY command from the 'builder' stage to 'scratch' is cut off at 'ca-c' instead of completing the full path 'ca-certificates.crt'. This could result in missing CA certificates in the final image, causing TLS verification failures or requiring users to work around certificate validation issues. Fix: Complete the COPY command with the full filename: 'COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt'. Ensure all necessary files are properly copied to the scratch image.
  • Low · Test Credentials in Repository — internal/testing/tls/ directory (ca.key, client.key, server.key, etc.). The repository contains TLS test certificates and keys (internal/testing/tls/ directory) including CA keys, client keys, and server keys. While these are clearly test/development artifacts, having private keys in version control is a security anti-pattern that could lead to accidental exposure of similar patterns in production code. Fix: Keep test credentials in the repository only if absolutely necessary for CI/CD. Consider using a test data generation script instead, or document clearly that these are non-sensitive test artifacts. Never follow this pattern with real credentials.
  • Low · Dependency on Deprecated golang/protobuf — go.mod. The project includes a direct dependency on 'github.com/golang/protobuf v1.5.4', which is deprecated in favor of 'google.golang.org/protobuf'. While google.golang.org/protobuf is already included, the deprecated package may introduce unnecessary complexity and potential compatibility issues. Fix: Evaluate whether golang/protobuf is still needed. If possible, migrate fully to google.golang.org/protobuf and remove the deprecated dependency. This reduces attack surface and maintenance burden.
  • Low · Missing COPY in Dockerfile Final Stage — Dockerfile (final FROM scratch stage). The final scratch image stage does not copy the /bin/grpcurl binary from the builder stage. The image only copies CA certificates but not the actual application binary, making the resulting container image non-functional. Fix: Add the missing COPY command: 'COPY --from=builder /grpcurl /bin/grpcurl'. Ensure the ENTRYPOINT remains pointing to /bin/grpcurl.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · fullstorydev/grpcurl — RepoPilot