claude_code_sdk/
lib.rs

1//! Claude SDK for Rust
2//! 
3//! Rust SDK for interacting with Claude Code.
4//! 
5//! This SDK provides structured logging through the `tracing` crate.
6//! To enable logging, initialize a tracing subscriber before using the SDK:
7//! 
8//! ```rust,no_run
9//! use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
10//! 
11//! tracing_subscriber::registry()
12//!     .with(tracing_subscriber::EnvFilter::new("claude_code_sdk=debug"))
13//!     .with(tracing_subscriber::fmt::layer())
14//!     .init();
15//! ```
16
17use std::pin::Pin;
18use futures::Stream;
19use tracing::{debug, info, instrument};
20
21pub mod types;
22pub mod errors;
23mod client;
24mod transport;
25
26pub use types::*;
27pub use errors::*;
28
29use client::InternalClient;
30
31/// Query Claude Code.
32/// 
33/// Rust SDK for interacting with Claude Code.
34/// 
35/// # Arguments
36/// 
37/// * `prompt` - The prompt to send to Claude
38/// * `options` - Optional configuration (defaults to ClaudeCodeOptions::default() if None).
39///              Set options.permission_mode to control tool execution:
40///              - `Default`: CLI prompts for dangerous tools  
41///              - `AcceptEdits`: Auto-accept file edits
42///              - `BypassPermissions`: Allow all tools (use with caution)
43///              Set options.cwd for working directory.
44/// 
45/// # Returns
46/// 
47/// A stream of messages from the conversation
48/// 
49/// # Example
50/// 
51/// ```rust,no_run
52/// use claude_code_sdk::{query, ClaudeCodeOptions};
53/// use tokio_stream::StreamExt;
54/// 
55/// #[tokio::main]
56/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
57///     // Simple usage
58///     let mut stream = query("Hello", None).await?;
59///     while let Some(message) = stream.next().await {
60///         println!("{:?}", message);
61///     }
62///     
63///     // With options
64///     let options = ClaudeCodeOptions {
65///         system_prompt: Some("You are helpful".to_string()),
66///         cwd: Some("/home/user".into()),
67///         ..Default::default()
68///     };
69///     
70///     let mut stream = query("Hello", Some(options)).await?;
71///     while let Some(message) = stream.next().await {
72///         println!("{:?}", message);
73///     }
74///     
75///     Ok(())
76/// }
77/// ```
78#[instrument(
79    level = "info",
80    skip(options),
81    fields(
82        prompt_length = prompt.len(),
83        has_options = options.is_some(),
84        system_prompt = options.as_ref().and_then(|o| o.system_prompt.as_deref()),
85        allowed_tools = options.as_ref().map(|o| o.allowed_tools.len()),
86        permission_mode = ?options.as_ref().and_then(|o| o.permission_mode.as_ref()),
87        cwd = ?options.as_ref().and_then(|o| o.cwd.as_ref()),
88    )
89)]
90pub async fn query(
91    prompt: &str,
92    options: Option<ClaudeCodeOptions>,
93) -> Result<Pin<Box<dyn Stream<Item = Message> + Send>>, ClaudeSDKError> {
94    info!("Starting Claude Code query");
95    
96    let options = options.unwrap_or_default();
97    debug!(?options, "Using query options");
98    
99    // Set environment variable
100    std::env::set_var("CLAUDE_CODE_ENTRYPOINT", "sdk-rust");
101    debug!("Set CLAUDE_CODE_ENTRYPOINT environment variable");
102    
103    let client = InternalClient::new();
104    info!("Created internal client");
105    
106    let stream = client.process_query(prompt, options).await?;
107    info!("Successfully created message stream");
108    
109    Ok(Box::pin(stream))
110}
111
112/// Initialize default tracing subscriber for development and testing.
113/// 
114/// This is a convenience function that sets up a basic tracing subscriber
115/// with environment filter support. For production use, you may want to
116/// configure logging more specifically.
117/// 
118/// # Example
119/// 
120/// ```rust,no_run
121/// claude_code_sdk::init_tracing();
122/// ```
123pub fn init_tracing() {
124    use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
125    
126    let env_filter = tracing_subscriber::EnvFilter::try_from_default_env()
127        .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("claude_code_sdk=info"));
128    
129    tracing_subscriber::registry()
130        .with(env_filter)
131        .with(tracing_subscriber::fmt::layer().with_target(true))
132        .init();
133}