custom commands 已併入 Skills:什麼時候該遷到 `.claude/skills/`,遷了之後能多做什麼
前三篇講了 slash command 的完整用法:從 Markdown 檔案,到 !命令 注入,再到 subagent 跟 MCP 編排。這些內容都沒過時——但官方在背後做了一次合併:custom commands 已經併入 Skills。
你的 .claude/commands/review.md 還是能跑,/review 還是能用,什麼都不用改。但如果打算讓命令長出更多能力(多檔案、fork 執行、按路徑自動啟用),新路徑是 .claude/skills/review/SKILL.md。這篇講清楚兩件事:怎麼遷,以及值不值得遷。
官方的相容性承諾很明確:.claude/commands/deploy.md 跟 .claude/skills/deploy/SKILL.md 都會註冊成 /deploy,行為完全一樣。同名衝突時 skills 優先。
最小遷移步驟:
cd .claude/commands
mkdir -p ../skills/review
mv review.md ../skills/review/SKILL.md
檔案內容一行都不用改。YAML frontmatter、!`命令`、@file、$ARGUMENTS——全都相容。
但光做這一步,讀者會問:那遷它幹嘛?答案是 skill 目錄可以放多個檔案,而 command 只能一個。
SKILL.md 是入口,同目錄可以放任意附屬檔案。想像一下這樣的目錄:
.claude/skills/review/
├── SKILL.md # 入口,簡短的指令 + 引用
├── checklist.md # 長長的程式碼審查清單
├── examples/
│ └── good-diff.md # 正面範例
└── scripts/
└── lint.sh # SKILL.md 可以呼叫的 script
在 SKILL.md 裡用相對路徑引用:
審查當前 diff,遵循 [checklist.md](checklist.md) 裡的標準。
參考 [examples/good-diff.md](examples/good-diff.md) 理解期望的輸出格式。
這些附屬檔案不會自動進 context——Claude 按需讀取。官方建議 SKILL.md 控制在 500 行以內,其他都丟到附屬檔案裡。
disable-model-invocation:哪些 skill 只能你手動觸發預設情況下,Claude 看到合適時機就會自主呼叫任何 skill。這對 /deploy、/commit、/send-email 這種有副作用的命令很危險——你不會希望它「看程式碼順眼就去部署」。
---
name: deploy
description: 部署到 production
disable-model-invocation: true
allowed-tools: Bash(kamal deploy:*), Bash(git push:*)
---
加這一行之後,/deploy 只能你手動輸入觸發,Claude 在對話裡不會自作主張叫它。
反過來 user-invocable: false 則是「只允許 Claude 自己呼叫,但不出現在 / 選單裡」——適合背景知識型的 skill(比如 legacy-system-context,相關情境下 Claude 自動載入,但你手動觸發沒有意義)。
context: fork:讓 skill 在子代理裡跑這是最大的升級。上一篇講到 command 可以用 allowed-tools: Task 讓模型去起子代理——但你得在 prompt 裡手動描述「起個 Explore 子代理做……」。
SKILL 直接一行 frontmatter 搞定:
---
name: deep-research
description: 深入調研某個符號
context: fork
agent: Explore
---
調研 $ARGUMENTS 的所有用法:
- 所有呼叫點
- 業務場景
- 替代實作
回傳 ≤300 字總結。
觸發 /deep-research SomeClass 時:整個 SKILL.md 變成一個獨立子代理的 prompt,用 Explore agent type 執行,跑完只回傳結論。主對話的 context 完全乾淨。
這等於把「起子代理」這件事從 prompt 裡的描述文字變成了 skill 的宣告屬性。
paths:按檔案類型自動啟用---
name: rails-conventions
description: Rails 專案的編碼規範
paths: ["app/**/*.rb", "config/**/*.rb"]
---
遵循本專案的 Rails 規範:
- 使用 service object,不要 fat controller
- ActiveRecord scope 必須命名化
...
當你正在編輯 app/models/user.rb 時,這個 skill 會自動加進 context;編輯 package.json 時不會。比 CLAUDE.md 的全域背景更精準——等於是「按路徑分層的 CLAUDE.md」。
/plan 升級成 skill上一篇最後那個 /plan 範例,原本是單檔 command:
.claude/commands/plan.md
升級成 skill:
.claude/skills/plan/
├── SKILL.md
├── research-prompt.md # 子代理 1 的指令
└── risk-prompt.md # 子代理 2 的指令
SKILL.md:
---
name: plan
description: 基於 Linear ticket 產出實作方案
disable-model-invocation: true
allowed-tools: mcp__linear__*, Task, Read, Grep, Bash(git log:*)
---
## 上下文
@.claude/context/architecture.md
## 狀態
!`git log --oneline -10`
## 任務
拉取 Linear ticket $ARGUMENTS 的描述和留言。
用 Task 起兩個子代理並行調研:
1. 程式碼調研:prompt 見 [research-prompt.md](research-prompt.md)
2. 風險評估:prompt 見 [risk-prompt.md](risk-prompt.md)
彙總兩個結果後輸出實作步驟 + 風險清單 + commit 粒度建議。
兩個子代理的 prompt 放在獨立檔案,維護時改一處不用動到 SKILL.md。Skill 本身 30 行內清爽,附屬檔案可以各自幾百行詳細。
如果不想自己調度子代理,可以更激進——把整個 skill 丟進 fork,讓 Explore agent 一口氣執行:
---
name: plan
context: fork
agent: Explore
allowed-tools: mcp__linear__*
---
觸發 /plan ENG-4213 → 獨立 context 裡的 Explore agent 接過全部 SKILL.md 內容當任務執行 → 只回傳最終方案。主對話完全不髒。
不是所有 command 都值得升級。留在 .claude/commands/ 更合適的情況:
簡單的 /commit、/pr-desc 這類就是一個 frontmatter + 幾行 prompt——放 .claude/commands/ 反而更直觀。官方明講兩種形式並存、都不會被淘汰。
現在 .claude/ 裡最乾淨的組織方式:
.claude/
├── commands/ # 輕量:單檔 + 簡單 prompt
│ ├── commit.md
│ └── pr-desc.md
├── skills/ # 重型:多檔 / fork / 權限控制
│ ├── plan/
│ │ ├── SKILL.md
│ │ ├── research-prompt.md
│ │ └── risk-prompt.md
│ ├── deploy/
│ │ └── SKILL.md # disable-model-invocation
│ └── rails-conventions/
│ └── SKILL.md # paths glob 自動啟用
└── context/
└── coding-standards.md
不要一股腦全遷。遷移的觸發條件是「這個 command 已經開始膨脹」——正文超過 200 行、需要拆文件、想讓子代理執行。到那一步再改路徑,幾分鐘的事。
| 想要的能力 | commands/ |
skills/ |
|---|---|---|
| 單檔提示詞快捷鍵 | ✅ | ✅ |
!`命令` / @file / $ARGUMENTS |
✅ | ✅ |
allowed-tools 權限控制 |
✅ | ✅ |
| 附屬檔案(reference、scripts) | ❌ | ✅ |
disable-model-invocation 防誤觸發 |
❌ | ✅ |
context: fork + agent: 隔離執行 |
❌ | ✅ |
paths: glob 按路徑自動啟用 |
❌ | ✅ |
前三項 commands 跟 skills 完全等價;後四項是 skills 獨有。需要哪個就用哪個,不需要就別折騰。
官方路線正往 skills 傾斜,但 commands/ 的相容性承諾很明確——這不是「立刻全遷不然被淘汰」的變更,而是「新能力給你但不強迫」的擴展。搞清楚差異,按需要遷,別為了形式上的整齊硬遷。