crimson-crab

crimson-crab v0.1 MIT OR Apache-2.0 MSRV 1.75

The production-grade Rust SDK for Claude.

The definitive Rust client for Anthropic's Claude API, engineered to first-party SDK standards: the complete API surface, identical retry semantics, and same-week support for every Claude release. Streaming, tool use, thinking, prompt caching and batches are first-class, not adapted.

cargo add crimson-crab

Spec fidelity, not surface area

The complete Claude API. Nothing lost in translation.

Streaming, tool use, adaptive thinking, prompt caching, batches — every Claude capability is a first-class Rust type that mirrors the wire exactly. And when Anthropic ships something new, you’re covered from day one: new models, new features, and new content types flow through without breaking a single build.

Streaming SSE

A hand-rolled SSE parser yields fine-grained StreamEvents and accumulates a final Message for you — no eventsource dependency.

Tool use

Define tools with raw JSON schemas, drive the agentic loop yourself, and pass any server-tool through ToolUnion::Raw.

Adaptive thinking

ThinkingConfig covers adaptive, budgeted and disabled modes, with effort and display controls surfaced directly.

Prompt caching

Attach CacheControl to any block with an optional 5m/1h TTL, and read cache hits back off Usage.

Message Batches

Create, poll and cancel batches, then stream results back with a JSONL-decoding Stream<BatchResult>.

Token counting

Turn any request into a count request and get exact input_tokens before you spend on generation.

Typed errors & retries

Every non-2xx maps to a precise Error variant with request_id. Backoff with jitter honors retry-after automatically.

Forward compatible

Unknown block types, stream events and stop reasons deserialize into Unknown catch-alls — new API surface never breaks a build.

Runtime-light & WASM-ready

The public API exposes futures_core::Stream, not tokio types. reqwest underneath means it also checks on wasm32-unknown-unknown.


From zero to streaming in one screen

Ergonomic, but nothing hidden.

A builder for every request, helpers for the common paths, and full command of stop_reason. Here it is end to end.

examples/basic.rs
use crimson_crab::{Client, MessagesRequest, MessageParam, models_ids};

// Reads ANTHROPIC_API_KEY from the environment.
let client = Client::from_env()?;

let req = MessagesRequest::builder()
    .model(models_ids::CLAUDE_OPUS_4_8)
    .max_tokens(1024)
    .system("You are terse.")
    .messages(vec![MessageParam::user("Hello, Claude")])
    .build()?;                              // validates required fields

let msg = client.messages().create(&req).await?;

if msg.stop_reason == Some(StopReason::Refusal) {
    // handle a declined response
}
println!("{}", msg.text());                    // concat of all text blocks

Depth beats breadth

Why a dedicated client?

Multi-provider frameworks like rig and genai are genuinely great — if you need one interface across many model vendors, use them. crimson-crab makes the winning bet for Claude builders: go deep on one API and track it relentlessly — so every new Claude capability lands here first, typed and tested.

Capability crimson-crab · dedicated rig / genai · multi-provider
Thinking, caching & batches First-class types Often lags or partial
Wire fidelity (no renamed concepts) Types mirror the API Abstracted to a common shape
New block / event types Catch-all, never a hard error Varies by adapter
Fine-grained streaming events Every delta exposed Usually text-only
One interface across many providers Claude only — by design Their whole point
Cadence tracking the Claude API The core promise One vendor among many

Straight talk: if your app talks to several model vendors, a framework will serve you better. crimson-crab is for teams who have chosen Claude and want the whole surface, exactly as Anthropic ships it.