Skip to content

Latest commit

 

History

History
143 lines (112 loc) · 7.41 KB

File metadata and controls

143 lines (112 loc) · 7.41 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Overview

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 & Development Commands

# 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

Architecture

.
├── 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:

  1. Query()/Client -> Transport interface -> subprocess.Transport -> Claude CLI
  2. CLI stdout -> parser.Parser -> shared.Message types -> User code
  3. 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.

Code Conventions

  • Idiomatic Go: Use gofmt formatting, standard naming conventions
  • Interface-driven: All message types implement Message, all content blocks implement ContentBlock
  • Error handling: Use fmt.Errorf with %w verb for wrapping, include contextual information
  • Context-first: All blocking functions accept context.Context as first parameter
  • JSON handling: Custom UnmarshalJSON for 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 use XxxError suffix
  • No unnecessary exports: Keep identifiers unexported unless needed by external consumers

Detected Patterns

  • Transport interface: Central abstraction for CLI communication; use MockTransport for tests
  • Process cleanup: SIGTERM -> wait 5 seconds -> SIGKILL pattern
  • Buffer protection: 1MB limit to prevent memory exhaustion
  • Environment variables: Set CLAUDE_CODE_ENTRYPOINT to 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 any to prevent dead code elimination, always call b.ReportAllocs() and b.ResetTimer()
  • tool_use_result metadata: UserMessage.ToolUseResult carries rich edit info (filePath, structuredPatch, diffs); check with HasToolUseResult() before accessing via GetToolUseResult()
  • Init error routing: subprocess.routeInitError() detects error ResultMessage arriving before transport is connected and calls protocol.HandleControlInitErr() to unblock SendControlRequest() via initErrChan

Git Insights

  • Conventional commit messages: feat:, fix:, docs:, test:, refactor:, chore:
  • Issue references in commits: (Issue #N) or (#N), use Closes #N in PR body
  • PR-based workflow with CI checks
  • Recent focus: staticcheck SA5011 fix - add return after t.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.md tracks 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)

Best Practices

  • 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() with return in subtests to prevent staticcheck SA5011 nil pointer dereference warnings (staticcheck does not track that t.Fatal() stops execution)

Custom Notes

Add project-specific notes here. This section is never auto-modified.