docs: public README + generic CI workflow
This commit is contained in:
parent
5b8ff3c5f1
commit
d32db8800e
2 changed files with 131 additions and 27 deletions
29
.github/workflows/ci.yml
vendored
Normal file
29
.github/workflows/ci.yml
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: install rust
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: fmt
|
||||
run: cargo fmt --all --check
|
||||
|
||||
- name: clippy
|
||||
run: cargo clippy --all-targets -- -D warnings
|
||||
|
||||
- name: build
|
||||
run: cargo build --all-targets
|
||||
|
||||
- name: test
|
||||
run: cargo test
|
||||
129
README.md
129
README.md
|
|
@ -4,22 +4,35 @@ 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:
|
||||
newline-delimited JSON stream as ergonomic, strongly-typed Rust values. The
|
||||
Python SDK's two entry points map directly:
|
||||
|
||||
- `query()` for fire-and-forget one-shot prompts.
|
||||
- `ClaudeSDKClient` → `claude_agent_sdk::Client` for bidirectional
|
||||
- `ClaudeSDKClient` → `claude_agent_sdk::Client` for bidirectional,
|
||||
multi-turn sessions.
|
||||
|
||||
It is an independent, community-maintained port and is not affiliated with or
|
||||
endorsed by Anthropic.
|
||||
|
||||
## 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.
|
||||
session store, sandbox, plugins, agents) are deferred. See
|
||||
[scope and known limitations](#scope-and-known-limitations) below.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Rust 1.85 or newer (the crate uses the 2024 edition).
|
||||
- The `claude` CLI available on `PATH` (or supplied explicitly via
|
||||
`ClaudeAgentOptions::with_cli_path()`), and an authenticated Claude
|
||||
session. **The SDK does not bundle the CLI binary** — it shells out to
|
||||
whatever `claude` it finds.
|
||||
|
||||
## Install
|
||||
|
||||
The crate is distributed as a git dependency:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
claude-agent-sdk = { git = "https://git.sulkta.com/Sulkta-OSS/claude-agent-sdk-rust" }
|
||||
|
|
@ -27,9 +40,8 @@ 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.
|
||||
Pin to a tag or commit (`rev = "..."` / `tag = "..."`) for reproducible
|
||||
builds.
|
||||
|
||||
## Quick start
|
||||
|
||||
|
|
@ -67,6 +79,9 @@ async fn main() -> claude_agent_sdk::Result<()> {
|
|||
}
|
||||
```
|
||||
|
||||
`query()` returns a stream that ends when the CLI emits its terminal `result`
|
||||
message, automatically tearing down the subprocess.
|
||||
|
||||
## Multi-turn sessions
|
||||
|
||||
```rust
|
||||
|
|
@ -83,7 +98,7 @@ async fn main() -> claude_agent_sdk::Result<()> {
|
|||
// ...consume messages until a Result frame, then ask a follow-up...
|
||||
client.send("And of Germany?").await?;
|
||||
|
||||
// Drain until next Result, then disconnect.
|
||||
// Drain until the next Result, then disconnect.
|
||||
while let Some(msg) = messages.next().await {
|
||||
if let Message::Result(_) = msg? {
|
||||
break;
|
||||
|
|
@ -94,7 +109,49 @@ async fn main() -> claude_agent_sdk::Result<()> {
|
|||
}
|
||||
```
|
||||
|
||||
See the `examples/` directory for runnable variants.
|
||||
`Client` keeps a single CLI subprocess alive across turns, so follow-up
|
||||
prompts don't pay the cold-start cost again.
|
||||
|
||||
## Configuration
|
||||
|
||||
Both entry points are configured with `ClaudeAgentOptions`, a builder you
|
||||
chain `.with_*()` methods on:
|
||||
|
||||
```rust
|
||||
use claude_agent_sdk::{ClaudeAgentOptions, PermissionMode};
|
||||
|
||||
let opts = ClaudeAgentOptions::new()
|
||||
.with_model("claude-sonnet-4-5")
|
||||
.with_permission_mode(PermissionMode::AcceptEdits)
|
||||
.with_allowed_tool("Read")
|
||||
.with_allowed_tool("Bash")
|
||||
.with_cwd("/tmp/my-project")
|
||||
.with_max_turns(5);
|
||||
```
|
||||
|
||||
See the `ClaudeAgentOptions` API docs for the full list of supported fields.
|
||||
|
||||
## Examples
|
||||
|
||||
Runnable examples live in [`examples/`](examples/). With the `claude` CLI on
|
||||
`PATH` and authenticated:
|
||||
|
||||
```sh
|
||||
cargo run --example basic # minimal one-shot query()
|
||||
cargo run --example with_options # query() with a configured options builder
|
||||
cargo run --example interactive # multi-turn Client session
|
||||
```
|
||||
|
||||
## Building and testing
|
||||
|
||||
```sh
|
||||
cargo build
|
||||
cargo test # unit + end-to-end tests. A fake CLI fixture stands in
|
||||
# for the real `claude` binary, so the suite needs no
|
||||
# network access or authenticated session to run.
|
||||
cargo clippy --all-targets
|
||||
cargo fmt --check
|
||||
```
|
||||
|
||||
## Mapping the Python SDK
|
||||
|
||||
|
|
@ -114,31 +171,49 @@ See the `examples/` directory for runnable variants.
|
|||
| `CLIJSONDecodeError` | `Error::JsonDecode { .. }` |
|
||||
| `MessageParseError` | `Error::MessageParse { .. }` |
|
||||
|
||||
## v0.1 scope and known limitations
|
||||
## Scope and known limitations
|
||||
|
||||
The v0.1 port covers the core path. The following are deferred:
|
||||
This release covers the core path of the Python SDK:
|
||||
|
||||
- **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.
|
||||
- Subprocess transport with newline-delimited JSON framing.
|
||||
- All message and content-block types parsed faithfully.
|
||||
- `query()` + `Client` for one-shot and bidirectional use.
|
||||
- The `ClaudeAgentOptions` flag surface relevant to subprocess arguments.
|
||||
|
||||
The following are deferred — see the upstream Python README for the current
|
||||
shape of these features:
|
||||
|
||||
- **Control protocol over JSON-RPC** — `interrupt()`, `set_permission_mode()`,
|
||||
`set_model()`, `get_mcp_status()`, etc. 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.
|
||||
- **In-process MCP servers (`@tool` / `create_sdk_mcp_server`)** — needs a
|
||||
Rust trait/derive-macro shape that isn't drafted yet.
|
||||
- **`HookMatcher`** — the 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.
|
||||
Each of these degrades gracefully — a caller using a newer CLI sees fewer
|
||||
features, not breakage.
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome. A good change:
|
||||
|
||||
- keeps the wire protocol faithful to the upstream Python SDK (cite the
|
||||
behavior you're matching where it isn't obvious);
|
||||
- comes with a test — the end-to-end suite drives a fake CLI over the real
|
||||
framing, so most behavior can be covered without a live `claude` binary;
|
||||
- passes `cargo fmt --check`, `cargo clippy --all-targets`, and `cargo test`.
|
||||
|
||||
Open an issue to discuss larger features (especially anything from the
|
||||
deferred list above) before sending a big patch.
|
||||
|
||||
## License
|
||||
|
||||
MIT. See [`LICENSE`](LICENSE).
|
||||
|
||||
This is an independent port; the upstream Python SDK is © Anthropic, PBC.
|
||||
This is an independent port; the upstream Python SDK is © Anthropic, PBC, and
|
||||
the bundled `LICENSE` preserves that notice alongside this port's copyright.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue