6.1 KiB
opencode_client
A Rust client library for interacting with the OpenCode.ai API.
Purpose
This package provides a type-safe, ergonomic Rust interface to the OpenCode.ai API, enabling any Rust application to interact with OpenCode sessions and messages. It's designed to be reusable across different UI frameworks and platforms (web, mobile, desktop, CLI).
⚠️ Important: API Ownership
ALL OpenCode.ai API functionality lives in this package. This includes:
- ✅ REST API endpoints (sessions, messages, files, etc.)
- 🚧 Server-Sent Events (SSE) for real-time streaming (planned)
- 🔮 WebSocket connections (if needed in future)
- 🔮 Authentication flows
- 🔮 Rate limiting and retry logic
UI packages (web, mobile, desktop) should remain thin presentation layers that consume this client library. Never implement API calls directly in UI code.
Features
- Type-safe API: Full Rust type definitions for all OpenCode API structures
- Async/await: Built on
reqwestfor non-blocking HTTP operations - Optional logging: Flexible logging callbacks for integration with any logging system
- WASM compatible: Works in browser environments via WebAssembly
- Zero UI dependencies: Pure business logic, usable anywhere
Usage
Basic Example
use opencode_client::OpenCodeClient;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = OpenCodeClient::new("http://localhost:12225");
// List all sessions
let sessions = client.list_sessions().await?;
println!("Found {} sessions", sessions.len());
// Get messages from a session
if let Some(session) = sessions.first() {
let messages = client.list_messages(&session.id).await?;
println!("Session has {} messages", messages.len());
}
Ok(())
}
With Logging Callbacks
use opencode_client::OpenCodeClient;
use std::sync::Arc;
let client = OpenCodeClient::new("http://localhost:12225")
.with_logging(
Arc::new(|cat, msg| println!("[INFO] {}: {}", cat, msg)),
Arc::new(|cat, msg| println!("[SUCCESS] {}: {}", cat, msg)),
Arc::new(|cat, msg| eprintln!("[ERROR] {}: {}", cat, msg)),
);
// Now all API calls will log through your callbacks
let sessions = client.list_sessions().await?;
Sending Messages
let message_with_parts = client
.send_message("session_id", "Hello, world!".to_string())
.await?;
// Access the message info and parts
println!("Message ID: {}", get_message_id(&message_with_parts.info));
for part in &message_with_parts.parts {
match part {
Part::Text(text) => println!("Text: {}", text.text),
Part::Reasoning(reasoning) => println!("Reasoning: {}", reasoning.text),
Part::Tool(tool) => println!("Tool: {} ({})", tool.tool, tool.state),
_ => {}
}
}
Architecture
The client is organized into three main modules:
- types.rs: All OpenCode API type definitions (Session, Message, Part, etc.)
- client.rs: HTTP client implementation with CRUD operations
- lib.rs: Public API exports
The client uses tagged enums for discriminated unions (e.g., Message::User vs Message::Assistant) and serde for JSON serialization/deserialization.
API Reference
For detailed API documentation, see:
- OpenCode API Documentation
- Or run:
cargo doc --open -p opencode_client
Key Types
- OpenCodeClient: Main client struct
- Session: Session metadata (id, title, project, timestamps)
- Message: Tagged enum for User or Assistant messages
UserMessage: User-sent messages with optional summaryAssistantMessage: AI responses with tokens, cost, system prompt, and metadata
- MessageWithParts: Complete message with content parts (info + parts array)
- Part: Message content enum:
Text(TextPart): Regular text contentReasoning(ReasoningPart): AI reasoning/thinking processTool(ToolPart): Tool execution with state trackingStepStart(GenericPart): Step boundary markerStepFinish(GenericPart): Step completion markerUnknown: Future-proof fallback
- ToolPart: Tool execution details with:
tool: Tool name (string)call_id: Unique call identifierstate: ToolState enum (Pending, Running, Completed, Error)
- ToolState: Execution state with status-specific data:
Pending: Waiting to startRunning { input, title?, metadata?, time }: Currently executingCompleted { input, output, title, metadata, time, attachments? }: Successful completionError { input, error, metadata?, time }: Failed execution
- ClientError: Error types (Http, Request, Serialization)
Dependencies
- reqwest: Async HTTP client (with JSON support)
- serde/serde_json: JSON serialization
- chrono: Timestamp handling
- wasm-bindgen/web-sys: WASM compatibility (target-specific)
Related Packages
- web: Uses this client for browser-based UI
- mobile (future): Will use this client for mobile apps
- desktop (future): Will use this client for desktop apps
Development
# Build
cargo build -p opencode_client
# Test
cargo test -p opencode_client
# Documentation
cargo doc --open -p opencode_client
Roadmap
See detailed implementation plans:
- SSE Implementation - Real-time event streaming
- OpenCode API Reference - Complete API documentation
Upcoming Features
-
SSE Event Streaming 🚧
- Real-time message part updates
- Live session state changes
- Connection resilience and reconnection
- See:
docs/building/sse_implementation.md
-
File Operations 📋
- Read files from workspace
- Search files and symbols
- Track file status
-
Advanced Session Management 📋
- Create/delete sessions
- Fork sessions
- Session diffs and summaries
Known Issues & Differences
See OpenCode API Documentation for details on differences between the official API spec and actual implementation (e.g., optional fields, missing fields, additional part types).