安裝外掛
理解 OpenCode 外掛什麼時候該用,以及如何安全擴充套件執行行為。
Plugin 是 OpenCode 的執行時擴充套件。它不是提示詞,也不是 Agent 角色,而是在 OpenCode 執行過程中監聽事件、注入環境、修改工具呼叫、傳送通知、寫日誌,或者新增自定義工具。
這一篇用 10 分鐘換什麼:你會知道什麼時候需要 Plugin,什麼時候應該用 Rules、Agent、Skill、MCP 或 custom tool,以及寫第一個外掛時怎麼把風險收住。
先給結論:大多數新手暫時不需要外掛
Plugin 站得很底層。它能改變 OpenCode 的執行過程,所以不要把它當成“高階提示詞”使用。
先按這個順序判斷:
| 你想解決的問題 | 優先用什麼 | 原因 |
|---|---|---|
| 讓 Agent 長期遵守專案規則 | Rules / AGENTS.md | 這是上下文約束,不是執行時擴充套件 |
| 複用一套操作流程 | Skill | Skill 按需載入,不會常駐改變執行時 |
| 給模型一個專案動作 | Custom tool | 只增加可呼叫能力,不必接管生命週期 |
| 接外部系統 | MCP | 外部服務接入更適合用標準協議 |
| 監聽事件、改工具呼叫、注入環境 | Plugin | 這才是外掛的職責 |
外掛越全域性,影響面越大。新外掛先放專案級目錄,先做只讀日誌或通知,確認穩定後再考慮攔截工具呼叫。
Plugin 在擴充套件層裡的位置
OpenCode 的擴充套件不是一層東西。把層級分清,後面才不會越配越亂。
flowchart TB
Rules[Rules / AGENTS.md<br/>專案長期約束]
Agent[Agents<br/>角色和許可權邊界]
Skill[Skills<br/>可複用流程說明]
Tool[Custom tools / MCP<br/>模型可呼叫能力]
Plugin[Plugins<br/>執行時事件和行為擴充套件]
Rules --> Agent
Agent --> Skill
Agent --> Tool
Plugin -.監聽和改變.-> Tool
Plugin -.注入或記錄.-> Agent
一句話判斷:如果你只是想讓模型“知道怎麼做”,不要寫外掛;如果你要在 OpenCode 執行時“發生某事時自動做某事”,才考慮外掛。
外掛放在哪裡
OpenCode 支援本地外掛和 npm 外掛。
| 來源 | 路徑或配置 | 適合場景 |
|---|---|---|
| 專案級本地外掛 | .opencode/plugins/ | 當前儲存庫專屬行為 |
| 全域性本地外掛 | ~/.config/opencode/plugins/ | 所有專案都需要的通用行為 |
| npm 外掛 | opencode.json 的 plugin 陣列 | 已有成熟社群外掛或團隊私有包 |
專案級外掛隻影響當前儲存庫,更適合試錯。全域性外掛會影響所有 OpenCode 會話,除非它已經很穩定,否則不要預設放全域性。
npm 外掛什麼時候用
如果社群已有成熟外掛,可以在配置裡引用 npm 包:
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-wakatime"]
}OpenCode 會在啟動時用 Bun(一個比 Node.js 快得多的 JavaScript 執行時和包管理器,OpenCode 內部用它跑外掛程式碼)自動安裝 npm 外掛,並把依賴快取到本機。使用前至少檢查三件事:
- 外掛原始碼做了什麼,有沒有讀寫檔案、執行 shell、上傳資料。
- 外掛是否仍在維護,是否和當前 OpenCode 版本匹配。
- 是否真的需要全域性啟用,還是隻在某個專案啟用。
不理解的 npm 外掛不要直接放進全域性配置。外掛能接觸執行過程,風險比普通文件依賴高。
載入順序怎麼理解
OpenCode 會從多個來源載入外掛,並按順序執行 hooks。官方載入順序是:
| 順序 | 來源 |
|---|---|
| 1 | 全域性配置:~/.config/opencode/opencode.json |
| 2 | 專案配置:opencode.json |
| 3 | 全域性外掛目錄:~/.config/opencode/plugins/ |
| 4 | 專案外掛目錄:.opencode/plugins/ |
如果同名同版本的 npm 包重複出現,只會載入一次;本地外掛和 npm 外掛即使名字相近,也會分別載入。
先寫一個只記錄日誌的最小外掛
第一個外掛不要攔截工具,也不要改 shell 環境。先驗證它能被載入,並能寫結構化日誌。
檔案:.opencode/plugins/audit-events.ts
export const AuditEventsPlugin = async ({ client }) => {
await client.app.log({
body: {
service: "audit-events",
level: "info",
message: "Plugin loaded",
},
})
return {}
}這類外掛失敗時影響面小,適合作為“外掛鏈路是否正常”的第一步。
事件怎麼選
你不需要背完整事件表。先按風險選擇:
| 目標 | 常見事件 | 風險 |
|---|---|---|
| 觀察會話狀態 | session.*、message.*、todo.updated | 低 |
| 記錄許可權互動 | permission.asked、permission.replied | 中 |
| 注入 shell 環境 | shell.env | 中 |
| 攔截工具執行 | tool.execute.before、tool.execute.after | 高 |
| 改變 TUI 行為 | tui.toast.show、tui.prompt.append、tui.command.execute | 中到高 |
| 處理檔案或 LSP 事件 | file.edited、lsp.client.diagnostics | 中 |
選事件前先問一句:我是觀察發生了什麼,還是要改變它?觀察型外掛風險低;攔截和修改型外掛要有測試儲存庫和停用方案。
依賴怎麼管理
本地外掛需要第三方 npm 包時,在配置目錄放 package.json。OpenCode 啟動時會執行 bun install。
{
"dependencies": {
"shescape": "^2.1.0"
}
}依賴越多,啟動、快取和排障成本越高。外掛依賴只放真正必要的包;如果只是幾行字串處理,不要引入新依賴。
外掛和 Custom Tool 的關係
Plugin 也可以新增 custom tool。這個能力很強,但也更容易誤用。
適合:
- 工具需要和外掛上下文繫結。
- 工具要配合事件監聽、日誌或許可權邏輯。
- 團隊希望用外掛包統一分發工具。
不適合:
- 只是封裝一個簡單專案命令。
- 只是讓模型多一個 API 呼叫入口。
- 沒有測試引數 schema 和錯誤輸出。
如果外掛提供的 tool 和內建工具重名,外掛工具會優先生效。不要隨便覆蓋內建工具名。
安全寫法
外掛可以影響 OpenCode 行為,所以預設按高風險擴充套件處理:
- 不在外掛裡硬編碼 API Key。
- 不把完整環境變數寫進日誌。
- 攔截
bash時,不拼接未經校驗的命令。 - 只在確實必要時修改工具引數。
- 外掛出錯時返回清楚錯誤,不靜默吞掉。
- 給每個外掛保留停用路徑,例如移出目錄或清空配置裡的
plugin陣列。
如果你的目標只是阻止模型讀 .env,優先用許可權或內建敏感檔案保護;只有需要更細粒度邏輯時才寫外掛。
怎麼判斷外掛寫對了
驗證外掛不要直接上真實任務。按這個順序驗收:
- 外掛能被載入,沒有啟動錯誤。
- 只讀日誌或通知能正常觸發。
- 如果攔截工具呼叫,先在測試儲存庫驗證。
- 外掛失敗時,錯誤資訊能定位到原因。
- 停用外掛後,OpenCode 能恢復預設行為。
一個好外掛應該可關閉、可解釋、可定位問題。否則它會讓排障變得更難。
新手常見坑
- 把外掛當成提示詞增強器。提示詞規則應放 Rules、Agent、Command 或 Skill。
- 在全域性目錄放專案專屬外掛,導致其他專案出現異常。
- 外掛裡直接執行危險 shell。
- 日誌裡列印完整環境變數。
- 本來只需要 custom tool,卻寫了一個會修改 OpenCode 生命週期的外掛。
- 沒有停用方案,一齣問題只能猜是不是外掛導致。
接下來去哪
配置 Agents
先把角色、許可權和主/子代理邊界理清,再考慮執行時擴充套件。
使用 Agent Skills
把可複用流程沉澱成 Skill,避免把流程邏輯寫進外掛。
建立自定義工具
如果只是給模型一個可呼叫動作,custom tool 通常比 plugin 更合適。
Agents、Skills、Plugins 怎麼分
用完整擴充套件層級判斷什麼時候該升級到外掛。