Skip to content

插件

编写您自己的插件来扩展 OpenCode。

插件允许您通过挂钩各种事件和自定义行为来扩展 OpenCode。您可以创建插件来添加新功能、与外部服务集成或修改 OpenCode 的默认行为。

有关示例,请查看由社区创建的 插件


使用插件

有两种加载插件的方法。


从本地文件加载

将 JavaScript 或 TypeScript 文件放在插件目录中。

  • .opencode/plugin/ - 项目级插件
  • ~/.config/opencode/plugin/ - 全局插件

这些目录中的文件会在启动时自动加载。


从 npm 加载

在配置文件中指定 npm 包。

opencode.json
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"]
}

支持常规 npm 包和带命名空间的 (scoped) 包。

生态系统 中浏览可用插件。


插件是如何安装的

npm 插件 在启动时使用 Bun 自动安装。包及其依赖项被缓存在 ~/.cache/opencode/node_modules/ 中。

本地插件 直接从插件目录加载。要使用外部包,您必须在配置目录中创建一个 package.json(参见 依赖管理),或者将插件发布到 npm 并将其 添加到您的配置 中。


加载顺序

插件从所有来源加载,并且所有挂钩 (hooks) 按顺序运行。加载顺序为:

  1. 全局配置 (~/.config/opencode/opencode.json)
  2. 项目配置 (opencode.json)
  3. 全局插件目录 (~/.config/opencode/plugin/)
  4. 项目插件目录 (.opencode/plugin/)

具有相同名称和版本的重复 npm 包只会加载一次。但是,名称相似的本地插件和 npm 插件会被分别加载。


创建插件

插件是一个 JavaScript/TypeScript 模块,它导出一个或多个插件函数。每个函数接收一个上下文对象并返回一个挂钩 (hooks) 对象。


依赖管理

本地插件和自定义工具可以使用外部 npm 包。在您的配置目录中添加一个包含所需依赖项的 package.json

.opencode/package.json
{
"dependencies": {
"shescape": "^2.1.0"
}
}

OpenCode 在启动时运行 bun install 来安装这些依赖。然后您的插件和工具就可以导入它们了。

.opencode/plugin/my-plugin.ts
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)
}
},
}
}

基本结构

.opencode/plugin/example.js
export const MyPlugin = async ({ project, client, $, directory, worktree }) => {
console.log("插件已初始化!")
return {
// 挂钩实现放在这里
}
}

插件函数接收以下参数:

  • project: 当前项目信息。
  • directory: 当前工作目录。
  • worktree: Git 工作树路径。
  • client: 用于与 AI 交互的 OpenCode SDK 客户端。
  • $: Bun 的 shell API,用于执行命令。

TypeScript 支持

对于 TypeScript 插件,您可以从插件包中导入类型:

my-plugin.ts
import type { Plugin } from "@opencode-ai/plugin"
export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => {
return {
// 类型安全的挂钩实现
}
}

事件

插件可以订阅事件,如下面示例部分所示。以下是可用事件的列表:

命令事件

  • command.executed

文件事件

  • file.edited
  • file.watcher.updated

安装事件

  • installation.updated

LSP 事件

  • lsp.client.diagnostics
  • lsp.updated

消息事件

  • message.part.removed
  • message.part.updated
  • message.removed
  • message.updated

权限事件

  • permission.replied
  • permission.updated

服务器事件

  • server.connected

会话事件

  • session.created
  • session.compacted
  • session.deleted
  • session.diff
  • session.error
  • session.idle
  • session.status
  • session.updated

待办事项事件

  • todo.updated

工具事件

  • tool.execute.after
  • tool.execute.before

TUI 事件

  • tui.prompt.append
  • tui.command.execute
  • tui.toast.show

示例

以下是一些可用于扩展 OpenCode 的插件示例。


发送通知

在发生某些事件时发送通知:

.opencode/plugin/notification.js
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"'`
}
},
}
}

我们使用 osascript 在 macOS 上运行 AppleScript。在这里,我们用它来发送通知。


.env 文件保护

防止 OpenCode 读取 .env 文件:

.opencode/plugin/env-protection.js
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 文件")
}
},
}
}

自定义工具

插件也可以向 OpenCode 添加自定义工具:

.opencode/plugin/custom-tools.ts
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 `Hello ${args.foo}!`
},
}),
},
}
}

tool 辅助函数创建 OpenCode 可以调用的自定义工具。它接收一个 Zod 模式函数并返回一个包含以下内容的工具定义:

  • description: 工具的功能描述
  • args: 工具参数的 Zod 模式
  • execute: 工具被调用时运行的函数

您的自定义工具将与内置工具一起供 OpenCode 使用。


日志记录

使用 client.app.log() 代替 console.log 进行结构化日志记录:

.opencode/plugin/my-plugin.ts
export const MyPlugin = async ({ client }) => {
await client.app.log({
service: "my-plugin",
level: "info",
message: "插件已初始化",
extra: { foo: "bar" },
})
}

日志级别:debuginfowarnerror。详情请参阅 SDK 文档


压缩挂钩

自定义会话压缩时包含的上下文:

.opencode/plugin/compaction.ts
import type { Plugin } from "@opencode-ai/plugin"
export const CompactionPlugin: Plugin = async (ctx) => {
return {
"experimental.session.compacting": async (input, output) => {
// 向压缩提示词中注入额外上下文
output.context.push(`
## 自定义上下文
包含任何应在压缩后持久保留的状态:
- 当前任务状态
- 做出的重要决策
- 正在积极处理的文件
`)
},
}
}

experimental.session.compacting 挂钩在 LLM 生成续篇摘要之前触发。使用它可以注入默认压缩提示词可能会遗漏的特定领域上下文。

您还可以通过设置 output.prompt 来完全替换压缩提示词:

.opencode/plugin/custom-compaction.ts
import type { Plugin } from "@opencode-ai/plugin"
export const CustomCompactionPlugin: Plugin = async (ctx) => {
return {
"experimental.session.compacting": async (input, output) => {
// 替换整个压缩提示词
output.prompt = `
您正在为一个多智能体集群会话生成续篇提示词。
总结:
1. 当前任务及其状态
2. 正在修改哪些文件以及由谁修改
3. 智能体之间的任何阻塞点或依赖关系
4. 完成工作的后续步骤
格式化为一个结构化提示词,以便新智能体可以使用它来恢复工作。
`
},
}
}

设置 output.prompt 后,它会完全替换默认的压缩提示词。在这种情况下,output.context 数组将被忽略。