scaffold the crate
Initial layout for an async Rust port of the Python claude-agent-sdk. Sets up Cargo.toml on 2024 edition, MIT LICENSE matching the upstream Python SDK's text with the Sulkta Coop copyright appended, a workspace .gitignore, and a README laying out the v0.1 scope and the Python -> Rust mapping table. No source modules yet — those land in the following commits.
This commit is contained in:
commit
6af8273f98
4 changed files with 206 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/target
|
||||
39
Cargo.toml
Normal file
39
Cargo.toml
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
[package]
|
||||
name = "claude-agent-sdk"
|
||||
version = "0.0.1"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
description = "Async Rust SDK for the Claude Agent CLI (subprocess-based, mirrors the Python claude-agent-sdk)."
|
||||
repository = "https://gitea.sulkta.com/Sulkta-Coop/claude-agent-sdk-rust"
|
||||
readme = "README.md"
|
||||
keywords = ["claude", "anthropic", "agent", "sdk", "async"]
|
||||
categories = ["api-bindings", "asynchronous"]
|
||||
rust-version = "1.85"
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tokio-stream = "0.1"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
thiserror = "2"
|
||||
tracing = "0.1"
|
||||
futures-core = "0.3"
|
||||
async-stream = "0.3"
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = "1"
|
||||
tokio = { version = "1", features = ["macros", "rt-multi-thread", "test-util"] }
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
futures-util = "0.3"
|
||||
|
||||
[[example]]
|
||||
name = "basic"
|
||||
path = "examples/basic.rs"
|
||||
|
||||
[[example]]
|
||||
name = "with_options"
|
||||
path = "examples/with_options.rs"
|
||||
|
||||
[[example]]
|
||||
name = "interactive"
|
||||
path = "examples/interactive.rs"
|
||||
22
LICENSE
Normal file
22
LICENSE
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2025 Anthropic, PBC
|
||||
Copyright (c) 2026 Sulkta Cooperative
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
144
README.md
Normal file
144
README.md
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
# claude-agent-sdk (Rust)
|
||||
|
||||
Async Rust SDK for the Claude Agent CLI — a faithful port of the official
|
||||
Python [`claude-agent-sdk`](https://github.com/anthropics/claude-agent-sdk-python).
|
||||
|
||||
This crate wraps the `claude` CLI as a subprocess and exposes its
|
||||
newline-delimited JSON stream as ergonomic Rust types. The Python SDK's
|
||||
two entry points map directly:
|
||||
|
||||
- `query()` for fire-and-forget one-shot prompts.
|
||||
- `ClaudeSDKClient` → `claude_agent_sdk::Client` for bidirectional
|
||||
multi-turn sessions.
|
||||
|
||||
## Status
|
||||
|
||||
**v0.0.1** — initial port. Core feature parity for the subprocess wire
|
||||
protocol; advanced features (control protocol, hooks, in-process MCP servers,
|
||||
session_store, sandbox, plugins, agents) are deferred to v0.2. See
|
||||
[v0.1 scope](#v01-scope-and-known-limitations) below.
|
||||
|
||||
## Install
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
claude-agent-sdk = { git = "https://gitea.sulkta.com/Sulkta-Coop/claude-agent-sdk-rust" }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tokio-stream = "0.1"
|
||||
```
|
||||
|
||||
Prerequisites: the `claude` CLI on `PATH` (or supply
|
||||
`ClaudeAgentOptions::with_cli_path()`), and an authenticated Claude
|
||||
session. The SDK does not bundle the CLI binary.
|
||||
|
||||
## Quick start
|
||||
|
||||
```rust
|
||||
use claude_agent_sdk::{query, ClaudeAgentOptions, Message, ContentBlock};
|
||||
use tokio_stream::StreamExt;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> claude_agent_sdk::Result<()> {
|
||||
let opts = ClaudeAgentOptions::new()
|
||||
.with_system_prompt("You are a helpful assistant.")
|
||||
.with_max_turns(1);
|
||||
|
||||
let mut stream = query("What is 2 + 2?", opts).await?;
|
||||
|
||||
while let Some(msg) = stream.next().await {
|
||||
match msg? {
|
||||
Message::Assistant(a) => {
|
||||
for block in a.message.content {
|
||||
if let ContentBlock::Text(t) = block {
|
||||
println!("Claude: {}", t.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::Result(r) => {
|
||||
if let Some(usd) = r.total_cost_usd {
|
||||
println!("Cost: ${:.4}", usd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
## Multi-turn sessions
|
||||
|
||||
```rust
|
||||
use claude_agent_sdk::{Client, ClaudeAgentOptions, Message, ContentBlock};
|
||||
use tokio_stream::StreamExt;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> claude_agent_sdk::Result<()> {
|
||||
let mut client = Client::new(ClaudeAgentOptions::new()).await?;
|
||||
client.connect().await?;
|
||||
let mut messages = client.messages();
|
||||
|
||||
client.send("What's the capital of France?").await?;
|
||||
// ...consume messages until a Result frame, then ask a follow-up...
|
||||
client.send("And of Germany?").await?;
|
||||
|
||||
// Drain until next Result, then disconnect.
|
||||
while let Some(msg) = messages.next().await {
|
||||
if let Message::Result(_) = msg? {
|
||||
break;
|
||||
}
|
||||
}
|
||||
client.disconnect().await?;
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
See the `examples/` directory for runnable variants.
|
||||
|
||||
## Mapping the Python SDK
|
||||
|
||||
| Python | Rust |
|
||||
| ---------------------------- | ------------------------------- |
|
||||
| `query(prompt=...)` | `query(prompt, opts).await?` |
|
||||
| `ClaudeSDKClient` | `Client` |
|
||||
| `ClaudeAgentOptions` | `ClaudeAgentOptions` |
|
||||
| `AssistantMessage` | `Message::Assistant(_)` |
|
||||
| `UserMessage` | `Message::User(_)` |
|
||||
| `SystemMessage` | `Message::System(_)` |
|
||||
| `ResultMessage` | `Message::Result(_)` |
|
||||
| `TextBlock` / `ToolUseBlock` | `ContentBlock::Text/ToolUse(_)` |
|
||||
| `CLINotFoundError` | `Error::CliNotFound` |
|
||||
| `CLIConnectionError` | `Error::CliConnection` |
|
||||
| `ProcessError` | `Error::Process { .. }` |
|
||||
| `CLIJSONDecodeError` | `Error::JsonDecode { .. }` |
|
||||
| `MessageParseError` | `Error::MessageParse { .. }` |
|
||||
|
||||
## v0.1 scope and known limitations
|
||||
|
||||
The v0.1 port covers the core path. The following are deferred:
|
||||
|
||||
- **Control protocol** — `interrupt()`, `set_permission_mode()`,
|
||||
`set_model()`, `get_mcp_status()`, etc. The Python SDK sends a JSON-RPC
|
||||
`initialize` request before the first user message and handles control
|
||||
requests/responses over the same stdio pair. The Rust `Client` currently
|
||||
speaks only the bare user / assistant / result frames. Adding the
|
||||
control protocol unlocks the rest of the API.
|
||||
- **`can_use_tool` permission callback** — requires the control protocol.
|
||||
- **In-process MCP servers (`@tool` / `create_sdk_mcp_server`)** — the
|
||||
Python decorator wraps a `mcp.server.Server` instance. The Rust shape
|
||||
for this (likely a derive macro on a `Tool` trait + a runtime that
|
||||
multiplexes over the control protocol) is not yet drafted.
|
||||
- **`HookMatcher`** — wire format is supported on the CLI side but the Rust
|
||||
callback surface is not designed.
|
||||
- **`SessionStore`** mirroring adapter.
|
||||
- **`Sandbox` settings**, **plugins**, **agents** dataclass.
|
||||
|
||||
Each of these degrades gracefully — a v0.1 caller using a newer CLI sees
|
||||
fewer features, not breakage.
|
||||
|
||||
## License
|
||||
|
||||
MIT. See [`LICENSE`](LICENSE).
|
||||
|
||||
This is an independent port; the upstream Python SDK is © Anthropic, PBC.
|
||||
Loading…
Add table
Add a link
Reference in a new issue