RepoPilotOpen in app →

twitchtv/twirp

A simple RPC framework with protobuf service definitions

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.

  • 35+ active contributors
  • Distributed ownership (top contributor 24% of recent commits)
  • Apache-2.0 licensed
Show all 6 evidence items →
  • CI configured
  • Tests present
  • Stale — last commit 2y 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/twitchtv/twirp)](https://repopilot.app/r/twitchtv/twirp)

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/twitchtv/twirp on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: twitchtv/twirp

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/twitchtv/twirp 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

  • 35+ active contributors
  • Distributed ownership (top contributor 24% of recent commits)
  • Apache-2.0 licensed
  • CI configured
  • Tests present
  • ⚠ Stale — last commit 2y 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 twitchtv/twirp repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/twitchtv/twirp.

What it runs against: a local clone of twitchtv/twirp — 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 twitchtv/twirp | Confirms the artifact applies here, not a fork | | 2 | License is still Apache-2.0 | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 670 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>twitchtv/twirp</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of twitchtv/twirp. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/twitchtv/twirp.git
#   cd twirp
#
# 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 twitchtv/twirp and re-run."
  exit 2
fi

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

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

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

# 4. Critical files exist
test -f "README.md" \\
  && ok "README.md" \\
  || miss "missing critical file: README.md"
test -f "PROTOCOL.md" \\
  && ok "PROTOCOL.md" \\
  || miss "missing critical file: PROTOCOL.md"
test -f "Makefile" \\
  && ok "Makefile" \\
  || miss "missing critical file: Makefile"
test -f ".github/workflows/commit-checks.yml" \\
  && ok ".github/workflows/commit-checks.yml" \\
  || miss "missing critical file: .github/workflows/commit-checks.yml"
test -f "Gopkg.lock" \\
  && ok "Gopkg.lock" \\
  || miss "missing critical file: Gopkg.lock"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 670 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~640d)"
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/twitchtv/twirp"
  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

Twirp is a lightweight RPC framework that generates Go client and server code from Protocol Buffer service definitions, running on the standard library's net/http server. It eliminates boilerplate routing and serialization logic by automatically handling HTTP request/response mapping, supports both JSON and Protobuf wire formats, and provides built-in error handling without requiring a custom HTTP/2 transport like gRPC does. Monorepo structure with protoc plugin generator (generates routing/marshaling code from .proto files), Go runtime library in root (handles HTTP transport, error encoding, middleware hooks), and _tools/ directory vendoring build dependencies (retool, errcheck, gotool). Example services and generated code live alongside core logic rather than separated into examples/ subdirectory.

👥Who it's for

Go backend engineers building microservices who want RPC simplicity without gRPC's operational overhead; service authors who value HTTP/1.1 compatibility, easy debugging with JSON, and minimal dependency footprint. Protocol Buffer users migrating from custom REST-over-JSON codebases.

🌱Maturity & risk

Production-ready. The codebase shows stability with CI/CD in .github/workflows (commit-checks.yml), comprehensive testing infrastructure via Makefile, and active maintenance (Travis CI configured in .travis.yml). Go dominance (1.3MB of 1.4MB total) indicates battle-tested core. Twitch ships this at scale; announcement blog post references indicate maturity from 2018 onward.

Low risk for core functionality but watch for: language ecosystem maturity varies (Go is solid, but JavaScript/TypeScript implementations listed are third-party and fragmented across repos). Single upstream Go implementation means breaking proto changes affect all consumers. Dependency management uses older Gopkg.toml/Gopkg.lock (pre-Go modules era) which may cause friction on newer Go versions. No obvious high-volume issue backlog visible in provided file list.

Active areas of work

Actively maintained with GitHub Actions workflows for commit checks and stale issue management (stale.yaml). No specific PRs or milestones are visible in the provided file structure, but the presence of CONTRIBUTING.md and PR template suggest ongoing contributor onboarding. Focus appears to be stability and cross-language implementation support rather than major feature additions.

🚀Get running

git clone https://github.com/twitchtv/twirp.git
cd twirp
make # uses Makefile for build and test

Dependencies are vendored in _tools/; you'll need Go 1.11+ (to support Gopkg.toml-era dependency management).

Daily commands:

make # builds and runs tests
make install # installs protoc-gen-twirp plugin

Then use protoc --go_out=. --twirp_out=. service.proto to generate server/client stubs, instantiate a service handler, and serve via http.ListenAndServe(":8080", server).

🗺️Map of the codebase

  • README.md — Defines Twirp's core mission: RPC framework with protobuf service definitions running on standard net/http, essential context for all contributors.
  • PROTOCOL.md — Specifies the Twirp wire protocol (HTTP routing, JSON/protobuf serialization), non-negotiable reference for client/server implementation.
  • Makefile — Build orchestration for code generation and testing; contributors must understand the build pipeline before modifying generator or core code.
  • .github/workflows/commit-checks.yml — CI/CD definition for all commits; defines what tests, lints, and checks must pass before merging.
  • Gopkg.lock — Locks dependency versions (protobuf, x/tools); changes here cascade to code generation output and must be carefully reviewed.
  • CONTRIBUTING.md — Development guidelines, contribution workflow, and expectations for code quality and testing in the Twirp project.
  • _tools/src/google.golang.org/protobuf/cmd/protoc-gen-go/main.go — Entry point for protobuf code generation; critical dependency that Twirp's own code generator likely extends or wraps.

🧩Components & responsibilities

  • Protocol Definition (.proto files) — Defines service interface,

🛠️How to make changes

Add a new Twirp service RPC method

  1. Define the service, request, and response message in a .proto file (e.g., myservice/service.proto) following protobuf3 syntax. (PROTOCOL.md (reference for message structure conventions))
  2. Run make generate or the appropriate protoc command to invoke the Twirp code generator, producing routing and serialization code. (Makefile (target for code generation))
  3. Implement the server handler method in your service struct; the generated interface will define the method signature. (README.md (shows example service implementation pattern))
  4. Register the service in your net/http server using the generated NewXXXServer(svc) constructor. (README.md (shows server setup example))
  5. Test the RPC by calling the generated client code or making HTTP requests per PROTOCOL.md routing rules. (PROTOCOL.md (HTTP method and path specification))

Extend Twirp's code generator with a custom plugin

  1. Create a new protoc plugin binary that imports the protogen API. (_tools/src/google.golang.org/protobuf/compiler/protogen/protogen.go (plugin interface))
  2. Register your plugin in the protoc invocation within the Makefile or build script. (Makefile (build targets and protoc flags))
  3. Use the CodeGenerator.Println() and File.Add() methods to inject custom code into generated outputs. (_tools/src/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/main.go (example of code generation pattern))
  4. Add tests for your generated code to verify correctness and add to CI. (.github/workflows/commit-checks.yml (add test step if needed))

Update Twirp's protobuf or dependencies

  1. Modify the required version constraint in Gopkg.toml for the protobuf or x/tools package. (Gopkg.toml (dependency version specifications))
  2. Run make or the dependency manager to update Gopkg.lock with new resolved versions. (Gopkg.lock (lock file to be regenerated))
  3. Run the test suite via CI or make test to ensure code generation and runtime behavior remain compatible. (.github/workflows/commit-checks.yml (validates compatibility after update))
  4. Document breaking changes or migration steps in CONTRIBUTING.md or a changelog if the update is major. (CONTRIBUTING.md (contributor documentation))

🔧Why these technologies

  • Protocol Buffers (protobuf3) — Provides efficient binary serialization, strong typing, and is language-agnostic; enables multi-language service ecosystems.
  • Go standard library net/http — Eliminates custom transport layer overhead; leverages battle-tested HTTP server with excellent performance and HTTP/1.1 + HTTP/2 support.
  • JSON serialization option — Enables human-readable debugging and integration with JavaScript/browser clients without requiring HTTP/2 or gRPC gateway.
  • Code generation (protoc plugins) — Eliminates boilerplate routing, serialization, and client code; ensures consistency across all RPC methods and services.

⚖️Trade-offs already made

  • Standard net/http instead of custom HTTP/2 transport

    • Why: Simplicity and operational familiarity for Go developers; reduces maintenance burden.
    • Consequence: Loses some gRPC optimizations (multiplexing efficiency) but gains HTTP/1.1 compatibility and easier deployment (no gRPC-specific load balancer config).
  • JSON as first-class serialization option alongside protobuf

    • Why: Enables debugging, browser clients, and gradual adoption without forcing binary-only protocols.
    • Consequence: Slightly larger message sizes in JSON mode; requires dual codec implementation in code generator.
  • Autogenerated clients and routing rather than reflection-based dispatch

    • Why: Provides compile-time type safety and IDE autocomplete; reduces runtime overhead.
    • Consequence: Requires regeneration when .proto changes; couples client and server to generated code (higher coupling than dynamic frameworks).

🚫Non-goals (don't propose these)

  • Real-time bidirectional streaming (uses request-response HTTP semantics only, no WebSocket or gRPC streaming).
  • Authentication/authorization framework (Twirp delegates auth to middleware or service logic).
  • Service discovery or load balancing (assumes external orchestration via Kubernetes, Consul, etc.).
  • Cross-language code generation for non-Go targets (focuses on Go as primary consumer, though protos can be used elsewhere).
  • HTTP path customization per RPC (all methods follow fixed /twirp/Package.Service/Method routing scheme).

🪤Traps & gotchas

Gopkg.toml era: This repo uses Go's older vendoring (Gopkg.toml/Gopkg.lock), not go.mod. If you have Go 1.16+, you may need export GO111MODULE=off or migrate the dependency declarations. protoc version: The protoc plugin may require a specific protoc version; check Makefile for version pins. No explicit test database or external services: appears to use only in-process testing, so no Docker/docker-compose setup needed. _tools/ directory: contains build tool sources—modifying them requires understanding retool manifest format.

🏗️Architecture

💡Concepts to learn

  • Protocol Buffers (protobuf) code generation — Twirp's core mechanism: protoc plugins read .proto files and emit routing tables, marshaling code, and RPC stubs—understanding this is essential to extending Twirp
  • HTTP method tunneling (POST-only RPC) — Unlike REST's GET/PUT/DELETE per resource, Twirp tunnels all RPCs through HTTP POST to /twirp/Package/Method; this simplifies routing but breaks standard HTTP caching and semantics
  • Interceptor middleware chain — Twirp's extensibility model (request hooks, auth, logging, metrics) uses composable interceptors—similar to Go's middleware pattern but codified for RPC lifecycle
  • Error code semantics (Twirp error model) — Instead of HTTP status codes, Twirp defines semantics for InvalidArgument, NotFound, Internal, etc. as first-class error types in JSON responses—clients parse error codes, not HTTP 4xx/5xx
  • Dual serialization format (JSON + Protobuf wire) — Twirp auto-detects request Content-Type and marshals to either human-readable JSON or binary protobuf; this enables debugging via curl while maintaining wire efficiency
  • Vendor-based dependency management (Gopkg.toml) — This repo predates Go modules; understanding Gopkg.lock reproducibility and retool tool management is necessary to build and extend the project without dependency hell
  • grpc/grpc-go — Direct competitor; gRPC is the industry standard RPC framework that Twirp explicitly positions against by avoiding HTTP/2 and custom transports
  • protocolbuffers/protobuf — Upstream dependency; Twirp's entire code generation and serialization relies on Protocol Buffers toolchain and Go runtime
  • tatethurston/TwirpScript — Community implementation bringing Twirp RPC to TypeScript/JavaScript; shows how Twirp protocol is implemented in other languages
  • mloughran/twirp.cr — Reference implementation in Crystal demonstrating Twirp's multi-language interoperability; useful for understanding protocol semantics independent of Go
  • twitchtv/twirp-example — Official example repository (if it exists) showing end-to-end Twirp service setup; check for companion examples repo on Twitch's GitHub

🪄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 Go client code generation tests for multiple protobuf versions

The repo uses protobuf service definitions as its core abstraction, but there's no visible test coverage for code generation across different protobuf compiler versions. Given the critical nature of code generation in a framework, adding integration tests that verify generated Go clients work correctly with protoc 3.x and 4.x would catch regressions early and document version compatibility guarantees.

  • [ ] Create a new test file in the root or test directory that defines sample .proto files with various RPC patterns (unary, streaming, error cases)
  • [ ] Add test cases that invoke the Twirp code generator and validate the generated Go code compiles and matches expected interface signatures
  • [ ] Integrate this into .github/workflows/commit-checks.yml to run against multiple protobuf versions in the CI matrix
  • [ ] Document minimum and tested protobuf versions in README.md

Add cross-language generated code validation (Go client vs Python/Node server interop test)

Twirp is positioned as a simpler alternative to gRPC, but the repo only contains Go implementations. Adding integration tests that validate a Go client can correctly communicate with services generated in other languages (Python, Node.js, Ruby) would strengthen the value proposition and catch protocol deviations early. This requires generating and running test servers in multiple languages.

  • [ ] Create a test fixture directory (e.g., test/interop/) with example .proto definitions
  • [ ] Add a Go test suite that generates clients, then spawns pre-built Python and Node.js test servers (via Docker or bundled binaries) and validates request/response behavior
  • [ ] Update .github/workflows/commit-checks.yml to include Docker or language-specific setup steps for running interop tests
  • [ ] Document the interop test setup in CONTRIBUTING.md with instructions for adding new language test servers

Add comprehensive benchmarks for serialization and routing performance against gRPC

The README claims Twirp is simpler than gRPC and runs on net/http, but there are no public benchmarks demonstrating performance characteristics. Adding a benchmarks/ directory with reproducible tests comparing JSON vs protobuf serialization, routing overhead, and throughput between Twirp and gRPC would provide concrete evidence and help users make informed decisions.

  • [ ] Create benchmarks/ directory with Go files defining identical RPC scenarios in both Twirp and gRPC
  • [ ] Write benchmark functions using Go's testing.B that measure latency, throughput, and memory allocation for various payload sizes
  • [ ] Add a CI workflow (.github/workflows/benchmarks.yml) that runs benchmarks on every commit and stores results for trend analysis
  • [ ] Document benchmark results and methodology in PROTOCOL.md or a new BENCHMARKS.md file

🌿Good first issues

  • Add missing error code documentation: PROTOCOL.md lists error types, but the Go runtime error package lacks inline godoc examples. Document each Twirp error (Internal, InvalidArgument, etc.) in the error-handling code with example usage.
  • Expand JavaScript client example: The repo lists third-party JS implementations but provides no official JS client in this repo. Create a simple example in examples/ or docs showing how to call a Twirp Go server from a Node.js or browser client using the wire protocol.
  • Add HTTP/2 performance benchmarks: Makefile and README claim HTTP/1.1 parity with gRPC, but no benchmark harness exists in the codebase. Create a benchmarks/ directory with a simple load test comparing gRPC vs. Twirp on identical proto schemas to validate claims.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • fb7430a — Merge pull request #394 from countableSet/update-readme (swiftyspiffy)
  • e0e41a7 — add github/flit to java list (countableSet)
  • b72d7e9 — Merge pull request #393 from twitchtv/automated_warning_removal (howsleya)
  • fef8e0a — fix typo (swiftyspiffy)
  • f685736 — add .well-known to static directory to resolve automated lookalike warning (swiftyspiffy)
  • 4e1d44e — Merge pull request #391 from yetyear/main (swiftyspiffy)
  • 90c6a70 — Merge pull request #392 from szepeviktor/typos (shellraiser)
  • f7008cb — Fix typos (szepeviktor)
  • 1ebd08f — chore: remove repetitive words (yetyear)
  • c174e53 — Merge pull request #389 from riprsa/patch-1 (shellraiser)

🔒Security observations

The Twirp RPC framework codebase shows moderate security posture. The main concerns are outdated dependency management tools (dep instead of Go modules) and vendored dependencies that may be difficult to track for vulnerabilities. The project uses some modern practices (GitHub Actions for CI/CD), but the presence of legacy configuration files suggests incomplete migration. No obvious hardcoded secrets, SQL injection, or XSS risks were identified in the visible file structure. For a framework handling inter-service communication, security documentation and best practices guidance for users could be strengthened.

  • Medium · Vendored Dependencies in _tools Directory — _tools/src/golang.org/x/tools, _tools/src/github.com/twitchtv/retool/vendor. The repository contains vendored dependencies in the _tools directory, including older versions of golang.org/x/tools and other packages. These vendored packages may contain known vulnerabilities and are difficult to track and update systematically. Fix: Use Go modules (go.mod/go.sum) for dependency management instead of vendoring. Regularly run 'go list -json -m all' and use 'go mod tidy' to keep dependencies updated. Consider using vulnerability scanning tools like 'govulncheck'.
  • Medium · Outdated Build Configuration — Gopkg.toml, Gopkg.lock, .travis.yml. The project uses Gopkg.toml and Gopkg.lock (deprecated dep tool) and .travis.yml for CI/CD. These are outdated and no longer maintained. The Travis CI configuration may not reflect current security best practices. Fix: Migrate to Go modules (go.mod/go.sum). Update CI/CD to use modern GitHub Actions (already partially present in .github/workflows) and ensure security checks are included in the pipeline (SAST, dependency scanning, etc).
  • Low · Missing Security Headers in HTTP Framework — Core framework implementation (not fully visible in provided structure). Twirp is an RPC framework that handles HTTP requests. Without explicit documentation or code review, there's risk that security headers (HSTS, X-Content-Type-Options, X-Frame-Options, CSP) may not be properly configured by default. Fix: Review the HTTP server implementation and ensure security headers are either set by default or well-documented. Provide middleware examples for common security headers. Document security best practices for users implementing Twirp services.
  • Low · No Visible Input Validation Documentation — Protocol handling and service implementation. As an RPC framework that handles protobuf deserialization, there's potential risk of insufficient input validation if not properly handled. The file structure doesn't show comprehensive validation examples or security guidelines. Fix: Document input validation best practices for service implementers. Ensure protobuf parsing handles malformed input safely. Consider providing validation middleware examples or integrating with validation libraries.

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 · twitchtv/twirp — RepoPilot