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}