This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Claude Agent SDK for Go - Unofficial Go SDK for Claude Code CLI integration. Provides programmatic interaction through Query() (one-shot) and Client (streaming) APIs with 100% Python SDK parity.
- Module:
github.com/severity1/claude-agent-sdk-go - Package:
claudecode - Go Version: 1.18+
# Build and test
go build ./... # Build all packages
go test ./... # Run all tests
go test -race ./... # Race condition detection
go test -cover ./... # Coverage analysis
make test-cover # Tests with coverage + HTML report
# Specific test patterns
go test -v -run TestClient # Run client tests (verbose)
go test -count=3 -run TestClient # Run tests multiple times for consistency
make bench # Run benchmarks
# Code quality (run before commits)
go fmt ./... # Format code
go vet ./... # Static analysis
golangci-lint run # Comprehensive linting
gocyclo -over 15 . # Cyclomatic complexity check
# Makefile targets (recommended)
make check # Run all checks (fmt, vet, lint, cyclo)
make cyclo # Show complex functions (threshold: 15)
make cyclo-check # Fail if complexity exceeds threshold (CI)
make fmt-check # Verify code formatting
make security # Run security vulnerability checks
make sdk-test # Test SDK as consumer would use it
make release-check # Pre-release validation
make ci # Run full CI pipeline locally.
├── client.go # Client interface and WithClient context manager
├── query.go # Query API (one-shot operations)
├── errors.go # Structured error types
├── transport.go # Transport interface abstraction
├── options.go # Options types and functional options
├── options_bench_test.go # Options performance benchmarks
├── internal/
│ ├── cli/ # CLI discovery and command building
│ ├── control/ # Bidirectional control protocol (hooks, permissions, MCP)
│ ├── parser/ # JSON message parsing with speculative parsing
│ ├── shared/ # Shared types (Message, ContentBlock interfaces)
│ └── subprocess/ # Subprocess management and protocol adapter
├── examples/ # Usage examples (numbered by complexity)
└── docs/
├── architecture/ # Detailed architecture documentation
└── tracking/ # Python SDK parity tracking (PR replay tracker)
Data Flow:
Query()/Client->Transportinterface ->subprocess.Transport-> Claude CLI- CLI stdout ->
parser.Parser->shared.Messagetypes -> User code - Control protocol:
control.Protocol<-> CLI (hooks, permissions, MCP)
Documentation: See ARCHITECTURE.md and CONTRIBUTING.md for comprehensive details on design patterns, interfaces, data flow, and contribution guidelines.
- Idiomatic Go: Use
gofmtformatting, standard naming conventions - Interface-driven: All message types implement
Message, all content blocks implementContentBlock - Error handling: Use
fmt.Errorfwith%wverb for wrapping, include contextual information - Context-first: All blocking functions accept
context.Contextas first parameter - JSON handling: Custom
UnmarshalJSONfor union types, discriminate on"type"field - Cyclomatic complexity: Keep functions under complexity 15 (measured by gocyclo); higher acceptable for table-driven tests, examples, orchestration code
- Naming patterns: Interfaces describe behavior, implementations use concrete names, options use
WithXxx(), errors useXxxErrorsuffix - No unnecessary exports: Keep identifiers unexported unless needed by external consumers
- Transport interface: Central abstraction for CLI communication; use
MockTransportfor tests - Process cleanup: SIGTERM -> wait 5 seconds -> SIGKILL pattern
- Buffer protection: 1MB limit to prevent memory exhaustion
- Environment variables: Set
CLAUDE_CODE_ENTRYPOINTto identify SDK to CLI - Table-driven tests: Use for complex scenarios with multiple test cases
- Functional options:
WithXxx()pattern for configuration - Benchmark tests: Use
var sink anyto prevent dead code elimination, always callb.ReportAllocs()andb.ResetTimer() - tool_use_result metadata:
UserMessage.ToolUseResultcarries rich edit info (filePath, structuredPatch, diffs); check withHasToolUseResult()before accessing viaGetToolUseResult() - Init error routing:
subprocess.routeInitError()detects errorResultMessagearriving before transport is connected and callsprotocol.HandleControlInitErr()to unblockSendControlRequest()viainitErrChan
- Conventional commit messages:
feat:,fix:,docs:,test:,refactor:,chore: - Issue references in commits:
(Issue #N)or(#N), useCloses #Nin PR body - PR-based workflow with CI checks
- Recent focus: staticcheck SA5011 fix - add
returnaftert.Fatal()in subtests to prevent nil pointer dereference warnings; CLI flag ordering fix -BuildCommandWithPrompt()places--print <prompt>after all option flags (Issue #111) - Benchmark organization: Table-driven benchmarks across all core modules (options, parser, shared, control, cli)
- Makefile integration: All code quality checks (fmt, vet, lint, cyclo) unified under
make check - Python SDK parity tracking:
docs/tracking/README.mdtracks all Python SDK PRs to port; organized into 4 chronological phases (Phase 1: Jan 26-Feb 20, Phase 2: Mar 3-Mar 16, Phase 3: Mar 20-Mar 30, Phase 4: Mar 31-Apr 8); last ported features: tool_use_result (Go PR #99), errors field on ResultMessage (Go PR #114, Python PR #749)
- TDD approach: Write failing tests first, implement to make them pass
- Test file organization: Test functions first, then mocks, then helpers
- Helper functions: Always call
t.Helper()in test utilities - Thread safety: All mocks must be thread-safe with proper mutex usage
- Self-contained tests: Each test file has its own helpers to avoid dependencies
- Benchmark organization: Use table-driven benchmarks with realistic scenarios, measure allocations with
b.ReportAllocs() - t.Fatal() + return: Always follow
t.Fatal()withreturnin subtests to prevent staticcheck SA5011 nil pointer dereference warnings (staticcheck does not track that t.Fatal() stops execution)
Add project-specific notes here. This section is never auto-modified.