这篇文章继续学习 OpenCode 的官方文档,学习基于 OpenCode 进行二次开发,从而对 OpenCode 进行二次扩展。
SDK
opencode JS/TS SDK 提供了一个类型安全的客户端,用于与服务器进行交互。 你可以用它来构建集成方案,并以编程方式控制 opencode。
1 npm install @opencode-ai/sdk
创建一个 opencode 实例:这会同时启动服务器和客户端
1 2 3 import { createOpencode } from "@opencode-ai/sdk" const { client } = await createOpencode ()
你可以传入一个配置对象来自定义行为。实例仍然会读取你的 opencode.json,但你可以通过内联方式覆盖或添加配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 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 实例,可以创建一个客户端实例来连接它:
1 2 3 4 5 import { createOpencodeClient } from "@opencode-ai/sdk" const client = createOpencodeClient ({ baseUrl : "http://localhost:4096" , })
SDK 通过类型安全的客户端暴露所有服务器 API ,具体参见 SDK 。
如下是使用opencode SDK 的一个完整例子,它使用了自定义 provider 来提供 model:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 import { createOpencode } from "@opencode-ai/sdk" async function main ( ) { const { client, server } = await createOpencode ({ config : { model : "chaitin/glm-4.7" , provider : { chaitin : { name : "chaitin" , options : { apiKey : "your api key" , baseURL : "your base url" , }, models : { "glm-4.7" : { name : "GLM-4.7" , }, }, }, }, } }) console .log ("Server started at:" , server.url ) const session = await client.session .create ({ body : { title : "Test Session" }, }) console .log ("Session:" , session.data .id ) const result = await client.session .prompt ({ path : { id : session.data .id }, body : { parts : [{ type : "text" , text : "中国首都在哪里?" }], }, }) console .log ("\n回复:" , JSON .stringify (result, null , 2 )) server.close () } main ().catch (console .error )
服务器
当你运行 opencode 时,它会启动一个 TUI 和一个服务器。TUI 是与服务器通信的客户端 。服务器暴露一个 OpenAPI 3.1 规范端点。该端点也用于生成 SDK。这种架构让 opencode 支持多个客户端,并允许你以编程方式与 opencode 交互 。
你可以运行 opencode serve 来启动一个独立的服务器。如果你已经在运行 opencode TUI,opencode serve 会启动一个新的服务器。服务器暴露的具体 API 可以参考这里 。
插件
插件允许你通过挂钩各种事件和自定义行为来扩展 OpenCode。你可以创建插件来添加新功能、集成外部服务,或修改 OpenCode 的默认行为。
有两种方式加载插件。
1 2 3 4 { "$schema" : "https://opencode.ai/config.json" , "plugin" : ["opencode-helicone-session" , "opencode-wakatime" , "@my-org/custom-plugin" ] }
npm 插件在启动时使用 Bun 自动安装。包及其依赖项会缓存在 ~/.cache/opencode/node_modules/ 中。本地插件直接从插件目录加载。如果需要使用外部包,你必须在配置目录中创建 package.json,或者将插件发布到 npm 并将其添加到配置中。
插件从所有来源加载,所有钩子按顺序执行。加载顺序为:
全局配置 (~/.config/opencode/opencode.json)
项目配置 (opencode.json)
全局插件目录 (~/.config/opencode/plugins/)
项目插件目录 (.opencode/plugins/)
创建插件
插件是一个 JavaScript/TypeScript 模块,它导出一个或多个插件函数。每个函数接收一个上下文对象,并返回一个钩子对象。
本地插件和自定义工具可以使用外部 npm 包。在配置目录中添加一个 package.json,列出所需的依赖项。
OpenCode 会在启动时运行 bun install 来安装这些依赖项。之后你的插件和工具就可以导入它们了
如下是一个插件的基本结构:
1 2 3 4 5 6 7 export const MyPlugin = async ({ project, client, $, directory, worktree } ) => { console .log ("Plugin initialized!" ) return { } }
插件函数接收以下参数:
project:当前项目信息
directory:当前工作目录
worktree:git 工作树路径
client:用于与 AI 交互的 OpenCode SDK 客户端
$:Bun 的 Shell API,用于执行命令
插件可以订阅事件,这里是具体的事件列表 。
生态系统
这里 介绍了基于 OpenCode 构建的社区项目合集。除此之外,您还可以查看 awesome-opencode 和 opencode.cafe ,这是一个聚合生态系统与社区资源的社区。
实际例子
接下来将通过一些实际例子,演示为 opencode 添加自定义 slash 命令、skill、agent、插件 等。
自定义 slash 命令
我们创建一个项目级别生效的 slash 命令,该命令可以获取某个国家的首都:
命令的定义如下:
1 2 3 4 5 description: 查询指定国家的首都 model: dashscope/qwen3.5-plus --- 请告诉我 $ARGUMENTS 的首都是哪个城市?请直接回答城市名称。
在当前目录下启动 opencode,就能使用 /oc-demo-capital 该命令了:
自定义 skill
创建两个项目级别的 skill,一个 skill 用于获取北京天气,另一个 skill 通过 python 脚本分析数据文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 --- name: beijing-weather description: 查询北京当前天气情况,包括温度、湿度、风力等信息 --- 查询北京当前天气状况,包括: - 当前温度和体感温度 - 湿度 - 风速和风向 - 空气质量指数(AQI) - 天气状况(晴、多云、雨等) 用户询问北京天气时使用此技能。 1. 使用 webfetch 工具访问天气 API 或天气网站 2. 解析返回的天气数据 3. 以简洁格式向用户报告天气信息 北京天气 [日期时间] 温度:XX°C(体感 XX°C) 天气:晴/多云/雨 湿度:XX% 风速:XX km/h,风向:XX 空气质量:X
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 --- name: data-analyzer description: Use when analyzing CSV or JSON data files to generate statistical reports, including numeric statistics and categorical value dist ributions --- Analyze data files (CSV/JSON) and generate comprehensive statistical reports with numeric and categorical field analysis. - User asks to analyze data files - Need statistical summary of datasets - Exploring data structure and distributions - Preparing data quality reports 1. Identify data file path (CSV or JSON) 2. Run Python script: `python .opencode/skills/data-analyzer/analyze_data.py <file>` 3. Use `--json` flag for JSON output if needed 4. Present results to user | Command | Purpose | |---------|---------| | `python analyze_data.py data.csv` | Analyze CSV file (text output) | | `python analyze_data.py data.json` | Analyze JSON file (text output) | | `python analyze_data.py data.csv --json` | JSON format output | ......
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 """ Data Analysis Tool Analyzes CSV/JSON data files and generates statistical reports. """ import jsonimport sysimport csvfrom pathlib import Pathfrom collections import Counterfrom typing import Any , Dict , List , Union ......
之后在项目目录下启动 opencode ,输入 /skills 就能看到这两个技能了。opencode 可以自动触发 SKILL 的调用
1 2 3 4 5 6 7 8 > 北京天气 Thinking: 用户询问北京天气。我看到有一个 "beijing-weather" skill 可以查询北京当前天气情况。根据指令,我应该在处理任务之前检查是否有相关的技能适用。 这个技能的描述是:"查询北京当前天气情况,包括温度、湿度、风力等信息" 这明显适用于用户的请求,所以我应该调用这个技能。 → Skill "beijing-weather"
自定义 agent
创建一个数学运算的子 agent,用来执行数学运算:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 --- description: 使用 bash 执行数学运算的代理 mode: subagent tools: write: false edit: false glob: false grep: false read : false --- 你是一个数学运算代理。你的任务是使用 bash 命令执行数学计算。 你只能使用 bash 工具。使用以下方法进行数学运算: 使用 `$(( ))` 进行整数运算: - 加法: `echo $((5 + 3 ))` - 减法: `echo $((10 - 4 ))` - 乘法: `echo $((6 * 7 ))` - 除法: `echo $((20 / 4 ))` - 取模: `echo $((17 % 5 ))` - 幂运算: `echo $((2 ** 10 ))` 使用 `bc` 或 `awk` 进行浮点运算: .......
之后就可以通过 @math 这种方式手动调用该这个 agent 了:
1 2 3 4 5 6 7 8 9 > @math 1 + 1 Thinking: The user is asking me to use the math subagent to calculate 1 + 1. Let me call the task tool with the math subagent type to perform this calculation. │ Task Calculate 1 + 1 └ 1 toolcalls · 8.0s ctrl+x down view subagents Thinking: The math subagent has returned the result. The answer is 2. 2
opencode 也可能会自动触发这个 agent(也可能不会):
1 2 3 4 5 6 > 帮我执行数学计算 1 + 1 Thinking: 用户要求执行一个简单的数学计算:1 + 1。这是一个非常简单的任务,不需要使用任何技能。我可以直接回答或使用数学代理。 实际上,我看到有一个 "math" 代理可以使用 bash 执行数学运算。但对于这么简单的问题,我可以直接回答,或者使用 bash 来计算。 让我直接回答吧 - 这是一个极其简单的问题。 2
1 2 3 4 5 6 7 8 9 10 11 12 > 帮我执行数学计算 9999 * 99999 Thinking: 用户请求执行一个数学计算:9999 * 99999。 查看可用的技能,我看到有一个 "math" 代理专门用于使用 bash 执行数学运算: - math: 使用 bash 执行数学运算的代理 我应该使用 Task 工具调用这个 math 子代理来完成数学计算。 │ Task 计算 9999 * 99999 └ 1 toolcalls · 7.0s ctrl+x down view subagents Thinking: 数学计算已完成。结果是 999,890,001。我应该简洁地回答用户。 9999 × 99999 = 999,890,001
如果触发了 subagent 的调用,我们可以通过 ctrl+x down 看到 subagent 的会话过程。
自定义插件
如下则展示了一个极简的 plugin 示例,它会在 opencode 启动时在当前目录下创建一个启动文件,记录启动时间。
1 2 3 4 5 6 7 8 9 10 11 12 13 import type { Plugin } from "@opencode-ai/plugin" import { writeFileSync } from "fs" import { join } from "path" export const StartupLoggerPlugin: Plugin = async ({ directory }) => { return { config: async () => { const timestamp = new Date().toISOString() const logFile = join (directory, "startup.log" ) writeFileSync(logFile, `OpenCode started at: ${timestamp} \n`, { flag: "a" }) }, } }
之后在当前目录下启动 opencode,输入 /status 应该就能看到加载的插件。同时当前目录下存在该启动文件:
1 2 3 $ more startup.log OpenCode started at: 2026-03-11T07:22:27.917Z OpenCode started at: 2026-03-11T07:26:41.889Z