10.1 內建工具系統

OpenCode 提供了一套豐富的內建工具,讓代理能夠讀取、寫入、搜尋、編輯檔案,執行命令,以及與外部服務互動。這些工具是代理與開發環境互動的基本介面。

工具名稱 功能說明 常用場景
bash 執行 shell 命令 編譯、測試、git 操作、啟動服務
edit 字串替換編輯檔案 精確修改既有檔案內容
write 寫入新檔案 建立新檔案、重置檔案內容
read 讀取檔案內容 瀏覽原始碼、檢查設定檔
grep 正則表達式內容搜尋 找出特定模式、跨檔案搜尋
glob 檔案名稱模式匹配 尋找特定命名規則的檔案
lsp_diagnostics 取得 LSP 診斷資訊 檢查語法錯誤、型別錯誤
patch 應用 diff 修補檔 批次修改多個位置
skill 載入領域技能 啟動特定任務的專用指引
todowrite 管理工作項目清單 建立與追蹤待辦事項
webfetch 擷取網頁內容 讀取 API 文件、線上手冊
websearch 網路搜尋 查詢技術問題、最新資訊
question 向使用者提問 需求釐清、決策確認
📘 備註: 所有工具的回傳結果會自動納入代理的上下文,因此代理可以根據工具輸出動態調整下一步行動。這形成了「觀察 → 思考 → 行動」的循環。

10.2 權限管理系統

OpenCode 的權限系統讓開發者精確控制每個工具的行為,在便利性與安全性之間取得平衡。每個工具都可以設定三種權限等級:

✅

allow(允許)

代理可以自由使用此工具,無需詢問使用者。適合安全且頻繁使用的工具,如 read、grep。

❓

ask(詢問)

代理每次使用工具時都需要獲得使用者明確許可。適合有潛在風險的工具,如 bash、write。

🚫

deny(拒絕)

完全禁止代理使用此工具。適用於不應自動化的操作,或特定專案中禁止的操作。

在 opencode.json 中設定權限

權限設定位於 opencode.json 的頂層 tools 欄位:

{
  "tools": {
    "bash": {
      "*": "ask",
      "git *": "allow",
      "npm *": "allow",
      "rm -rf *": "deny"
    },
    "write": {
      "*": "ask",
      "src/**": "allow"
    },
    "edit": {
      "*": "ask",
      "*.md": "allow"
    },
    "read": {
      "*": "allow"
    },
    "websearch": {
      "*": "allow"
    },
    "webfetch": {
      "*": "ask",
      "api.github.com/*": "allow"
    }
  }
}
💡 規則比對: 權限規則支援 glob 模式比對。代理會依序檢查規則,第一個匹配的規則決定權限。若無任何規則匹配,預設行為由全域設定決定。

權限規則範例

規則 效果 說明
"bash": { "git *": "allow" } 允許 git 命令 代理可自由執行 git 相關操作
"bash": { "rm -rf *": "deny" } 禁止刪除命令 防止代理意外刪除檔案
"write": { "src/**": "allow" } 允許寫入原始碼 代理可自由編輯 src 目錄下的檔案
"write": { "*": "ask" } 其他寫入需詢問 非 src 目錄的寫入需使用者確認
"edit": { "*.md": "allow" } 允許編輯文件 代理可直接修改 markdown 文件
⚠️ 安全建議: 對於任何可能影響生產環境的操作(如 DROP TABLE、rm -rf、force-push),建議明確設定為 deny 或至少 ask。此外,可以搭配 /careful 命令啟用全域安全護欄。

10.3 細粒度規則:物件語法

除了簡單的字串匹配,OpenCode 的權限系統還支援更精細的物件語法,允許根據工具參數的具體內容進行判斷:

{
  "tools": {
    "bash": {
      "rules": [
        {
          "match": { "command": "git push --force *" },
          "permission": "deny",
          "reason": "禁止強制推送,可能造成歷史遺失"
        },
        {
          "match": { "command": "npm publish *" },
          "permission": "ask",
          "reason": "發佈套件需要人工確認"
        },
        {
          "match": { "command": "git *" },
          "permission": "allow"
        }
      ]
    }
  }
}

這種語法讓權限管理變得極具彈性——你可以針對特定命令參數、檔案路徑、或任何工具輸入內容設定不同的權限策略。

10.4 LSP 伺服器整合

語言伺服器協定(Language Server Protocol, LSP)是 OpenCode 提供即時語法檢查與型別診斷的關鍵技術。每當代理編輯檔案後,OpenCode 會自動查詢 LSP 伺服器獲取診斷結果,並將這些發現回饋給代理,形成閉迴路修正。

LSP 診斷回饋流程
◉ 代理編輯檔案 src/auth.ts
→ 寫入 42 行新程式碼
◉ LSP 自動診斷...
→ TypeScript 伺服器回應:
⚠ src/auth.ts:128:5 — 類型 'string | undefined' 不可指派給 'string'
◉ 代理收到診斷結果
→ 正在修復型別錯誤...
✅ 修正完成,LSP 確認無誤
$

內建 LSP 支援列表

OpenCode 內建支援以下語言的 LSP 伺服器,無需額外外掛:

🅰️

TypeScript / JavaScript

typescript-language-server — 最完整的型別檢查與重構支援

🐍

Python

python-lsp-server (pylsp) — 語法檢查、自動完成、重構

🦀

Rust

rust-analyzer — 完整的 Rust 語言支援

☕

Java

eclipse-jdtls — Eclipse JDT 語言伺服器

💎

Ruby

ruby-lsp — Ruby 語言伺服器

🐘

PHP

php-language-server — PHP 智慧編輯支援

語言 LSP 伺服器 識別名稱
TypeScripttypescript-language-servertypescript
JavaScripttypescript-language-serverjavascript
Pythonpython-lsp-serverpython
Rustrust-analyzerrust
Gogoplsgo
Javaeclipse-jdtlsjava
Rubyruby-lspruby
PHPphp-language-serverphp
C#csharp-lscsharp
C/C++clangdclangd
Dartdart-language-serverdart
Denodeno-lspdeno
Swiftsourcekit-lspswift
Kotlinkotlin-language-serverkotlin
Lualua-language-serverlua
SQLsql-language-serversql
Bashbash-language-serverbash
Astroastro-lsastro
Sveltesvelte-language-serversvelte
ESLinteslint-lspeslint

10.5 LSP 設定選項

每個 LSP 伺服器都可以在 opencode.json 中進行細部設定:

{
  "lsp": {
    "typescript": {
      "command": "typescript-language-server",
      "args": ["--stdio"],
      "extensions": [".ts", ".tsx", ".js", ".jsx"],
      "priority": 10,
      "env": {
        "NODE_OPTIONS": "--max-old-space-size=4096"
      }
    },
    "python": {
      "command": "pylsp",
      "extensions": [".py"],
      "priority": 5,
      "settings": {
        "pylsp.plugins.pyflakes.enabled": true,
        "pylsp.plugins.mccabe.enabled": false
      }
    },
    "rust": {
      "command": "rust-analyzer",
      "extensions": [".rs"],
      "priority": 10,
      "settings": {
        "rust-analyzer.checkOnSave": true
      }
    }
  }
}
設定項 說明 預設值
command LSP 伺服器的執行檔路徑或名稱 —
args 啟動參數 ["--stdio"]
extensions 此 LSP 關聯的副檔名列表 —
priority 當多個 LSP 支援同一語言時的優先權(越高越優先) 0
env 環境變數覆蓋 {}
settings 傳遞給 LSP 伺服器的初始化設定 {}
💡 效能建議: 大型專案中建議僅啟用所需的 LSP 伺服器。過多的 LSP 實例會增加記憶體消耗。可以透過 priority 設定來控制當多個 LSP 競爭同一語言時的選擇。

10.6 自訂工具 API

除了內建工具,OpenCode 提供了自訂工具 API,讓開發者可以建立專屬的工具來擴充代理的能力。自訂工具透過 OpenCode SDK 開發,並在 opencode.json 中註冊。

基本結構

{
  "customTools": [
    {
      "name": "send-slack-notification",
      "description": "發送通知到 Slack 頻道",
      "schema": {
        "type": "object",
        "properties": {
          "channel": { "type": "string", "description": "目標頻道名稱" },
          "message": { "type": "string", "description": "要發送的訊息內容" }
        },
        "required": ["channel", "message"]
      },
      "handler": "tools/slack-notifier.js"
    }
  ]
}
📘 進階主題: 自訂工具 API 的完整開發指南將在第 12 章中介紹,包含 SDK 使用方式、測試策略與部署最佳實踐。

📝 本章測驗

1. 在 OpenCode 的權限系統中,若希望代理執行 git 命令時不需詢問,應如何設定?
2. 下列哪一個不是 OpenCode 內建的 LSP 支援語言?

❓ 常見問題

權限規則的比對順序是怎樣的? ▼

權限規則是「依序比對,先匹配先採用」。OpenCode 會按照 rules 陣列中的順序逐一檢查每個規則。如果某個規則的 match 模式與實際工具呼叫相符,就採用該規則的 permission 值。若沒有任何規則匹配,則使用該工具的全域設定;若連全域設定都沒有,預設為 ask。這表示你可以先放入精確的特殊規則,再放入通用的 catch-all 規則。

LSP 伺服器無法啟動怎麼辦? ▼

首先確認 LSP 伺服器已經安裝在系統上(例如 npm install -g typescript-language-server)。若已安裝仍無法啟動,可以在 opencode.json 的 LSP 設定中指定完整的命令路徑。若使用的是 env 設定環境變數,請確認變數名稱正確。最後,可以檢查 OpenCode 的日誌輸出(通常位於專案目錄下的 .opencode/logs/)獲取詳細的錯誤資訊。

自訂工具與 MCP 伺服器有什麼不同? ▼

兩者的主要差異在於使用範圍與通訊協定。自訂工具是定義在 opencode.json 中的本機工具,僅在目前專案中可用,適合簡單的腳本整合(如發送 Slack 通知、呼叫內部 API)。MCP 伺服器則是遵循 Model Context Protocol 的獨立服務,可以跨專案共用,支援遠端執行、OAuth 認證等進階功能,適合需要共用或需要複雜初始化的工具。第 11 章會詳細介紹 MCP 的設定與使用。