插件
编写插件扩展 OpenCode。
插件(Plugins)允许你通过订阅事件、修改默认行为等方式扩展 OpenCode。你可以编写插件来添加新功能、集成外部服务,或调整 OpenCode 的默认逻辑。
更多示例可以参考社区维护的 插件生态。
使用插件
加载插件有两种方式。
本地文件
在插件目录中放置 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 包。
可在 生态页面 中浏览可用插件。
插件是如何安装的
- npm 插件:启动时由 Bun 自动安装,包及其依赖会缓存在
~/.cache/opencode/node_modules/。 - 本地插件:直接从插件目录加载。如果需要使用外部依赖,需要在配置目录下创建
package.json(详见依赖),或者将插件发布到 npm 并在配置中引用。
加载顺序
插件会从所有来源加载,其 Hook 依次执行。加载顺序为:
- 全局配置(
~/.config/opencode/opencode.json) - 项目配置(
opencode.json) - 全局插件目录(
~/.config/opencode/plugin/) - 项目插件目录(
.opencode/plugin/)
同名同版本的 npm 包只会加载一次。但如果本地插件和 npm 插件名称“看起来相似”,它们仍然是两个独立插件,都会被加载。
编写插件
插件本质上是一个 JavaScript/TypeScript 模块,导出一个或多个插件函数。每个函数接收一个上下文对象,并返回包含 Hook 的对象。
依赖
本地插件和自定义工具可以使用外部 npm 包。只需在配置目录中添加一个 package.json:
{ "dependencies": { "shescape": "^2.1.0" }}OpenCode 会在启动时执行 bun install 安装这些依赖,之后你的插件和工具就可以直接 import:
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) } }, }}基本结构
export const MyPlugin = async ({ project, client, $, directory, worktree }) => { console.log("Plugin initialized!")
return { // 在这里实现各类 Hook }}插件函数会收到:
project:当前项目信息directory:当前工作目录worktree:Git worktree 路径client:用于与 AI 交互的 OpenCode SDK 客户端$:Bun 的 shell API,可执行命令
TypeScript 支持
在 TypeScript 插件中,可以从插件包中引入类型:
import type { Plugin } from "@opencode-ai/plugin"
export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => { return { // 类型安全的 Hook 实现 }}事件
插件可以订阅多种事件(在下面的示例中有具体用法)。可用事件包括:
命令事件
command.executed
文件事件
file.editedfile.watcher.updated
安装事件
installation.updated
LSP 事件
lsp.client.diagnosticslsp.updated
消息事件
message.part.removedmessage.part.updatedmessage.removedmessage.updated
权限事件
permission.repliedpermission.updated
服务器事件
server.connected
会话事件
session.createdsession.compactedsession.deletedsession.diffsession.errorsession.idlesession.statussession.updated
待办事件
todo.updated
工具事件
tool.execute.aftertool.execute.before
TUI 事件
tui.prompt.appendtui.command.executetui.toast.show
示例
下面是一些可以用来扩展 OpenCode 的插件示例。
发送通知
在某些事件发生时发送系统通知:
export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => { return { event: async ({ event }) => { // 会话空闲时发送通知 if (event.type === "session.idle") { await $`osascript -e 'display notification "Session completed!" with title "opencode"'` } }, }}这里通过 osascript 在 macOS 上运行 AppleScript 来发送通知。
保护 .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("Do not read .env files") } }, }}自定义工具
插件也可以为 OpenCode 注册自定义工具:
import { type Plugin, tool } from "@opencode-ai/plugin"
export const CustomToolsPlugin: Plugin = async (ctx) => { return { tool: { mytool: tool({ description: "This is a custom tool", args: { foo: tool.schema.string(), }, async execute(args, ctx) { return `Hello ${args.foo}!` }, }), }, }}tool 帮助函数会为 OpenCode 创建一个可调用的自定义工具,包含:
description:工具的说明args:参数的 Zod schema 定义execute:工具实际执行逻辑
自定义工具会和内置工具一起提供给 OpenCode 使用。
日志
使用 client.app.log() 替代 console.log,便于结构化日志收集:
export const MyPlugin = async ({ client }) => { await client.app.log({ service: "my-plugin", level: "info", message: "Plugin initialized", extra: { foo: "bar" }, })}可用日志级别:debug、info、warn、error。更多信息见 SDK 文档。
压缩(Compaction)钩子
在会话压缩时自定义需要保留的上下文:
import type { Plugin } from "@opencode-ai/plugin"
export const CompactionPlugin: Plugin = async (ctx) => { return { "experimental.session.compacting": async (input, output) => { // 向压缩提示中注入额外上下文 output.context.push(`## Custom Context
Include any state that should persist across compaction:- Current task status- Important decisions made- Files being actively worked on`) }, }}experimental.session.compacting Hook 会在 LLM 生成继续会话所需摘要前触发。你可以在这里注入默认压缩逻辑可能遗漏的领域上下文。
也可以通过设置 output.prompt 完全替换压缩提示词:
import type { Plugin } from "@opencode-ai/plugin"
export const CustomCompactionPlugin: Plugin = async (ctx) => { return { "experimental.session.compacting": async (input, output) => { // 完全替换压缩提示词 output.prompt = `You are generating a continuation prompt for a multi-agent swarm session.
Summarize:1. The current task and its status2. Which files are being modified and by whom3. Any blockers or dependencies between agents4. The next steps to complete the work
Format as a structured prompt that a new agent can use to resume work.` }, }}当设置了 output.prompt 时,会完全替换默认的压缩提示;此时 output.context 数组会被忽略。