OpenCode 插件 (Plugins)
插件可通过挂钩到各种事件并自定义行为来扩展 OpenCode 功能。你可以创建插件以添加新功能、集成外部服务或修改 OpenCode 的默认行为。
使用插件 (Usage)
1. 加载方式 (Loading)
- 本地文件加载:将 JavaScript 或 TypeScript 文件放置在插件目录中
- 项目级插件:
.opencode/plugin/ - 全局插件:
~/.config/opencode/plugin/这些目录中的文件会在启动时自动加载。
- 项目级插件:
- npm 加载:在配置文件中指定 npm 包
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"]
}
支持常规和作用域 npm 包,可在生态系统中浏览可用插件。
2. 安装机制 (Installation)
- npm 插件:启动时通过 Bun 自动安装,包及其依赖项缓存于
~/.cache/opencode/node_modules/ - 本地插件:直接从插件目录加载,若需使用外部包,需在配置目录中创建
package.json(见依赖项部分),或发布插件到 npm 并添加到配置中
3. 加载顺序 (Order)
插件从所有来源加载,所有挂钩按以下顺序执行:
- 全局配置 (
~/.config/opencode/opencode.json) - 项目配置 (
opencode.json) - 全局插件目录 (
~/.config/opencode/plugin/) - 项目插件目录 (
.opencode/plugin/)
相同名称和版本的重复 npm 包仅加载一次,但本地插件和名称相似的 npm 插件会分别加载。
创建插件 (Creating)
1. 依赖项 (Dependencies)
本地插件和自定义工具可使用外部 npm 包,需在配置目录中添加
package.json 并指定依赖项:{
"dependencies": {
"shescape": "^2.1.0"
}
}
OpenCode 启动时会运行
bun install 安装依赖,插件和工具可直接导入使用:import { escape } from "shescape"
export const MyPlugin = async (ctx) => {
return {
"tool.execute.before": async (input, output) => {
if (input.tool === "bash") {
output.args.command = escape(output.args.command)
}
},
}
}
2. 基本结构 (Structure)
export const MyPlugin = async ({ project, client, $, directory, worktree }) => {
console.log("插件初始化!")
return {
// 挂钩实现
}
}
插件函数接收的参数:
project:当前项目信息directory:当前工作目录worktree:git 工作树路径client:用于与 AI 交互的 OpenCode SDK 客户端$:用于执行命令 de Bun shell API
3. TypeScript 支持
TypeScript 插件可从插件包导入类型:
import type { Plugin } from "@opencode-ai/plugin"
export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => {
return {
// 类型安全的挂钩实现
}
}
事件 (Events)
插件可订阅以下事件:
命令与工具
command.executedtool.execute.aftertool.execute.before
文件与代码
file.editedfile.watcher.updatedlsp.client.diagnosticslsp.updated
会话与消息
session.createdsession.compactedsession.deletedsession.diffsession.errorsession.idlesession.statussession.updatedmessage.part.removedmessage.part.updatedmessage.removedmessage.updated
其他
installation.updatedpermission.repliedpermission.updatedserver.connectedtodo.updatedtui.prompt.appendtui.command.executetui.toast.show
插件示例 (Examples)
1. 发送通知
当特定事件发生时发送通知:
export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => {
return {
event: async ({ event }) => {
// 会话完成时发送通知
if (event.type === "session.idle") {
await $`osascript -e 'display notification "会话完成!" with title "opencode"'`
}
},
}
}
[!NOTE] 上述示例使用osascript在 macOS 上运行 AppleScript 发送通知。若使用 OpenCode 桌面应用,当响应就绪或会话出错时,它会自动发送系统通知。
2. .env 保护
阻止 OpenCode 读取
.env 文件:export const EnvProtection = async ({ project, client, $, directory, worktree }) => {
return {
"tool.execute.before": async (input, output) => {
if (input.tool === "read" && output.args.filePath.includes(".env")) {
throw new Error("禁止读取 .env 文件")
}
},
}
}
3. 自定义工具 (Custom Tools)
插件可向 OpenCode 添加自定义工具:
import { type Plugin, tool } from "@opencode-ai/plugin"
export const CustomToolsPlugin: Plugin = async (ctx) => {
return {
tool: {
mytool: tool({
description: "这是一个自定义工具",
args: {
foo: tool.schema.string(),
},
async execute(args, ctx) {
return `你好 ${args.foo}!`
},
}),
},
}
}
tool 辅助函数用于创建 OpenCode 可调用的自定义工具,接收 Zod 架构函数并返回工具定义,包含 description、args(Zod 架构)和 execute 函数。4. 日志记录 (Logging)
使用
client.app.log() 进行结构化日志记录,而非 console.log:export const MyPlugin = async ({ client }) => {
await client.app.log({
service: "my-plugin",
level: "info",
message: "插件初始化",
extra: { foo: "bar" },
})
}
5. 压缩挂钩 (Compaction Hook)
自定义会话压缩时包含的上下文:
import type { Plugin } from "@opencode-ai/plugin"
export const CompactionPlugin: Plugin = async (ctx) => {
return {
"experimental.session.compacting": async (input, output) => {
// 向压缩提示注入额外上下文
output.context.push(`## 自定义上下文
需包含压缩后需保留的状态:
- 当前任务及状态
- 正在处理的文件
- 已做出的重要决策`)
},
}
}
也可以通过设置
output.prompt 完全替换默认的压缩提示。