# claudecode_rs

A Rust SDK for programmatically interacting with [Claude Code](https://claude.ai/code), providing a type-safe, asynchronous API to launch Claude sessions, send queries, and handle responses in various formats.

## Table of Contents

- [Installation](#installation)
- [Usage](#usage)
  - [Basic Query](#basic-query)
  - [Streaming Events](#streaming-events)
- [Features](#features)
- [Configuration](#configuration)
  - [Session Configuration](#session-configuration)
  - [MCP Configuration](#mcp-configuration)
- [Error Handling](#error-handling)
- [Contributing](#contributing)
- [License](#license)

## Installation

To use `claudecode_rs` in your Rust project, add the following to your `Cargo.toml`:

```toml
[dependencies]
claudecode = "0.1.0"
```

**Note:** If the crate is not yet published on [crates.io](https://crates.io), you can include it via a git repository or local path:

```toml
[dependencies]
claudecode = { git = "https://github.com/AdjectiveAllison/claudecode_rs" }
```

Ensure the Claude CLI is installed and available in your system's PATH. Verify this by running:

```bash
which claude
```

## Usage

### Basic Query

Send a simple query to Claude and print the response:

```rust
use claudecode::{Client, SessionConfig, Model};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new().await?;
    
    let config = SessionConfig::builder("What is the capital of France?")
        .model(Model::Sonnet)
        .build()?;
    
    let result = client.launch_and_wait(config).await?;
    
    if let Some(content) = result.content {
        println!("Claude says: {}", content);
    }
    
    Ok(())
}
```

### Streaming Events

Receive real-time events from Claude using streaming JSON output:

```rust
use claudecode::{Client, SessionConfig, OutputFormat, Event};
use futures::StreamExt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new().await?;
    
    let config = SessionConfig::builder("Tell me a story")
        .output_format(OutputFormat::StreamingJson)
        .build()?;
    
    let mut session = client.launch(config).await?;
    
    if let Some(mut events) = session.take_event_stream() {
        while let Some(event) = events.recv().await {
            match event {
                Event::Assistant(msg) => {
                    for content in &msg.message.content {
                        if let Content::Text { text } = content {
                            print!("{}", text);
                        }
                    }
                }
                Event::Result(result) => {
                    if let Some(cost) = result.total_cost_usd {
                        println!("\nTotal cost: ${:.4}", cost);
                    }
                }
                _ => {}
            }
        }
    }
    
    let result = session.wait().await?;
    Ok(())
}
```

## Features

- **Asynchronous API** using the Tokio runtime for non-blocking operations.
- **Type-safe event handling** with enums for different event types.
- **Multiple output formats**: Text, JSON, and Streaming JSON.
- **Flexible session configuration** including model selection, max turns, and system prompts.
- **Model Context Protocol (MCP) integration** for extended functionality.
- **Automatic resource cleanup** and robust error handling.

## Configuration

### Session Configuration

Use `SessionConfig::builder` to configure Claude sessions:

```rust
let config = SessionConfig::builder("Your query here")
    .model(Model::Opus)
    .output_format(OutputFormat::Json)
    .max_turns(5)
    .verbose(true)
    .build()?;
```

Available options include:
- `model`: `Model::Sonnet`, `Model::Opus`, or `Model::Haiku`
- `output_format`: `OutputFormat::Text`, `OutputFormat::Json`, or `OutputFormat::StreamingJson`
- `max_turns`: Limit interaction turns
- `system_prompt`: Custom system prompt
- `append_system_prompt`: Append to existing system prompt
- `custom_instructions`: Provide custom instructions for the session
- `allowed_tools` / `disallowed_tools`: Control which tools Claude can use
- `verbose`: Enable verbose output

### MCP Configuration

Use `MCPConfig` to configure Model Context Protocol servers:

```rust
use std::collections::HashMap;

let mut servers = HashMap::new();
servers.insert(
    "calculator".to_string(),
    MCPServer {
        command: "npx".to_string(),
        args: vec!["@modelcontextprotocol/server-calculator".to_string()],
        env: None,
    },
);

let mcp_config = MCPConfig {
    mcp_servers: servers,
};

let config = SessionConfig::builder("What is 42 * 17?")
    .mcp_config(mcp_config)
    .build()?;
```

### Session Management

Sessions can be controlled after launching:

```rust
let mut session = client.launch(config).await?;

// Check if session is running
if session.is_running().await {
    // Send interrupt signal (graceful shutdown on Unix)
    session.interrupt().await?;
    
    // Or forcefully kill the process
    session.kill().await?;
}

// Wait for completion
let result = session.wait().await?;
```

## Error Handling

The SDK uses `Result<T, ClaudeError>` for operations that can fail. The `ClaudeResult` type includes an `is_error` flag and an optional `error` message:

```rust
match client.launch_and_wait(config).await {
    Ok(result) => {
        if result.is_error {
            eprintln!("Error: {}", result.error.unwrap_or_default());
        } else {
            println!("Success: {}", result.content.unwrap_or_default());
        }
    }
    Err(e) => eprintln!("SDK Error: {}", e),
}
```

## Contributing

Contributions are welcome! See [CLAUDE.md](CLAUDE.md) for guidelines on building, testing, and contributing to this project.

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.