claude-agent-sdk-rust/src/lib.rs
Sulkta 76a790972f fix rustdoc warnings on transport links
- Re-export TransportHandle / TransportReader / TransportWriter alongside
  SubprocessTransport. Without these in the public API, rustdoc refused
  to resolve [`TransportHandle::close`] from SubprocessTransport's docs.
- Inline the close()/end_input() link prose where the broken-link
  warning fired.

cargo doc --no-deps now builds clean.
2026-05-14 08:06:10 -07:00

132 lines
5 KiB
Rust

//! Async Rust SDK for the Claude Agent CLI.
//!
//! This crate is a Rust port of the official Python
//! [`claude-agent-sdk`](https://github.com/anthropics/claude-agent-sdk-python).
//! It wraps the `claude` CLI as a subprocess and exposes its
//! newline-delimited JSON stream as ergonomic Rust types.
//!
//! # Quick start
//!
//! ```no_run
//! use claude_agent_sdk::{query, ClaudeAgentOptions, Message, ContentBlock};
//! use tokio_stream::StreamExt;
//!
//! #[tokio::main]
//! async fn main() -> claude_agent_sdk::Result<()> {
//! let opts = ClaudeAgentOptions::new()
//! .with_system_prompt("You are a helpful assistant.")
//! .with_max_turns(1);
//!
//! let mut stream = query("What is 2 + 2?", opts).await?;
//!
//! while let Some(msg) = stream.next().await {
//! match msg? {
//! Message::Assistant(a) => {
//! for block in a.message.content {
//! if let ContentBlock::Text(t) = block {
//! println!("Claude: {}", t.text);
//! }
//! }
//! }
//! Message::Result(r) => {
//! if let Some(usd) = r.total_cost_usd {
//! println!("Cost: ${:.4}", usd);
//! }
//! break;
//! }
//! _ => {}
//! }
//! }
//! Ok(())
//! }
//! ```
//!
//! # Two entry points
//!
//! - [`query`] — one-shot prompts. Returns a stream that ends when the CLI
//! emits its terminal `result` message, automatically tearing down the
//! subprocess.
//! - [`Client`] — bidirectional, multi-turn sessions. Lets you send
//! follow-up prompts in response to assistant messages, mirroring the
//! Python SDK's `ClaudeSDKClient`.
//!
//! # Configuration
//!
//! Configure both entry points via [`ClaudeAgentOptions`]. It uses a builder
//! pattern — chain `.with_*()` methods on a default value:
//!
//! ```
//! use claude_agent_sdk::{ClaudeAgentOptions, PermissionMode};
//!
//! let opts = ClaudeAgentOptions::new()
//! .with_model("claude-sonnet-4-5")
//! .with_permission_mode(PermissionMode::AcceptEdits)
//! .with_allowed_tool("Read")
//! .with_allowed_tool("Bash")
//! .with_cwd("/tmp/my-project")
//! .with_max_turns(5);
//! ```
//!
//! See [`ClaudeAgentOptions`] for the full list of supported fields.
//!
//! # Field naming
//!
//! The CLI wire protocol is `snake_case`, so deserialized field names match
//! the Python SDK directly (`session_id`, `total_cost_usd`, `tool_use_id`,
//! etc.). Where the wire used `camelCase` historically — `modelUsage` — we
//! preserve it via `#[serde(rename = "...")]` rather than blanket-renaming
//! the container.
//!
//! # v0.1 scope and known limitations
//!
//! The v0.1 port covers the core path of the Python SDK:
//!
//! - Subprocess transport with newline-delimited JSON framing.
//! - All message and content-block types parsed faithfully.
//! - `query()` + `Client` for one-shot and bidirectional use.
//! - The full `ClaudeAgentOptions` flag surface relevant to subprocess args.
//!
//! Deferred to v0.2 — see the upstream README for the current shape of these
//! features in Python:
//!
//! - **Control protocol over JSON-RPC**: `interrupt()`, `set_permission_mode()`,
//! `set_model()`, `get_mcp_status()`, etc. The Rust [`Client`] today only
//! speaks the bare user / assistant / result frames.
//! - **`can_use_tool` permission callback**: requires the control protocol.
//! - **`@tool` decorator / `create_sdk_mcp_server()`**: in-process MCP
//! servers — needs a derive macro or trait shape, deferred until
//! downstream demand is clearer.
//! - **`HookMatcher`** and hook callbacks: the wire format is supported
//! (initialize-payload + hook_callback responses) but the Rust callback
//! surface is not designed yet.
//! - **`SessionStore`** mirroring adapter trait.
//! - **`Sandbox` settings**, **plugins**, **agents** dataclass.
//!
//! These all degrade gracefully — the CLI ignores absent stdin frames, so
//! a v0.1 caller using a `claude` build that supports control requests will
//! simply see fewer features than the Python SDK exposes.
#![deny(missing_docs)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
mod client;
mod errors;
mod messages;
mod options;
mod query;
mod transport;
pub use client::Client;
pub use errors::{Error, Result};
pub use messages::{
AssistantMessage, AssistantMessageInner, ContentBlock, Message, ResultMessage,
ServerToolResultBlock, ServerToolUseBlock, StreamEventMessage, SystemMessage, TextBlock,
ThinkingBlock, ToolResultBlock, ToolUseBlock, UserContent, UserMessage, UserMessageInner,
};
pub use options::{ClaudeAgentOptions, Effort, McpServersConfig, PermissionMode, SystemPrompt};
pub use query::query;
pub use transport::{SubprocessTransport, TransportHandle, TransportReader, TransportWriter};
/// Crate version, as set in `Cargo.toml`. Sent to the CLI as
/// `CLAUDE_AGENT_SDK_VERSION` in the subprocess env.
pub const VERSION: &str = env!("CARGO_PKG_VERSION");