claudecode

package module
v0.2.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 20, 2025 License: MIT Imports: 8 Imported by: 0

README

Claude Code SDK for Go

Go Gopher

CI Go Reference Go Report Card codecov

Unofficial Go SDK for Claude Code CLI integration. Build production-ready applications that leverage Claude's advanced code understanding, secure file operations, and external tool integrations through a clean, idiomatic Go API with comprehensive error handling and automatic resource management.

🚀 Two powerful APIs for different use cases:

  • Query API: One-shot operations, automation, CI/CD integration
  • Client API: Interactive conversations, multi-turn workflows, streaming responses
  • WithClient: Go-idiomatic context manager for automatic resource management

Claude Code SDK in Action

Installation

go get github.com/severity1/claude-code-sdk-go

Prerequisites: Go 1.18+, Node.js, Claude Code (npm install -g @anthropic-ai/claude-code)

Key Features

Two APIs for different needs - Query for automation, Client for interaction 100% Python SDK compatibility - Same functionality, Go-native design Automatic resource management - WithClient provides Go-idiomatic context manager pattern Session management - Isolated conversation contexts with Query() and QueryWithSession() Built-in tool integration - File operations, AWS, GitHub, databases, and more Production ready - Comprehensive error handling, timeouts, resource cleanup Security focused - Granular tool permissions and access controls Context-aware - Maintain conversation state across multiple interactions

Usage

Query API - One-Shot Operations

Best for automation, scripting, and tasks with clear completion criteria:

package main

import (
    "context"
    "errors"
    "fmt"
    "log"

    "github.com/severity1/claude-code-sdk-go"
)

func main() {
    fmt.Println("Claude Code SDK - Query API Example")
    fmt.Println("Asking: What is 2+2?")

    ctx := context.Background()

    // Create and execute query
    iterator, err := claudecode.Query(ctx, "What is 2+2?")
    if err != nil {
        log.Fatalf("Query failed: %v", err)
    }
    defer iterator.Close()

    fmt.Println("\nResponse:")

    // Iterate through messages
    for {
        message, err := iterator.Next(ctx)
        if err != nil {
            if errors.Is(err, claudecode.ErrNoMoreMessages) {
                break
            }
            log.Fatalf("Failed to get message: %v", err)
        }

        if message == nil {
            break
        }

        // Handle different message types
        switch msg := message.(type) {
        case *claudecode.AssistantMessage:
            for _, block := range msg.Content {
                if textBlock, ok := block.(*claudecode.TextBlock); ok {
                    fmt.Print(textBlock.Text)
                }
            }
        case *claudecode.ResultMessage:
            if msg.IsError {
                log.Printf("Error: %s", msg.Result)
            }
        }
    }

    fmt.Println("\nQuery completed!")
}
Client API - Interactive & Multi-Turn

WithClient provides automatic resource management (equivalent to Python's async with):

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/severity1/claude-code-sdk-go"
)

func main() {
    fmt.Println("Claude Code SDK - Client Streaming Example")
    fmt.Println("Asking: Explain Go goroutines with a simple example")

    ctx := context.Background()
    question := "Explain what Go goroutines are and show a simple example"

    // WithClient handles connection lifecycle automatically
    err := claudecode.WithClient(ctx, func(client claudecode.Client) error {
        fmt.Println("\nConnected! Streaming response:")

        // Simple query uses default session
        if err := client.Query(ctx, question); err != nil {
            return fmt.Errorf("query failed: %w", err)
        }

        // Stream messages in real-time
        msgChan := client.ReceiveMessages(ctx)
        for {
            select {
            case message := <-msgChan:
                if message == nil {
                    return nil // Stream ended
                }

                switch msg := message.(type) {
                case *claudecode.AssistantMessage:
                    // Print streaming text as it arrives
                    for _, block := range msg.Content {
                        if textBlock, ok := block.(*claudecode.TextBlock); ok {
                            fmt.Print(textBlock.Text)
                        }
                    }
                case *claudecode.ResultMessage:
                    if msg.IsError {
                        return fmt.Errorf("error: %s", msg.Result)
                    }
                    return nil // Success, stream complete
                }
            case <-ctx.Done():
                return ctx.Err()
            }
        }
    })

    if err != nil {
        log.Fatalf("Streaming failed: %v", err)
    }

    fmt.Println("\n\nStreaming completed!")
}
Session Management

Maintain conversation context across multiple queries with session management:

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/severity1/claude-code-sdk-go"
)

func main() {
    fmt.Println("Claude Code SDK - Session Management Example")

    ctx := context.Background()

    err := claudecode.WithClient(ctx, func(client claudecode.Client) error {
        fmt.Println("\nDemonstrating isolated sessions:")

        // Session A: Math conversation
        sessionA := "math-session"
        if err := client.QueryWithSession(ctx, "Remember this: x = 5", sessionA); err != nil {
            return err
        }

        // Session B: Programming conversation
        sessionB := "programming-session"
        if err := client.QueryWithSession(ctx, "Remember this: language = Go", sessionB); err != nil {
            return err
        }

        // Query each session - they maintain separate contexts
        fmt.Println("\nQuerying math session:")
        if err := client.QueryWithSession(ctx, "What is x * 2?", sessionA); err != nil {
            return err
        }

        fmt.Println("\nQuerying programming session:")
        if err := client.QueryWithSession(ctx, "What language did I mention?", sessionB); err != nil {
            return err
        }

        // Default session query (separate from above)
        fmt.Println("\nDefault session (no context from above):")
        return client.Query(ctx, "What did I just ask about?") // Won't know about x or Go
    })

    if err != nil {
        log.Fatalf("Session demo failed: %v", err)
    }

    fmt.Println("Session management demo completed!")
}

Traditional Client API (still supported):

Click to see manual resource management approach
func traditionalClientExample() {
    ctx := context.Background()
    
    client := claudecode.NewClient()
    if err := client.Connect(ctx); err != nil {
        log.Fatalf("Failed to connect: %v", err)
    }
    defer client.Disconnect() // Manual cleanup required
    
    // Use client...
}

Tool Integration & External Services

Integrate with file systems, cloud services, databases, and development tools:

Core Tools (built-in file operations):

// File analysis and documentation generation
claudecode.Query(ctx, "Read all Go files and create API documentation",
    claudecode.WithAllowedTools("Read", "Write"))

MCP Tools (external service integrations):

// AWS infrastructure automation
claudecode.Query(ctx, "List my S3 buckets and analyze their security settings", 
    claudecode.WithAllowedTools("mcp__aws-api-mcp__call_aws", "mcp__aws-api-mcp__suggest_aws_commands", "Write"))

When to Use Which API

🎯 Use Query API when you:

  • Need one-shot automation or scripting
  • Have clear task completion criteria
  • Want automatic resource cleanup
  • Are building CI/CD integrations
  • Prefer simple, stateless operations

🔄 Use Client API (WithClient) when you:

  • Need interactive conversations
  • Want to build context across multiple requests
  • Are creating complex, multi-step workflows
  • Need real-time streaming responses
  • Want to iterate and refine based on previous results
  • Need automatic resource management (recommended)

Examples & Documentation

Comprehensive examples covering every use case:

Learning Path (Easiest → Hardest):

Tool Integration:

Advanced Patterns:

📖 Full Documentation with usage patterns, security best practices, and troubleshooting.

License

MIT

Documentation

Overview

Package claudecode provides the Claude Code SDK for Go.

This SDK enables programmatic interaction with Claude Code CLI through two main APIs: - Query() for one-shot requests with automatic cleanup - Client for bidirectional streaming conversations

The SDK follows Go-native patterns with goroutines and channels instead of async/await, providing context-first design for cancellation and timeouts.

Example usage:

import "github.com/jrpospos/claude-code-sdk-go"

// One-shot query
messages, err := claudecode.Query(ctx, "Hello, Claude!")
if err != nil {
	log.Fatal(err)
}

// Streaming client
client := claudecode.NewClient(
	claudecode.WithSystemPrompt("You are a helpful assistant"),
)
defer client.Close()

The SDK provides 100% feature parity with the Python SDK while embracing Go idioms and patterns.

Index

Constants

View Source
const (
	PermissionModeDefault           = shared.PermissionModeDefault
	PermissionModeAcceptEdits       = shared.PermissionModeAcceptEdits
	PermissionModePlan              = shared.PermissionModePlan
	PermissionModeBypassPermissions = shared.PermissionModeBypassPermissions
	McpServerTypeStdio              = shared.McpServerTypeStdio
	McpServerTypeSSE                = shared.McpServerTypeSSE
	McpServerTypeHTTP               = shared.McpServerTypeHTTP
)

Re-export constants

View Source
const (
	MessageTypeUser      = shared.MessageTypeUser
	MessageTypeAssistant = shared.MessageTypeAssistant
	MessageTypeSystem    = shared.MessageTypeSystem
	MessageTypeResult    = shared.MessageTypeResult
)

Re-export message type constants

View Source
const (
	ContentBlockTypeText       = shared.ContentBlockTypeText
	ContentBlockTypeThinking   = shared.ContentBlockTypeThinking
	ContentBlockTypeToolUse    = shared.ContentBlockTypeToolUse
	ContentBlockTypeToolResult = shared.ContentBlockTypeToolResult
)

Re-export content block type constants

View Source
const Version = "0.1.0"

Version represents the current version of the Claude Code SDK for Go.

Variables

View Source
var ErrNoMoreMessages = errors.New("no more messages")

ErrNoMoreMessages indicates the message iterator has no more messages.

View Source
var NewCLINotFoundError = shared.NewCLINotFoundError

NewCLINotFoundError creates a new CLI not found error.

View Source
var NewConnectionError = shared.NewConnectionError

NewConnectionError creates a new connection error.

View Source
var NewJSONDecodeError = shared.NewJSONDecodeError

NewJSONDecodeError creates a new JSON decode error.

View Source
var NewMessageParseError = shared.NewMessageParseError

NewMessageParseError creates a new message parse error.

View Source
var NewProcessError = shared.NewProcessError

NewProcessError creates a new process error.

Functions

func WithClient

func WithClient(ctx context.Context, fn func(Client) error, opts ...Option) error

WithClient provides Go-idiomatic resource management equivalent to Python SDK's async context manager. It automatically connects to Claude Code CLI, executes the provided function, and ensures proper cleanup. This eliminates the need for manual Connect/Disconnect calls and prevents resource leaks.

The function follows Go's established resource management patterns using defer for guaranteed cleanup, similar to how database connections, files, and other resources are typically managed in Go.

Example - Basic usage:

err := claudecode.WithClient(ctx, func(client claudecode.Client) error {
    return client.Query(ctx, "What is 2+2?")
})
if err != nil {
    log.Fatal(err)
}

Example - With configuration options:

err := claudecode.WithClient(ctx, func(client claudecode.Client) error {
    if err := client.Query(ctx, "Calculate the area of a circle with radius 5"); err != nil {
        return err
    }

    // Process responses
    for msg := range client.ReceiveMessages(ctx) {
        if assistantMsg, ok := msg.(*claudecode.AssistantMessage); ok {
            fmt.Println("Claude:", assistantMsg.Content[0].(*claudecode.TextBlock).Text)
        }
    }
    return nil
}, claudecode.WithSystemPrompt("You are a helpful math tutor"),
   claudecode.WithAllowedTools("Read", "Write"))

The client will be automatically connected before fn is called and disconnected after fn returns, even if fn returns an error or panics. This provides 100% functional parity with Python SDK's 'async with ClaudeSDKClient()' pattern while using idiomatic Go resource management.

Parameters:

  • ctx: Context for connection management and cancellation
  • fn: Function to execute with the connected client
  • opts: Optional client configuration options

Returns an error if connection fails or if fn returns an error. Disconnect errors are handled gracefully without overriding the original error from fn.

func WithClientTransport

func WithClientTransport(ctx context.Context, transport Transport, fn func(Client) error, opts ...Option) error

WithClientTransport provides Go-idiomatic resource management with a custom transport for testing. This is the testing-friendly version of WithClient that accepts an explicit transport parameter.

Usage in tests:

transport := newClientMockTransport()
err := WithClientTransport(ctx, transport, func(client claudecode.Client) error {
    return client.Query(ctx, "What is 2+2?")
}, opts...)

Parameters:

  • ctx: Context for connection management and cancellation
  • transport: Custom transport to use (typically a mock for testing)
  • fn: Function to execute with the connected client
  • opts: Optional client configuration options

Returns an error if connection fails or if fn returns an error. Disconnect errors are handled gracefully without overriding the original error from fn.

Types

type AssistantMessage

type AssistantMessage = shared.AssistantMessage

AssistantMessage represents a message from the assistant.

type BaseError

type BaseError = shared.BaseError

BaseError provides common error functionality across the SDK.

type CLINotFoundError

type CLINotFoundError = shared.CLINotFoundError

CLINotFoundError indicates that the Claude Code CLI was not found.

type Client

type Client interface {
	Connect(ctx context.Context, prompt ...StreamMessage) error
	Disconnect() error
	Query(ctx context.Context, prompt string) error
	QueryWithSession(ctx context.Context, prompt string, sessionID string) error
	QueryStream(ctx context.Context, messages <-chan StreamMessage) error
	ReceiveMessages(ctx context.Context) <-chan Message
	ReceiveResponse(ctx context.Context) MessageIterator
	Interrupt(ctx context.Context) error
}

Client provides bidirectional streaming communication with Claude Code CLI.

func NewClient

func NewClient(opts ...Option) Client

NewClient creates a new Client with the given options.

func NewClientWithTransport

func NewClientWithTransport(transport Transport, opts ...Option) Client

NewClientWithTransport creates a new Client with a custom transport (for testing).

type ClientImpl

type ClientImpl struct {
	// contains filtered or unexported fields
}

ClientImpl implements the Client interface.

func (*ClientImpl) Connect

func (c *ClientImpl) Connect(ctx context.Context, _ ...StreamMessage) error

Connect establishes a connection to the Claude Code CLI.

func (*ClientImpl) Disconnect

func (c *ClientImpl) Disconnect() error

Disconnect closes the connection to the Claude Code CLI.

func (*ClientImpl) Interrupt

func (c *ClientImpl) Interrupt(ctx context.Context) error

Interrupt sends an interrupt signal to stop the current operation.

func (*ClientImpl) Query

func (c *ClientImpl) Query(ctx context.Context, prompt string) error

Query sends a simple text query using the default session. This is equivalent to QueryWithSession(ctx, prompt, "default").

Example:

client.Query(ctx, "What is Go?")

func (*ClientImpl) QueryStream

func (c *ClientImpl) QueryStream(ctx context.Context, messages <-chan StreamMessage) error

QueryStream sends a stream of messages.

func (*ClientImpl) QueryWithSession added in v0.2.4

func (c *ClientImpl) QueryWithSession(ctx context.Context, prompt string, sessionID string) error

QueryWithSession sends a simple text query using the specified session ID. Each session maintains its own conversation context, allowing for isolated conversations within the same client connection.

If sessionID is empty, it defaults to "default".

Example:

client.QueryWithSession(ctx, "Remember this", "my-session")
client.QueryWithSession(ctx, "What did I just say?", "my-session") // Remembers context
client.Query(ctx, "What did I just say?")                          // Won't remember, different session

func (*ClientImpl) ReceiveMessages

func (c *ClientImpl) ReceiveMessages(_ context.Context) <-chan Message

ReceiveMessages returns a channel of incoming messages.

func (*ClientImpl) ReceiveResponse

func (c *ClientImpl) ReceiveResponse(_ context.Context) MessageIterator

ReceiveResponse returns an iterator for the response messages.

type ConnectionError

type ConnectionError = shared.ConnectionError

ConnectionError represents errors that occur during CLI connection.

type ContentBlock

type ContentBlock = shared.ContentBlock

ContentBlock represents a content block within a message.

type JSONDecodeError

type JSONDecodeError = shared.JSONDecodeError

JSONDecodeError represents JSON parsing errors from CLI responses.

type McpHTTPServerConfig

type McpHTTPServerConfig = shared.McpHTTPServerConfig

McpHTTPServerConfig represents an HTTP MCP server configuration.

type McpSSEServerConfig

type McpSSEServerConfig = shared.McpSSEServerConfig

McpSSEServerConfig represents an SSE MCP server configuration.

type McpServerConfig

type McpServerConfig = shared.McpServerConfig

McpServerConfig represents an MCP server configuration.

type McpServerType

type McpServerType = shared.McpServerType

McpServerType defines the type of MCP server.

type McpStdioServerConfig

type McpStdioServerConfig = shared.McpStdioServerConfig

McpStdioServerConfig represents a stdio MCP server configuration.

type Message

type Message = shared.Message

Message represents any message type in the conversation.

type MessageIterator

type MessageIterator = shared.MessageIterator

MessageIterator provides iteration over messages.

func Query

func Query(ctx context.Context, prompt string, opts ...Option) (MessageIterator, error)

Query executes a one-shot query with automatic cleanup. This follows the Python SDK pattern but uses dependency injection for transport.

func QueryWithTransport

func QueryWithTransport(
	ctx context.Context,
	prompt string,
	transport Transport,
	opts ...Option,
) (MessageIterator, error)

QueryWithTransport executes a query with a custom transport. The transport parameter is required and must not be nil.

type MessageParseError

type MessageParseError = shared.MessageParseError

MessageParseError represents errors parsing message content.

type Option

type Option func(*Options)

Option configures Options using the functional options pattern.

func WithAddDirs

func WithAddDirs(dirs ...string) Option

WithAddDirs adds directories to the context.

func WithAllowedTools

func WithAllowedTools(tools ...string) Option

WithAllowedTools sets the allowed tools list.

func WithAppendSystemPrompt

func WithAppendSystemPrompt(prompt string) Option

WithAppendSystemPrompt sets the append system prompt.

func WithCLIPath

func WithCLIPath(path string) Option

WithCLIPath sets a custom CLI path.

func WithContinueConversation

func WithContinueConversation(continueConversation bool) Option

WithContinueConversation enables conversation continuation.

func WithCwd

func WithCwd(cwd string) Option

WithCwd sets the working directory.

func WithDisallowedTools

func WithDisallowedTools(tools ...string) Option

WithDisallowedTools sets the disallowed tools list.

func WithExtraArgs

func WithExtraArgs(args map[string]*string) Option

WithExtraArgs sets arbitrary CLI flags via ExtraArgs.

func WithMaxThinkingTokens

func WithMaxThinkingTokens(tokens int) Option

WithMaxThinkingTokens sets the maximum thinking tokens.

func WithMaxTurns

func WithMaxTurns(turns int) Option

WithMaxTurns sets the maximum number of conversation turns.

func WithMcpServers

func WithMcpServers(servers map[string]McpServerConfig) Option

WithMcpServers sets the MCP server configurations.

func WithModel

func WithModel(model string) Option

WithModel sets the model to use.

func WithPermissionMode

func WithPermissionMode(mode PermissionMode) Option

WithPermissionMode sets the permission mode.

func WithPermissionPromptToolName

func WithPermissionPromptToolName(toolName string) Option

WithPermissionPromptToolName sets the permission prompt tool name.

func WithResume

func WithResume(sessionID string) Option

WithResume sets the session ID to resume.

func WithSettings

func WithSettings(settings string) Option

WithSettings sets the settings file path or JSON string.

func WithSystemPrompt

func WithSystemPrompt(prompt string) Option

WithSystemPrompt sets the system prompt.

func WithTransport

func WithTransport(_ Transport) Option

WithTransport sets a custom transport for testing. Since Transport is not part of Options struct, this is handled in client creation.

type Options

type Options = shared.Options

Options contains configuration for Claude Code CLI interactions.

func NewOptions

func NewOptions(opts ...Option) *Options

NewOptions creates Options with default values using functional options pattern.

type PermissionMode

type PermissionMode = shared.PermissionMode

PermissionMode defines the permission handling mode.

type ProcessError

type ProcessError = shared.ProcessError

ProcessError represents errors from the CLI process execution.

type ResultMessage

type ResultMessage = shared.ResultMessage

ResultMessage represents a result or status message.

type SDKError

type SDKError = shared.SDKError

SDKError represents the base interface for all SDK errors.

type StreamMessage

type StreamMessage = shared.StreamMessage

StreamMessage represents a message in the streaming protocol.

type SystemMessage

type SystemMessage = shared.SystemMessage

SystemMessage represents a system prompt message.

type TextBlock

type TextBlock = shared.TextBlock

TextBlock represents a text content block.

type ThinkingBlock

type ThinkingBlock = shared.ThinkingBlock

ThinkingBlock represents a thinking content block.

type ToolResultBlock

type ToolResultBlock = shared.ToolResultBlock

ToolResultBlock represents a tool result content block.

type ToolUseBlock

type ToolUseBlock = shared.ToolUseBlock

ToolUseBlock represents a tool usage content block.

type Transport

type Transport interface {
	Connect(ctx context.Context) error
	SendMessage(ctx context.Context, message StreamMessage) error
	ReceiveMessages(ctx context.Context) (<-chan Message, <-chan error)
	Interrupt(ctx context.Context) error
	Close() error
}

Transport abstracts the communication layer with Claude Code CLI. This interface stays in main package because it's used by client code.

type UserMessage

type UserMessage = shared.UserMessage

UserMessage represents a message from the user.

Directories

Path Synopsis
internal
cli
Package cli provides CLI discovery and command building functionality.
Package cli provides CLI discovery and command building functionality.
parser
Package parser provides JSON message parsing functionality with speculative parsing and buffer management.
Package parser provides JSON message parsing functionality with speculative parsing and buffer management.
shared
Package shared provides shared types and interfaces used across internal packages.
Package shared provides shared types and interfaces used across internal packages.
subprocess
Package subprocess provides the subprocess transport implementation for Claude Code CLI.
Package subprocess provides the subprocess transport implementation for Claude Code CLI.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL