06 · 把重複的話寫成檔案
Skills 不是給 Claude 裝新能力,而是把你反覆說的流程寫成檔案。description 決定何時觸發,正文決定怎麼做。
翔宇有一段時間每天都跟 Claude Code 說同樣的話:處理 PDF 先提取文本,再處理表格;掃描件走 OCR;表格結果轉 CSV;最後給一份可複核摘要。說了十幾遍以後突然意識到——這不是提示詞技巧,這是一個應該寫進檔案的工作流。——翔宇
這一篇用 15 分鐘換什麼:前 5 篇分別講了位置、上下文、記憶、提示詞和思考深度。現在進入第一個"複用層":Skills(技能)。讀完你會知道,什麼該寫進 CLAUDE.md,什麼該寫成 SKILL.md,什麼時候讓 Claude 自動觸發,什麼時候必須你手動輸入 /skill-name。
1. 你每天重複的不是"知識",是"流程"
先看一個具體場景。
你讓 Claude 處理一個 PDF:
👤 你:幫我把這個 PDF 裡的表格提出來。
Claude 能做嗎?能。第 1 篇講過,Claude Code 住在你電腦上。你電腦裝了 pdfplumber、OCR 工具、Python 指令碼,它就能讀檔案、跑命令、改指令碼。
但第一次結果常常不穩。它可能先嚐試普通文本提取,漏掉掃描頁;也可能把表格當段落處理;還可能直接給你總結,沒有留下 CSV。
你只好補一句:
处理 PDF 时先判断是不是扫描件。普通 PDF 用 pdfplumber 提取文本和表格。
扫描件先 OCR。表格转 CSV,保留页码,最后输出摘要和异常页列表。第二天又來一個 PDF。你再說一遍。
第三天又說一遍。
這時要停下來判斷:你重複的不是"PDF 是什麼",也不是"pdfplumber 怎麼安裝"。Claude 大機率知道這些。你重複的是你的處理流程。
第一性原理:Skill 解決的不是"Claude 不會什麼",而是"Claude 不知道你遇到某類任務時希望它按什麼流程做"。
這句話很關鍵。很多人寫 Skill 寫偏,就是因為把 Skill 當成百科詞條,開始解釋 PDF、CSV、OCR 的定義。真正該寫的是:
- 先判斷什麼
- 用哪個工具
- 遇到什麼異常怎麼分支
- 輸出什麼格式
- 做完怎麼驗收
這些才是你每天反覆說的東西。
這一篇要回答的三個核心問題
寫一個 Skill 的程式碼很容易,難的是理解它怎麼被 Claude 看見 / 何時被載入 / 跟其它機制怎麼分工。後面 12 節就是按這三個問題展開:
- description 寫什麼 Claude 才會真用它?——§3 看 description 怎麼作為"觸發索引"被模型在每輪決策前掃一遍;§5 看 frontmatter 控制面板的全部欄位。
- 一篇 SKILL.md 幾千字 Claude 不會被淹?——§6 看 supporting files 外接;§7 看漸進式載入怎麼把"裝很多"和"上下文不爆"同時做到。
- Skill 跟 CLAUDE.md / SubAgent / Plugin 邊界在哪?——§9 看跟 CLAUDE.md / Hook / MCP 的 4 維對照;§11 看跟 SubAgent 的銜接;12 篇 Plugin 看怎麼被打包分發。
讀完每一節自檢:這一節回答了哪個問題、用什麼機制回答的、為什麼不是另一種實現。
2. 寫進 SKILL.md
最小 Skill 只有一個檔案:SKILL.md。
目錄長這樣:
檔案可以這樣寫:
---
description: 从 PDF 中抽取文本和表格。用户提到处理 PDF、抽表格、跑 OCR、把 PDF 数据转成 CSV 时使用。
---
## 工作流程
1. 先检查 PDF 本身,判断每页是文本型还是扫描图像。
2. 文本型页面用 pdfplumber 抽取文本和表格。
3. 扫描页面先跑 OCR 再抽取。
4. 提取出来的表格按页码存成 CSV。
5. 返回摘要:包含产出文件、跳过的页、置信度偏低的 OCR 段落。注意它沒有寫"PDF 是 Portable Document Format"。也沒有寫"OCR 是光學字元識別"。這些不是你的流程,是百科。
它寫的是:遇到 PDF 任務時,Claude 應該怎麼做。
一句話理解:SKILL.md 是"遇到這類任務時,請按這個流程處理"的說明書。它不是程式碼,也不是外掛,更不是知識庫百科。
這就是 Skills 和第 4 篇提示詞的關係:提示詞是本輪臨時說明,Skill 是反覆出現的說明。當你發現一段提示詞第三次出現,就該考慮把它寫成 Skill。
新手最常見的寫法誤區:把 Skill 當百科詞條寫。開篇先解釋"PDF 是什麼"、"OCR 是什麼",然後才進流程。Claude 已經知道這些定義,正文應該直接進流程。把"概念解釋"塞進 SKILL.md 等於讓 Claude 每次觸發都把百科再"讀"一遍——既占上下文又稀釋流程主線。
3. description 才是觸發器
只寫流程還不夠。Claude 怎麼知道什麼時候讀這個檔案?
關鍵在 frontmatter(檔案開頭 --- 之間的後設資料)。
官方文件說,每個 Skill 需要 SKILL.md,frontmatter 告訴 Claude 什麼時候用,正文告訴 Claude 用的時候怎麼做。description 幫 Claude 決定是否自動載入這個 Skill。完整說明見 Extend Claude with skills。
所以 description 不是簡介文案,它是觸發索引。
壞寫法:
---
description: 处理文件相关的任务。
---這個描述太泛。PDF 是檔案,圖片是檔案,程式碼也是檔案。Claude 無法判斷它什麼時候該觸發。
好寫法:
---
description: 从 PDF 中抽取文本和表格。用户提到处理 PDF、抽表格、跑 OCR、把 PDF 数据转成 CSV 时使用。
---這裡有四類觸發詞:PDF、抽表格、OCR、CSV。使用者說"把這個掃描 PDF 裡的發票表格轉成 CSV",Claude 就容易匹配上。
flowchart LR
User["👤 使用者請求<br/>把掃描 PDF 表格轉 CSV"]
Index["📇 Skill 索引<br/>description 常駐上下文"]
Match{"匹配到<br/>PDF / OCR / CSV?"}
Load["📖 載入 SKILL.md 正文"]
Work["🛠️ 按流程執行"]
User --> Index
Index --> Match
Match -->|是| Load
Match -->|否| Work
Load --> Work
style Index fill:#dbeafe,stroke:#3b82f6
style Match fill:#fef3c7,stroke:#f59e0b,stroke-width:2px
style Load fill:#dcfce7,stroke:#22c55e
要寫好 description,得先理解它什麼時候被讀、被誰讀。
註冊時機:會話啟動時,Claude Code 把所有可用 Skill 的 name + description + frontmatter(不含正文)拼進 system prompt(system prompt = 啟動時 Claude 看到的指令背景)註冊,相當於給 Claude 擺了一份"工具選單"。
決策時機:你每發一句話,Claude 在生成回答前會掃一遍選單,決定要不要開啟某個 Skill 的正文。這跟 09 篇 MCP 裡 tool 的發現機制是同一類——區別是 Skill 描述的是"工作流",MCP tool 描述的是"動作"。
Token 經濟學:每個 Skill metadata 大約 50-150 token。裝 50 個 Skill 啟動時常駐約 5-8 K token——只佔 1M 上下文視窗的不到 1%,但佔啟動 system prompt 的相當一塊。這就是為什麼 description 寫法直接決定 Skill 是不是真有用:
| 寫法 | 後果 |
|---|---|
| 寫得太寬("處理檔案相關的任務") | 模型每輪都把它當候選,誤觸發率高 —— 使用者說"開啟 README" 也可能錯觸發,主對話被 SKILL.md 正文淹 |
| 寫得太窄("處理 2026 Q4 發票 PDF") | 模型在使用者說"提取這個 PDF"時識別不到,該用沒用 |
| 寫得精準 + 列觸發詞("從 PDF 抽取... 使用者提到 PDF / OCR / CSV 時使用") | 模型只在真相關時拉正文,不汙染主對話 |
為什麼 Anthropic 選"模型決策"而不是"keyword 索引":keyword 匹配(grep)會被語義近義、跨語言、措辭變體打敗——使用者說"掃描發票轉表格"包含"發票"、"掃描"、"表格",但沒"PDF"也沒"CSV",keyword 匹配就漏了。讓模型自己讀 description 決策能跟人類自然語言對齊,代價是佔 system prompt token——這是 Anthropic 在"準確率 vs 上下文成本"之間選了準確率。
類比:description 像選單上的菜名 + "什麼時候點"。菜名太泛("美食")服務員(Claude)不知道你想吃什麼;菜名太窄("週三限定×××套餐")你點了別的相似菜它也認不出。
這裡有一個設計細節:Claude 會自動判斷,但你也可以手動呼叫。
如果 Skill 叫 pdf-workflow,你可以直接輸入:
/pdf-workflow 处理 invoice.pdf官方文件也明確說,custom commands 已經合併進 Skills:.claude/commands/deploy.md 和 .claude/skills/deploy/SKILL.md 都能建立 /deploy,現有 .claude/commands/ 還可用,但 Skills 支援 supporting files、frontmatter 控制自動觸發等更多能力。
關鍵點:不要把 Skill 理解成"只能自動觸發"。它同時有兩種入口:Claude 覺得相關時自動載入;你也可以用 /skill-name 手動呼叫。
4. 什麼時候自動,什麼時候手動
這一步很容易混。
不是所有 Skill 都應該讓 Claude 自動觸發。
PDF 提取這種流程,自動觸發沒問題。使用者說 PDF、OCR、表格,Claude 自動用它,符合預期。
但 PDF 自動覆蓋原檔案 / 處理完直接發郵件給客戶這種有副作用的流程,不能讓 Claude 自己看起來"時機合適"就執行。
這時用 disable-model-invocation: true:
---
name: pdf-archive-and-email
description: 处理 PDF 后用结果覆盖原文件并发邮件给收件人。
disable-model-invocation: true
---意思是:Claude 不會自動呼叫,只有你輸入 /pdf-archive-and-email 才會觸發。
另一個方向也存在:有些 Skill 只是背景知識,不適合人手動呼叫。比如:
---
name: pdf-legacy-format-notes
description: 说明 2020 年以前归档 PDF 的特殊格式约定与解析陷阱。
user-invocable: false
---它可以讓 Claude 在相關任務中自動載入(使用者處理老 PDF 時自動參考),但不出現在你日常要手動執行的命令入口裡。
可以這樣判斷:
- PDF 提取、讀取分析、生成摘要:預設自動即可,Claude 能安全自動觸發。
- PDF 自動覆蓋、自動發郵件、自動歸檔刪原始檔:
disable-model-invocation: true,必須由你決定時機。 - PDF 歷史格式說明、領域詞典、舊系統約定:
user-invocable: false,給 Claude 讀,不給人當命令用。
關鍵原則:只要一個 Skill 會產生真實外部副作用(覆蓋檔案 / 發訊息 / 呼叫付費 API / 刪資料),就不要讓它自動觸發。自動觸發適合"指導 Claude 怎麼思考和處理",不適合"替你決定何時釋出、提交或通知別人"。
為什麼 Anthropic 設計成"預設允許 + 高危 opt-out"而不是反過來:
如果預設全部禁止自動觸發,所有 Skill 都要 /skill-name 手動調——失去 Skill 最大價值"按需自動載入"。如果預設全部允許自動,副作用 Skill 危險。Anthropic 選了"預設允許 + 高危顯式 opt-out"——把"什麼算危險"的判斷權交給 Skill 作者,因為:
- 平臺不知道每個 Skill 實際做什麼(覆蓋檔案?只讀分析?)
- 靜態掃描判斷"是否有副作用" 太弱(指令碼里調外部 API 難自動識別)
- 讓作者宣告意圖,比讓平臺猜更準確
代價:壞作者可以寫"自動覆蓋"還不加 opt-out。這就是 12 篇 Plugin 強調"外掛是 high-trust 元件"的根因——Skill 系統的安全模型依賴作者誠信 + 安裝者審查,不靠平臺兜底。
新手最常踩的坑:把"PDF 自動歸檔" Skill 預設 auto,description 寫得寬("處理 PDF 檔案")。當使用者說"這個 PDF 太長幫我看看" 時,Claude 誤識別成歸檔場景,把原檔案覆蓋成提取摘要——真實資料沒了。修復方式不是改提示詞,是改 Skill 配置:副作用 Skill 必須 disable-model-invocation: true。
5. frontmatter 是控制面板
到這裡,Skill 已經不是一段純文字了。frontmatter 讓你控制它的工作方式。
常用欄位一張表看清:每個欄位的作用 + 什麼時候用 + 不寫會怎樣:
| 欄位 | 作用 | 什麼時候用 | 不寫會怎樣 / 預設 |
|---|---|---|---|
name | 顯示名 / 命令名 | 想固定 /skill-name 呼叫時 | 預設用目錄名(如目錄叫 pdf-workflow 就是 /pdf-workflow) |
description | 觸發索引 | 幾乎每個 Skill 都該寫 | 不寫 = Claude 完全不知道何時用,等於裝了等於沒裝 |
when_to_use | 追加觸發場景 | 觸發條件複雜、單條 description 寫不完時 | 不寫 = 僅靠 description;寫了 = 跟 description 疊加增強匹配 |
argument-hint | / 自動補全顯示引數提示 | 手動命令型 Skill | 不寫 = 手動呼叫時使用者不知道傳什麼引數(如 /pdf-workflow 不知道傳不傳路徑) |
allowed-tools | 預批准某些工具 | 確認安全、想減少重複確認時 | 不寫 = 使用者全域性許可權規則約束(11 篇 Permissions);列了 = 這些工具在 Skill 啟用時無需逐次確認 |
model | Skill 啟用時臨時切模型 | 某類任務固定需要 Opus / Haiku 時 | 不寫 = 沿用主會話模型 |
effort | Skill 啟用時覆蓋思考深度 | 審計類深想、格式類低 effort | 不寫 = 沿用主會話 effort(詳見 05 篇) |
context | fork 時在子代理上下文執行 | 不想汙染主對話時 | 不寫 = 在主對話執行;寫 fork = 啟動 SubAgent(07 篇) |
disable-model-invocation | 禁止自動觸發 | 副作用 Skill | 預設 false(允許自動) |
user-invocable | 使用者能否手動呼叫 | 後臺知識 Skill | 預設 true(使用者可 /cmd) |
第 5 篇剛講過 effort。這裡它開始進入工程配置。
比如 PDF 審查 Skill 需要深度推理:
---
name: pdf-content-review
description: 审查 PDF 中的合同条款是否存在风险点。
effort: xhigh
allowed-tools: Read Grep Glob
---這說明:這個 Skill 主要讀檔案、搜文本,不應該隨便改檔案;同時合同審查需要更深推理,所以 effort 提高。
再比如 PDF 格式潤色 Skill 路徑很直,不需要高 effort:
---
name: pdf-extracted-text-polish
description: 润色已抽取的 PDF 文本格式(断行 / 表头 / 标点),不改事实。
effort: low
---邊界要講清:allowed-tools 是預批准工具,不是唯一可用工具。官方文件說明,它讓列出的工具在 Skill 啟用時無需逐次確認;其它工具仍受你的 11 篇許可權設定 約束。不要把它當成完整沙箱。
新手最常漏寫的欄位是 argument-hint:寫了一個 /pdf-workflow Skill 但不寫 hint,使用者在終端打 /pdf-workflow 後不知道下一步該輸什麼——是空格加路徑?還是帶引號?還是直接Enter?hint 一行就解決:argument-hint: "[PDF 路徑]"。
6. 支援檔案:別把正文寫成儲存庫
很多人第一次寫 Skill,會把所有東西都塞進 SKILL.md:
- 20 個示例
- 詳細 API 文件
- 專案模板
- 完整檢查清單
- 大段背景說明
這樣很快失控。3000 行 SKILL.md 觸發後會一次性注入主對話——主任務上下文直接被擠壓,Claude 還沒幹活就已經"滿桌子",跟 02 篇上下文 講的"桌子要乾淨"原則反著幹。
官方建議 SKILL.md 控制在 500 行以內。這不是協議硬限,是經驗閾值:
- 一行 markdown 平均 8-12 token,500 行 ≈ 5-7 K token
- Skill 觸發後正文一次性注入主對話,5-7 K token 是"顯著佔空間但不擠壓主對話"的臨界點
- 超過 1 萬 token 的 Skill 正文會讓 Claude 在每輪都得重讀這一大段——上下文經濟崩了
- 低於 200 行又意味著流程描述不夠細,Claude 仍然要靠猜
所以"500 行" 的本質是:在 Claude 當前 1M 上下文 + 多 Skill 同時啟用 + 每輪重讀全文的約束下,給單個 Skill 留約 0.5-0.7% 的上下文配額。
大型參考資料應該放到同目錄的 supporting files。比如:
SKILL.md 只寫導航:
## 附加资源
- 表格抽取边界情况详见同目录 `reference.md`。
- 最终报告格式见 `templates/extraction-report.md` 模板。
- 辅助脚本见 [scripts/extract_tables.py](scripts/extract_tables.py),需要时直接运行。這樣 Claude 先讀流程。只有當它真的需要處理表格邊界、生成報告或執行指令碼時,才去看對應檔案。
為什麼這種"分層"特別划算:你寫 100 個 PDF 處理示例放 examples/,單次任務可能只用到 1-2 個發票類。如果全塞 SKILL.md,觸發後 100 個示例全進上下文;放 supporting files 只在 Claude 真要參考時 Read 進來——上下文成本差幾十倍。
7. 漸進式載入:裝很多,但只讀當前需要的
Skills 能規模化,靠的是漸進式載入。
它不是啟動時把所有 Skill 正文都塞進上下文。它更像三層索引:
flowchart TB
Level1["第 1 層:Skill metadata<br/>name / description 常駐"]
Level2["第 2 層:SKILL.md 正文<br/>觸發後載入"]
Level3["第 3 層:supporting files<br/>需要時再讀"]
Work["當前任務上下文"]
Level1 -->|匹配使用者請求| Level2
Level2 -->|正文提示需要| Level3
Level2 --> Work
Level3 --> Work
style Level1 fill:#dbeafe,stroke:#3b82f6
style Level2 fill:#dcfce7,stroke:#22c55e
style Level3 fill:#fef3c7,stroke:#f59e0b
style Work fill:#f3e8ff,stroke:#a855f7
這解決了一個實際矛盾:
- 你希望裝很多 Skill,讓 Claude 懂你的各種工作流
- 你又不希望上下文被無關 Skill 塞滿
漸進式載入讓兩件事同時成立。
| 載入層級 | 載入什麼 | 為什麼這樣設計 |
|---|---|---|
| 啟動時 | name / description 等後設資料 | Claude 需要知道有哪些 Skill 可用 |
| 觸發時 | SKILL.md 正文 | 只把當前任務相關流程放進上下文 |
| 執行中 | reference.md / examples/ / scripts/ | 詳細資料按需讀取,不常駐 |
把"漸進式載入"攤到一次真實會話的時間線上,更直觀:
flowchart TB
T0["🚀 <b>T0 啟動會話</b><br/>註冊全部 Skill metadata<br/>≈ 50-150 token / 個 · <b>常駐整場</b>"]
T1["💬 <b>T1 使用者輸入</b><br/>把這個 PDF 表格轉 CSV<br/>Claude 掃選單 → 命中 pdf-workflow"]
T2["📖 <b>T2 觸發載入正文</b><br/>SKILL.md ≤ 500 行 / 5-7K token<br/>進主對話 · <b>常駐直到 /compact 或 /clear</b>"]
T3["📂 <b>T3 執行中按需讀</b><br/>Read reference.md / 跑指令碼<br/><b>單次讀完不常駐</b>,除非被引入對話"]
T4["✅ <b>T4 完成回報</b><br/>摘要 + 輸出檔案列表給你"]
T0 --> T1 --> T2 --> T3 --> T4
style T0 fill:#fef3c7,stroke:#f59e0b,stroke-width:2px
style T1 fill:#dbeafe,stroke:#3b82f6
style T2 fill:#dcfce7,stroke:#22c55e,stroke-width:2px
style T3 fill:#f3e8ff,stroke:#a855f7
style T4 fill:#fee2e2,stroke:#ef4444
讀一遍這條時間線,幾個反直覺的點會變直觀:
- metadata 永遠在 system prompt:裝了 50 個 Skill,不管你今天用不用,啟動時這 50 份 metadata 都線上——這是"自動觸發"的代價。
- 正文進了主對話就留在主對話:觸發後 Skill body 不會"用完釋放"。如果同一會話連續觸發 5 個 Skill,主對話上下文會累積 5 份正文。這是為什麼"不要在一個會話裡調一堆 Skill",跟 02 篇 的桌子原則一致。
- supporting files 是真的"按需":只有 Claude 顯式 Read 才進上下文,這就是為什麼 500 行的硬資料外接最划算——你寫 100 個示例放 examples/,Claude 大多數任務只讀 1-2 個。
一句話理解:description 像書架目錄,SKILL.md 像當前開啟的書,references/ 和 scripts/ 像書裡的附錄。你不會把整座圖書館都攤在桌上。
這也解釋了為什麼 description 要寫得準。metadata 常駐,但正文不常駐。Claude 是否能開啟正確那本書,首先取決於目錄條目寫得清不清楚。
8. 放在哪裡:個人、專案、外掛
Skill 的位置決定作用範圍。
官方列了幾類位置,日常最常用的是個人級和專案級:
| 位置 | 路徑 | 適合放什麼 |
|---|---|---|
| 個人級 | ~/.claude/skills/<skill-name>/SKILL.md | 你自己跨專案都用的 PDF 通用流程 |
| 專案級 | .claude/skills/<skill-name>/SKILL.md | 這個專案獨有的 PDF 處理約定(如發票格式 / 業務欄位對映),可提交 git |
| 外掛級 | <plugin>/skills/<skill-name>/SKILL.md | 隨外掛分發的 PDF 工具集(詳見 12 篇) |
| 企業級 | managed settings | 公司統一下發的合規 PDF 審查 Skill |
如果同名 Skill 出現在多個層級,企業級 > 個人級 > 專案級。外掛 Skill 會帶外掛名稱空間(詳見 12 篇),避免和普通 Skill 衝突。
還有一個細節:Claude Code 會監聽 Skill 目錄變化。你在現有 ~/.claude/skills/ 或專案 .claude/skills/ 裡新增、編輯、刪除 Skill,當前會話內會自動生效。只有頂層 skills 目錄本身原來不存在、你剛建立時,可能需要重啟 Claude Code 才能被監聽。
把它和第 3 篇記憶系統對應起來:
- 個人偏好型 PDF 流程:放
~/.claude/skills/pdf-workflow/ - 團隊共享 PDF 流程:放專案
.claude/skills/pdf-invoice/ - 單純專案事實(用 pdfplumber 不用 PyMuPDF):放
CLAUDE.md - 複雜可複用 PDF 工作流:放
SKILL.md
9. Skills 和 CLAUDE.md / Hook / MCP 的邊界
四者都是"配置 Claude 行為"的方式,但職責不同。一張 4 維對照表看清:
| 維度 | CLAUDE.md(03 篇) | SKILL.md(本篇) | Hook(10 篇) | MCP(09 篇) |
|---|---|---|---|---|
| 載入時機 | 每次會話啟動全量注入 | 觸發後才注入正文 | 事件點自動執行 | 工具被呼叫時連線 |
| 上下文成本 | 全量常駐(建議 ≤200 行) | metadata 約 50-150 token / Skill;觸發後正文進上下文 | Hook 自身不佔上下文,輸出可能進 | 工具 schema 常駐;輸出可能進 |
| 觸發條件 | 不需要觸發,啟動即生效 | description 模型語義匹配 | 事件型別 + matcher | 模型決定 / 使用者 @ 引用 |
| 複用粒度 | 專案 / 使用者 / 系統 / 本地 4 層 | 專案 / 使用者 / 外掛 / 企業 4 類 | settings scope(同 CLAUDE.md) | local / project / user 3 類 |
| 典型用法 | 專案規則 / 團隊約定 / 個人偏好 | 任務流程 / 領域工作流 | 自動化檢查 / 副作用攔截 | 接外部系統 / 資料來源 |
| 何時升級 | 重複 ≥3 次的話 → 寫 CLAUDE.md | 重複 ≥3 次的流程 → 寫 Skill | 漏一次會出事的規則 → 寫 Hook | 頻繁複制貼上的外部系統資料 → 裝 MCP |
讀這張表的訣竅:機制選錯的代價——CLAUDE.md 寫流程會膨脹;Skill 寫規則會"載入晚了不起作用";Hook 寫偏好會"動不動就攔你";MCP 寫本地操作是"用大炮打蚊子"。每個機制有它最貼的活,錯配是大多數 Claude Code 配置失控的根因。
3 個判斷練習——下面三句話,分別該寫進哪裡?讀完答案再看你判斷對了幾個:
場景 A:團隊約定 PDF 處理一律用
pdfplumber,不要 PyMuPDF。場景 B:處理 PDF 的完整 7 步流程(判斷掃描 → OCR → 抽表 → 轉 CSV → 摘要)。
場景 C:每次寫 PDF 處理程式碼後自動跑
pytest tests/pdf_test.py。
📌 看答案
- A → CLAUDE.md:是專案級"用什麼庫"約定,每次會話都要知道,不需要觸發。
- B → SKILL.md:是反覆出現的工作流,只在 PDF 任務時才需要。
- C → Hook(PostToolUse):是"動作完成後自動執行"的規則,不依賴 Claude 觸發判斷。
判斷訣竅——問自己:
- 這條資訊每次會話都要進上下文嗎?是 → CLAUDE.md。
- 這條資訊只在某類任務才需要?是 → SKILL.md。
- 這條規則漏一次就出事?是 → Hook。
- 這條資訊來自外部系統(GitHub / 資料庫 / SaaS)?是 → MCP。
10. 一個合格 Skill 長什麼樣
回到 PDF 例子。一個更完整的版本可以這樣寫:
---
name: pdf-workflow
description: 从 PDF 中抽取文本和表格。用户提到处理 PDF、抽表格、给扫描页跑 OCR、把 PDF 数据转成 CSV 时使用。
argument-hint: "[PDF 路径]"
allowed-tools: Read Bash(python *) Bash(mkdir *) Bash(ls *)
effort: medium
---
## 目标
从 PDF 中抽取可用的文本和表格,保留每段内容到对应页码的追踪关系。
## 工作流程
1. 从 $ARGUMENTS 拿到 PDF 路径。
2. 判断每一页是文本型还是扫描图像。
3. 文本型页面用 pdfplumber 抽取。
4. 扫描页面用 OCR 抽取。
5. 表格按页码导出成 CSV。
6. 写一份摘要:含产出文件、跳过的页、置信度偏低的段落。
## 输出
返回:
- 抽取出的文本文件路径
- 各 CSV 文件路径
- 跳过或需人工复核的页
- 一段话摘要這個 Skill 有幾個優點:
- description 含清晰觸發詞(PDF / OCR / CSV / 抽表格)
argument-hint讓手動呼叫更順allowed-tools只預批准必要命令effort: medium和任務複雜度匹配- 正文寫流程,不寫百科
- 輸出格式明確
再對照一個壞版本:
---
description: 帮忙处理文档。
---
PDF 是 Adobe 推出的文件格式。OCR 指光学字符识别。
请使用工具处理文件,并返回有用的结果。壞在哪裡?
- description 太泛:容易誤觸發,或該觸發時不觸發。
- 寫百科知識:占上下文,不改變執行質量。
- 沒有流程:Claude 還是要猜先後順序。
- 沒有輸出契約:每次結果格式不穩定。
- 沒有邊界:可能動不該動的檔案或命令。
這就是 Skill 寫作的核心:描述要窄,流程要清,輸出要定,參考資料要外接。
理解 Skill 的所有設計選擇,可以壓成一張決策矩陣——這一篇所有"為什麼"彙總:
flowchart TB
Core["💡 <b>Skills 的核心設計選擇</b>"]
subgraph 觸發["🎯 觸發方式"]
T1["預設<b>自動</b><br/>+ 高危 opt-out<br/>責任在作者"]
end
subgraph 載入["📦 載入策略"]
L1["<b>漸進式</b>三層<br/>metadata 常駐<br/>正文觸發載入<br/>files 按需讀"]
end
subgraph 表達["📝 表達層級"]
E1["<b>prompt 層 markdown</b><br/>不是 typed function<br/>不是 flat command"]
end
subgraph 安全["🔒 安全模型"]
S1["作者誠信 + 使用者審查<br/>平臺不兜底<br/>詳見 12 篇 Plugin"]
end
Core --> 觸發
Core --> 載入
Core --> 表達
Core --> 安全
style Core fill:#fef3c7,stroke:#f59e0b,stroke-width:3px
style 觸發 fill:#dbeafe,stroke:#3b82f6
style 載入 fill:#dcfce7,stroke:#22c55e
style 表達 fill:#f3e8ff,stroke:#a855f7
style 安全 fill:#fee2e2,stroke:#ef4444
4 個選擇各自的"為什麼不是另一種":
- 觸發為什麼不是預設全手動:失去自動載入價值,新手記不住命令名 = 裝了等於沒裝。
- 載入為什麼不是全量注入:50 個 Skill 全量 ≈ 50 萬 token,主對話直接爆。
- 表達為什麼不是 typed function:function 強引數校驗,但工作流裡"這頁是不是掃描件"是自然語言判斷,schema 表達不了"if-else 內嵌經驗"。
- 安全為什麼不靠平臺:平臺不知道每個 Skill 實際做什麼,作者宣告意圖比讓平臺靜態掃描更準確。
底層取捨:Skill 是"用 system prompt token 換語義觸發的靈活性"。裝得多 = 啟動 token 成本上升 + 誤觸發機率上升;裝得少 = 自動複用價值丟失。所以這一篇所有"description 寫窄一點"、"500 行外接"、"高危 opt-out" 的勸告,本質都是在幫你對齊這個取捨。
11. 和 SubAgents 的連線
下一篇會講 SubAgents(子代理 = 派分身做子任務,詳見 07 篇)。這裡先提前接一條線:Skill 可以在主會話裡執行,也可以在 forked subagent context(分叉子代理上下文)裡執行。
為什麼需要這個?
還是 PDF 例子。普通 PDF 提取,主會話直接做就行。
但如果你讓 Claude 批次處理 200 個 PDF,中間會讀大量檔案、跑很多命令、產出許多日誌。這些過程會汙染主會話上下文。
這時可以讓 Skill 在子代理裡跑:
---
name: pdf-batch-workflow
description: 批量处理一整个目录的 PDF,返回抽取出的文本、CSV 文件和异常报告。
context: fork
agent: general-purpose
effort: medium
---主會話只拿回結果摘要,具體處理過程留在子代理上下文裡。
實際何時升級到 SubAgent,按這張決策樹判斷:
flowchart TD
Start["拿到一個反覆出現的 PDF 任務"]
Q1{"流程能寫清楚嗎?<br/>步驟、判斷、輸出格式"}
Q2{"主對話裝得下嗎?<br/>過程產出大量日誌/檔案"}
Q3{"任務之間需要互相對齊嗎?<br/>多角色多模組"}
OneShot["單步 prompt 解決<br/>不要做 Skill"]
Skill["寫 Skill<br/>放在主對話執行"]
Sub["Skill 用 context: fork<br/>跑在子代理裡"]
Teams["不用 Skill<br/>開 Agent Teams"]
Start --> Q1
Q1 -->|否,每次任務都不一樣| OneShot
Q1 -->|是,能模板化| Q2
Q2 -->|裝得下| Skill
Q2 -->|裝不下,過程會汙染主對話| Q3
Q3 -->|否,單點任務| Sub
Q3 -->|是,多角色協作| Teams
style Skill fill:#dcfce7,stroke:#22c55e,stroke-width:2px
style Sub fill:#dbeafe,stroke:#3b82f6,stroke-width:2px
style Teams fill:#f3e8ff,stroke:#a855f7,stroke-width:2px
style OneShot fill:#fef3c7,stroke:#f59e0b
讀這張圖的訣竅:Skill 是預設選項,SubAgent 是"上下文太髒"時的升級,Agent Teams 是"需要協作"時的再升級。從下往上反著選——先問"能不能用 Skill 就解決",再考慮分身和團隊。這跟 07 篇 講的"SubAgent 不是任務拆分儀式" 是同一邏輯。
回到 PDF:
- 單個 PDF 處理 → Skill(主對話)
- 200 個 PDF 批次處理 → Skill +
context: fork(SubAgent) - 200 個 PDF + 財務 / 法務 / 技術多角色審查 + 互相確認 → 不用 Skill,開 Agent Teams(08 篇)
提前劇透:當一個 Skill 的執行過程很長、會讀很多檔案、會跑很多命令時,就開始接近 SubAgent 的使用場景。
12. 檢驗你真懂了嗎
試著用自己的話回答:
- 有人說"Skill 就是給 Claude 裝外掛"。你能解釋為什麼這個說法不準確嗎?對應 §1 + §2。
- 為什麼
description比正文第一段更像 Skill 的入口?一個太泛的 description 會造成什麼問題?對應 §3。 - 動手題 ⭐:現在開啟一個真實專案,寫一個 Skill 的
description欄位(≤80 字),讓 Claude 在使用者說"掃描發票轉表格"時觸發,但在使用者說"開啟這個 PDF 讓我看看" 時不觸發。寫完檢查:觸發詞覆蓋了"掃描"、"發票"、"表格" 三類輸入嗎?有沒有把"PDF" 單字作為唯一錨點(這會讓"看這個 PDF" 也命中)?
過關標準:能用一句話說清——Skill 是按需載入的工作流檔案:description 負責觸發,正文負責流程,supporting files 負責深層資料;長期事實進 CLAUDE.md,任務流程進 SKILL.md。 加上動手題真寫過一遍 description,你才算真會。
13. 還沒回答的問題
為了不把本篇撐爆,幾個進階問題被推到後面或官方文件:
- 多個 Skill 命名衝突時怎麼辦? → §6 名稱空間已點;完整規則在 12 篇 Plugin 的 namespace 章節
- Skill 內部能不能
@import引用其它 markdown? → 行為類似 03 篇 CLAUDE.md 的 import;具體限制看 Anthropic skills 文件 當前版本 - Skill 能不能跨會話保留狀態? → 不能直接保留;要持久化用 03 篇 Auto Memory 或自己寫檔案
- Skill 跟 Permissions / Hooks 怎麼聯動? → Skill frontmatter
allowed-tools是 Permission 的預批准入口;Skill 觸發後仍受 10 篇 Hooks 攔截 - Skill 怎麼版本化分發? → 單倉 Skill 跟 git 走;要打包給團隊 / 社群,看 12 篇 Plugin 的 marketplace 章節
- Skill description 實際匹配的演算法是什麼? → 當前實現是模型基於 system prompt 決策(詳見 §3),具體調權細節官方未公開
把這些標記出來不是寫不全,是想讓你知道:Skill 是個完整子系統,但它依賴 CLAUDE.md / Permission / Hook / Plugin 這些相鄰系統。理解 Skill 的最大槓桿,是搞清楚它跟誰聯動、誰負責什麼——本篇 §9 對照表和 §11 決策樹就是這層聯動的入口。
📖 本篇術語速查表
- Skill:技能,按需載入的任務流程檔案。
SKILL.md:Skill 入口檔案,frontmatter + 正文流程。- frontmatter:檔案頭後設資料,
---包裹的配置欄位。 - description:觸發描述,Claude 判斷是否載入 Skill 的主要依據。
- supporting files:支援檔案,Skill 目錄下按需讀取的參考、模板、指令碼。
- slash command:斜槓命令,用
/skill-name手動呼叫 Skill 的入口。 disable-model-invocation:禁止模型自動呼叫,讓 Skill 只能由使用者手動觸發。user-invocable:使用者是否可呼叫,設為 false 時可作為後臺知識 Skill。- system prompt:系統提示,啟動時 Claude 看到的指令背景,Skill metadata 註冊在這裡。
- forked subagent context:分叉子代理上下文,Skill
context: fork時啟動的隔離上下文(詳見 07 篇)。
官方資料
接下來去哪
07 · 派助手去幹活
Skill 解決"流程複用"。下一篇講 SubAgents:怎麼把長任務放到另一張桌子上,不汙染主會話。
05 · AI 怎麼決定想多深(上一篇)
複習 effort:很多 Skill 應該把思考深度寫進 frontmatter,而不是每次臨場手調。
03 · 怎麼記住你的習慣
分不清 CLAUDE.md 和 SKILL.md 時,回到記憶篇:長期身份和規則進記憶,任務流程進 Skill。
如果你只記一個判斷:凡是你第三次複製貼上給 Claude 的流程,就該考慮寫成 Skill。