opencode-client-sdk 1.2.20

Rust SDK for integrating OpenCode via local server + OpenAPI HTTP client
Documentation

OpenCode Rust SDK

English | 中文

Rust SDK for integrating OpenCode by launching the local OpenCode CLI server and calling its HTTP/SSE APIs.

Table of Contents

Overview

This crate is a parity-focused Rust implementation aligned with official OpenCode SDK behavior (@opencode-ai/sdk v1.2.20) while using Rust-idiomatic APIs.

It supports:

  • Local server lifecycle (create_opencode_server, create_opencode)
  • TUI process lifecycle (create_opencode_tui)
  • Typed client entry with endpoint namespaces (session, global, project, provider, mcp, tui, etc.)
  • Generic operation-id dispatch (call_operation, call_operation_sse)
  • Robust SSE parsing (split UTF-8 chunks, trailing non-blank-terminated lines)

Status

  • Package version: 1.2.20 (opencode-client-sdk)
  • Scope: parity-focused implementation of OpenCode CLI server + SDK HTTP workflows
  • Validation: crate check/tests are maintained with fixture-based subprocess and HTTP tests
  • Rust docs: public APIs are documented and exported through opencode

Installation

This repository currently uses a workspace/local package layout.

[dependencies]
opencode = { package = "opencode-client-sdk", path = "../../crates/opencode" }

Runtime prerequisites:

  • Rust 1.85+ (edition 2024)
  • OpenCode CLI installed and accessible (opencode)

Authentication and Environment Setup

This SDK calls the external OpenCode CLI/server. Authentication is typically handled by your OpenCode runtime configuration.

Option A: existing CLI/runtime environment

Use your existing OpenCode environment setup and login/session state.

Option B: programmatic headers and runtime options

use std::collections::HashMap;
use opencode::{create_opencode_client, OpencodeClientConfig};

# fn example() -> opencode::Result<()> {
let mut headers = HashMap::new();
headers.insert("x-custom-header".to_string(), "value".to_string());

let _client = create_opencode_client(Some(OpencodeClientConfig {
    base_url: "http://127.0.0.1:4096".to_string(),
    headers,
    bearer_token: None,
    directory: Some("/tmp/project".to_string()),
    ..Default::default()
}))?;
# Ok(())
# }

Security note: do not hard-code or commit secrets.

Quickstart

Start local server + create client

use opencode::{create_opencode, RequestOptions};
use serde_json::json;

# async fn run() -> opencode::Result<()> {
let mut app = create_opencode(None).await?;

let session = app
    .client
    .session()
    .create(RequestOptions::default())
    .await?;

let session_id = session.data["id"].as_str().unwrap();

let response = app
    .client
    .session()
    .prompt(
        RequestOptions::default()
            .with_path("sessionID", session_id)
            .with_body(json!({
                "parts": [
                    { "type": "text", "text": "Summarize this repository" }
                ]
            })),
    )
    .await?;

println!("status={} data={}", response.status, response.data);
app.server.close().await?;
# Ok(())
# }

Subscribe to SSE events

use futures::StreamExt;
use opencode::{create_opencode_client, RequestOptions};

# async fn run() -> opencode::Result<()> {
let client = create_opencode_client(None)?;
let mut stream = client.global().event(RequestOptions::default()).await?;

while let Some(event) = stream.next().await {
    let event = event?;
    println!("event={:?} data={}", event.event, event.data);
}
# Ok(())
# }

API Selection Guide

Use case Recommended API Why
Launch local OpenCode and call APIs in one object create_opencode Returns Opencode { server, client }
Manage server lifecycle explicitly create_opencode_server + create_opencode_client Fine-grained process control
Use endpoint wrappers with readable names client.session()/global()/... methods Clear, typed namespace access
Call by official operation id call_operation / call_operation_sse Close parity with OpenAPI operation naming
Consume streaming events request_sse / global().event() / event().subscribe() SSE parser and typed SseEvent output

Core API Surface

  • Server and process lifecycle
    • create_opencode_server
    • create_opencode_tui
    • create_opencode
    • OpencodeServer::close
    • OpencodeTui::close
  • Client construction and request primitives
    • create_opencode_client
    • OpencodeClientConfig
    • RequestOptions
    • ApiResponse
    • SseEvent, SseStream
    • OpencodeClient::request_json
    • OpencodeClient::request_sse
    • OpencodeClient::call_operation
    • OpencodeClient::call_operation_sse
  • Endpoint namespaces
    • SessionApi, GlobalApi, AppApi, ProjectApi, ProviderApi, AuthApi, OauthApi
    • FindApi, FileApi, PathApi, LspApi, ToolApi, CommandApi, ConfigApi, FormatterApi, VcsApi, InstanceApi
    • McpApi, McpAuthApi, PtyApi, EventApi, TuiApi, TuiControlApi (ControlApi alias)
  • Input helper types
    • SessionCreateInput
    • PromptInput
    • PartInput

Feature Highlights

  • Path parameter resolution compatible with OpenCode naming variants (sessionID / messageID / snake_case alternatives)
  • Safer multi-parameter route behavior (avoids accidental single id fallback substitution)
  • SSE parser hardened for streaming edge cases
  • Explicit typed error model (thiserror) with SDK/HTTP/process/CLI-not-found categories
  • Fixture-based tests for server lifecycle, CLI args/env forwarding, HTTP paths, and SSE parsing

Feature Comparison with Official JavaScript SDK

Feature Official JavaScript SDK This Rust SDK Notes
Local server helper (createOpencode) ✅ (create_opencode) Same workflow, Rust async style
Endpoint namespace access Similar surface with Rust naming
Operation-id based invocation call_operation parity-oriented API
SSE event subscription Rust returns futures::Stream of SseEvent
Directory header support x-opencode-directory auto-applied
Typed error hierarchy JS Error objects ✅ (Error enum) Rust uses explicit typed errors
Core SDK workflow Parity on behavior, Rust-native structure

Note: this crate targets behavior parity rather than identical internal structure. Rust-specific API and error modeling are intentionally idiomatic.

Compatibility Matrix

Component Requirement / Notes
Rust 1.85+
Edition 2024
OpenCode CLI Required at runtime (opencode)
Runtime Tokio async runtime
HTTP client Reqwest (rustls-tls)

Known Limitations

  • Behavior depends on installed OpenCode CLI/server version.
  • API payloads intentionally use serde_json::Value at boundaries for schema-forward compatibility.
  • The crate validates parity through fixture/mocked workflows; full production environment matrix is not bundled.

Testing and Validation

Validation commands:

cargo fmt --all
cargo check -p opencode-client-sdk
cargo test -p opencode-client-sdk
cargo clippy -p opencode-client-sdk --all-targets --all-features -- -D warnings

Concurrency Model

  • Server/TUI lifecycle is process-based (tokio::process) and can be managed asynchronously.
  • Request APIs are async and cloneable (OpencodeClient uses shared inner state).
  • SSE APIs produce Send streams suitable for async task pipelines.

Development

  • Keep API behavior aligned with official OpenCode SDK semantics.
  • Prefer typed errors and explicit request/response handling.
  • Add fixture-based tests when changing CLI transport, path rendering, or SSE parsing behavior.

Contributing

Please follow repository contribution and validation rules in AGENTS.md.

License

Apache-2.0