---
title: 插件
description: 编写您自己的插件来扩展 OpenCode。
---

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

例如，查看社区创建的[插件](/docs/ecosystem#plugins)。

---

## 使用插件

有兩種加載插件的方法。

---

### 從本地文件

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

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

這些目錄中的文件會在啟動時自動加載。

---

### 来自 npm

在配置文件中指定 npm 包。

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

支持常规和范围的 npm 包。

浏览[生态系统](/docs/ecosystem#plugins)中的可用插件。

---

### 插件是如何安裝的

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

**本地插件**直接从插件目录加载。要使用外部包，您必须在配置目录中创建`package.json`（请参阅[依赖关系](#dependencies)），或将插件发布到npm和[将其添加到您的配置中](/docs/config#plugins)。

---

### 加載順序

插件從所有源加載，所有掛鉤按順序運行。加載順序為：

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

具有相同的名称和版本，但是重复的 npm 包将被加载一次。，本地插件和名称相似的 npm 插件都是分开加载的。

---

## 創建一個插件

插件是一个 **JavaScript/TypeScript 模块多个**，它导出一个或插件
功能。每個函數接收一個上下文對象並返回一個鉤子對象。

---

### 依賴關係

本地插件和自定义工具可以使用外部 npm 包。将 `package.json` 添加到您的配置目录，其中包含您需要的依赖项。

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

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

```ts title=".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)
      }
    },
  }
}
```

---

### 基本結構

```js title=".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交互的开放代码SDK客户端。
- `$`：Bun的[外壳API](https://bun.com/docs/runtime/shell)用于执行命令。

---

### TypeScript 支持

对于 TypeScript 插件，您可以从插件包中导入类型：

```ts title="my-plugin.ts" {1}
import type { Plugin } from "@opencode-ai/plugin"

export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => {
  return {
    // Type-safe hook implementations
  }
}
```

---

### 活動

插件可以訂閱事件，如下面的示例部分所示。以下是可用的不同事件的列表。

#### 命令事件

- `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.asked`
- `permission.replied`

#### 服務器事件

- `server.connected`

#### 會議活動

- `session.created`
- `session.compacted`
- `session.deleted`
- `session.diff`
- `session.error`
- `session.idle`
- `session.status`
- `session.updated`

#### 都都活動

- `todo.updated`

#### 殼牌活動

- `shell.env`

#### 工具事件

- `tool.execute.after`
- `tool.execute.before`

#### 途易活動

- `tui.prompt.append`
- `tui.command.execute`
- `tui.toast.show`

---

## 示例

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

---

### 發送通知

當某些事件發生時發送通知：

```js title=".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"'`
      }
    },
  }
}
```

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

:::note
如果您使用 OpenCode 桌面应用程序，它可以在响应准备就绪或会话错误时自动发送系统通知。
:::

---

### .env 保护

阻止opencode读取`.env`文件：

```javascript title=".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")
      }
    },
  }
}
```

---

### 注入環境變量

将环境变量注入所有shell执行（AI工具和用户终端）：

```javascript title=".opencode/plugins/inject-env.js"
export const InjectEnvPlugin = async () => {
  return {
    "shell.env": async (input, output) => {
      output.env.MY_API_KEY = "secret"
      output.env.PROJECT_ROOT = input.cwd
    },
  }
}
```

---

### 定制工具

插件还可以向 opencode 添加自定义工具：

```ts title=".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` 帮助器创建一个可以调用的自定义工具的开放代码。它采用 Zod 模式函数并返回一个工具定义：

- `description`：该工具的作用
- `args`：Zod 模式的工具参数
- `execute`：调用工具时运行的函数

您的自定義工具將可與內置工具一起用於開放代碼。

---

### 記錄

使用 `client.app.log()` 而不是 `console.log` 进行成型日志记录：

```ts title=".opencode/plugins/my-plugin.ts"
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文档](https://opencode.ai/docs/sdk)。

---

### 壓實鉤

自定義壓縮會話時包含的上下文：

```ts title=".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`钩子在LLM生成驱动机之前触发。使用它来填充默认压缩提示会丢失的特定于域的上下文。

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

```ts title=".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` 内存将被忽略。
