claudecode

package module
v0.0.0-...-be3af0d Latest Latest
Warning

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

Go to latest
Published: Jun 18, 2025 License: MIT Imports: 10 Imported by: 0

README

Claude Code SDK for Go

Go Reference Go Report Card

A Go SDK for Claude Code that provides programmatic access to Claude's agentic coding capabilities. This SDK wraps the Claude Code CLI and provides a Go-native interface compatible with the TypeScript and Python SDKs.

Features

  • Full CLI Option Support: All Claude Code CLI options are supported
  • TypeScript/Python SDK Compatible API: QueryRequest pattern for consistency across languages
  • True Streaming: Real-time message processing using Go channels
  • Session Management: Resume and continue conversations
  • MCP Support: Model Context Protocol integration
  • Multiple Output Formats: text, json, and stream-json
  • Robust Error Handling: Detailed error types with context
  • Backward Compatibility: Existing APIs continue to work

Prerequisites

  • Go 1.21 or later
  • Claude CLI: npm install -g @anthropic-ai/claude-code
  • Authenticated Claude CLI (run claude to verify)

Installation

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

Quick Start

Basic Usage (TypeScript/Python Compatible API)
package main

import (
    "context"
    "fmt"
    "log"
    
    claudecode "github.com/yukifoo/claude-code-sdk-go"
)

func main() {
    ctx := context.Background()
    
    // Create a request using the TypeScript/Python SDK compatible format
    request := claudecode.QueryRequest{
        Prompt: "Create a simple hello.go file that prints 'Hello, World!'",
        Options: &claudecode.Options{
            MaxTurns:     intPtr(3),
            AllowedTools: []string{"Read", "Write"},
            SystemPrompt: stringPtr("You are a helpful Go programming assistant"),
        },
    }
    
    messages, err := claudecode.QueryWithRequest(ctx, request)
    if err != nil {
        log.Fatalf("Query failed: %v", err)
    }
    
    fmt.Printf("Received %d messages\n", len(messages))
    for _, message := range messages {
        fmt.Printf("Message type: %s\n", message.Type())
        for _, block := range message.Content() {
            if textBlock, ok := block.(*claudecode.TextBlock); ok {
                fmt.Printf("Content: %s\n", textBlock.Text)
            }
        }
    }
}

func intPtr(i int) *int { return &i }
func stringPtr(s string) *string { return &s }
Streaming Usage
package main

import (
    "context"
    "fmt"
    "log"
    
    claudecode "github.com/yukifoo/claude-code-sdk-go"
)

func main() {
    ctx := context.Background()
    
    request := claudecode.QueryRequest{
        Prompt: "Analyze this Go project and suggest improvements",
        Options: &claudecode.Options{
            AllowedTools: []string{"Read", "LS", "Grep"},
            OutputFormat: outputFormatPtr(claudecode.OutputFormatStreamJSON),
            Verbose:      boolPtr(true),
        },
    }
    
    messageChan, errorChan := claudecode.QueryStreamWithRequest(ctx, request)
    
    for {
        select {
        case message, ok := <-messageChan:
            if !ok {
                fmt.Println("Streaming completed")
                return
            }
            
            fmt.Printf("Received %s message\n", message.Type())
            // Process message...
            
        case err := <-errorChan:
            if err != nil {
                log.Fatalf("Streaming error: %v", err)
            }
            
        case <-ctx.Done():
            fmt.Println("Context cancelled")
            return
        }
    }
}

func boolPtr(b bool) *bool { return &b }
func outputFormatPtr(f claudecode.OutputFormat) *claudecode.OutputFormat { return &f }

Configuration Options

The Options struct supports all Claude Code CLI options:

type Options struct {
    // System prompts
    SystemPrompt       *string           // Custom system prompt
    AppendSystemPrompt *string           // Append to default system prompt
    
    // Conversation control
    MaxTurns           *int              // Limit conversation turns
    
    // Tool configuration
    AllowedTools       []string          // Tools Claude can use
    DisallowedTools    []string          // Tools Claude cannot use
    
    // Session management
    Resume             *string           // Resume session by ID
    Continue           *bool             // Continue latest session
    
    // Output and logging
    OutputFormat       *OutputFormat     // text, json, stream-json
    Verbose            *bool             // Enable verbose logging
    
    // MCP (Model Context Protocol)
    MCPConfig          *string           // Path to MCP config JSON
    PermissionPromptTool *string         // MCP tool for permissions
    
    // System
    WorkingDirectory   *string           // Working directory
    Executable         *string           // Custom CLI path
}
Output Formats
// Available output formats
claudecode.OutputFormatText       // Plain text (default for Query)
claudecode.OutputFormatJSON       // Structured JSON
claudecode.OutputFormatStreamJSON // Streaming JSON (default for QueryStream)

Advanced Features

Session Management
// Start a session and get session ID
messages, err := claudecode.QueryWithRequest(ctx, claudecode.QueryRequest{
    Prompt: "Create a function",
    Options: &claudecode.Options{
        OutputFormat: outputFormatPtr(claudecode.OutputFormatJSON),
    },
})

// Extract session ID from result message
var sessionID string
for _, msg := range messages {
    if result, ok := msg.(*claudecode.ResultMessage); ok {
        // Parse session ID from result
        // sessionID = ... 
    }
}

// Resume the session
claudecode.QueryWithRequest(ctx, claudecode.QueryRequest{
    Prompt: "Add tests for that function",
    Options: &claudecode.Options{
        Resume: &sessionID,
    },
})

// Or continue the latest session
claudecode.QueryWithRequest(ctx, claudecode.QueryRequest{
    Prompt: "Optimize the code",
    Options: &claudecode.Options{
        Continue: boolPtr(true),
    },
})
MCP Integration
// mcp-servers.json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path"]
    }
  }
}

// Use MCP tools
request := claudecode.QueryRequest{
    Prompt: "Analyze project files",
    Options: &claudecode.Options{
        MCPConfig:    stringPtr("mcp-servers.json"),
        AllowedTools: []string{"mcp__filesystem__read_file", "mcp__filesystem__list_directory"},
        PermissionPromptTool: stringPtr("mcp__permissions__approve"),
    },
}
Tool Restrictions
options := &claudecode.Options{
    AllowedTools:    []string{"Read", "LS", "Grep"},     // Only these tools
    DisallowedTools: []string{"Bash", "Write"},          // Block these tools
}

API Compatibility

This SDK provides two API styles:

// Single object parameter like TypeScript/Python SDKs
claudecode.QueryWithRequest(ctx, claudecode.QueryRequest{
    Prompt: "...",
    Options: &claudecode.Options{...},
})

claudecode.QueryStreamWithRequest(ctx, claudecode.QueryRequest{
    Prompt: "...",
    Options: &claudecode.Options{...},
})
2. Traditional Go API (Backward Compatible)
// Multiple parameters (original API)
claudecode.Query(ctx, prompt, options)
claudecode.QueryStream(ctx, prompt, options)

Error Handling

The SDK provides detailed error types:

if err != nil {
    switch e := err.(type) {
    case *claudecode.CLINotFoundError:
        fmt.Printf("Claude CLI not found: %v\n", e)
    case *claudecode.ProcessError:
        fmt.Printf("CLI process error (exit %d): %s\n", e.ExitCode, e.Stderr)
    case *claudecode.CLIConnectionError:
        fmt.Printf("Connection error: %v\n", e)
    case *claudecode.CLIJSONDecodeError:
        fmt.Printf("JSON decode error: %v\n", e)
    default:
        fmt.Printf("Unknown error: %v\n", e)
    }
}

Message Types

The SDK handles all Claude Code message types:

for _, message := range messages {
    switch msg := message.(type) {
    case *claudecode.AssistantMessage:
        fmt.Println("Assistant response")
    case *claudecode.UserMessage:
        fmt.Println("User message")
    case *claudecode.SystemMessage:
        fmt.Println("System message")
    case *claudecode.ResultMessage:
        fmt.Println("Final result")
    }
    
    // Process content blocks
    for _, block := range message.Content() {
        switch b := block.(type) {
        case *claudecode.TextBlock:
            fmt.Printf("Text: %s\n", b.Text)
        case *claudecode.ToolUseBlock:
            fmt.Printf("Tool: %s\n", b.Name)
        case *claudecode.ToolResultBlock:
            fmt.Printf("Result: %v\n", b.Content)
        }
    }
}

Examples

See the examples directory for complete working examples:

  • basic/ - Basic usage with both API styles
  • streaming/ - Real-time streaming examples
  • advanced/ - MCP, sessions, and advanced features

Development

Running Tests
# Run all tests
go test -v

# Run tests with coverage
go test -v -cover

# Run only unit tests (skip integration tests)
go test -v -short

# Run specific test
go test -v -run TestOptions
Building
go build
Integration Tests

Integration tests require an authenticated Claude CLI:

# Ensure Claude CLI is working
claude --help

# Run integration tests
go test -v

Implementation Notes

CLI Integration

This SDK communicates with Claude Code by:

  1. Finding the Claude CLI executable (claude command)
  2. Executing it with --print and appropriate flags
  3. Sending prompts via stdin and reading JSON responses from stdout
  4. Parsing streaming JSON messages in real-time
Streaming vs Non-Streaming
  • Query: Reads all messages at once, suitable for simple requests
  • QueryStream: Processes messages in real-time as they arrive
CLI Option Limitations

Some options are only available in --print mode (which this SDK uses):

  • SystemPrompt and AppendSystemPrompt ✅ Available
  • MaxTurns ✅ Available
  • PermissionPromptTool ✅ Available

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass
  5. Submit a pull request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func QueryStream

func QueryStream(ctx context.Context, prompt string, options *Options) (<-chan Message, <-chan error)

QueryStream executes a query against Claude Code and returns a channel of messages This provides true streaming by reading messages in real-time

func QueryStreamWithRequest

func QueryStreamWithRequest(ctx context.Context, request QueryRequest) (<-chan Message, <-chan error)

QueryStreamWithRequest executes a streaming query using the TypeScript/Python SDK compatible request format

Types

type AssistantMessage

type AssistantMessage struct {
	ContentBlocks   []ContentBlock `json:"content"`
	ParentToolUseID *string        `json:"parent_tool_use_id,omitempty"`
	SessionID       string         `json:"session_id"`
	CreatedAt       time.Time      `json:"created_at"`
}

AssistantMessage represents a message from the assistant

func (*AssistantMessage) Content

func (m *AssistantMessage) Content() []ContentBlock

func (*AssistantMessage) Timestamp

func (m *AssistantMessage) Timestamp() time.Time

func (*AssistantMessage) Type

func (m *AssistantMessage) Type() MessageType

type CLIConnectionError

type CLIConnectionError struct {
	Message string
	Cause   error
}

CLIConnectionError is returned when there's an error connecting to the CLI

func (*CLIConnectionError) Error

func (e *CLIConnectionError) Error() string

func (*CLIConnectionError) Unwrap

func (e *CLIConnectionError) Unwrap() error

type CLIJSONDecodeError

type CLIJSONDecodeError struct {
	Data  string
	Cause error
}

CLIJSONDecodeError is returned when JSON from the CLI cannot be decoded

func (*CLIJSONDecodeError) Error

func (e *CLIJSONDecodeError) Error() string

func (*CLIJSONDecodeError) Unwrap

func (e *CLIJSONDecodeError) Unwrap() error

type CLINotFoundError

type CLINotFoundError struct {
	Path string
}

CLINotFoundError is returned when the Claude Code CLI cannot be found

func (*CLINotFoundError) Error

func (e *CLINotFoundError) Error() string

type ClaudeSDKError

type ClaudeSDKError struct {
	Message string
	Cause   error
}

ClaudeSDKError represents a general SDK error

func (*ClaudeSDKError) Error

func (e *ClaudeSDKError) Error() string

func (*ClaudeSDKError) Unwrap

func (e *ClaudeSDKError) Unwrap() error

type ContentBlock

type ContentBlock interface {
	Type() ContentBlockType
}

ContentBlock represents a block of content within a message

type ContentBlockType

type ContentBlockType string

ContentBlockType represents the type of content block

const (
	ContentBlockTypeText       ContentBlockType = "text"
	ContentBlockTypeToolUse    ContentBlockType = "tool_use"
	ContentBlockTypeToolResult ContentBlockType = "tool_result"
)

type MCPServer

type MCPServer struct {
	Name   string `json:"name"`
	Status string `json:"status"`
}

MCPServer represents an MCP server status

type McpServerConfig

type McpServerConfig struct {
	Transport []string               `json:"transport"`
	Env       map[string]interface{} `json:"env,omitempty"`
}

McpServerConfig represents MCP server configuration

type Message

type Message interface {
	Type() MessageType
	Content() []ContentBlock
	Timestamp() time.Time
}

Message represents a message in the conversation

func Query

func Query(ctx context.Context, prompt string, options *Options) ([]Message, error)

Query executes a query against Claude Code and returns the messages

func QueryWithRequest

func QueryWithRequest(ctx context.Context, request QueryRequest) ([]Message, error)

QueryWithRequest executes a query using the TypeScript/Python SDK compatible request format

type MessageType

type MessageType string

MessageType represents the type of message

const (
	MessageTypeAssistant MessageType = "assistant"
	MessageTypeUser      MessageType = "user"
	MessageTypeSystem    MessageType = "system"
	MessageTypeResult    MessageType = "result"
)

type Options

type Options struct {
	// Core behavior options
	// Model specifies the model to use (e.g., 'sonnet', 'opus', or full model name)
	Model *string `json:"model,omitempty"`

	// SystemPrompt sets a custom system prompt to guide Claude's behavior
	SystemPrompt *string `json:"system_prompt,omitempty"`

	// AppendSystemPrompt appends to the default system prompt
	AppendSystemPrompt *string `json:"append_system_prompt,omitempty"`

	// MaxTurns limits the number of conversation turns
	MaxTurns *int `json:"max_turns,omitempty"`

	// Session management
	// Continue indicates whether to continue the latest session
	Continue *bool `json:"continue,omitempty"`

	// Resume specifies a session ID to resume
	Resume *string `json:"resume,omitempty"`

	// Tool configuration
	// AllowedTools specifies which tools Claude can use (comma or space-separated)
	AllowedTools []string `json:"allowed_tools,omitempty"`

	// DisallowedTools specifies which tools Claude cannot use (comma or space-separated)
	DisallowedTools []string `json:"disallowed_tools,omitempty"`

	// MCP (Model Context Protocol) configuration
	// MCPTools specifies MCP tools to use
	MCPTools []string `json:"mcp_tools,omitempty"`

	// MCPServers specifies MCP server configurations
	MCPServers map[string]McpServerConfig `json:"mcp_servers,omitempty"`

	// MCPConfig specifies the path to MCP server configuration JSON file or JSON string
	MCPConfig *string `json:"mcp_config,omitempty"`

	// Permission and security
	// PermissionMode defines the interaction permission level
	// Options: "default", "acceptEdits", "bypassPermissions", "plan"
	PermissionMode *string `json:"permission_mode,omitempty"`

	// PermissionPromptTool specifies the MCP tool to use for permission prompts
	PermissionPromptTool *string `json:"permission_prompt_tool,omitempty"`

	// DangerouslySkipPermissions bypasses all permission checks
	// Recommended only for sandboxes with no internet access
	DangerouslySkipPermissions *bool `json:"dangerously_skip_permissions,omitempty"`

	// Directory and environment
	// Cwd sets the working directory for Claude Code
	Cwd *string `json:"cwd,omitempty"`

	// AddDir specifies additional directories to allow tool access to
	AddDir []string `json:"add_dir,omitempty"`

	// I/O format options
	// InputFormat specifies the input format: "text" (default) or "stream-json"
	InputFormat *string `json:"input_format,omitempty"`

	// OutputFormat specifies the output format: "text", "json", or "stream-json"
	OutputFormat *OutputFormat `json:"output_format,omitempty"`

	// Debug and logging
	// Debug enables debug mode (shows MCP server errors)
	Debug *bool `json:"debug,omitempty"`

	// Verbose enables verbose logging (automatically enabled for stream-json output)
	Verbose *bool `json:"verbose,omitempty"`

	// SDK-specific options
	// AbortController allows cancellation of the query (Go context handles this)
	// This field is not used directly but kept for API compatibility
	AbortController interface{} `json:"abort_controller,omitempty"`

	// Executable specifies a custom path to the Claude Code CLI
	Executable *string `json:"executable,omitempty"`
}

Options represents configuration options for Claude Code queries

type OutputFormat

type OutputFormat string

OutputFormat represents the output format for Claude Code queries

const (
	OutputFormatText       OutputFormat = "text"
	OutputFormatJSON       OutputFormat = "json"
	OutputFormatStreamJSON OutputFormat = "stream-json"
)

type ProcessError

type ProcessError struct {
	ExitCode int
	Stderr   string
	Stdout   string
}

ProcessError is returned when the CLI process encounters an error

func (*ProcessError) Error

func (e *ProcessError) Error() string

type QueryRequest

type QueryRequest struct {
	// Prompt is the query to send to Claude Code
	Prompt string `json:"prompt"`

	// Options contains configuration options for the query
	Options *Options `json:"options,omitempty"`
}

QueryRequest represents a query request compatible with TypeScript/Python SDKs

type ResultMessage

type ResultMessage struct {
	Subtype       string    `json:"subtype"`
	DurationMs    int       `json:"duration_ms"`
	DurationAPIMs int       `json:"duration_api_ms"`
	IsError       bool      `json:"is_error"`
	NumTurns      int       `json:"num_turns"`
	SessionID     string    `json:"session_id"`
	TotalCostUSD  *float64  `json:"total_cost_usd,omitempty"`
	Usage         *Usage    `json:"usage,omitempty"`
	Result        *string   `json:"result,omitempty"`
	CreatedAt     time.Time `json:"created_at"`
}

ResultMessage represents a result message

func (*ResultMessage) Content

func (m *ResultMessage) Content() []ContentBlock

func (*ResultMessage) Timestamp

func (m *ResultMessage) Timestamp() time.Time

func (*ResultMessage) Type

func (m *ResultMessage) Type() MessageType

type SystemMessage

type SystemMessage struct {
	Subtype        string      `json:"subtype"`
	APIKeySource   *string     `json:"apiKeySource,omitempty"`
	Cwd            *string     `json:"cwd,omitempty"`
	SessionID      string      `json:"session_id"`
	Tools          []string    `json:"tools,omitempty"`
	MCPServers     []MCPServer `json:"mcp_servers,omitempty"`
	Model          *string     `json:"model,omitempty"`
	PermissionMode *string     `json:"permissionMode,omitempty"`
	CreatedAt      time.Time   `json:"created_at"`
}

SystemMessage represents a system message

func (*SystemMessage) Content

func (m *SystemMessage) Content() []ContentBlock

func (*SystemMessage) Timestamp

func (m *SystemMessage) Timestamp() time.Time

func (*SystemMessage) Type

func (m *SystemMessage) Type() MessageType

type TextBlock

type TextBlock struct {
	Text string `json:"text"`
}

TextBlock represents a text content block

func (*TextBlock) Type

func (t *TextBlock) Type() ContentBlockType

type ToolResultBlock

type ToolResultBlock struct {
	ToolUseID string      `json:"tool_use_id"`
	Content   interface{} `json:"content"`
	IsError   bool        `json:"is_error,omitempty"`
}

ToolResultBlock represents a tool result content block

func (*ToolResultBlock) Type

type ToolUseBlock

type ToolUseBlock struct {
	ID    string                 `json:"id"`
	Name  string                 `json:"name"`
	Input map[string]interface{} `json:"input"`
}

ToolUseBlock represents a tool use content block

func (*ToolUseBlock) Type

func (t *ToolUseBlock) Type() ContentBlockType

type Usage

type Usage struct {
	InputTokens  int `json:"input_tokens"`
	OutputTokens int `json:"output_tokens"`
}

Usage represents API usage information

type UserMessage

type UserMessage struct {
	ContentBlocks   []ContentBlock `json:"content"`
	ParentToolUseID *string        `json:"parent_tool_use_id,omitempty"`
	SessionID       string         `json:"session_id"`
	CreatedAt       time.Time      `json:"created_at"`
}

UserMessage represents a message from the user

func (*UserMessage) Content

func (m *UserMessage) Content() []ContentBlock

func (*UserMessage) Timestamp

func (m *UserMessage) Timestamp() time.Time

func (*UserMessage) Type

func (m *UserMessage) Type() MessageType

Jump to

Keyboard shortcuts

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