跳转到内容

插件 Plugins

编写你自己的插件以扩展 OpenCode。

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

要查看示例,请查看社区创建的 插件。


使用插件 Use a plugin

有两种加载插件的方式。


从本地文件 From local files

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

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

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


从 npm From npm

在你的配置文件中指定 npm 包。

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

支持常规和作用域 npm 包。

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


插件如何安装 How plugins are installed

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

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


加载顺序 Load order

插件从所有源加载,所有 hook 按顺序运行。加载顺序为:

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

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


创建插件 Create a plugin

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


依赖项 Dependencies

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

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

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

.opencode/plugins/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)
}
},
}
}

基本结构 Basic structure

.opencode/plugins/example.js
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 support

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

my-plugin.ts
import type { Plugin } from "@opencode-ai/plugin"
export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => {
return {
// Type-safe hook implementations
}
}

事件 Events

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

命令事件 Command Events

  • command.executed

文件事件 File Events

  • file.edited
  • file.watcher.updated

安装事件 Installation Events

  • installation.updated

LSP 事件 LSP Events

  • lsp.client.diagnostics
  • lsp.updated

消息事件 Message Events

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

权限事件 Permission Events

  • permission.asked
  • permission.replied

服务器事件 Server Events

  • server.connected

会话事件 Session Events

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

待办事项事件 Todo Events

  • todo.updated

工具事件 Tool Events

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

TUI 事件 TUI Events

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

示例 Examples

以下是你可以用来扩展 opencode 的一些插件示例。


发送通知 Send notifications

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

.opencode/plugins/notification.js
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 保护 .env protection

防止 opencode 读取 .env 文件:

.opencode/plugins/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("Do not read .env files")
}
},
}
}

自定义工具 Custom tools

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

.opencode/plugins/custom-tools.ts
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 架构函数并返回一个工具定义,包含:

  • description: 工具做什么
  • args: 工具参数的 Zod 架构
  • execute: 调用工具时运行的函数

你的自定义工具将与内置工具一起提供给 opencode。


日志记录 Logging

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

.opencode/plugins/my-plugin.ts
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 文档。


压缩 hooks Compaction hooks

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

.opencode/plugins/compaction.ts
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 hook 在 LLM 生成延续摘要之前触发。使用它注入默认压缩提示符可能会遗漏的特定于域的上下文。

你也可以通过设置 output.prompt 完全替换压缩提示符:

.opencode/plugins/custom-compaction.ts
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 status
2. Which files are being modified and by whom
3. Any blockers or dependencies between agents
4. 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 数组将被忽略。