openpencil/crates/anthropic-agent-sdk
Kayshen-X f3f57081da chore(crates): move vendored SDKs into workspace as forkable crates
Per user direction "可以不放在 vendor 里面,我们移动到自己的工程,
后面就和他们分叉" — promote the two community SDKs from vendor/ to
crates/ so they become first-class OP workspace members we own and
evolve, instead of read-only vendored snapshots.

Moves:
  vendor/anthropic-agent-sdk/  →  crates/anthropic-agent-sdk/
  vendor/copilot-sdk-rust/     →  crates/copilot-sdk/

Workspace integration:
  - Root `Cargo.toml` exclude list drops both vendor entries; the
    existing `members = ["crates/*"]` glob auto-includes them.
  - `crates/copilot-sdk/Cargo.toml`: stripped all `[[example]]`
    blocks (22 of them) — the examples/ dir was already removed
    during the import, and leaving the entries broke
    `cargo test --workspace --no-run`.
  - `crates/anthropic-agent-sdk/Cargo.toml`: already had its
    `[[example]]` blocks pruned in the previous commit.

Lockfile pins (workspace `Cargo.lock`):
  Pulling reqwest 0.12.28 (via anthropic-agent-sdk) into the
  unified workspace dep graph re-resolved several `icu_*` crates to
  the 2.2 line, which requires rustc 1.86. OP's toolchain is 1.85
  (locked to stay compatible with the skia-safe-op fork). Pinned:
    icu_collections      2.2.0 → 2.1.1
    icu_locale_core      2.2.0 → 2.1.1
    icu_normalizer       2.2.0 → 2.1.1
    icu_normalizer_data  2.2.0 → 2.1.1
    icu_properties       2.2.0 → 2.1.2
    icu_properties_data  2.2.0 → 2.1.2
    icu_provider         2.2.0 → 2.1.1
    idna_adapter         1.2.2 → 1.2.1
  All eight pins are the latest versions on each crate's 2.1.x /
  1.2.x line that compile on rustc 1.85.

Verification:
  - `cargo check -p anthropic-agent-sdk` ✓
  - `cargo check -p copilot-sdk` ✓
  - `cargo test --workspace --no-run` ✓
  - `cargo test -p openpencil-shell-core --lib` → 250 pass
  - `cargo test -p openpencil-desktop chat_` → 16 pass

Next: replace the hand-rolled subprocess parser in chat_subprocess.rs
with thin per-CLI adapters that route Claude Code through
`anthropic_agent_sdk::SubprocessTransport` and Copilot through
`copilot_sdk::Client + Session`. Gemini stays on the generic stdin
bridge until an upstream Rust SDK exists. Codex + OpenCode get an
HttpServerProvider that spawns `<bin> serve` then connects via a
local HTTP client.
2026-05-14 16:49:17 +08:00
..
.cargo chore(crates): move vendored SDKs into workspace as forkable crates 2026-05-14 16:49:17 +08:00
src chore(crates): move vendored SDKs into workspace as forkable crates 2026-05-14 16:49:17 +08:00
.codannaignore chore(crates): move vendored SDKs into workspace as forkable crates 2026-05-14 16:49:17 +08:00
.gitignore chore(crates): move vendored SDKs into workspace as forkable crates 2026-05-14 16:49:17 +08:00
Cargo.lock chore(crates): move vendored SDKs into workspace as forkable crates 2026-05-14 16:49:17 +08:00
Cargo.toml chore(crates): move vendored SDKs into workspace as forkable crates 2026-05-14 16:49:17 +08:00
CHANGELOG.md chore(crates): move vendored SDKs into workspace as forkable crates 2026-05-14 16:49:17 +08:00
LICENSE chore(crates): move vendored SDKs into workspace as forkable crates 2026-05-14 16:49:17 +08:00
README.md chore(crates): move vendored SDKs into workspace as forkable crates 2026-05-14 16:49:17 +08:00
README_API.md chore(crates): move vendored SDKs into workspace as forkable crates 2026-05-14 16:49:17 +08:00
SECURITY.md chore(crates): move vendored SDKs into workspace as forkable crates 2026-05-14 16:49:17 +08:00

Claude Agent SDK for Rust

Rust SDK for building AI agents powered by Claude Code. Mirrors the TypeScript Claude Agent SDK with idiomatic Rust patterns.

Installation

Prerequisites:

  • Rust 1.85.0+ (edition 2024)
  • Node.js
  • Claude Code 2.0.75+: npm install -g @anthropic-ai/claude-code
[dependencies]
anthropic-agent-sdk = "0.2"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }

Quick Start

use anthropic_agent_sdk::{query, Message, ContentBlock, StreamExt};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let stream = query("What is 2 + 2?", None).await?;
    let mut stream = Box::pin(stream);

    while let Some(message) = stream.next().await {
        if let Message::Assistant { message, .. } = message? {
            for block in &message.content {
                if let ContentBlock::Text { text } = block {
                    println!("{}", text);
                }
            }
        }
    }
    Ok(())
}

Examples

# Core functionality
cargo run --example simple_query
cargo run --example convenience_methods
cargo run --example bidirectional_demo
cargo run --example message_queue_demo
cargo run --example session_binding_demo
cargo run --example interactive_client

# Hooks and permissions
cargo run --example hooks_demo
cargo run --example permissions_demo
cargo run --example hooks_lifecycle_test

# Introspection and runtime
cargo run --example introspection_demo
cargo run --example result_fields_demo
cargo run --example runtime_setters_demo

# Security
cargo run --example security_demo

# OAuth authentication
cargo run --example oauth_demo
cargo run --example oauth_demo -- status
cargo run --example oauth_demo -- logout

# Structured output
cargo run --example structured_output_demo

# MCP (requires --features rmcp for mcp_server)
cargo run --example mcp_integration
cargo run --example mcp_server --features rmcp

TypeScript SDK Parity

Hook Events

Event TypeScript Rust SDK
PreToolUse ✓ ✓
PostToolUse ✓ ✓
PostToolUseFailure ✓ ✓
Notification ✓ ✓
UserPromptSubmit ✓ ✓
SessionStart ✓ ✓
SessionEnd ✓ ✓
Stop ✓ ✓
SubagentStart ✓ ✓
SubagentStop ✓ ✓
PreCompact ✓ ✓
PermissionRequest ✓ ✓

Query/Client Methods

Method TypeScript Rust SDK
interrupt() ✓ ✓
setPermissionMode() ✓ ✓
setModel() ✓ ✓
setMaxThinkingTokens() ✓ ✓
supportedCommands() ✓ ✓
supportedModels() ✓ ✓
mcpServerStatus() ✓ ✓
accountInfo() ✓ ✓

Options

Option TypeScript Rust SDK
allowedTools ✓ ✓
disallowedTools ✓ ✓
systemPrompt ✓ ✓
mcpServers ✓ ✓
permissionMode ✓ ✓
canUseTool ✓ ✓
hooks ✓ ✓
agents ✓ ✓
maxTurns ✓ ✓
model ✓ ✓
cwd ✓ ✓
env ✓ ✓
resume ✓ ✓
forkSession ✓ ✓
settingSources ✓ ✓
maxBudgetUsd ✓ ✓
maxThinkingTokens ✓ ✓
fallbackModel ✓ ✓
outputFormat ✓ ✓
sandbox ✓ ✓
plugins ✓ ✓
betas ✓ ✓
strictMcpConfig ✓ ✓
resumeSessionAt ✓ ✓
allowDangerouslySkipPermissions ✓ ✓
pathToClaudeCodeExecutable ✓ ✓
stderr ✓ ✓
tools (preset) ✓ ✓
enableFileCheckpointing ✓ ✓
sessionId ✓ ✓

MCP Server Types

Type TypeScript Rust SDK
stdio ✓ ✓
sse ✓ ✓
http ✓ ✓
sdk (in-process) ✓ ✓

Result Message Fields

Field TypeScript Rust SDK
modelUsage ✓ ✓
permission_denials ✓ ✓
structured_output ✓ ✓
errors ✓ ✓

Development

cargo build
cargo test
cargo clippy
cargo doc --open

Security

The SDK implements strict security measures:

  • Environment variables: Dangerous vars (LD_PRELOAD, PATH, etc.) cause errors
  • CLI arguments: Only allowlisted flags permitted, others rejected
  • Session binding: Auto-binds on first Result, validates on send
  • Buffer limits: Configurable max buffer size (default 1MB)
  • 100% safe Rust: No unsafe code

See SECURITY.md for full documentation.

OAuth Authentication

For Claude Max/Pro subscribers, authenticate without API keys:

use anthropic_agent_sdk::auth::OAuthClient;

let client = OAuthClient::new()?;
let token = client.authenticate().await?;
// Token is cached in platform-specific config directory

See oauth_demo example for full usage including status check and logout.

Documentation

License

MIT