Skip to main content

DuplexOptions

Struct DuplexOptions 

Source
pub struct DuplexOptions { /* private fields */ }
Expand description

Configuration for DuplexSession::spawn.

Builder methods cover the spawn-time options shared with QueryCommand; the flag emission lives on a common internal SharedSpawnArgs, so the oneshot and duplex paths cannot drift on how a knob is rendered. The spawn call always includes --print --verbose --input-format stream-json --output-format stream-json regardless of these options.

A few QueryCommand knobs are intentionally not surfaced here because they only make sense for a oneshot run or are owned by the duplex transport itself:

  • Transport is fixed: output_format, input_format, verbose, and prompt_via_stdin are pinned by the duplex spawn and not configurable. Partial message chunks are off by default; opt in with Self::include_partial_messages.
  • retry_policy reruns a whole oneshot invocation; a duplex session holds one child open across turns, so there is nothing to retry at this layer.
  • brief and from_pr shape a single oneshot run (SendUserMessage for one-turn agent-to-user replies, resume-from-PR startup); a duplex host drives turns and session selection itself.
  • prompt_suggestions and replay_user_messages shape stdin/stream echoing; the duplex layer owns its own stream plumbing.

Use Self::arg if you need one of these on a duplex spawn anyway.

Resource and time policies (Self::max_frame_bytes, Self::max_turn_bytes, Self::max_turn_events, Self::turn_timeout, Self::control_timeout) are host-side and emit no CLI flags. All are unlimited by default. See the module docs.

Implementations§

Source§

impl DuplexOptions

Source

pub fn model(self, model: impl Into<String>) -> Self

Set the model for this session (--model).

Source

pub fn system_prompt(self, prompt: impl Into<String>) -> Self

Set the system prompt for this session (--system-prompt).

Source

pub fn append_system_prompt(self, prompt: impl Into<String>) -> Self

Append to the default system prompt (--append-system-prompt).

Source

pub fn resume(self, session_id: impl Into<String>) -> Self

Resume a prior session by id (--resume <session_id>).

Mirrors QueryCommand::resume for the duplex path. The spawned claude process picks up the conversation that produced session_id and continues it; turns sent through DuplexSession::send append to the existing history rather than starting fresh.

Use case: a host (IDE, MCP server, agent backend) wants to upgrade a passive on-disk session to a live duplex one – pulls the session_id out of the existing JSONL log, opens a duplex session here, and the next turn extends the same conversation.

resume and Self::continue_session are mutually exclusive at the CLI; passing both lets the CLI decide (it errors today).

Source

pub fn continue_session(self) -> Self

Continue the most recent session in the current working directory (--continue).

Mirrors QueryCommand::continue_session for the duplex path. Use Self::resume to pick a specific session id; use this when “the last one” is what you want.

Source

pub fn worktree(self, name: Option<impl Into<String>>) -> Self

Run this session in a fresh git worktree (--worktree [name]).

name is the optional worktree name (the CLI auto-generates one if omitted). Calling this method always enables the worktree flag, with or without a name.

Use case: an agent host wants the chat’s writes isolated from the current working tree – the chat opens with a fresh worktree, mutations land there, and the host can inspect or merge later.

Source

pub fn agent(self, name: impl Into<String>) -> Self

Pin the session to a named subagent (--agent <name>).

name is resolved by the CLI in this order: inline definitions from Self::agents_json, then user-level ~/.claude/agents/<name>.md files, then project-level dirs loaded by the active --setting-sources.

Caveat: as of Claude Code 2.1.143, the CLI silently ignores an unknown name and falls back to the default behavior – no warning, no error. Callers that want a hard “agent must exist” semantics should validate the name out of band (e.g. via crate::artifacts::AgentsRoot::get) before passing it here.

Source

pub fn agents_json(self, json: impl Into<String>) -> Self

Inline subagent definitions for this session (--agents <json>).

json is a JSON object keyed by agent name, with each value carrying at least description and prompt. Inline definitions take precedence over on-disk ~/.claude/agents/*.md of the same name. Pass Self::agent to select which one to use as the session’s persona.

Example: {"reviewer": {"description": "Reviews code", "prompt": "You are a code reviewer"}}.

Source

pub fn permission_mode(self, mode: PermissionMode) -> Self

Set the permission mode for this session (--permission-mode <mode>).

Mirrors QueryCommand::permission_mode for the duplex path. The default mode (when this method isn’t called) drops to the CLI’s interactive prompt for every tool-use approval, which is broken for non-interactive duplex sessions – nothing answers the prompts and the session stalls or fails. Call this with PermissionMode::AcceptEdits for the “edit files autonomously” pattern, PermissionMode::Plan for read-only planning, etc.

Bypass mode is a footgun; reach for Self::dangerously_skip_permissions (or, for stricter discipline, crate::dangerous::DangerousClient) when you really need it.

Source

pub fn forward_subagent_text(self) -> Self

Forward nested subagent text and thinking as stream-json messages (--forward-subagent-text). Parent tool-use IDs remain in the raw events. Only meaningful with stream-json output; duplex sessions already use it.

Source

pub fn allow_dangerously_skip_permissions(self) -> Self

Make bypass mode available without activating it (--allow-dangerously-skip-permissions). This does not select a bypass permission mode or disable permission checks by itself.

Source

pub fn dangerously_skip_permissions(self) -> Self

Pass --dangerously-skip-permissions to the spawned session.

Bypasses ALL permission checks – file edits, bash, network, the lot. Use only when you know the session runs in a trusted sandbox (a fresh worktree, a container, etc.). For most “run autonomously” cases you want Self::permission_mode with PermissionMode::AcceptEdits instead.

Source

pub fn session_id(self, id: impl Into<String>) -> Self

Start a new session under a caller-chosen id (--session-id <uuid>).

Mirrors QueryCommand::session_id for the duplex path. Unlike Self::resume (pick up an existing session) or Self::continue_session (pick up the most recent one), this mints a fresh session whose id the host knows up front – useful when the host indexes sessions externally before the first turn completes.

Source

pub fn json_schema(self, schema: impl Into<String>) -> Self

Set a JSON schema for structured output validation (--json-schema <schema>).

Mirrors QueryCommand::json_schema for the duplex path. schema is the inline JSON of the schema; the turn’s closing result message carries the validated structured_output.

Source

pub fn allowed_tools<I, T>(self, tools: I) -> Self
where I: IntoIterator<Item = T>, T: Into<ToolPattern>,

Add allowed tool patterns (--allowed-tools).

Mirrors QueryCommand::allowed_tools for the duplex path: accepts anything convertible into ToolPattern, including bare strings (e.g. "Bash", "Bash(git log:*)", "mcp__my-server__*"), and joins them into the comma-separated form the CLI expects.

Source

pub fn allowed_tool(self, tool: impl Into<ToolPattern>) -> Self

Add a single allowed tool pattern.

Source

pub fn disallowed_tools<I, T>(self, tools: I) -> Self
where I: IntoIterator<Item = T>, T: Into<ToolPattern>,

Add disallowed tool patterns (--disallowed-tools).

Source

pub fn disallowed_tool(self, tool: impl Into<ToolPattern>) -> Self

Add a single disallowed tool pattern.

Source

pub fn max_turns(self, turns: u32) -> Self

Cap the number of agentic turns (--max-turns <n>).

The cap applies per turn sent through DuplexSession::send; a turn that exhausts it closes with an error_max_turns result rather than an assistant reply.

Source

pub fn max_budget_usd(self, budget: f64) -> Self

Cap claude’s own spend for the session (--max-budget-usd <usd>).

This is the CLI’s cap, checked post-hoc after each API call, so a session can overspend before tripping. It is distinct from the wrapper’s BudgetTracker ceiling, which gates dispatch host-side – attach one via Conversation::with_budget to stop a duplex conversation before the next turn is sent.

Source

pub fn fallback_model(self, model: impl Into<String>) -> Self

Set a fallback model for when the primary is overloaded (--fallback-model <model>).

Source

pub fn effort(self, effort: Effort) -> Self

Set the reasoning effort level (--effort <level>).

Source

pub fn add_dir(self, dir: impl Into<String>) -> Self

Add an additional directory for tool access (--add-dir <dir>, repeatable).

Source

pub fn mcp_config(self, path: impl Into<String>) -> Self

Add an MCP config file path (--mcp-config <path>, repeatable).

Pair with crate::McpConfigBuilder to generate the file.

Source

pub fn strict_mcp_config(self) -> Self

Only use MCP servers from --mcp-config files, ignoring the user- and project-level MCP configuration (--strict-mcp-config).

Source

pub fn setting_sources(self, sources: impl Into<String>) -> Self

Comma-separated list of setting sources the CLI loads, for example "user,project,local" (--setting-sources). Pass an empty string to load none, sealing the session’s promptspace against ambient project config (agents, skills, CLAUDE.md). Mirrors QueryCommand::setting_sources.

Source

pub fn hermetic(self) -> Self

Seal the ambient ~/.claude config for a reproducible session (HermeticScope::Full).

Sets --setting-sources "", --strict-mcp-config, and --exclude-dynamic-system-prompt-sections. This gives a warm duplex session a clean seal without the Self::arg escape hatch. Mirrors QueryCommand::hermetic.

This is not Self::bare: a hermetic seal leaves OAuth and keychain auth working, whereas --bare forces API-key billing. A later Self::setting_sources call overrides the seal scope.

Source

pub fn hermetic_scoped(self, scope: HermeticScope) -> Self

Seal the ambient ~/.claude config at an explicit HermeticScope.

See Self::hermetic for the flag set. Mirrors QueryCommand::hermetic_scoped.

Source

pub fn no_session_persistence(self) -> Self

Do not persist the session to on-disk history (--no-session-persistence).

Source

pub fn tools(self, tools: impl IntoIterator<Item = impl Into<String>>) -> Self

Set the list of available built-in tools (--tools).

Use "" to disable all tools, "default" for all tools, or specific tool names like ["Bash", "Edit", "Read"]. This is distinct from Self::allowed_tools, which controls tool permissions rather than which built-ins load. Mirrors QueryCommand::tools.

Source

pub fn file(self, spec: impl Into<String>) -> Self

Add a file resource to download at startup (--file).

Format: file_id:relative_path (e.g. file_abc:doc.txt). Repeatable. Mirrors QueryCommand::file.

Source

pub fn settings(self, settings: impl Into<String>) -> Self

Path to a settings JSON file or a JSON string (--settings).

Mirrors QueryCommand::settings.

Source

pub fn fork_session(self) -> Self

When resuming, create a new session id instead of reusing the original (--fork-session).

Only meaningful alongside Self::resume or Self::continue_session. Mirrors QueryCommand::fork_session.

Source

pub fn debug_filter(self, filter: impl Into<String>) -> Self

Enable debug logging with an optional filter, e.g. "api,hooks" (--debug). Mirrors QueryCommand::debug_filter.

Source

pub fn debug_file(self, path: impl Into<String>) -> Self

Write debug logs to the given file path (--debug-file).

Mirrors QueryCommand::debug_file.

Source

pub fn betas(self, betas: impl Into<String>) -> Self

Beta feature headers for API key authentication (--betas).

Mirrors QueryCommand::betas.

Source

pub fn plugin_dir(self, dir: impl Into<String>) -> Self

Load plugins from the given directory for this session (--plugin-dir). Repeatable. Mirrors QueryCommand::plugin_dir.

Source

pub fn plugin_url(self, url: impl Into<String>) -> Self

Fetch a plugin .zip from a URL for this session only (--plugin-url). Repeatable. Mirrors QueryCommand::plugin_url.

Source

pub fn tmux(self) -> Self

Create a tmux session for the worktree (--tmux).

Mirrors QueryCommand::tmux.

Source

pub fn bare(self) -> Self

Run in minimal mode (--bare).

Skips hooks, LSP, plugin sync, attribution, auto-memory, background prefetches, keychain reads, and CLAUDE.md auto-discovery. Anthropic auth is restricted to ANTHROPIC_API_KEY or apiKeyHelper; OAuth and keychain are never read. Mirrors QueryCommand::bare.

Source

pub fn safe_mode(self) -> Self

Start with all customizations disabled (--safe-mode).

Disables CLAUDE.md, skills, plugins, hooks, MCP servers, custom commands and agents, and output styles for troubleshooting. Mirrors QueryCommand::safe_mode.

Source

pub fn disable_slash_commands(self) -> Self

Disable all slash-command skills (--disable-slash-commands).

Mirrors QueryCommand::disable_slash_commands.

Source

pub fn include_hook_events(self) -> Self

Include every hook lifecycle event in the stream-json output (--include-hook-events).

Duplex sessions always run in stream-json, so this takes effect without extra configuration. Mirrors QueryCommand::include_hook_events.

Source

pub fn exclude_dynamic_system_prompt_sections(self) -> Self

Move per-machine sections (cwd, env info, memory paths, git status) out of the system prompt and into the first user message (--exclude-dynamic-system-prompt-sections).

Improves cross-user prompt-cache reuse. Only applies with the default system prompt; ignored with Self::system_prompt. Mirrors QueryCommand::exclude_dynamic_system_prompt_sections.

Source

pub fn name(self, name: impl Into<String>) -> Self

Set a display name for this session (--name). Shown in the /resume picker and terminal title. Mirrors QueryCommand::name.

Source

pub fn arg(self, arg: impl Into<String>) -> Self

Add a raw argument to the spawn command line.

Escape hatch for flags not covered by the dedicated builder methods.

Source

pub fn subscriber_capacity(self, capacity: usize) -> Self

Set the per-session broadcast::Sender capacity backing DuplexSession::subscribe.

Defaults to DEFAULT_SUBSCRIBER_CAPACITY (256). Larger values give slow subscribers more room before they Lagged; smaller values reclaim memory if you do not subscribe.

Source

pub fn on_permission(self, handler: PermissionHandler) -> Self

Register a PermissionHandler to answer the CLI’s tool-use permission prompts in-flight.

When set, the spawn command line includes --permission-prompt-tool stdio, which configures the CLI to emit control_request messages for tool use over the duplex channel rather than blocking on a TUI prompt.

Without a handler, the session does not pass --permission-prompt-tool and the CLI applies its default permission policy (driven by --permission-mode).

Runs only when the CLI’s permission rules request a decision. Allowed tools or permissive modes may resolve an action without calling it. Configure an explicit ask rule through Self::settings for actions that should reach the callback. The resident transport keeps stdin open; native denial and deferred-denial are tested at both supported endpoints.

Source

pub fn include_partial_messages(self) -> Self

Emit partial message chunks as they arrive (--include-partial-messages). Off by default.

The CLI then writes stream_event messages while a turn is in progress. They are broadcast to DuplexSession::subscribe receivers as InboundEvent::StreamEvent and retained in TurnResult::events like any other event, so a long reply can produce many events. Pair this with Self::max_turn_events or Self::max_turn_bytes when per-turn memory must be bounded.

Source

pub fn max_frame_bytes(self, bytes: usize) -> Self

Cap the size of one stdout frame (one NDJSON line), in bytes, including its newline terminator. Default: unlimited.

The check runs before an unterminated line is extended, so a child that writes an endless line without a newline cannot grow the retained raw frame past this size. Applies whether or not a turn is in flight. Exceeding it closes the session with Error::DuplexLimitExceeded (see the module docs).

ClaudeBuilder::output_limit does not apply to duplex sessions.

Source

pub fn max_turn_bytes(self, bytes: usize) -> Self

Cap the stdout bytes consumed during one turn. Default: unlimited.

Counts every byte read while a turn is pending, from the moment the session accepts the DuplexSession::send through the closing result line: newline terminators, blank lines, and lines that fail to parse all count. The counter resets for each turn; bytes read while no turn is pending do not count, except for a partial frame carried into the new turn: its buffered prefix counts too. Exceeding the limit closes the session with Error::DuplexLimitExceeded.

Source

pub fn max_turn_events(self, events: usize) -> Self

Cap the number of events retained in one turn’s TurnResult::events. Default: unlimited.

The count resets for each turn. Exceeding it closes the session with Error::DuplexLimitExceeded instead of returning a truncated turn. This is separate from Self::subscriber_capacity: a slow subscriber sees RecvError::Lagged and the session continues, while a retained-event overflow ends the session.

Source

pub fn turn_timeout(self, timeout: Duration) -> Self

Bound each turn with a deadline. Default: none.

The clock starts when the session task accepts a DuplexSession::send, before the prompt is written to stdin, and stops when the closing result line is read. The deadline covers the stdin write, every PermissionHandler call made during the turn, and any wait for DuplexSession::respond_to_permission after a PermissionDecision::Defer. Expiry closes the session with Error::DuplexDeadlineExceeded.

Independent of the client’s ClaudeBuilder::timeout, which does not apply to duplex sessions. An idle session with no pending turn has no lifetime limit. Cleanup can extend the wait beyond the deadline by the configured kill grace and process settlement time. Zero expires immediately; durations too large for the clock are treated as unlimited. An expired deadline takes precedence over a result still awaiting dispatch, even if that result is already buffered.

Source

pub fn control_timeout(self, timeout: Duration) -> Self

Bound each outbound control request, such as DuplexSession::interrupt, with a deadline. Default: none.

The clock starts when the session task accepts the request, before it is written to stdin, and stops when the matching control_response is read. The acknowledgment is independent of any turn result: an interrupted turn’s result does not satisfy this deadline, and an acknowledgment does not end the turn. Expiry closes the session with Error::DuplexDeadlineExceeded. Cleanup can extend the wait beyond the deadline; zero and unrepresentable durations have the same behavior as Self::turn_timeout.

Source

pub fn to_command_string(&self, claude: &Claude) -> String

Return the full spawn command as a string that could be run in a shell.

The duplex analog of QueryCommand::to_command_string: the binary path from the Claude client plus the exact arguments DuplexSession::spawn would pass for these options, including the client’s global args. Both share one args-assembly path, so this preview always matches the real spawn. Arguments containing spaces or special shell characters are shell-quoted.

§Example
use claude_wrapper::{Claude, DuplexOptions};

let claude = Claude::builder().build()?;

let opts = DuplexOptions::default()
    .agent("reviewer")
    .setting_sources("project");

println!("Would spawn: {}", opts.to_command_string(&claude));

Trait Implementations§

Source§

impl Clone for DuplexOptions

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for DuplexOptions

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for DuplexOptions

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more