Code Reader
首页
帮助
设计文档
首页
帮助
设计文档
  • Plugin

Plugin

Plugin 系统允许扩展 OpenCode 的功能。

概述

Plugin 是动态加载的模块,可以提供钩子(hooks)来自定义 OpenCode 的行为。插件可以是内置的、从 npm 安装的,或本地文件。

定义位置

packages/opencode/src/plugin/index.ts:1-136

Plugin 接口

插件必须导出一个函数,接收 PluginInput 并返回 Hooks。

type Plugin = (input: PluginInput) => Promise<Hooks> | Hooks

interface PluginInput {
  client: OpencodeClient
  project: Project
  worktree: string
  directory: string
  serverUrl: string
  $: typeof Bun.$
}

interface Hooks {
  config?: (config: Config) => void
  auth?: (input: AuthInput, output: AuthOutput) => AuthOutput
  tool?: (input: ToolInput, output: ToolOutput) => ToolOutput
  event?: (input: EventInput) => void
}

内置插件

OpenCode 内置以下插件:

1. CodexAuthPlugin

OpenAI Codex 认证插件。

2. CopilotAuthPlugin

GitHub Copilot 认证插件。

插件配置

在 opencode.jsonc 中配置插件:

{
  "plugin": [
    // 从 npm 安装
    "my-plugin@1.0.0",

    // 使用 latest 版本
    "another-plugin",

    // 本地文件
    "file:///home/user/my-plugin.js",

    // 相对路径
    "./local-plugin.js",

    // 内置插件(自动安装)
    "opencode-anthropic-auth@0.0.9",
    "@gitlab/opencode-gitlab-auth@1.3.0",
  ],
}

Hooks

config

在配置加载后调用,允许插件修改配置。

hooks.config = (config) => {
  // 修改配置
  config.agent = {
    ...config.agent,
    "my-agent": {
      description: "Plugin-provided agent",
      mode: "primary",
    },
  }
}

auth

在认证请求时调用。

hooks.auth = (input, output) => {
  // 处理认证
  return output
}

tool

在工具调用前/后调用。

hooks.tool = (input, output) => {
  // 修改工具调用
  return output
}

event

监听所有事件。

hooks.event = (input) => {
  // 处理事件
  console.log(`Event: ${input.event.type}`)
}

典型使用场景

1. 创建简单插件

// my-plugin.js
export default async function plugin(input) {
  console.log(`Plugin loaded for project: ${input.project.id}`)

  return {
    config: (config) => {
      console.log("Config hook called")
      // 修改配置
    },

    event: (eventInput) => {
      console.log(`Event: ${eventInput.event.type}`)
      // 处理事件
    },
  }
}

2. 安装插件

# 全局安装
bun add -g my-plugin

# 在 OpenCode 项目中
bun add my-plugin

3. 配置插件

{
  "plugin": ["my-plugin@1.0.0"],
}

4. 插件访问 OpenCode Client

export default async function plugin(input) {
  const { client, project, worktree } = input

  // 使用 SDK 访问会话
  const sessions = await client.session.list()
  console.log(`Found ${sessions.length} sessions`)

  // 创建新会话
  const session = await client.session.create({
    title: "Plugin-created session",
    directory: worktree,
  })

  return {}
}

5. 插件执行命令

export default async function plugin(input) {
  const { $ } = input

  // 使用 Bun.$ 执行命令
  const result = await $`npm test`.quiet()

  if (result.exitCode !== 0) {
    console.error("Tests failed")
  }

  return {}
}

6. 列出加载的插件

const hooks = await Plugin.list()

for (const hook of hooks) {
  console.log(`Plugin has hooks:`)
  if (hook.config) console.log("  - config")
  if (hook.auth) console.log("  - auth")
  if (hook.tool) console.log("  - tool")
  if (hook.event) console.log("  - event")
}

插件目录

插件在以下位置查找:

  1. 全局配置目录: ~/.opencode/
  2. 项目配置目录: .opencode/(向上搜索)
  3. 全局 Claude 目录: ~/.claude/
  4. 项目 Claude 目录: .claude/(向上搜索)

每个目录还扫描 node_modules/ 中的插件。

插件安装

当插件目录检测到需要安装时:

// 检查 node_modules 是否存在
const exists = await fs.stat(path.join(dir, "node_modules"))

// 如不存在,自动安装
if (!exists) {
  // 安装 @opencode-ai/plugin
  await BunProc.run(["add", "@opencode-ai/plugin@" + version, "--exact"], { cwd: dir })

  // 安装 package.json 中的依赖
  await BunProc.run(["install"], { cwd: dir })
}

插件触发

同步钩子

config 和 auth 钩子在特定操作时同步触发。

异步事件钩子

event 钩子订阅所有事件总线消息:

Bus.subscribeAll(async (event) => {
  const hooks = await Plugin.list()
  for (const hook of hooks) {
    hook.event?.({ event })
  }
})

插件错误处理

插件初始化失败时的处理:

try {
  const mod = await import(pluginPath)
  const init = await plugin(input)
  hooks.push(init)
} catch (error) {
  log.error("failed to load plugin", {
    path: pluginPath,
    error: error.message,
  })
  //继续加载其他插件
}

插件依赖

插件可以声明依赖:

{
  "name": "my-plugin",
  "dependencies": {
    "@opencode-ai/sdk": "^2.0.0"
  }
}

依赖会自动安装到插件的 node_modules/ 目录。

内置插件列表

const BUILTIN = ["opencode-anthropic-auth@0.0.9", "@gitlab/opencode-gitlab-auth@1.3.0"]

加载流程

安全考虑

插件隔离

  • 插件运行在 Bun 沙箱中
  • 使用 Bun.$ 执行命令受权限系统控制
  • 文件访问受权限系统控制

插件验证

  • 仅允许导出函数的模块
  • 防止恶意代码执行
  • 记录所有插件加载失败

插件开发最佳实践

  1. 错误处理: 始终捕获并记录错误
  2. 性能: 避免阻塞主线程
  3. 兼容性: 检查 API 版本
  4. 文档: 提供清晰的 README

示例插件

日志插件

export default async function plugin(input) {
  return {
    event: (eventInput) => {
      const { event } = eventInput
  console.log(`[${event.type}]`, event.properties)

    // 写入日志文件
    await Bun.appendFile('plugin-events.log', JSON.stringify(event) + '\n')
  }
}

Agent 注入插件

export default async function plugin(input) {
  return {
    config: (config) => {
      // 注入自定义 agent
      config.agent = {
        ...config.agent,
        "plugin-agent": {
          description: "Agent provided by plugin",
          mode: "primary",
        },
      }
    },
  }
}

对象关系

变更历史

版本变更内容日期
v1初始 Plugin 架构-
v1.1添加内置插件支持-
v1.2改进错误处理-

相关文档

  • Config - 配置系统