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