golang-grpc — Claude Code skill: what it does, how to install
A Go gRPC skill covering .proto files, servers, clients, errors, TLS, testing, and streaming RPCs. Use it while building, reviewing, or debugging services.
npx skills add samber/cc-skills-golang --skill golang-grpc -a claude-codeWhat golang-grpc does
This skill guides Go gRPC work from API design to service operations. It covers domain- and version-based .proto layouts, code generation with protoc or buf, server and client patterns, interceptors for logging, auth, and recovery, plus explicit errors built with status and codes.
The guidance includes connection reuse, call deadlines, metadata, round_robin, TLS/mTLS, health checks, and graceful shutdown. It uses bufconn for tests and points to godig and gopls for Go package and code navigation. Your project needs Go and protoc; protoc-gen-go and protoc-gen-go-grpc are installed with go install.
For production, disabling reflection deserves a direct check because it exposes the API surface.
What it helps with
- organize
.protofiles by domain and version - build a gRPC server with interceptors and health checks
- map service failures to actionable
statuscodes - test RPC calls with
bufconnand configure TLS/mTLS
Example prompts for the agent
- Review this Go gRPC server for deadline handling, status codes, and graceful shutdown.
- Design a user service in `.proto`, generate its Go code with `protoc`, and add a health check.
- Inspect this gRPC client and configure connection reuse, metadata, and `round_robin`.
How to install golang-grpc
1Skills CLI (Vercel)
npx skills add samber/cc-skills-golang --skill golang-grpc -a claude-code2Manually: put the files in place
~/.claude/skills/golang-grpc/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/golang-grpc/
1Skills CLI (Vercel)
npx skills add samber/cc-skills-golang --skill golang-grpc -a codex2Manually: put the files in place
.agents/skills/golang-grpc/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add samber/cc-skills-golang --skill golang-grpc -a cursor2Manually: put the files in place
.cursor/skills/golang-grpc/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install samber/cc-skills-golang golang-grpc2Manually: put the files in place
.github/skills/golang-grpc/SKILL.md1Skills CLI (Vercel)
npx skills add samber/cc-skills-golang --skill golang-grpc -a gemini-cli2Platform CLI
gemini skills install https://github.com/samber/cc-skills-golang --path skills/golang-grpcManually: put the files in place
.devin/skills/golang-grpc/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add samber/cc-skills-golang --skill golang-grpc -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
From the same set32
The whole set →Similar
Questions about golang-grpc
How do I install golang-grpc in Claude Code?
Run npx skills add samber/cc-skills-golang --skill golang-grpc -a claude-code, then run the same command again: npx skills add samber/cc-skills-golang --skill golang-grpc -a claude-code. The skill file is at ~/.claude/skills/golang-grpc/SKILL.md.
What does golang-grpc do?
It provides guidance for building, reviewing, and debugging Go gRPC servers and clients. Topics include .proto files, interceptors, status codes, TLS/mTLS, streaming RPCs, and bufconn testing.
What does golang-grpc require?
The project should use Go. Code generation requires protoc, protoc-gen-go, and protoc-gen-go-grpc; install protoc with brew install protobuf.
Source text
SKILL.md · MIT
---
name: golang-grpc
description: "Provides gRPC usage guidelines, protobuf organization, and production-ready patterns for Golang microservices. Use when implementing, reviewing, or debugging gRPC servers/clients, writing proto files, setting up interceptors, handling gRPC errors with status codes, configuring TLS/mTLS, testing with bufconn, or working with streaming RPCs."
user-invocable: true
license: MIT
compatibility: Designed for Claude Code, Codex or similar harness, and for projects using Golang.
metadata:
author: samber
version: "1.2.2"
openclaw:
emoji: "🌐"
homepage: https://github.com/samber/cc-skills-golang
requires:
bins:
- go
- protoc
install:
- kind: brew
formula: protobuf
bins: [protoc]
allowed-tools: Read Edit Write Glob Grep Bash(go:*) Bash(golangci-lint:*) Bash(git:*) Agent WebFetch mcp__context7__resolve-library-id mcp__context7__query-docs Bash(protoc:*) AskUserQuestion Bash(godig:*) Bash(gopls:*) LSP mcp__gopls__*
paths:
- "**/*.go"
---
**Persona:** You are a Go distributed systems engineer. You design gRPC services for correctness and operability — proper status codes, deadlines, interceptors, and graceful shutdown matter as much as the happy path.
**Modes:**
- **Build mode** — implementing a new gRPC server or client from scratch.
- **Review mode** — auditing existing gRPC code for correctness, security, and operability issues.
**Dependencies:**
- protoc: `brew install protobuf`
- protoc-gen-go: `go install google.golang.org/protobuf/cmd/protoc-gen-go@latest`
- protoc-gen-go-grpc: `go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest`
# Go gRPC Best Practices
Treat gRPC as a pure transport layer — keep it separate from business logic. The official Go implementation is `google.golang.org/grpc`.
This skill is not exhaustive — refer to library documentation and code examples for more information:
- For Go package docs, symbols, versions, importers, and known vulnerabilities, → See `samber/cc-skills-golang@golang-pkg-go-dev` skill (`godig`), preferred over Context7 for Go package facts.
- To navigate this library's usage in your own code (definitions, call sites, diagnostics), → See `samber/cc-skills-golang@golang-gopls` skill (`gopls`).
- Context7 remains a fallback for docs not indexed on pkg.go.dev.
## Quick Reference
| Concern | Package / Tool |
| --- | --- |
| Service definition | `protoc` or `buf` with `.proto` files |
| Code generation | `protoc-gen-go`, `protoc-gen-go-grpc` |
| Error handling | `google.golang.org/grpc/status` with `codes` |
| Rich error details | `google.golang.org/genproto/googleapis/rpc/errdetails` |
| Interceptors | `grpc.ChainUnaryInterceptor`, `grpc.ChainStreamInterceptor` |
| Middleware ecosystem | `github.com/grpc-ecosystem/go-grpc-middleware` |
| Testing | `google.golang.org/grpc/test/bufconn` |
| TLS / mTLS | `google.golang.org/grpc/credentials` |
| Health checks | `google.golang.org/grpc/health` |
## Proto File Organization
Organize by domain with versioned directories (`proto/user/v1/`). Always use `Request`/`Response` wrapper messages — bare types like `string` cannot have fields added later. Generate with `buf generate` or `protoc`.
[Proto & code generation reference](references/protoc-reference.md)
## Server Implementation
- Implement health check service (`grpc_health_v1`) — Kubernetes probes need it to determine readiness
- Use interceptors for cross-cutting concerns (logging, auth, recovery) — keeps business logic clean
- Use `GracefulStop()` with a timeout fallback to `Stop()` — drains in-flight RPCs while preventing hangs
- Disable reflection in production — it exposes your full API surface
```go
srv := grpc.NewServer(
grpc.ChainUnaryInterceptor(loggingInterceptor, recoveryInterceptor),
)
pb.RegisterUserServiceServer(srv, svc)
healthpb.RegisterHealthServer(srv, health.NewServer())
go srv.Serve(lis)
// On shutdown signal:
stopped := make(chan struct{})
go func() { srv.GracefulStop(); close(stopped) }()
select {
case <-stopped:
case <-time.After(15 * time.Second):
srv.Stop()
}
```
### Interceptor Pattern
```go
func loggingInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
start := time.Now()
resp, err := handler(ctx, req)
log.Printf("method=%s duration=%s code=%s", info.FullMethod, time.Since(start), status.Code(err))
return resp, err
}
```
## Client Implementation
- Reuse connections — gRPC multiplexes RPCs on a single HTTP/2 connection; one-per-request wastes TCP/TLS handshakes
- Set deadlines on every call (`context.WithTimeout`) — without one, a slow upstream hangs goroutines indefinitely
- Use `round_robin` with headless Kubernetes services via `dns:///` scheme
- Pass metadata (auth tokens, trace IDs) via `metadata.NewOutgoingContext`
```go
conn, err := grpc.NewClient("dns:///user-service:50051",
grpc.WithTransportCredentials(creds),
grpc.WithDefaultServiceConfig(`{
"loadBalancingPolicy": "round_robin",
"methodConfig": [{
"name": [{"service": ""}],
"timeout": "5s",
"retryPolicy": {
"maxAttempts": 3,
"initialBackoff": "0.1s",
"maxBackoff": "1s",
"backoffMultiplier": 2,
"retryableStatusCodes": ["UNAVAILABLE"]
}
}]
}`),
)
client := pb.NewUserServiceClient(conn)
```
## Error Handling
Always return gRPC errors using `status.Error` with a specific code — a raw `error` becomes `codes.Unknown`, telling the client nothing actionable. Clients use codes to decide retry vs fail-fast vs degrade.
| Code | When to Use |
| -------------------- | ------------------------------------------- |
| `InvalidArgument` | Malformed input (missing field, bad format) |
| `NotFound` | Entity does not exist |
| `AlreadyExists` | Create failed, entity exists |
| `PermissionDenied` | Caller lacks permission |
| `Unauthenticated` | Missing or invalid token |
| `FailedPrecondition` | System not in required state |
| `ResourceExhausted` | Rate limit or quota exceeded |
| `Unavailable` | Transient issue, safe to retry |
| `Internal` | Unexpected bug |
| `DeadlineExceeded` | Timeout |
```go
// ✗ Bad — caller gets codes.Unknown, can't decide whether to retry
return nil, fmt.Errorf("user not found")
// ✓ Good — specific code lets clients act appropriately
if errors.Is(err, ErrNotFound) {
return nil, status.Errorf(codes.NotFound, "user %q not found", req.UserId)
}
return nil, status.Errorf(codes.Internal, "lookup failed: %v", err)
```
For field-level validation errors, attach `errdetails.BadRequest` via `status.WithDetails`.
## Streaming
| Pattern | Use Case |
| --- | --- |
| Server streaming | Server sends a sequence (log tailing, result sets) |
| Client streaming | Client sends a sequence, server responds once (file upload, batch) |
| Bidirectional | Both send independently (chat, real-time sync) |
Prefer streaming over large single messages — avoids per-message size limits and lowers memory pressure.
```go
func (s *server) ListUsers(req *pb.ListUsersRequest, stream pb.UserService_ListUsersServer) error {
for _, u := range users {
if err := stream.Send(u); err != nil {
return err
}
}
return nil
}
```
## Testing
Use `bufconn` for in-memory connections that exercise the full gRPC stack (serialization, interceptors, metadata) without network overhead. Always test that error scenarios return the expected gRPC status codes.
[Testing patterns and examples](references/testing.md)
## Security
- TLS MUST be enabled in production — credentials travel in metadata
- For service-to-service auth, use mTLS or delegate to a service mesh (Istio, Linkerd)
- For user auth, implement `credentials.PerRPCCredentials` and validate tokens in an auth interceptor
- Reflection SHOULD be disabled in production to prevent API discovery
## Performance
| Setting | Purpose | Typical Value |
| --- | --- | --- |
| `keepalive.ServerParameters.Time` | Ping interval for idle connections | 30s |
| `keepalive.ServerParameters.Timeout` | Ping ack timeout | 10s |
| `grpc.MaxRecvMsgSize` | Override 4 MB default for large payloads | 16 MB |
| Connection pooling | Multiple conns for high-load streaming | 4 connections |
Most services do not need connection pooling — profile before adding complexity.
## Common Mistakes
| Mistake | Fix |
| --- | --- |
| Returning raw `error` | Becomes `codes.Unknown` — client can't decide whether to retry. Use `status.Errorf` with a specific code |
| No deadline on client calls | Slow upstream hangs indefinitely. Always `context.WithTimeout` |
| New connection per request | Wastes TCP/TLS handshakes. Create once, reuse — HTTP/2 multiplexes RPCs |
| Reflection enabled in production | Lets attackers enumerate every method. Enable only in dev/staging |
| `codes.Internal` for all errors | Wrong codes break client retry logic. `Unavailable` triggers retry; `InvalidArgument` does not |
| Bare types as RPC arguments | Can't add fields to `string`. Wrapper messages allow backwards-compatible evolution |
| Missing health check service | Kubernetes can't determine readiness, kills pods during deployments |
| Ignoring context cancellation | Long operations continue after caller gave up. Check `ctx.Err()` |
## Cross-References
- → See `samber/cc-skills-golang@golang-context` skill for deadline and cancellation patterns
- → See `samber/cc-skills-golang@golang-error-handling` skill for gRPC error to Go error mapping
- → See `samber/cc-skills-golang@golang-observability` skill for gRPC interceptors (logging, tracing, metrics)
- → See `samber/cc-skills-golang@golang-testing` skill for gRPC testing with bufconn
© samber · MIT · samber/cc-skills-golang