OpenCode 为它的服务端推出了一个 TypeScript/JavaScript SDK,为开发者提供了一套类型安全、可直接在代码中操控 OpenCode 的编程接口。不管是构建第三方集成,还是想用脚本自动控制 OpenCode 的行为,这套 SDK 都提供了完整的工具链。如果对服务端的运作原理感兴趣,可以去查阅更深入的资料;想找灵感的话,社区里也有一些基于这个 SDK 做的项目可以参考。
下面就来拆解一下这个 SDK 能做什么,以及具体怎么用。

安装
第一步自然是安装。SDK 已经发布在 npm 上,用一行命令就能装好:
npm install @opencode-ai/sdk
创建客户端
SDK 的核心是 createOpencode 函数。调用它时,它会在后台启动一个 OpenCode 服务端,同时返回一个已经连好的客户端实例:
import { createOpencode } from "@opencode-ai/sdk"
const { client } = await createOpencode()
这么做的好处是,开发者不需要手动管理服务端进程,一切都在同一段代码里搞定。
可配置的选项
createOpencode 接受一个可选的配置对象,用来定制服务端的行为。可用的字段包括:
| hostname | string | 服务端主机名 | 127.0.0.1 |
| port | number | 服务端口 | 4096 |
| signal | AbortSignal | 用于取消操作的终止信号 | undefined |
| timeout | number | 等待服务端启动的超时时间(毫秒) | 5000 |
| config | Config | 配置对象,可覆盖项目里的 opencode.json | {} |
通过 Config 微调
即使项目里已经有了 opencode.json 配置文件,也可以在代码中传入一个 config 字段,对模型等设置进行覆盖或补充。比如,可以把默认模型指定为某个 Claude 版本:
import { createOpencode } from "@opencode-ai/sdk"
const opencode = await createOpencode({
hostname: "127.0.0.1",
port: 4096,
config: {
model: "anthropic/claude-3-5-sonnet-20241022",
},
})
console.log(`Server running at ${opencode.server.url}`)
opencode.server.close()
这里返回的 opencode.server 对象上有一个 close() 方法,可以在不需要的时候主动关闭服务端。
只连接客户端(不启动服务端)
如果已经有一个独立运行的 OpenCode 服务端,就不需要再次启动,只需要创建一个客户端连上去就好。SDK 为此提供了 createOpencodeClient 函数:
import { createOpencodeClient } from "@opencode-ai/sdk"
const client = createOpencodeClient({
baseUrl: "http://localhost:4096",
})
这个函数接受的选项如下:
| baseUrl | string | 服务端 URL | http://localhost:4096 |
| fetch | function | 自定义 fetch 实现 | globalThis.fetch |
| parseAs | string | 响应解析方式 | auto |
| responseStyle | string | 返回风格:data 或 fields | fields |
| throwOnError | boolean | 是否在出错时抛出异常 | false |
这样一来,即使服务器是由其他工具或进程启动的,也能轻松地用 SDK 与之交互。
类型定义
SDK 包里包含了所有 API 类型的 TypeScript 定义,直接从服务端的 OpenAPI 规范生成。需要的话,可以这样引入:
import type { Session, Message, Part } from "@opencode-ai/sdk"
所有类型都可以从 types 文件中找到,这让在 TypeScript 项目里使用时有完整的智能提示和编译时检查。
错误处理
SDK 在执行请求时可能会抛出错误,用 try/catch 可以捕获并处理它们:
try {
await client.session.get({ path: { id: "invalid-id" } })
} catch (error) {
console.error("Failed to get session:", (error as Error).message)
}
结构化输出
SDK 支持一种叫做“结构化输出”的功能:让模型按照预先定义好的 JSON Schema 返回严格校验过的 JSON 数据,而不是自由格式的文本。模型内部会使用一个 StructuredOutput 工具来确保输出符合要求。
基本用法
发送一次带格式要求的提示:
const result = await client.session.prompt({
path: { id: sessionId },
body: {
parts: [{ type: "text", text: "Research Anthropic and provide company info" }],
format: {
type: "json_schema",
schema: {
type: "object",
properties: {
company: { type: "string", description: "Company name" },
founded: { type: "number", description: "Year founded" },
products: {
type: "array",
items: { type: "string" },
description: "Main products",
},
},
required: ["company", "founded"],
},
},
},
})
// 从返回结果中取出结构化数据
console.log(result.data.info.structured_output)
// { company: "Anthropic", founded: 2021, products: ["Claude", "Claude API"] }
输出格式的类型
- text(默认):标准文本响应,不做结构化。
- json_schema:返回经过校验、符合 Schema 的 JSON。
JSON Schema 模式下需要提供的字段
| type | ‘json_schema’ | 必填,指明使用 JSON Schema 模式 |
| schema | object | 必填,描述输出结构的 JSON Schema 对象 |
| retryCount | number | 可选,校验重试次数,默认 2 次 |
错误处理
如果模型在所有重试后仍然没有产生合法的结构化输出,返回的结果里会包含一个 StructuredOutputError,可以这样检查:
if (result.data.info.error?.name === "StructuredOutputError") {
console.error("Failed to produce structured output:", result.data.info.error.message)
console.error("Attempts:", result.data.info.error.retries)
}
使用建议
- 在 schema 的属性里填写清晰的描述,帮助模型理解该提取什么数据。
- 用 required 标记哪些字段必须出现。
- 保持 schema 结构聚焦、不过于复杂,过于嵌套的定义可能让模型难以准确填充。
- 根据复杂度调整 retryCount,简单结构可以少重试,复杂的可适当增加。
完整的 API 一览
SDK 将服务端的所有接口都包装成了类型安全的方法,按功能模块划分。
Global(全局)
- global.health() — 检查服务端健康状态和版本号
const health = await client.global.health()
console.log(health.data.version)
App(应用)
- app.log() — 写一条日志
- app.agents() — 列出所有可用的代理
await client.app.log({
body: {
service: "my-app",
level: "info",
message: "Operation completed",
},
})
const agents = await client.app.agents()
Project(项目)
- project.list() — 列出所有项目
- project.current() — 获取当前项目信息
const projects = await client.project.list()
const currentProject = await client.project.current()
Path(路径)
- path.get() — 获取当前路径信息
const pathInfo = await client.path.get()
Config(配置)
- config.get() — 获取配置信息
- config.providers() — 列出所有提供者及其默认模型
const config = await client.config.get()
const { providers, default: defaults } = await client.config.providers()
Sessions(会话)
会话是 SDK 的核心功能,支持完整的生命周期管理:
| session.list() | 列出所有会话 | Session[] |
| session.get({ path }) | 获取单个会话 | Session |
| session.children({ path }) | 列出子会话 | Session[] |
| session.create({ body }) | 创建新会话 | Session |
| session.delete({ path }) | 删除会话 | boolean |
| session.update({ path, body }) | 更新会话属性 | Session |
| session.init({ path, body }) | 分析应用并生成 AGENTS.md | boolean |
| session.abort({ path }) | 中止正在运行的会话 | boolean |
| session.share({ path }) | 分享会话 | Session |
| session.unshare({ path }) | 取消分享 | Session |
| session.summarize({ path, body }) | 对会话进行总结 | boolean |
| session.messages({ path }) | 列出会话中的所有消息 | { info: Message, parts: Part[]}[] |
| session.message({ path }) | 获取某条消息的详情 | { info: Message, parts: Part[]} |
| session.prompt({ path, body }) | 发送提示消息 | 若 body.noReply: true,返回 UserMessage(仅注入上下文);否则返回 AssistantMessage。支持 body.outputFormat 做结构化输出 |
| session.command({ path, body }) | 向会话发送命令 | { info: AssistantMessage, parts: Part[]} |
| session.shell({ path, body }) | 运行一个 shell 命令 | AssistantMessage |
| session.revert({ path, body }) | 回退一条消息 | Session |
| session.unrevert({ path }) | 恢复已回退的消息 | Session |
| postSessionByIdPermissionsByPermissionId({ path, body }) | 响应权限请求 | boolean |
几个常见的用法示例:
// 创建并管理会话
const session = await client.session.create({
body: { title: "My session" },
})
const sessions = await client.session.list()
// 发送一个带模型的提示
const result = await client.session.prompt({
path: { id: session.id },
body: {
model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" },
parts: [{ type: "text", text: "Hello!" }],
},
})
// 仅注入上下文,不触发 AI 回复(插件场景常用)
await client.session.prompt({
path: { id: session.id },
body: {
noReply: true,
parts: [{ type: "text", text: "You are a helpful assistant." }],
},
})
Files(文件)
提供文件搜索和读取能力:
| find.text({ query }) | 在文件中搜索文本 | 包含路径、行号、偏移等信息的匹配对象数组 |
| find.files({ query }) | 按名称查找文件或目录 | 路径字符串数组 |
| find.symbols({ query }) | 查找工作区符号 | Symbol[] |
| file.read({ query }) | 读取文件内容 | `{ type: “raw” |
| file.status({ query? }) | 获取被跟踪文件的状态 | File[] |
其中 find.files 还支持一些可选的查询参数:type("file" 或 "directory")、directory(覆盖搜索根目录)、limit(1 到 200)。
// 文本搜索
const textResults = await client.find.text({
query: { pattern: "function.*opencode" },
})
// 查找 .ts 文件
const files = await client.find.files({
query: { query: "*.ts", type: "file" },
})
// 查找目录,限制返回数量
const directories = await client.find.files({
query: { query: "packages", type: "directory", limit: 20 },
})
// 读取文件内容
const content = await client.file.read({
query: { path: "src/index.ts" },
})
TUI(终端界面控制)
可以直接控制 OpenCode 的终端界面(TUI):
| tui.appendPrompt({ body }) | 在提示输入框中追加文本 |
| tui.openHelp() | 打开帮助对话框 |
| tui.openSessions() | 打开会话选择器 |
| tui.openThemes() | 打开主题选择器 |
| tui.openModels() | 打开模型选择器 |
| tui.submitPrompt() | 提交当前提示 |
| tui.clearPrompt() | 清空提示输入框 |
| tui.executeCommand({ body }) | 执行一个命令 |
| tui.showToast({ body }) | 显示一条提示通知 |
这些方法都返回 boolean,表示操作是否成功。
await client.tui.appendPrompt({
body: { text: "Add this to prompt" },
})
await client.tui.showToast({
body: { message: "Task completed", variant: "success" },
})
Auth(认证)
- auth.set({ … }) — 设置认证凭据,返回 boolean。
await client.auth.set({
path: { id: "anthropic" },
body: { type: "api", key: "your-api-key" },
})
Events(事件)
- event.subscribe() — 订阅服务端发送的实时事件流(Server-Sent Events)。
const events = await client.event.subscribe()
for await (const event of events.stream) {
console.log("Event:", event.type, event.properties)
}
这样就能在代码里监听 OpenCode 内部发生的各种状态变化。
这套 SDK 把 OpenCode 的所有能力都暴露成了清晰的函数调用,无论是构建自动化脚本、开发插件,还是做更复杂的集成,都能直接在 TypeScript 里享受类型安全带来的便利。只要跟着这份指南动手试一试,就能很快用代码驾驭这个强大的 AI 编程助手了。






