claude-wrapper
A type-safe Claude Code CLI wrapper for Rust
Overview
claude-wrapper provides a type-safe builder-pattern interface for invoking the claude CLI programmatically. It follows the same design philosophy as docker-wrapper and terraform-wrapper: each CLI subcommand is a builder struct that produces typed output.
Perfect for Rust applications that need to integrate with Claude Code CLI.
Installation
Quick Start
use ;
async
Two-Layer Builder Architecture
The Claude client holds shared configuration (binary path, environment, timeout). Command builders hold per-invocation options and call execute(&claude).
Claude Client
Configure once, reuse across commands:
let claude = builder
.env
.timeout_secs
.build?;
Options:
binary()- Path toclaudebinary (auto-detected from PATH by default)working_dir()- Working directory for commandsenv()/envs()- Set environment variablestimeout_secs()/timeout()- Command timeout (no default)arg()- Add a global argument applied to every commandretry()- Default [RetryPolicy] applied to every command
Command Builders
Each CLI subcommand is a separate builder. Available commands:
Query
QueryCommand- The workhorse;claude -pwith full option coverage
MCP server management
McpListCommand/McpGetCommand/McpAddCommand/McpAddJsonCommand/McpRemoveCommand/McpAddFromDesktopCommand/McpResetProjectChoicesCommand/McpServeCommand
Plugins
PluginListCommand/PluginInstallCommand/PluginUninstallCommand/PluginEnableCommand/PluginDisableCommand/PluginUpdateCommand/PluginValidateCommand
Plugin marketplace
MarketplaceListCommand/MarketplaceAddCommand/MarketplaceRemoveCommand/MarketplaceUpdateCommand
Auth
AuthStatusCommand/AuthLoginCommand/AuthLogoutCommand/SetupTokenCommand
Misc
VersionCommand- Get CLI versionDoctorCommand- Run health checkAgentsCommand- List available agentsRawCommand- Escape hatch for unsupported subcommands
QueryCommand: The Workhorse
Full coverage of claude -p (print mode). QueryCommand exposes a builder method for every CLI flag; see docs.rs for the full list. The common ones:
| Method | CLI flag | Purpose |
|---|---|---|
model() |
--model |
Model alias or full ID |
system_prompt() / append_system_prompt() |
--system-prompt / --append-system-prompt |
Override or extend the system prompt |
output_format() |
--output-format |
text, json, stream-json |
effort() |
--effort |
low, medium, high |
max_turns() |
--max-turns |
Turn cap |
max_budget_usd() |
--max-budget-usd |
Spend cap |
permission_mode() |
--permission-mode |
default, acceptEdits, bypassPermissions, dontAsk, plan, auto |
allowed_tools() / disallowed_tools() / tools() |
tool-filter flags | Allow/deny/restrict tools |
mcp_config() / strict_mcp_config() |
--mcp-config / --strict-mcp-config |
MCP server config |
json_schema() |
--json-schema |
Structured output validation |
agent() / agents_json() |
--agent / --agents |
Agent or custom agents JSON |
no_session_persistence() |
--no-session-persistence |
Don't save the session to disk |
dangerously_skip_permissions() |
--dangerously-skip-permissions |
Sandbox escape hatch |
input_format() / include_partial_messages() |
--input-format / --include-partial-messages |
Input/streaming shape |
settings() / fallback_model() / add_dir() / file() |
various | Misc per-turn knobs |
Raw session flags (prefer Session for multi-turn)
| Method | CLI flag | Purpose |
|---|---|---|
continue_session() |
--continue |
Resume most recent session |
resume() |
--resume |
Resume a specific session id |
session_id() |
--session-id |
Force a session id |
fork_session() |
--fork-session |
Fork when resuming |
For multi-turn conversations you almost always want Session instead, which threads the id across turns automatically.
Usage Examples
Simple query with model override:
let output = new
.model
.execute
.await?;
println!;
JSON output with schema validation:
let output = new
.output_format
.json_schema
.execute
.await?;
With permissions and tools:
let output = new
.model
.permission_mode
.allowed_tools
.max_budget_usd
.execute
.await?;
Low-level session flags on QueryCommand (rarely needed):
// Force a specific session id
let output = new
.session_id
.execute
.await?;
// Resume later
let output = new
.resume
.execute
.await?;
Session management
For multi-turn conversations, wrap the client in an Arc and use Session. It threads the CLI session_id across turns automatically, tracks cumulative cost + history, and supports both plain-prompt and streaming turns:
use Arc;
use ;
use Session;
let claude = new;
// Fresh session
let mut session = new;
// Plain prompt: session_id is captured from the first turn
let first = session.send.await?;
// Full control: pass a configured QueryCommand. Any session-related
// flags on `cmd` are overridden with this session's current id so
// they can't conflict.
let second = session
.execute
.await?;
// Reattach to an existing session id
let mut resumed = resume;
let next = resumed.send.await?;
// Cumulative state
println!;
println!;
println!;
Session is Send + Sync and holds an Arc<Claude>, so it can be
moved between tasks or stored in long-lived actor state. Streaming
turns use Session::stream / Session::stream_execute, which capture
the session id from the first event that carries one — and persist
it even if the stream errors partway through.
Streaming NDJSON events
For real-time output, use stream_query(). The handler is called once per parsed NDJSON line:
use ;
use ;
let claude = builder.build?;
let cmd = new
.output_format;
stream_query.await?;
For multi-turn streaming with automatic session-id capture, use Session::stream / Session::stream_execute instead.
MCP Server Commands
List Servers
let output = new
.execute
.await?;
println!;
Add HTTP Server
new
.transport
.execute
.await?;
Add Stdio Server
new
.server_args
.env
.execute
.await?;
Add from JSON
new
.execute
.await?;
Remove Server
new
.execute
.await?;
MCP config builder
Generate .mcp.json files programmatically:
use McpConfigBuilder;
new
.http_server
.stdio_server
.write_to?;
With the tempfile feature (on by default), build_temp() writes to a temporary file that is deleted when the returned TempMcpConfig is dropped — useful for one-shot queries.
Plugin Management
// List plugins
new.execute.await?;
// Install plugin
new
.execute
.await?;
// Enable plugin
new
.execute
.await?;
// Update plugin
new
.execute
.await?;
Other Commands
// Check auth
new.execute.await?;
// Get version
new.execute.await?;
// Health check
new.execute.await?;
// List agents
new.execute.await?;
Escape hatch: RawCommand
For subcommands not yet wrapped, use RawCommand. Pass the subcommand name to new() and any flags via .arg():
let output = new
.arg
.arg
.execute
.await?;
Error Handling
All commands return Result<T>, where errors are typed with thiserror:
use Error;
match new.execute.await
Features
Optional Cargo features (all enabled by default):
json- JSON output parsing via serde_jsontempfile- Temporary file support for MCP config generation
Examples
Runnable examples in examples/:
Testing
Requires the claude CLI binary to be installed:
License
MIT OR Apache-2.0