插件
编写自己的插件来扩展 OpenCode。
插件允许你通过挂钩各种事件和自定义行为来扩展 OpenCode。你可以创建插件来添加新功能、集成外部服务,或修改 OpenCode 的默认行为。
如需了解示例,请查看社区创建的插件。
使用插件
有两种方式加载插件。
从本地文件加载
将 JavaScript 或 TypeScript 文件放置在插件目录中。
.opencode/plugins/- 项目级插件~/.config/opencode/plugins/- 全局插件
这些目录中的文件会在启动时自动加载。
从 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 并将其添加到配置中。
加载顺序
插件从所有来源加载,所有钩子按顺序执行。加载顺序为:
- 全局配置 (
~/.config/opencode/opencode.json) - 项目配置 (
opencode.json) - 全局插件目录 (
~/.config/opencode/plugins/) - 项目插件目录 (
.opencode/plugins/)
名称和版本相同的重复 npm 包只会加载一次。但本地插件和名称相似的 npm 插件会分别独立加载。
创建插件
插件是一个 JavaScript/TypeScript 模块,它导出一个或多个插件函数。每个函数接收一个上下文对象,并返回一个钩子对象。
依赖项
本地插件和自定义工具可以使用外部 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) } }, }}基本结构
export const MyPlugin = async ({ project, client, $, directory, worktree }) => { console.log("Plugin initialized!")
return { // Hook implementations go here }}插件函数接收以下参数:
project:当前项目信息。directory:当前工作目录。worktree:git 工作树路径。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 { // Type-safe hook implementations }}事件
插件可以订阅事件,如下方示例部分所示。以下是所有可用事件的列表。
命令事件
command.executed
文件事件
file.editedfile.watcher.updated
安装事件
installation.updated
LSP 事件
lsp.client.diagnosticslsp.updated
消息事件
message.part.removedmessage.part.updatedmessage.removedmessage.updated
权限事件
permission.askedpermission.replied
服务器事件
server.connected
会话事件
session.createdsession.compactedsession.deletedsession.diffsession.errorsession.idlesession.statussession.updated
待办事项事件
todo.updated
Shell 事件
shell.env
工具事件
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 }) => { // Send notification on session completion 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") } }, }}注入环境变量
将环境变量注入所有 Shell 执行(AI 工具和用户终端):
export const InjectEnvPlugin = async () => { return { "shell.env": async (input, output) => { output.env.MY_API_KEY = "secret" output.env.PROJECT_ROOT = input.cwd }, }}自定义工具
插件还可以为 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, context) { const { directory, worktree } = context return `Hello ${args.foo} from ${directory} (worktree: ${worktree})` }, }), }, }}tool 辅助函数用于创建 OpenCode 可调用的自定义工具。它接受一个 Zod schema 函数,并返回一个工具定义,包含:
description:工具的功能描述args:工具参数的 Zod schemaexecute:工具被调用时执行的函数
你的自定义工具将与内置工具一起在 OpenCode 中可用。
日志记录
使用 client.app.log() 代替 console.log 进行结构化日志记录:
export const MyPlugin = async ({ client }) => { await client.app.log({ body: { service: "my-plugin", level: "info", message: "Plugin initialized", extra: { foo: "bar" }, }, })}日志级别:debug、info、warn、error。详情请参阅 SDK 文档。
压缩钩子
自定义会话压缩时包含的上下文:
import type { Plugin } from "@opencode-ai/plugin"
export const CompactionPlugin: Plugin = async (ctx) => { return { "experimental.session.compacting": async (input, output) => { // Inject additional context into the compaction prompt 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 钩子在 LLM 生成续接摘要之前触发。使用它来注入默认压缩提示词可能遗漏的领域特定上下文。
你还可以通过设置 output.prompt 来完全替换压缩提示词:
import type { Plugin } from "@opencode-ai/plugin"
export const CustomCompactionPlugin: Plugin = async (ctx) => { return { "experimental.session.compacting": async (input, output) => { // Replace the entire compaction prompt 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 数组将被忽略。