學習目標
- 理解 SKILL.md 的放置位置與發現機制
- 掌握 YAML frontmatter 的所有欄位
- 學會撰寫完整的技能定義
- 設定技能的工具描述與權限
- 排查技能載入問題
什麼是代理技能?
代理技能(Skill)是一種以 SKILL.md 檔案封裝的指令集,定義了代理在特定任務中應遵循的行為模式。技能系統讓你可以將複雜的工作流程標準化,並在多個專案中重複使用。
技能與一般 AGENTS.md 的關鍵差異:
| 特性 | AGENTS.md | SKILL.md |
|---|---|---|
| 範圍 | 專案全域 | 按需載入 |
| 命名 | 無名稱 | 有唯一名稱,可被代理引用 |
| 可重用性 | 單一專案 | 可跨專案、跨使用者分享 |
| 工具 | 無 | 可定義關聯工具 |
| 觸發 | 自動 | 需代理明確載入 |
SKILL.md 放置位置與發現機制
opencode 會從以下位置掃描並發現 SKILL.md 檔案:
| 位置 | 說明 |
|---|---|
~/.config/opencode/skills/<name>/SKILL.md | 全域技能目錄(所有專案共用) |
.opencode/skills/<name>/SKILL.md | 專案技能目錄(僅限當前專案) |
當代理需要載入技能時,它會依序搜尋上述兩個目錄。技能的名稱即為目錄的名稱,目錄內必須包含一個 SKILL.md 檔案。
搜尋順序:全域技能目錄優先於專案技能目錄。如果你在兩個位置定義了相同名稱的技能,全域版本會優先被使用。
YAML Frontmatter 欄位
SKILL.md 以 YAML frontmatter 定義技能的後設資料。以下是完整的可用欄位:
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
name | string | 是 | 技能的唯一名稱,必須符合命名規則 |
description | string | 是 | 技能的簡短描述,用於觸發判斷 |
trigger | string 或 array | 否 | 觸發模式(always / on-topic),預設為 on-topic |
tools | array | 否 | 技能需要的工具描述清單 |
permissions | object | 否 | 技能運作時需要的特定權限 |
名稱驗證規則
技能名稱必須遵守以下規則:
- 只能包含小寫字母(
a-z)、數字(0-9)、連字號(-) - 長度限制:1 到 100 個字元
- 不能以連字號開頭或結尾
- 不能包含空格或特殊字元(底線
_也不允許) - 必須是有效的檔案系統目錄名稱
有效名稱範例:web-design、code-reviewer、python-test-runner
無效名稱範例:Web Design(含大寫和空格)、my_skill(含底線)、-skill(以連字號開頭)
完整範例
以下是一個完整的 SKILL.md 檔案,定義了一個程式碼審查技能:
---
name: code-reviewer
description: |
專門進行程式碼審查的技能。能夠分析程式碼品質、
找出潛在問題,並提供具體的改善建議。
trigger: on-topic
tools:
- name: bash
description: 用於執行 linter 或測試指令
- name: read
description: 讀取待審查的原始碼
- name: grep
description: 在專案中搜尋相關的程式碼模式
permissions:
bash:
allow:
- "npm run lint"
- "npx eslint"
- "npm test"
deny:
- "npm install"
- "rm"
edit: deny
---
# Code Review 技能
當你需要進行程式碼審查時,我會按照以下流程進行:
## 審查流程
1. **理解上下文** — 先讀取相關檔案,了解功能與設計意圖
2. **執行程式碼分析** — 使用 linter 等工具進行靜態分析
3. **逐行審查** — 關注可讀性、效能、安全性與最佳實務
4. **提供具體建議** — 每個問題附上範例程式碼與說明
## 審查重點
- 安全性漏洞(SQL injection、XSS 等)
- 效能瓶頸(不必要的迴圈、過多的 DOM 操作)
- 程式碼重複(DRY 原則)
- 錯誤處理是否完善
- 型別與邊界情況
工具描述與載入方式
在 SKILL.md 的 tools 區塊中,你可以描述技能需要使用的工具。這些工具描述會影響代理的行為:
- 限制工具範圍 — 代理在技能中只能使用你列出的工具
- 自訂描述 — 你可以為工具提供更貼近技能場景的說明,讓代理更有效地使用它
- 不影響全域權限 — 即使技能中列出了某個工具,實際執行時仍受
permissions設定約束
技能由代理透過 skill 工具載入。當代理認為你的請求與某個技能的 description 相符時,它會自動載入該技能。你也可以在對話中明確要求代理載入特定技能。
trigger 欄位說明
trigger 欄位控制技能何時被載入:
| 值 | 行為 |
|---|---|
on-topic(預設) | 當對話主題與技能描述相符時自動載入 |
always | 每次對話都會自動載入此技能 |
注意:使用 always 觸發模式會讓技能在每個對話中都自動載入,這可能影響效能。建議只在真正需要的技能上使用此模式。
權限設定
技能可以在 frontmatter 的 permissions 區塊中設定自己的權限規則。權限覆蓋層級如下(由低到高):
- 全域權限 —
opencode.json中的permissions設定 - 技能權限 — SKILL.md 中的
permissions設定(覆蓋全域) - 代理權限 — 自訂代理定義中的
permissions(覆蓋技能與全域)
範例:全域將 bash 設為 ask,但技能中將特定指令設為 allow:
---
name: test-runner
description: 執行與維護測試
permissions:
bash:
allow:
- "npm test"
- "npx jest"
- "npx vitest"
deny:
- "sudo"
---
停用技能工具
如果你不希望代理在特定技能中使用某個工具,可以在 permissions 中將它設為 deny,或直接在 tools 清單中省略它:
---
name: safe-analyzer
description: 安全的程式碼分析(不執行任何指令)
tools:
- name: read
description: 讀取原始碼
- name: grep
description: 搜尋程式碼模式
- name: glob
description: 尋找檔案
# 注意:沒有列出 bash、write、edit
# 這些工具在技能中無法使用
---
排查載入問題
如果你的技能沒有被正確載入,請檢查以下常見問題:
| 問題 | 解決方法 |
|---|---|
| SKILL.md 不在正確的目錄中 | 確認放置在 ~/.config/opencode/skills/<name>/SKILL.md 或 .opencode/skills/<name>/SKILL.md |
| YAML frontmatter 語法錯誤 | 檢查 YAML 格式,注意縮排與冒號後的空格 |
| 名稱包含不合法字元 | 確認名稱只使用小寫字母、數字和連字號 |
| 缺少必填欄位(name 或 description) | 確認 frontmatter 包含 name 和 description |
| 目錄名稱與 name 不符 | 確保目錄名稱與 frontmatter 中的 name 一致 |
| 技能未觸發 | 確認 trigger 設定是否正確;或明確要求代理載入技能 |
除錯提示:啟動 opencode 時,注意終端機的輸出訊息。opencode 會顯示已載入的技能數量。如果技能數目不如預期,可檢查是否有錯誤提示。
實戰練習
練習 1:建立你的第一個技能
- 在
~/.config/opencode/skills/下建立log-analyzer/SKILL.md - 定義技能名稱為
log-analyzer - 設定描述:專門分析應用程式日誌,找出錯誤模式與異常
- 列出需要的工具:
bash(用 grep 分析日誌)、read(讀取日誌檔) - 設定權限:允許
grep相關指令,禁止寫入操作
練習 2:設定觸發模式
- 複製上一個技能,修改名稱為
always-helper - 將
trigger設為always - 啟動 opencode 並確認技能在每個對話中自動載入
- 將
trigger改回on-topic,觀察行為差異
練習 3:技能權限覆蓋測試
- 在全域
opencode.json中將websearch設為deny - 建立一個技能
research-assistant,在其 permissions 中將websearch設為ask - 載入此技能,確認技能層級的權限覆蓋了全域設定
- 再建立一個自訂代理,在其 permissions 中將
websearch設為deny - 使用該代理載入技能,確認代理層級最終覆蓋了技能層級