claude-code-sdk 0.0.1

Rust SDK for Claude Code
Documentation
# Claude Code SDK for Rust

Rust SDK for Claude Code. See the [Claude Code SDK documentation](https://docs.anthropic.com/en/docs/claude-code/sdk) for more information.

## Installation

Add this to your `Cargo.toml`:

```toml
[dependencies]
claude-code-sdk = "0.0.10"
tokio = { version = "1.0", features = ["full"] }
```

**Prerequisites:**
- Rust 1.70+
- Node.js 
- Claude Code: `npm install -g @anthropic-ai/claude-code`

## Quick Start

```rust
use claude_code_sdk::query;
use tokio_stream::StreamExt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Optional: Initialize logging to see detailed SDK operations
    claude_code_sdk::init_tracing();
    
    let mut stream = query("What is 2 + 2?", None).await?;
    
    while let Some(message) = stream.next().await {
        println!("{:?}", message);
    }
    
    Ok(())
}
```

## Usage

### Basic Query

```rust
use claude_code_sdk::{query, ClaudeCodeOptions, Message};
use tokio_stream::StreamExt;

// Simple query
let mut stream = query("Hello Claude", None).await?;
while let Some(message) = stream.next().await {
    match message {
        Message::Assistant(msg) => {
            for block in &msg.content {
                if let ContentBlock::Text(text_block) = block {
                    println!("Claude: {}", text_block.text);
                }
            }
        }
        _ => {}
    }
}

// With options
let options = ClaudeCodeOptions {
    system_prompt: Some("You are a helpful assistant".to_string()),
    max_turns: Some(1),
    ..Default::default()
};

let mut stream = query("Tell me a joke", Some(options)).await?;
while let Some(message) = stream.next().await {
    println!("{:?}", message);
}
```

### Using Tools

```rust
let options = ClaudeCodeOptions {
    allowed_tools: vec!["Read".to_string(), "Write".to_string()],
    permission_mode: Some(PermissionMode::AcceptEdits),
    ..Default::default()
};

let mut stream = query("Create a hello.rs file", Some(options)).await?;
while let Some(message) = stream.next().await {
    // Process tool use and results
}
```

### Working Directory

```rust
use std::path::PathBuf;

let options = ClaudeCodeOptions {
    cwd: Some(PathBuf::from("/path/to/project")),
    ..Default::default()
};
```

## Logging

The Claude Code SDK provides comprehensive structured logging using the [`tracing`](https://tracing.rs/) ecosystem. This helps with debugging, monitoring, and understanding SDK operations.

### Quick Setup

```rust
use claude_code_sdk;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize default logging
    claude_code_sdk::init_tracing();
    
    // Your code here...
    Ok(())
}
```

### Environment Variables

Control logging levels with the `RUST_LOG` environment variable:

```bash
# Show info and above (default)
RUST_LOG=claude_code_sdk=info cargo run

# Show debug messages (recommended for development)
RUST_LOG=claude_code_sdk=debug cargo run

# Show all messages including trace
RUST_LOG=claude_code_sdk=trace cargo run

# Show only errors
RUST_LOG=claude_code_sdk=error cargo run

# Multiple modules
RUST_LOG=claude_code_sdk=debug,tokio=info cargo run
```

### Custom Logging Setup

For more control over logging, set up `tracing-subscriber` directly:

```rust
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};

// JSON structured logging
tracing_subscriber::registry()
    .with(tracing_subscriber::EnvFilter::new("claude_code_sdk=debug"))
    .with(tracing_subscriber::fmt::layer().json())
    .init();

// Custom formatting
tracing_subscriber::registry()
    .with(tracing_subscriber::EnvFilter::new("claude_code_sdk=debug"))
    .with(
        tracing_subscriber::fmt::layer()
            .with_target(true)
            .with_thread_ids(true)
            .with_file(true)
            .with_line_number(true)
            .pretty()
    )
    .init();

// File logging
let file = std::fs::OpenOptions::new()
    .create(true)
    .write(true)
    .truncate(true)
    .open("claude_sdk.log")?;

tracing_subscriber::registry()
    .with(tracing_subscriber::EnvFilter::new("claude_code_sdk=trace"))
    .with(tracing_subscriber::fmt::layer().with_writer(file))
    .init();
```

### What Gets Logged

The SDK logs various operations at different levels:

- **ERROR**: CLI not found, connection failures, JSON decode errors
- **WARN**: Process termination issues, unexpected states
- **INFO**: Query start/completion, connection events, major operations
- **DEBUG**: Message processing, command building, subprocess management
- **TRACE**: Individual message parsing, detailed state changes

### Log Fields

Structured logs include useful fields:

```json
{
  "timestamp": "2024-01-01T12:00:00.000Z",
  "level": "INFO",
  "target": "claude_code_sdk::client",
  "message": "Processing query through transport",
  "fields": {
    "prompt_length": 25,
    "has_options": true,
    "system_prompt": "You are helpful",
    "allowed_tools": 2,
    "permission_mode": "AcceptEdits"
  }
}
```

### Performance Monitoring

Enable performance monitoring with tracing spans:

```rust
use tracing::{info, Instrument};

async fn my_function() -> Result<(), Box<dyn std::error::Error>> {
    let span = tracing::info_span!("my_operation", operation_type = "query");
    
    async move {
        let start = std::time::Instant::now();
        
        // Your Claude SDK operations here
        let mut stream = query("Hello", None).await?;
        // ... process stream
        
        info!(duration_ms = start.elapsed().as_millis(), "Operation completed");
        Ok(())
    }
    .instrument(span)
    .await
}
```

## API Reference

### `query(prompt: &str, options: Option<ClaudeCodeOptions>)`

Main async function for querying Claude.

**Parameters:**
- `prompt`: The prompt to send to Claude
- `options`: Optional configuration

**Returns:** `Result<Pin<Box<dyn Stream<Item = Message>>>, ClaudeSDKError>`

### Types

See [src/types.rs](src/types.rs) for complete type definitions:
- `ClaudeCodeOptions` - Configuration options
- `Message` variants - `Assistant`, `User`, `System`, `Result`
- `ContentBlock` variants - `Text`, `ToolUse`, `ToolResult`

## Error Handling

```rust
use claude_code_sdk::{
    ClaudeSDKError,      // Base error
    CLINotFoundError,    // Claude Code not installed
    CLIConnectionError,  // Connection issues
    ProcessError,        // Process failed
    CLIJSONDecodeError,  // JSON parsing issues
};

match query("Hello", None).await {
    Ok(mut stream) => {
        // Process messages
    }
    Err(ClaudeSDKError::CLINotFound(e)) => {
        println!("Please install Claude Code: {}", e);
    }
    Err(ClaudeSDKError::Process(e)) => {
        println!("Process failed with exit code: {:?}", e.exit_code);
    }
    Err(e) => {
        println!("Error: {}", e);
    }
}
```

## Available Tools

See the [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-code/security#tools-available-to-claude) for a complete list of available tools.

## Examples

- **[examples/quick_start.rs]examples/quick_start.rs** - Complete working example with logging
- **[examples/logging_demo.rs]examples/logging_demo.rs** - Advanced logging configurations

### Running Examples

```bash
# Basic example with default logging
cargo run --example quick_start

# Advanced logging demo with JSON output
cargo run --example logging_demo -- --json

# File logging
cargo run --example logging_demo -- --file logs/claude.log

# Performance monitoring
RUST_LOG=claude_code_sdk=debug cargo run --example logging_demo -- --perf
```

## License

MIT