claude_code/types.rs
1//! Core data types for the Claude Code SDK.
2//!
3//! This module defines all the configuration, message, and permission types used
4//! throughout the SDK. These types correspond to the Python SDK's type definitions
5//! documented at <https://platform.claude.com/docs/en/agent-sdk/python>.
6
7use std::collections::HashMap;
8use std::path::PathBuf;
9use std::sync::Arc;
10
11use futures::future::BoxFuture;
12use serde::{Deserialize, Deserializer, Serialize, Serializer};
13use serde_json::Value;
14
15use crate::errors::Error;
16use crate::sdk_mcp::McpSdkServer;
17
18/// Permission mode controlling how Claude Code handles tool execution permissions.
19///
20/// Corresponds to the Python SDK's `PermissionMode` literal type.
21///
22/// # Variants
23///
24/// - `Default` — Standard permission behavior; Claude prompts for approval on sensitive operations.
25/// - `AcceptEdits` — Auto-accept file edits without prompting.
26/// - `Plan` — Planning mode; Claude describes actions without executing them.
27/// - `BypassPermissions` — Bypass all permission checks. **Use with caution.**
28#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
29pub enum PermissionMode {
30 /// Standard permission behavior with interactive approval when needed.
31 #[serde(rename = "default")]
32 Default,
33 /// Auto-accept file edits without interactive approval.
34 #[serde(rename = "acceptEdits")]
35 AcceptEdits,
36 /// Planning mode where the model proposes actions instead of executing them.
37 #[serde(rename = "plan")]
38 Plan,
39 /// Bypass all permission checks.
40 #[serde(rename = "bypassPermissions")]
41 BypassPermissions,
42}
43
44/// Controls which filesystem-based configuration sources the SDK loads settings from.
45///
46/// When `setting_sources` is omitted or `None` in [`ClaudeAgentOptions`], the SDK does
47/// **not** load any filesystem settings, providing isolation for SDK applications.
48///
49/// # Variants
50///
51/// - `User` — Global user settings (`~/.claude/settings.json`).
52/// - `Project` — Shared project settings (`.claude/settings.json`), version controlled.
53/// Must be included to load `CLAUDE.md` files.
54/// - `Local` — Local project settings (`.claude/settings.local.json`), typically gitignored.
55///
56/// # Precedence
57///
58/// When multiple sources are loaded, settings merge with this precedence (highest first):
59/// 1. Local settings
60/// 2. Project settings
61/// 3. User settings
62///
63/// Programmatic options (e.g., `agents`, `allowed_tools`) always override filesystem settings.
64#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
65#[serde(rename_all = "camelCase")]
66pub enum SettingSource {
67 /// Load user-level settings from the home directory.
68 User,
69 /// Load project-level shared settings.
70 Project,
71 /// Load local project settings (typically not committed).
72 Local,
73}
74
75/// Preset configuration for the system prompt.
76///
77/// Uses Claude Code's built-in system prompt with an optional appended section.
78///
79/// # Fields
80///
81/// - `type_` — Must be `"preset"`.
82/// - `preset` — Must be `"claude_code"` to use Claude Code's system prompt.
83/// - `append` — Optional additional instructions to append to the preset system prompt.
84#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
85pub struct SystemPromptPreset {
86 /// Discriminator field for preset prompts (typically `"preset"`).
87 #[serde(rename = "type")]
88 pub type_: String,
89 /// Preset name (typically `"claude_code"`).
90 pub preset: String,
91 /// Extra instructions appended to the preset prompt.
92 #[serde(skip_serializing_if = "Option::is_none")]
93 pub append: Option<String>,
94}
95
96impl Default for SystemPromptPreset {
97 fn default() -> Self {
98 Self {
99 type_: "preset".to_string(),
100 preset: "claude_code".to_string(),
101 append: None,
102 }
103 }
104}
105
106/// Preset tools configuration for using Claude Code's default tool set.
107///
108/// # Fields
109///
110/// - `type_` — Must be `"preset"`.
111/// - `preset` — Must be `"claude_code"` for the default tool set.
112#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
113pub struct ToolsPreset {
114 /// Discriminator field for preset tools (typically `"preset"`).
115 #[serde(rename = "type")]
116 pub type_: String,
117 /// Preset name (typically `"claude_code"`).
118 pub preset: String,
119}
120
121impl Default for ToolsPreset {
122 fn default() -> Self {
123 Self {
124 type_: "preset".to_string(),
125 preset: "claude_code".to_string(),
126 }
127 }
128}
129
130/// System prompt configuration.
131///
132/// Either provide a custom text prompt or use Claude Code's preset system prompt.
133///
134/// # Variants
135///
136/// - `Text` — A custom system prompt string.
137/// - `Preset` — Use Claude Code's built-in system prompt via [`SystemPromptPreset`].
138#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
139#[serde(untagged)]
140pub enum SystemPrompt {
141 /// Use a custom system prompt string.
142 Text(String),
143 /// Use Claude Code's preset system prompt.
144 Preset(SystemPromptPreset),
145}
146
147/// Tools configuration.
148///
149/// Either provide an explicit list of tool names or use Claude Code's preset tools.
150///
151/// # Variants
152///
153/// - `List` — An explicit list of tool name strings.
154/// - `Preset` — Use Claude Code's default tool set via [`ToolsPreset`].
155#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
156#[serde(untagged)]
157pub enum ToolsOption {
158 /// Explicit list of allowed tool names.
159 List(Vec<String>),
160 /// Use the default Claude Code tools preset.
161 Preset(ToolsPreset),
162}
163
164/// Configuration for a programmatically defined subagent.
165///
166/// Subagents are specialized agents that can be invoked by the main Claude Code agent
167/// for specific tasks.
168///
169/// # Fields
170///
171/// - `description` — Natural language description of when to use this agent.
172/// - `prompt` — The agent's system prompt.
173/// - `tools` — Optional list of allowed tool names. If omitted, inherits all tools.
174/// - `model` — Optional model override (e.g., `"sonnet"`, `"opus"`, `"haiku"`, `"inherit"`).
175/// If omitted, uses the main model.
176#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
177pub struct AgentDefinition {
178 /// Human-readable description of when this agent should be used.
179 pub description: String,
180 /// The sub-agent system prompt.
181 pub prompt: String,
182 /// Optional tool allowlist for this sub-agent.
183 #[serde(skip_serializing_if = "Option::is_none")]
184 pub tools: Option<Vec<String>>,
185 /// Optional model override for this sub-agent.
186 #[serde(skip_serializing_if = "Option::is_none")]
187 pub model: Option<String>,
188}
189
190/// A rule to add, replace, or remove in a permission update.
191///
192/// # Fields
193///
194/// - `tool_name` — The name of the tool this rule applies to.
195/// - `rule_content` — Optional rule content string (e.g., a glob pattern or path).
196#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
197#[serde(rename_all = "camelCase")]
198pub struct PermissionRuleValue {
199 /// Tool name that this rule applies to.
200 pub tool_name: String,
201 /// Optional rule body (for example a path or glob).
202 #[serde(skip_serializing_if = "Option::is_none")]
203 pub rule_content: Option<String>,
204}
205
206/// Destination for applying a permission update.
207///
208/// Determines where the permission change is persisted.
209#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
210#[serde(rename_all = "camelCase")]
211pub enum PermissionUpdateDestination {
212 /// Persist update to user settings.
213 UserSettings,
214 /// Persist update to project settings.
215 ProjectSettings,
216 /// Persist update to local project settings.
217 LocalSettings,
218 /// Apply update only for the current session.
219 Session,
220}
221
222/// Behavior for rule-based permission operations.
223#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
224#[serde(rename_all = "lowercase")]
225pub enum PermissionBehavior {
226 /// Explicitly allow matching operations.
227 Allow,
228 /// Explicitly deny matching operations.
229 Deny,
230 /// Ask for confirmation on matching operations.
231 Ask,
232}
233
234/// The type of a permission update operation.
235#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
236#[serde(rename_all = "camelCase")]
237pub enum PermissionUpdateType {
238 /// Add permission rules to the existing set.
239 AddRules,
240 /// Replace all existing rules with the provided rules.
241 ReplaceRules,
242 /// Remove matching rules from the existing set.
243 RemoveRules,
244 /// Set the current permission mode.
245 SetMode,
246 /// Add directories to the permission scope.
247 AddDirectories,
248 /// Remove directories from the permission scope.
249 RemoveDirectories,
250}
251
252/// Configuration for updating permissions programmatically.
253///
254/// Used to modify permission rules, change modes, or manage directory access
255/// during a session.
256///
257/// # Fields
258///
259/// - `type_` — The type of permission update operation.
260/// - `rules` — Rules for add/replace/remove operations.
261/// - `behavior` — Behavior for rule-based operations (`"allow"`, `"deny"`, `"ask"`).
262/// - `mode` — Mode for `SetMode` operations.
263/// - `directories` — Directories for add/remove directory operations.
264/// - `destination` — Where to apply the permission update.
265#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
266pub struct PermissionUpdate {
267 /// Operation type to apply.
268 #[serde(rename = "type")]
269 pub type_: PermissionUpdateType,
270 /// Rule set used by rule-based updates.
271 #[serde(skip_serializing_if = "Option::is_none")]
272 pub rules: Option<Vec<PermissionRuleValue>>,
273 /// Behavior used by rule-based updates.
274 #[serde(skip_serializing_if = "Option::is_none")]
275 pub behavior: Option<PermissionBehavior>,
276 /// Permission mode used by `SetMode`.
277 #[serde(skip_serializing_if = "Option::is_none")]
278 pub mode: Option<PermissionMode>,
279 /// Directory paths used by directory updates.
280 #[serde(skip_serializing_if = "Option::is_none")]
281 pub directories: Option<Vec<String>>,
282 /// Where this update should be persisted/applied.
283 #[serde(skip_serializing_if = "Option::is_none")]
284 pub destination: Option<PermissionUpdateDestination>,
285}
286
287impl PermissionUpdate {
288 /// Converts this permission update to a JSON value suitable for the CLI protocol.
289 ///
290 /// # Example
291 ///
292 /// ```rust
293 /// use claude_code::{PermissionUpdate};
294 /// use claude_code::types::{PermissionBehavior, PermissionRuleValue, PermissionUpdateType};
295 ///
296 /// let update = PermissionUpdate {
297 /// type_: PermissionUpdateType::AddRules,
298 /// rules: Some(vec![PermissionRuleValue {
299 /// tool_name: "Bash".to_string(),
300 /// rule_content: Some("git status".to_string()),
301 /// }]),
302 /// behavior: Some(PermissionBehavior::Allow),
303 /// mode: None,
304 /// directories: None,
305 /// destination: None,
306 /// };
307 ///
308 /// let json = update.to_cli_dict();
309 /// assert_eq!(json["type"], "addRules");
310 /// ```
311 pub fn to_cli_dict(&self) -> Value {
312 let mut result = serde_json::Map::new();
313 result.insert(
314 "type".to_string(),
315 serde_json::to_value(&self.type_).unwrap_or(Value::Null),
316 );
317
318 if let Some(destination) = &self.destination {
319 result.insert(
320 "destination".to_string(),
321 serde_json::to_value(destination).unwrap_or(Value::Null),
322 );
323 }
324
325 match self.type_ {
326 PermissionUpdateType::AddRules
327 | PermissionUpdateType::ReplaceRules
328 | PermissionUpdateType::RemoveRules => {
329 if let Some(rules) = &self.rules {
330 let rules_json: Vec<Value> = rules
331 .iter()
332 .map(|rule| {
333 serde_json::json!({
334 "toolName": rule.tool_name,
335 "ruleContent": rule.rule_content
336 })
337 })
338 .collect();
339 result.insert("rules".to_string(), Value::Array(rules_json));
340 }
341 if let Some(behavior) = &self.behavior {
342 result.insert(
343 "behavior".to_string(),
344 serde_json::to_value(behavior).unwrap_or(Value::Null),
345 );
346 }
347 }
348 PermissionUpdateType::SetMode => {
349 if let Some(mode) = &self.mode {
350 result.insert(
351 "mode".to_string(),
352 serde_json::to_value(mode).unwrap_or(Value::Null),
353 );
354 }
355 }
356 PermissionUpdateType::AddDirectories | PermissionUpdateType::RemoveDirectories => {
357 if let Some(directories) = &self.directories {
358 result.insert(
359 "directories".to_string(),
360 serde_json::to_value(directories).unwrap_or(Value::Null),
361 );
362 }
363 }
364 }
365
366 Value::Object(result)
367 }
368}
369
370/// Context information passed to tool permission callbacks.
371///
372/// Provides additional context when the [`CanUseToolCallback`] is invoked, including
373/// permission update suggestions from the CLI.
374///
375/// # Fields
376///
377/// - `suggestions` — Permission update suggestions from the CLI for the user to consider.
378/// - `blocked_path` — Optional path rejected by permission checks.
379/// - `signal` — Reserved placeholder for future abort signal support.
380#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
381pub struct ToolPermissionContext {
382 /// CLI-suggested permission updates for this tool request.
383 #[serde(default)]
384 pub suggestions: Vec<PermissionUpdate>,
385 /// Optional blocked path associated with the request.
386 #[serde(default, skip_serializing_if = "Option::is_none")]
387 pub blocked_path: Option<String>,
388 /// Reserved signal placeholder for future API compatibility.
389 #[serde(default, skip_serializing_if = "Option::is_none")]
390 pub signal: Option<()>,
391}
392
393/// Result indicating the tool call should be allowed.
394///
395/// Returned from a [`CanUseToolCallback`] to approve tool execution.
396///
397/// # Fields
398///
399/// - `updated_input` — Optional modified input to use instead of the original.
400/// - `updated_permissions` — Optional permission updates to apply alongside this approval.
401#[derive(Debug, Clone, PartialEq, Default)]
402pub struct PermissionResultAllow {
403 /// Optional rewritten tool input payload.
404 pub updated_input: Option<Value>,
405 /// Optional additional permission updates to apply.
406 pub updated_permissions: Option<Vec<PermissionUpdate>>,
407}
408
409/// Result indicating the tool call should be denied.
410///
411/// Returned from a [`CanUseToolCallback`] to reject tool execution.
412///
413/// # Fields
414///
415/// - `message` — Message explaining why the tool was denied.
416/// - `interrupt` — Whether to interrupt the current execution entirely.
417#[derive(Debug, Clone, PartialEq, Default)]
418pub struct PermissionResultDeny {
419 /// Human-readable denial reason.
420 pub message: String,
421 /// Whether processing should be interrupted after denial.
422 pub interrupt: bool,
423}
424
425/// Union type for permission callback results.
426///
427/// Returned by [`CanUseToolCallback`] functions to indicate whether a tool call
428/// should be allowed or denied.
429#[derive(Debug, Clone, PartialEq)]
430pub enum PermissionResult {
431 /// Approve the tool call with optional adjusted input/permissions.
432 Allow(PermissionResultAllow),
433 /// Reject the tool call.
434 Deny(PermissionResultDeny),
435}
436
437/// Callback type for custom tool permission logic.
438///
439/// This function is invoked before each tool execution, receiving:
440/// - `tool_name` (`String`) — The name of the tool being called.
441/// - `input_data` (`Value`) — The tool's input parameters.
442/// - `context` ([`ToolPermissionContext`]) — Additional context including permission suggestions.
443///
444/// Returns a [`PermissionResult`] indicating whether the tool call should be allowed or denied.
445///
446/// # Note
447///
448/// When using `can_use_tool`, the prompt must be provided as streaming messages
449/// (not a plain text string), and `permission_prompt_tool_name` must not be set.
450pub type CanUseToolCallback = Arc<
451 dyn Fn(
452 String,
453 Value,
454 ToolPermissionContext,
455 ) -> BoxFuture<'static, std::result::Result<PermissionResult, Error>>
456 + Send
457 + Sync,
458>;
459
460/// Context information passed to hook callbacks.
461///
462/// Currently a marker type; reserved for future abort signal support.
463#[derive(Debug, Clone, Default)]
464pub struct HookContext;
465
466/// Input data passed to hook callbacks.
467///
468/// A raw JSON value whose structure depends on the hook event type (e.g.,
469/// `PreToolUse`, `PostToolUse`, `UserPromptSubmit`, etc.).
470/// See the [hooks documentation](https://platform.claude.com/docs/en/agent-sdk/hooks)
471/// for the expected shapes per event.
472pub type HookInput = Value;
473
474/// Return value from hook callbacks.
475///
476/// A JSON value that may contain control fields such as:
477/// - `decision` — `"block"` to block the action.
478/// - `systemMessage` — A system message to add to the transcript.
479/// - `hookSpecificOutput` — Hook-specific output data.
480/// - `continue_` — Whether to proceed (maps to `"continue"` in the CLI protocol).
481/// - `async_` — Set to `true` to defer execution (maps to `"async"` in the CLI protocol).
482pub type HookJSONOutput = Value;
483
484/// Callback type for hook functions.
485///
486/// Invoked when a matching hook event occurs. Receives:
487/// - `input` ([`HookInput`]) — Event-specific input data.
488/// - `tool_use_id` (`Option<String>`) — Optional tool use identifier (for tool-related hooks).
489/// - `context` ([`HookContext`]) — Hook context with additional information.
490///
491/// Returns a [`HookJSONOutput`] JSON value with optional control and output fields.
492pub type HookCallback = Arc<
493 dyn Fn(
494 HookInput,
495 Option<String>,
496 HookContext,
497 ) -> BoxFuture<'static, std::result::Result<HookJSONOutput, Error>>
498 + Send
499 + Sync,
500>;
501
502/// Configuration for matching hooks to specific events or tools.
503///
504/// # Fields
505///
506/// - `matcher` — Optional tool name or regex pattern to match (e.g., `"Bash"`, `"Write|Edit"`).
507/// If `None`, the hook applies to all tools.
508/// - `hooks` — List of callback functions to execute when matched.
509/// - `timeout` — Optional timeout in seconds for all hooks in this matcher (default: 60).
510#[derive(Clone, Default)]
511pub struct HookMatcher {
512 /// Optional matcher expression for selecting hook targets.
513 pub matcher: Option<String>,
514 /// Hook callbacks to execute when this matcher is selected.
515 pub hooks: Vec<HookCallback>,
516 /// Optional timeout in seconds applied to callbacks in this matcher.
517 pub timeout: Option<f64>,
518}
519
520/// Configuration for an MCP server using stdio transport.
521///
522/// Launches an external process and communicates via stdin/stdout.
523///
524/// # Fields
525///
526/// - `type_` — Optional; set to `"stdio"` for explicit typing (backwards compatible if omitted).
527/// - `command` — The command to execute.
528/// - `args` — Optional command-line arguments.
529/// - `env` — Optional environment variables to set.
530#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
531pub struct McpStdioServerConfig {
532 /// Optional discriminator for stdio transport (`"stdio"`).
533 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
534 pub type_: Option<String>,
535 /// Command used to launch the MCP server process.
536 pub command: String,
537 /// Optional command arguments.
538 #[serde(skip_serializing_if = "Option::is_none")]
539 pub args: Option<Vec<String>>,
540 /// Optional environment variables passed to the process.
541 #[serde(skip_serializing_if = "Option::is_none")]
542 pub env: Option<HashMap<String, String>>,
543}
544
545/// Configuration for an MCP server using Server-Sent Events (SSE) transport.
546///
547/// # Fields
548///
549/// - `type_` — Must be `"sse"`.
550/// - `url` — The SSE endpoint URL.
551/// - `headers` — Optional HTTP headers to include in requests.
552#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
553pub struct McpSSEServerConfig {
554 /// Discriminator for SSE transport (`"sse"`).
555 #[serde(rename = "type")]
556 pub type_: String,
557 /// SSE endpoint URL.
558 pub url: String,
559 /// Optional HTTP headers for the SSE connection.
560 #[serde(skip_serializing_if = "Option::is_none")]
561 pub headers: Option<HashMap<String, String>>,
562}
563
564/// Configuration for an MCP server using HTTP transport.
565///
566/// # Fields
567///
568/// - `type_` — Must be `"http"`.
569/// - `url` — The HTTP endpoint URL.
570/// - `headers` — Optional HTTP headers to include in requests.
571#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
572pub struct McpHttpServerConfig {
573 /// Discriminator for HTTP transport (`"http"`).
574 #[serde(rename = "type")]
575 pub type_: String,
576 /// HTTP endpoint URL.
577 pub url: String,
578 /// Optional HTTP headers.
579 #[serde(skip_serializing_if = "Option::is_none")]
580 pub headers: Option<HashMap<String, String>>,
581}
582
583/// Configuration for an in-process SDK MCP server.
584///
585/// Created via [`create_sdk_mcp_server()`](crate::create_sdk_mcp_server). The server
586/// runs within your Rust application and handles tool calls in-process.
587///
588/// # Fields
589///
590/// - `type_` — Always `"sdk"`.
591/// - `name` — Unique name identifier for the server.
592/// - `instance` — Shared reference to the [`McpSdkServer`] instance.
593#[derive(Clone)]
594pub struct McpSdkServerConfig {
595 /// Discriminator for in-process SDK transport (`"sdk"`).
596 pub type_: String,
597 /// Logical server name used in MCP config maps.
598 pub name: String,
599 /// In-process server instance.
600 pub instance: Arc<McpSdkServer>,
601}
602
603/// Union type for MCP server configurations.
604///
605/// Supports four transport types for MCP (Model Context Protocol) servers:
606///
607/// - `Stdio` — External process communicating via stdin/stdout.
608/// - `Sse` — Remote server using Server-Sent Events.
609/// - `Http` — Remote server using HTTP.
610/// - `Sdk` — In-process server running within your application.
611#[derive(Clone)]
612pub enum McpServerConfig {
613 /// External stdio MCP server process.
614 Stdio(McpStdioServerConfig),
615 /// Remote SSE MCP server.
616 Sse(McpSSEServerConfig),
617 /// Remote HTTP MCP server.
618 Http(McpHttpServerConfig),
619 /// In-process SDK MCP server.
620 Sdk(McpSdkServerConfig),
621}
622
623impl McpServerConfig {
624 /// Converts this configuration to a JSON value for the CLI protocol.
625 ///
626 /// SDK-type servers are serialized as `{"type": "sdk", "name": "<name>"}` since
627 /// the actual server instance runs in-process and doesn't need full serialization.
628 ///
629 /// # Example
630 ///
631 /// ```rust
632 /// use claude_code::{McpServerConfig, McpSSEServerConfig};
633 ///
634 /// let config = McpServerConfig::Sse(McpSSEServerConfig {
635 /// type_: "sse".to_string(),
636 /// url: "https://example.com/mcp".to_string(),
637 /// headers: None,
638 /// });
639 ///
640 /// let json = config.to_cli_json();
641 /// assert_eq!(json["type"], "sse");
642 /// ```
643 pub fn to_cli_json(&self) -> Value {
644 match self {
645 McpServerConfig::Stdio(config) => serde_json::to_value(config).unwrap_or(Value::Null),
646 McpServerConfig::Sse(config) => serde_json::to_value(config).unwrap_or(Value::Null),
647 McpServerConfig::Http(config) => serde_json::to_value(config).unwrap_or(Value::Null),
648 McpServerConfig::Sdk(config) => {
649 serde_json::json!({
650 "type": "sdk",
651 "name": config.name
652 })
653 }
654 }
655 }
656}
657
658/// MCP server configuration option for [`ClaudeAgentOptions`].
659///
660/// # Variants
661///
662/// - `None` — No MCP servers configured (default).
663/// - `Servers` — A map of server name to [`McpServerConfig`].
664/// - `Raw` — A raw JSON string or file path to an MCP configuration.
665#[derive(Clone, Default)]
666pub enum McpServersOption {
667 #[default]
668 /// No MCP servers are configured.
669 None,
670 /// Explicit map of server names to server configs.
671 Servers(HashMap<String, McpServerConfig>),
672 /// Raw CLI `--mcp-config` payload (JSON string or path).
673 Raw(String),
674}
675
676/// SDK MCP server config shape used in MCP status responses.
677#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
678pub struct McpSdkServerStatusConfig {
679 /// Discriminator for in-process SDK transport (`"sdk"`).
680 #[serde(rename = "type")]
681 pub type_: String,
682 /// Logical server name used in MCP config maps.
683 pub name: String,
684}
685
686/// Claude.ai proxy MCP server config shape used in MCP status responses.
687#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
688pub struct McpClaudeAiProxyServerConfig {
689 /// Discriminator for Claude.ai proxy transport (`"claudeai-proxy"`).
690 #[serde(rename = "type")]
691 pub type_: String,
692 /// Proxy endpoint URL.
693 pub url: String,
694 /// Proxy identifier.
695 pub id: String,
696}
697
698/// MCP server config shape returned by `get_mcp_status`.
699#[derive(Debug, Clone, PartialEq, Eq)]
700pub enum McpServerStatusConfig {
701 /// stdio server configuration.
702 Stdio(McpStdioServerConfig),
703 /// SSE server configuration.
704 Sse(McpSSEServerConfig),
705 /// HTTP server configuration.
706 Http(McpHttpServerConfig),
707 /// In-process SDK server configuration.
708 Sdk(McpSdkServerStatusConfig),
709 /// Claude.ai proxy server configuration.
710 ClaudeAiProxy(McpClaudeAiProxyServerConfig),
711 /// Forward-compatible fallback for unknown config payloads.
712 Unknown(Value),
713}
714
715impl Serialize for McpServerStatusConfig {
716 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
717 where
718 S: Serializer,
719 {
720 match self {
721 McpServerStatusConfig::Stdio(value) => value.serialize(serializer),
722 McpServerStatusConfig::Sse(value) => value.serialize(serializer),
723 McpServerStatusConfig::Http(value) => value.serialize(serializer),
724 McpServerStatusConfig::Sdk(value) => value.serialize(serializer),
725 McpServerStatusConfig::ClaudeAiProxy(value) => value.serialize(serializer),
726 McpServerStatusConfig::Unknown(value) => value.serialize(serializer),
727 }
728 }
729}
730
731impl<'de> Deserialize<'de> for McpServerStatusConfig {
732 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
733 where
734 D: Deserializer<'de>,
735 {
736 let value = Value::deserialize(deserializer)?;
737 let config_type = value
738 .get("type")
739 .and_then(Value::as_str)
740 .unwrap_or_default();
741
742 match config_type {
743 "stdio" => serde_json::from_value::<McpStdioServerConfig>(value)
744 .map(McpServerStatusConfig::Stdio)
745 .map_err(serde::de::Error::custom),
746 "sse" => serde_json::from_value::<McpSSEServerConfig>(value)
747 .map(McpServerStatusConfig::Sse)
748 .map_err(serde::de::Error::custom),
749 "http" => serde_json::from_value::<McpHttpServerConfig>(value)
750 .map(McpServerStatusConfig::Http)
751 .map_err(serde::de::Error::custom),
752 "sdk" => serde_json::from_value::<McpSdkServerStatusConfig>(value)
753 .map(McpServerStatusConfig::Sdk)
754 .map_err(serde::de::Error::custom),
755 "claudeai-proxy" => serde_json::from_value::<McpClaudeAiProxyServerConfig>(value)
756 .map(McpServerStatusConfig::ClaudeAiProxy)
757 .map_err(serde::de::Error::custom),
758 _ => Ok(McpServerStatusConfig::Unknown(value)),
759 }
760 }
761}
762
763/// Tool annotations returned in MCP status payloads.
764#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
765pub struct McpToolAnnotations {
766 /// Whether the tool is read-only.
767 #[serde(rename = "readOnly", skip_serializing_if = "Option::is_none")]
768 pub read_only: Option<bool>,
769 /// Whether the tool is destructive.
770 #[serde(skip_serializing_if = "Option::is_none")]
771 pub destructive: Option<bool>,
772 /// Whether the tool interacts with open-world/external systems.
773 #[serde(rename = "openWorld", skip_serializing_if = "Option::is_none")]
774 pub open_world: Option<bool>,
775}
776
777/// Tool metadata returned in MCP status payloads.
778#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
779pub struct McpToolInfo {
780 /// Tool name.
781 pub name: String,
782 /// Optional tool description.
783 #[serde(skip_serializing_if = "Option::is_none")]
784 pub description: Option<String>,
785 /// Optional tool annotations.
786 #[serde(skip_serializing_if = "Option::is_none")]
787 pub annotations: Option<McpToolAnnotations>,
788}
789
790/// Server metadata returned for connected MCP servers.
791#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
792pub struct McpServerInfo {
793 /// Server name.
794 pub name: String,
795 /// Server version.
796 pub version: String,
797}
798
799/// MCP server connection status.
800#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
801pub enum McpServerConnectionStatus {
802 /// Server is connected.
803 #[serde(rename = "connected")]
804 Connected,
805 /// Server connection failed.
806 #[serde(rename = "failed")]
807 Failed,
808 /// Server needs authentication.
809 #[serde(rename = "needs-auth")]
810 NeedsAuth,
811 /// Server connection is pending.
812 #[serde(rename = "pending")]
813 Pending,
814 /// Server is disabled.
815 #[serde(rename = "disabled")]
816 Disabled,
817}
818
819/// Status entry for a single MCP server.
820#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
821pub struct McpServerStatus {
822 /// Server name as configured.
823 pub name: String,
824 /// Current connection status.
825 pub status: McpServerConnectionStatus,
826 /// Server info from MCP initialize handshake.
827 #[serde(rename = "serverInfo", skip_serializing_if = "Option::is_none")]
828 pub server_info: Option<McpServerInfo>,
829 /// Error message when status is `failed`.
830 #[serde(skip_serializing_if = "Option::is_none")]
831 pub error: Option<String>,
832 /// Server configuration payload.
833 #[serde(skip_serializing_if = "Option::is_none")]
834 pub config: Option<McpServerStatusConfig>,
835 /// Configuration scope (for example `project`, `user`, `local`).
836 #[serde(skip_serializing_if = "Option::is_none")]
837 pub scope: Option<String>,
838 /// Tools exposed by this server.
839 #[serde(skip_serializing_if = "Option::is_none")]
840 pub tools: Option<Vec<McpToolInfo>>,
841}
842
843/// Typed MCP status response payload returned by `get_mcp_status`.
844#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
845pub struct McpStatusResponse {
846 /// Status entries for all configured servers.
847 #[serde(rename = "mcpServers")]
848 pub mcp_servers: Vec<McpServerStatus>,
849}
850
851/// Configuration for loading plugins in the SDK.
852///
853/// Only local plugins are currently supported.
854///
855/// # Fields
856///
857/// - `type_` — Must be `"local"`.
858/// - `path` — Absolute or relative path to the plugin directory.
859#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
860pub struct SdkPluginConfig {
861 /// Plugin type discriminator (currently `"local"`).
862 #[serde(rename = "type")]
863 pub type_: String,
864 /// Filesystem path to the plugin directory.
865 pub path: String,
866}
867
868/// Network-specific configuration for sandbox mode.
869///
870/// Controls how sandboxed processes can access network resources.
871///
872/// # Fields
873///
874/// - `allow_unix_sockets` — Unix socket paths that processes can access (e.g., Docker socket).
875/// - `allow_all_unix_sockets` — Allow access to all Unix sockets.
876/// - `allow_local_binding` — Allow processes to bind to local ports (e.g., for dev servers).
877/// - `http_proxy_port` — HTTP proxy port for network requests.
878/// - `socks_proxy_port` — SOCKS proxy port for network requests.
879#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
880pub struct SandboxNetworkConfig {
881 /// Allowed unix socket paths.
882 #[serde(rename = "allowUnixSockets", skip_serializing_if = "Option::is_none")]
883 pub allow_unix_sockets: Option<Vec<String>>,
884 /// Whether all unix sockets are allowed.
885 #[serde(
886 rename = "allowAllUnixSockets",
887 skip_serializing_if = "Option::is_none"
888 )]
889 pub allow_all_unix_sockets: Option<bool>,
890 /// Whether local port binding is allowed.
891 #[serde(rename = "allowLocalBinding", skip_serializing_if = "Option::is_none")]
892 pub allow_local_binding: Option<bool>,
893 /// HTTP proxy port exposed into the sandbox.
894 #[serde(rename = "httpProxyPort", skip_serializing_if = "Option::is_none")]
895 pub http_proxy_port: Option<u16>,
896 /// SOCKS proxy port exposed into the sandbox.
897 #[serde(rename = "socksProxyPort", skip_serializing_if = "Option::is_none")]
898 pub socks_proxy_port: Option<u16>,
899}
900
901/// Configuration for ignoring specific sandbox violations.
902///
903/// # Fields
904///
905/// - `file` — File path patterns to ignore violations for.
906/// - `network` — Network patterns to ignore violations for.
907#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
908pub struct SandboxIgnoreViolations {
909 /// File path patterns to ignore.
910 #[serde(skip_serializing_if = "Option::is_none")]
911 pub file: Option<Vec<String>>,
912 /// Network patterns to ignore.
913 #[serde(skip_serializing_if = "Option::is_none")]
914 pub network: Option<Vec<String>>,
915}
916
917/// Sandbox configuration for controlling command execution isolation.
918///
919/// Use this to enable command sandboxing and configure network restrictions
920/// programmatically.
921///
922/// # Fields
923///
924/// - `enabled` — Enable sandbox mode for command execution.
925/// - `auto_allow_bash_if_sandboxed` — Auto-approve bash commands when sandbox is enabled.
926/// - `excluded_commands` — Commands that always bypass sandbox restrictions (e.g., `["docker"]`).
927/// - `allow_unsandboxed_commands` — Allow the model to request running commands outside the sandbox.
928/// - `network` — Network-specific sandbox configuration.
929/// - `ignore_violations` — Configure which sandbox violations to ignore.
930/// - `enable_weaker_nested_sandbox` — Enable a weaker nested sandbox for compatibility.
931#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
932pub struct SandboxSettings {
933 /// Enables or disables sandboxing.
934 #[serde(skip_serializing_if = "Option::is_none")]
935 pub enabled: Option<bool>,
936 /// Auto-approve bash tool when sandboxing is enabled.
937 #[serde(
938 rename = "autoAllowBashIfSandboxed",
939 skip_serializing_if = "Option::is_none"
940 )]
941 pub auto_allow_bash_if_sandboxed: Option<bool>,
942 /// Commands excluded from sandbox restrictions.
943 #[serde(rename = "excludedCommands", skip_serializing_if = "Option::is_none")]
944 pub excluded_commands: Option<Vec<String>>,
945 /// Whether unsandboxed command execution can be requested.
946 #[serde(
947 rename = "allowUnsandboxedCommands",
948 skip_serializing_if = "Option::is_none"
949 )]
950 pub allow_unsandboxed_commands: Option<bool>,
951 /// Network-related sandbox settings.
952 #[serde(skip_serializing_if = "Option::is_none")]
953 pub network: Option<SandboxNetworkConfig>,
954 /// Violation categories to ignore.
955 #[serde(rename = "ignoreViolations", skip_serializing_if = "Option::is_none")]
956 pub ignore_violations: Option<SandboxIgnoreViolations>,
957 /// Enables weaker nested sandbox mode for compatibility.
958 #[serde(
959 rename = "enableWeakerNestedSandbox",
960 skip_serializing_if = "Option::is_none"
961 )]
962 pub enable_weaker_nested_sandbox: Option<bool>,
963}
964
965/// A text content block in an assistant message.
966#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
967pub struct TextBlock {
968 /// Textual content for this block.
969 pub text: String,
970}
971
972/// A thinking content block (for models with extended thinking capability).
973///
974/// Contains the model's internal reasoning and a cryptographic signature.
975#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
976pub struct ThinkingBlock {
977 /// Model-generated reasoning content.
978 pub thinking: String,
979 /// Signature associated with the reasoning block.
980 pub signature: String,
981}
982
983/// A tool use request block.
984///
985/// Represents Claude's request to invoke a specific tool with given parameters.
986///
987/// # Fields
988///
989/// - `id` — Unique identifier for this tool use request.
990/// - `name` — Name of the tool to invoke.
991/// - `input` — JSON input parameters for the tool.
992#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
993pub struct ToolUseBlock {
994 /// Tool use identifier.
995 pub id: String,
996 /// Invoked tool name.
997 pub name: String,
998 /// Tool input payload.
999 pub input: Value,
1000}
1001
1002/// A tool execution result block.
1003///
1004/// Contains the output from a previously executed tool.
1005///
1006/// # Fields
1007///
1008/// - `tool_use_id` — The ID of the [`ToolUseBlock`] this result corresponds to.
1009/// - `content` — Optional result content (text or structured data).
1010/// - `is_error` — Whether the tool execution resulted in an error.
1011#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1012pub struct ToolResultBlock {
1013 /// Corresponding tool use identifier.
1014 pub tool_use_id: String,
1015 /// Optional tool result payload.
1016 #[serde(skip_serializing_if = "Option::is_none")]
1017 pub content: Option<Value>,
1018 /// Whether this tool result represents an error.
1019 #[serde(skip_serializing_if = "Option::is_none")]
1020 pub is_error: Option<bool>,
1021}
1022
1023/// Union type for all content block types in messages.
1024///
1025/// Content blocks make up the body of [`AssistantMessage`] and [`UserMessage`] responses.
1026#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1027pub enum ContentBlock {
1028 /// Plain text content.
1029 Text(TextBlock),
1030 /// Reasoning content.
1031 Thinking(ThinkingBlock),
1032 /// Tool invocation request.
1033 ToolUse(ToolUseBlock),
1034 /// Tool invocation result.
1035 ToolResult(ToolResultBlock),
1036}
1037
1038/// User message content — either plain text or structured content blocks.
1039#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1040#[serde(untagged)]
1041pub enum UserContent {
1042 /// Plain string user content.
1043 Text(String),
1044 /// Structured content blocks.
1045 Blocks(Vec<ContentBlock>),
1046}
1047
1048/// A user input message.
1049///
1050/// # Fields
1051///
1052/// - `content` — Message content as text or content blocks.
1053/// - `uuid` — Optional unique message identifier.
1054/// - `parent_tool_use_id` — Tool use ID if this message is a tool result response.
1055/// - `tool_use_result` — Tool result data if applicable.
1056#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1057pub struct UserMessage {
1058 /// User message body.
1059 pub content: UserContent,
1060 /// Optional message UUID.
1061 pub uuid: Option<String>,
1062 /// Optional parent tool use identifier.
1063 pub parent_tool_use_id: Option<String>,
1064 /// Optional embedded tool-use result payload.
1065 pub tool_use_result: Option<Value>,
1066}
1067
1068/// An assistant response message with content blocks.
1069///
1070/// # Fields
1071///
1072/// - `content` — List of content blocks in the response.
1073/// - `model` — The model that generated this response.
1074/// - `parent_tool_use_id` — Tool use ID if this is a nested subagent response.
1075/// - `error` — Error type string if the response encountered an error
1076/// (e.g., `"authentication_failed"`, `"rate_limit"`, `"server_error"`).
1077#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1078pub struct AssistantMessage {
1079 /// Assistant content blocks.
1080 pub content: Vec<ContentBlock>,
1081 /// Model identifier used for generation.
1082 pub model: String,
1083 /// Optional parent tool use identifier.
1084 pub parent_tool_use_id: Option<String>,
1085 /// Optional error classification string.
1086 pub error: Option<String>,
1087}
1088
1089/// A system message with metadata.
1090///
1091/// # Fields
1092///
1093/// - `subtype` — The system message subtype identifier.
1094/// - `data` — The full raw data of the system message.
1095#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1096pub struct SystemMessage {
1097 /// System message subtype.
1098 pub subtype: String,
1099 /// Full raw system payload.
1100 pub data: Value,
1101}
1102
1103/// Token/tool usage reported in task-related system messages.
1104#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1105pub struct TaskUsage {
1106 /// Total token count used so far.
1107 pub total_tokens: i64,
1108 /// Number of tool invocations used so far.
1109 pub tool_uses: i64,
1110 /// Task duration in milliseconds.
1111 pub duration_ms: i64,
1112}
1113
1114/// Status values for task notification messages.
1115#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1116pub enum TaskNotificationStatus {
1117 /// Task completed successfully.
1118 #[serde(rename = "completed")]
1119 Completed,
1120 /// Task failed.
1121 #[serde(rename = "failed")]
1122 Failed,
1123 /// Task was stopped.
1124 #[serde(rename = "stopped")]
1125 Stopped,
1126}
1127
1128/// Typed view for `system` messages with subtype `task_started`.
1129#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1130pub struct TaskStartedMessage {
1131 /// Always `task_started`.
1132 pub subtype: String,
1133 /// Raw system payload.
1134 pub data: Value,
1135 /// Task identifier.
1136 pub task_id: String,
1137 /// Human-readable task description.
1138 pub description: String,
1139 /// Message UUID.
1140 pub uuid: String,
1141 /// Session identifier.
1142 pub session_id: String,
1143 /// Optional parent tool use id.
1144 pub tool_use_id: Option<String>,
1145 /// Optional task type.
1146 pub task_type: Option<String>,
1147}
1148
1149/// Typed view for `system` messages with subtype `task_progress`.
1150#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1151pub struct TaskProgressMessage {
1152 /// Always `task_progress`.
1153 pub subtype: String,
1154 /// Raw system payload.
1155 pub data: Value,
1156 /// Task identifier.
1157 pub task_id: String,
1158 /// Human-readable task description.
1159 pub description: String,
1160 /// Current task usage metrics.
1161 pub usage: TaskUsage,
1162 /// Message UUID.
1163 pub uuid: String,
1164 /// Session identifier.
1165 pub session_id: String,
1166 /// Optional parent tool use id.
1167 pub tool_use_id: Option<String>,
1168 /// Optional last tool name.
1169 pub last_tool_name: Option<String>,
1170}
1171
1172/// Typed view for `system` messages with subtype `task_notification`.
1173#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1174pub struct TaskNotificationMessage {
1175 /// Always `task_notification`.
1176 pub subtype: String,
1177 /// Raw system payload.
1178 pub data: Value,
1179 /// Task identifier.
1180 pub task_id: String,
1181 /// Task status.
1182 pub status: TaskNotificationStatus,
1183 /// Output file path.
1184 pub output_file: String,
1185 /// Human-readable task summary.
1186 pub summary: String,
1187 /// Message UUID.
1188 pub uuid: String,
1189 /// Session identifier.
1190 pub session_id: String,
1191 /// Optional parent tool use id.
1192 pub tool_use_id: Option<String>,
1193 /// Optional task usage metrics.
1194 pub usage: Option<TaskUsage>,
1195}
1196
1197impl SystemMessage {
1198 /// Returns a typed `TaskStartedMessage` view for `task_started` messages.
1199 pub fn as_task_started(&self) -> Option<TaskStartedMessage> {
1200 if self.subtype != "task_started" {
1201 return None;
1202 }
1203 let obj = self.data.as_object()?;
1204 Some(TaskStartedMessage {
1205 subtype: self.subtype.clone(),
1206 data: self.data.clone(),
1207 task_id: obj.get("task_id")?.as_str()?.to_string(),
1208 description: obj.get("description")?.as_str()?.to_string(),
1209 uuid: obj.get("uuid")?.as_str()?.to_string(),
1210 session_id: obj.get("session_id")?.as_str()?.to_string(),
1211 tool_use_id: obj
1212 .get("tool_use_id")
1213 .and_then(Value::as_str)
1214 .map(ToString::to_string),
1215 task_type: obj
1216 .get("task_type")
1217 .and_then(Value::as_str)
1218 .map(ToString::to_string),
1219 })
1220 }
1221
1222 /// Returns a typed `TaskProgressMessage` view for `task_progress` messages.
1223 pub fn as_task_progress(&self) -> Option<TaskProgressMessage> {
1224 if self.subtype != "task_progress" {
1225 return None;
1226 }
1227 let obj = self.data.as_object()?;
1228 let usage = serde_json::from_value::<TaskUsage>(obj.get("usage")?.clone()).ok()?;
1229 Some(TaskProgressMessage {
1230 subtype: self.subtype.clone(),
1231 data: self.data.clone(),
1232 task_id: obj.get("task_id")?.as_str()?.to_string(),
1233 description: obj.get("description")?.as_str()?.to_string(),
1234 usage,
1235 uuid: obj.get("uuid")?.as_str()?.to_string(),
1236 session_id: obj.get("session_id")?.as_str()?.to_string(),
1237 tool_use_id: obj
1238 .get("tool_use_id")
1239 .and_then(Value::as_str)
1240 .map(ToString::to_string),
1241 last_tool_name: obj
1242 .get("last_tool_name")
1243 .and_then(Value::as_str)
1244 .map(ToString::to_string),
1245 })
1246 }
1247
1248 /// Returns a typed `TaskNotificationMessage` view for `task_notification` messages.
1249 pub fn as_task_notification(&self) -> Option<TaskNotificationMessage> {
1250 if self.subtype != "task_notification" {
1251 return None;
1252 }
1253 let obj = self.data.as_object()?;
1254 let status =
1255 serde_json::from_value::<TaskNotificationStatus>(obj.get("status")?.clone()).ok()?;
1256 let usage = obj
1257 .get("usage")
1258 .and_then(|value| serde_json::from_value::<TaskUsage>(value.clone()).ok());
1259 Some(TaskNotificationMessage {
1260 subtype: self.subtype.clone(),
1261 data: self.data.clone(),
1262 task_id: obj.get("task_id")?.as_str()?.to_string(),
1263 status,
1264 output_file: obj.get("output_file")?.as_str()?.to_string(),
1265 summary: obj.get("summary")?.as_str()?.to_string(),
1266 uuid: obj.get("uuid")?.as_str()?.to_string(),
1267 session_id: obj.get("session_id")?.as_str()?.to_string(),
1268 tool_use_id: obj
1269 .get("tool_use_id")
1270 .and_then(Value::as_str)
1271 .map(ToString::to_string),
1272 usage,
1273 })
1274 }
1275}
1276
1277/// Final result message with cost and usage information.
1278///
1279/// This is the last message received for a query, containing summary statistics.
1280///
1281/// # Fields
1282///
1283/// - `subtype` — The result subtype (e.g., `"success"`, `"error"`).
1284/// - `duration_ms` — Total wall-clock duration in milliseconds.
1285/// - `duration_api_ms` — Time spent in API calls in milliseconds.
1286/// - `is_error` — Whether the query resulted in an error.
1287/// - `num_turns` — Number of conversation turns in the query.
1288/// - `session_id` — The session identifier.
1289/// - `stop_reason` — Optional reason for why the turn ended.
1290/// - `total_cost_usd` — Optional total cost in USD.
1291/// - `usage` — Optional token usage breakdown (input_tokens, output_tokens,
1292/// cache_creation_input_tokens, cache_read_input_tokens).
1293/// - `result` — Optional result text.
1294/// - `structured_output` — Optional structured output if `output_format` was configured.
1295#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1296pub struct ResultMessage {
1297 /// Result subtype.
1298 pub subtype: String,
1299 /// End-to-end duration in milliseconds.
1300 pub duration_ms: i64,
1301 /// API-only duration in milliseconds.
1302 pub duration_api_ms: i64,
1303 /// Indicates whether execution ended in error.
1304 pub is_error: bool,
1305 /// Number of turns performed.
1306 pub num_turns: i64,
1307 /// Session identifier.
1308 pub session_id: String,
1309 /// Optional reason for why the turn ended.
1310 pub stop_reason: Option<String>,
1311 /// Optional total cost in USD.
1312 pub total_cost_usd: Option<f64>,
1313 /// Optional usage summary payload.
1314 pub usage: Option<Value>,
1315 /// Optional text result.
1316 pub result: Option<String>,
1317 /// Optional structured output payload.
1318 pub structured_output: Option<Value>,
1319}
1320
1321/// Stream event for partial message updates during streaming.
1322///
1323/// Only received when `include_partial_messages` is set to `true` in [`ClaudeAgentOptions`].
1324///
1325/// # Fields
1326///
1327/// - `uuid` — Unique identifier for this event.
1328/// - `session_id` — Session identifier.
1329/// - `event` — The raw Claude API stream event data.
1330/// - `parent_tool_use_id` — Parent tool use ID if this event is from a subagent.
1331#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1332pub struct StreamEvent {
1333 /// Event identifier.
1334 pub uuid: String,
1335 /// Session identifier for this event.
1336 pub session_id: String,
1337 /// Raw stream event payload.
1338 pub event: Value,
1339 /// Optional parent tool use identifier.
1340 pub parent_tool_use_id: Option<String>,
1341}
1342
1343/// Session metadata returned by [`list_sessions`](crate::list_sessions).
1344#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1345pub struct SDKSessionInfo {
1346 /// Session identifier (UUID).
1347 pub session_id: String,
1348 /// Display summary for the session.
1349 pub summary: String,
1350 /// Last modified time in milliseconds since epoch.
1351 pub last_modified: i64,
1352 /// Session file size in bytes.
1353 pub file_size: u64,
1354 /// User-defined custom title if present.
1355 pub custom_title: Option<String>,
1356 /// First meaningful prompt from the session.
1357 pub first_prompt: Option<String>,
1358 /// Git branch associated with the session.
1359 pub git_branch: Option<String>,
1360 /// Working directory associated with the session.
1361 pub cwd: Option<String>,
1362}
1363
1364/// User/assistant message returned by [`get_session_messages`](crate::get_session_messages).
1365#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1366pub struct SessionMessage {
1367 /// Message type (`"user"` or `"assistant"`).
1368 #[serde(rename = "type")]
1369 pub type_: String,
1370 /// Message UUID.
1371 pub uuid: String,
1372 /// Session identifier.
1373 pub session_id: String,
1374 /// Raw Anthropic message payload.
1375 pub message: Value,
1376 /// Always `None` for top-level conversation messages.
1377 pub parent_tool_use_id: Option<String>,
1378}
1379
1380/// Union type of all possible messages from the Claude Code CLI.
1381///
1382/// When receiving messages via [`ClaudeSdkClient::receive_message()`](crate::ClaudeSdkClient::receive_message)
1383/// or iterating results from [`query()`](crate::query_fn::query), each message will be one of these variants.
1384#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1385pub enum Message {
1386 /// A user input message echoed back.
1387 User(UserMessage),
1388 /// An assistant response with content blocks.
1389 Assistant(AssistantMessage),
1390 /// A system notification or status message.
1391 System(SystemMessage),
1392 /// The final result message with cost/usage information.
1393 Result(ResultMessage),
1394 /// A partial streaming event (only when `include_partial_messages` is enabled).
1395 StreamEvent(StreamEvent),
1396}
1397
1398/// Controls extended thinking behavior.
1399///
1400/// Extended thinking allows Claude to reason through complex problems before responding.
1401///
1402/// # Variants
1403///
1404/// - `Adaptive` — Claude adaptively decides when and how much to think.
1405/// - `Enabled { budget_tokens }` — Enable thinking with a specific token budget.
1406/// - `Disabled` — Disable extended thinking entirely.
1407#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1408#[serde(tag = "type")]
1409pub enum ThinkingConfig {
1410 /// Let Claude pick thinking depth adaptively.
1411 #[serde(rename = "adaptive")]
1412 Adaptive,
1413 /// Enable explicit thinking with a fixed token budget.
1414 #[serde(rename = "enabled")]
1415 Enabled {
1416 /// Maximum reasoning token budget when thinking is enabled.
1417 budget_tokens: i64,
1418 },
1419 /// Disable thinking blocks.
1420 #[serde(rename = "disabled")]
1421 Disabled,
1422}
1423
1424/// MCP tool annotations providing hints about tool behavior.
1425///
1426/// These annotations help Claude and the system understand tool characteristics
1427/// for better permission handling and execution planning.
1428///
1429/// # Fields
1430///
1431/// - `read_only_hint` — Whether the tool only reads data without side effects.
1432/// - `destructive_hint` — Whether the tool performs destructive operations.
1433/// - `idempotent_hint` — Whether calling the tool multiple times has the same effect as once.
1434/// - `open_world_hint` — Whether the tool interacts with external systems.
1435#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
1436#[serde(rename_all = "camelCase")]
1437pub struct ToolAnnotations {
1438 /// Hint that the tool is read-only.
1439 #[serde(skip_serializing_if = "Option::is_none")]
1440 pub read_only_hint: Option<bool>,
1441 /// Hint that the tool may be destructive.
1442 #[serde(skip_serializing_if = "Option::is_none")]
1443 pub destructive_hint: Option<bool>,
1444 /// Hint that repeated calls have same effect.
1445 #[serde(skip_serializing_if = "Option::is_none")]
1446 pub idempotent_hint: Option<bool>,
1447 /// Hint that the tool interacts with external/open systems.
1448 #[serde(skip_serializing_if = "Option::is_none")]
1449 pub open_world_hint: Option<bool>,
1450}
1451
1452/// Main configuration for Claude Code queries and sessions.
1453///
1454/// This is the primary configuration struct passed to [`query()`](crate::query_fn::query) or
1455/// [`ClaudeSdkClient::new()`](crate::ClaudeSdkClient::new). All fields are optional
1456/// and have sensible defaults.
1457///
1458/// Corresponds to the Python SDK's `ClaudeAgentOptions` dataclass.
1459///
1460/// # Fields
1461///
1462/// | Field | Description |
1463/// |-------|-------------|
1464/// | `tools` | Tools configuration — explicit list or preset |
1465/// | `allowed_tools` | List of allowed tool names |
1466/// | `system_prompt` | System prompt — custom text or preset |
1467/// | `mcp_servers` | MCP server configurations |
1468/// | `permission_mode` | Permission mode for tool usage |
1469/// | `continue_conversation` | Continue the most recent conversation |
1470/// | `resume` | Session ID to resume |
1471/// | `max_turns` | Maximum conversation turns |
1472/// | `max_budget_usd` | Maximum budget in USD for the session |
1473/// | `disallowed_tools` | List of disallowed tool names |
1474/// | `model` | Claude model to use |
1475/// | `fallback_model` | Fallback model if the primary fails |
1476/// | `betas` | Beta features to enable |
1477/// | `permission_prompt_tool_name` | MCP tool name for permission prompts |
1478/// | `cwd` | Current working directory |
1479/// | `cli_path` | Custom path to the Claude Code CLI executable |
1480/// | `settings` | Path to settings file or inline JSON |
1481/// | `add_dirs` | Additional directories Claude can access |
1482/// | `env` | Environment variables |
1483/// | `extra_args` | Additional CLI arguments |
1484/// | `max_buffer_size` | Maximum bytes when buffering CLI stdout |
1485/// | `can_use_tool` | Tool permission callback function |
1486/// | `hooks` | Hook configurations for intercepting events |
1487/// | `user` | User identifier |
1488/// | `include_partial_messages` | Include [`StreamEvent`] partial messages |
1489/// | `fork_session` | Fork to new session ID when resuming |
1490/// | `agents` | Programmatically defined subagents |
1491/// | `setting_sources` | Which filesystem settings to load |
1492/// | `sandbox` | Sandbox configuration |
1493/// | `strict_settings_merge` | Fail instead of warn when sandbox/settings JSON merge fails |
1494/// | `plugins` | Local plugins to load |
1495/// | `max_thinking_tokens` | *Deprecated:* use `thinking` instead |
1496/// | `thinking` | Extended thinking configuration |
1497/// | `effort` | Effort level (`"low"`, `"medium"`, `"high"`, `"max"`) |
1498/// | `output_format` | Structured output format (e.g., JSON schema) |
1499/// | `enable_file_checkpointing` | Enable file change tracking for rewinding |
1500#[derive(Clone)]
1501pub struct ClaudeAgentOptions {
1502 /// Tools configuration. Use [`ToolsOption::Preset`] with [`ToolsPreset::default()`]
1503 /// for Claude Code's default tools.
1504 pub tools: Option<ToolsOption>,
1505 /// List of allowed tool names.
1506 pub allowed_tools: Vec<String>,
1507 /// System prompt configuration. Pass a string via [`SystemPrompt::Text`] for a custom
1508 /// prompt, or use [`SystemPrompt::Preset`] for Claude Code's built-in system prompt.
1509 pub system_prompt: Option<SystemPrompt>,
1510 /// MCP server configurations or path to config file.
1511 pub mcp_servers: McpServersOption,
1512 /// Permission mode for tool usage.
1513 pub permission_mode: Option<PermissionMode>,
1514 /// Continue the most recent conversation.
1515 pub continue_conversation: bool,
1516 /// Session ID to resume.
1517 pub resume: Option<String>,
1518 /// Maximum conversation turns.
1519 pub max_turns: Option<i64>,
1520 /// Maximum budget in USD for the session.
1521 pub max_budget_usd: Option<f64>,
1522 /// List of disallowed tool names.
1523 pub disallowed_tools: Vec<String>,
1524 /// Claude model to use (e.g., `"sonnet"`, `"opus"`).
1525 pub model: Option<String>,
1526 /// Fallback model to use if the primary model fails.
1527 pub fallback_model: Option<String>,
1528 /// Beta features to enable.
1529 pub betas: Vec<String>,
1530 /// MCP tool name for permission prompts. Mutually exclusive with `can_use_tool`.
1531 pub permission_prompt_tool_name: Option<String>,
1532 /// Current working directory for the Claude Code process.
1533 pub cwd: Option<PathBuf>,
1534 /// Custom path to the Claude Code CLI executable.
1535 pub cli_path: Option<PathBuf>,
1536 /// Path to settings file or inline JSON string.
1537 pub settings: Option<String>,
1538 /// Additional directories Claude can access.
1539 pub add_dirs: Vec<PathBuf>,
1540 /// Environment variables to pass to the CLI process.
1541 pub env: HashMap<String, String>,
1542 /// Additional CLI arguments to pass directly to the CLI.
1543 /// Keys are flag names (without `--`), values are optional flag values.
1544 pub extra_args: HashMap<String, Option<String>>,
1545 /// Maximum bytes when buffering CLI stdout. Defaults to 1MB.
1546 pub max_buffer_size: Option<usize>,
1547 /// Custom tool permission callback function.
1548 pub can_use_tool: Option<CanUseToolCallback>,
1549 /// Hook configurations for intercepting events. Keys are hook event names
1550 /// (e.g., `"PreToolUse"`, `"PostToolUse"`, `"UserPromptSubmit"`).
1551 pub hooks: Option<HashMap<String, Vec<HookMatcher>>>,
1552 /// User identifier.
1553 pub user: Option<String>,
1554 /// Include partial message streaming events ([`StreamEvent`]).
1555 pub include_partial_messages: bool,
1556 /// When resuming with `resume`, fork to a new session ID instead of continuing
1557 /// the original session.
1558 pub fork_session: bool,
1559 /// Programmatically defined subagents.
1560 pub agents: Option<HashMap<String, AgentDefinition>>,
1561 /// Control which filesystem settings to load.
1562 /// When omitted, no settings are loaded (SDK isolation).
1563 pub setting_sources: Option<Vec<SettingSource>>,
1564 /// Sandbox configuration for command execution isolation.
1565 pub sandbox: Option<SandboxSettings>,
1566 /// When `true`, fail command construction if sandbox merge with `settings` fails.
1567 /// When `false`, merge failures emit a warning and fallback to sandbox-only settings.
1568 pub strict_settings_merge: bool,
1569 /// Local plugins to load.
1570 pub plugins: Vec<SdkPluginConfig>,
1571 /// *Deprecated:* Maximum tokens for thinking blocks. Use `thinking` instead.
1572 pub max_thinking_tokens: Option<i64>,
1573 /// Extended thinking configuration. Takes precedence over `max_thinking_tokens`.
1574 pub thinking: Option<ThinkingConfig>,
1575 /// Effort level for thinking depth (`"low"`, `"medium"`, `"high"`, `"max"`).
1576 pub effort: Option<String>,
1577 /// Output format for structured responses.
1578 /// Example: `{"type": "json_schema", "schema": {...}}`
1579 pub output_format: Option<Value>,
1580 /// Enable file change tracking for rewinding via
1581 /// [`ClaudeSdkClient::rewind_files()`](crate::ClaudeSdkClient::rewind_files).
1582 pub enable_file_checkpointing: bool,
1583 /// Optional callback for stderr output lines from the CLI process.
1584 ///
1585 /// When set, stderr is piped and each non-empty line is passed to this callback.
1586 /// When `None`, stderr is still drained to prevent subprocess blocking, but
1587 /// lines are discarded.
1588 pub stderr: Option<StderrCallback>,
1589}
1590
1591/// Callback type for receiving stderr output lines from the CLI process.
1592pub type StderrCallback = Arc<dyn Fn(String) + Send + Sync>;
1593
1594impl Default for ClaudeAgentOptions {
1595 fn default() -> Self {
1596 Self {
1597 tools: None,
1598 allowed_tools: Vec::new(),
1599 system_prompt: None,
1600 mcp_servers: McpServersOption::None,
1601 permission_mode: None,
1602 continue_conversation: false,
1603 resume: None,
1604 max_turns: None,
1605 max_budget_usd: None,
1606 disallowed_tools: Vec::new(),
1607 model: None,
1608 fallback_model: None,
1609 betas: Vec::new(),
1610 permission_prompt_tool_name: None,
1611 cwd: None,
1612 cli_path: None,
1613 settings: None,
1614 add_dirs: Vec::new(),
1615 env: HashMap::new(),
1616 extra_args: HashMap::new(),
1617 max_buffer_size: None,
1618 can_use_tool: None,
1619 hooks: None,
1620 user: None,
1621 include_partial_messages: false,
1622 fork_session: false,
1623 agents: None,
1624 setting_sources: None,
1625 sandbox: None,
1626 strict_settings_merge: false,
1627 plugins: Vec::new(),
1628 max_thinking_tokens: None,
1629 thinking: None,
1630 effort: None,
1631 output_format: None,
1632 enable_file_checkpointing: false,
1633 stderr: None,
1634 }
1635 }
1636}