claude-code-client-sdk 0.1.46

Rust SDK for integrating Claude Code as a subprocess with typed APIs
Documentation
//! Convenience function for one-off Claude Code queries.
//!
//! This module provides the [`query()`] function, which is the simplest way to
//! send a prompt to Claude Code and receive all response messages. Each call
//! creates a new session, sends the prompt, collects all messages, and closes
//! the connection automatically.
//!
//! For multi-turn conversations, use [`ClaudeSdkClient`](crate::ClaudeSdkClient) instead.

use crate::client::InputPrompt;
use crate::errors::Result;
use crate::internal_client::InternalClient;
use crate::transport::Transport;
use crate::types::{ClaudeAgentOptions, Message};
use futures::Stream;
use futures::stream::BoxStream;
use serde_json::Value;

/// Sends a one-off query to Claude Code and returns all response messages.
///
/// This is the simplest entry point for interacting with Claude Code. It handles
/// the full lifecycle: connecting, initializing, sending the prompt, collecting
/// all messages, and disconnecting.
///
/// # Arguments
///
/// * `prompt` — The input prompt (text or structured messages).
/// * `options` — Optional [`ClaudeAgentOptions`] for configuration. Defaults to
///   [`ClaudeAgentOptions::default()`] if `None`.
/// * `transport` — Optional custom [`Transport`] implementation. If `None`,
///   the default [`SubprocessCliTransport`](crate::SubprocessCliTransport) is used.
///
/// # Returns
///
/// A `Vec<Message>` containing all messages from the interaction, including
/// user echoes, assistant responses, system messages, and the final result.
///
/// # Example
///
/// ```rust,no_run
/// # use claude_code::{query, ClaudeAgentOptions, InputPrompt, Message, PermissionMode};
/// # async fn example() -> claude_code::Result<()> {
///     let messages = query(
///     InputPrompt::Text("Explain Rust ownership".to_string()),
///     Some(ClaudeAgentOptions {
///         permission_mode: Some(PermissionMode::BypassPermissions),
///         max_turns: Some(1),
///         ..Default::default()
///     }),
///     None,
///     ).await?;
///
///     for msg in &messages {
///     if let Message::Result(result) = msg {
///         println!("Cost: ${:.4}", result.total_cost_usd.unwrap_or(0.0));
///     }
///     }
/// # Ok(())
/// # }
/// ```
pub async fn query(
    prompt: InputPrompt,
    options: Option<ClaudeAgentOptions>,
    transport: Option<Box<dyn Transport>>,
) -> Result<Vec<Message>> {
    let options = options.unwrap_or_default();
    let client = InternalClient::new();
    client.process_query(prompt, options, transport).await
}

/// Sends a one-off query using streamed JSON input messages.
///
/// This is a Rust-idiomatic equivalent of Python's `AsyncIterable` prompt mode.
///
/// # Example
///
/// ```rust,no_run
/// use claude_code::{query_from_stream, ClaudeAgentOptions};
/// use futures::stream;
/// use serde_json::json;
///
/// # async fn example() -> claude_code::Result<()> {
///     let messages = query_from_stream(
///     stream::iter(vec![json!({"type":"user","message":{"role":"user","content":"hello"}})]),
///     Some(ClaudeAgentOptions::default()),
///     None,
///     )
///     .await?;
///
///     assert!(!messages.is_empty());
/// # Ok(())
/// # }
/// ```
pub async fn query_from_stream<S>(
    prompt: S,
    options: Option<ClaudeAgentOptions>,
    transport: Option<Box<dyn Transport>>,
) -> Result<Vec<Message>>
where
    S: Stream<Item = Value> + Unpin,
{
    let options = options.unwrap_or_default();
    let client = InternalClient::new();
    client
        .process_query_from_stream(prompt, options, transport)
        .await
}

/// Sends a one-off query and returns responses as a stream.
///
/// The returned stream yields parsed [`Message`] values as they arrive.
///
/// The stream is `Send` and can be consumed from any tokio task.
///
/// # Example
///
/// ```rust,no_run
/// use claude_code::{query_stream, InputPrompt};
/// use futures::StreamExt;
///
/// # async fn example() -> claude_code::Result<()> {
///     let mut stream = query_stream(
///     InputPrompt::Text("Summarize Rust ownership".to_string()),
///     None,
///     None,
///     )
///     .await?;
///
///     let _ = stream.next().await;
/// # Ok(())
/// # }
/// ```
pub async fn query_stream(
    prompt: InputPrompt,
    options: Option<ClaudeAgentOptions>,
    transport: Option<Box<dyn Transport>>,
) -> Result<BoxStream<'static, Result<Message>>> {
    let options = options.unwrap_or_default();
    let client = InternalClient::new();
    client
        .process_query_as_stream(prompt, options, transport)
        .await
}

/// Sends a one-off query with streamed input and streamed output.
///
/// The returned stream is `Send` and can be consumed from any tokio task.
///
/// # Example
///
/// ```rust,no_run
/// use claude_code::query_stream_from_stream;
/// use futures::{stream, StreamExt};
/// use serde_json::json;
///
/// # async fn example() -> claude_code::Result<()> {
///     let mut output = query_stream_from_stream(
///     stream::iter(vec![json!({"type":"user","message":{"role":"user","content":"hello"}})]),
///     None,
///     None,
///     )
///     .await?;
///
///     let _ = output.next().await;
/// # Ok(())
/// # }
/// ```
pub async fn query_stream_from_stream<S>(
    prompt: S,
    options: Option<ClaudeAgentOptions>,
    transport: Option<Box<dyn Transport>>,
) -> Result<BoxStream<'static, Result<Message>>>
where
    S: Stream<Item = Value> + Unpin,
{
    let options = options.unwrap_or_default();
    let client = InternalClient::new();
    client
        .process_query_from_stream_as_stream(prompt, options, transport)
        .await
}