AI 程式設計教程中文版
從原理到實戰

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 節就是按這三個問題展開:

  1. description 寫什麼 Claude 才會真用它?——§3 看 description 怎麼作為"觸發索引"被模型在每輪決策前掃一遍;§5 看 frontmatter 控制面板的全部欄位。
  2. 一篇 SKILL.md 幾千字 Claude 不會被淹?——§6 看 supporting files 外接;§7 看漸進式載入怎麼把"裝很多"和"上下文不爆"同時做到。
  3. Skill 跟 CLAUDE.md / SubAgent / Plugin 邊界在哪?——§9 看跟 CLAUDE.md / Hook / MCP 的 4 維對照;§11 看跟 SubAgent 的銜接;12 篇 Plugin 看怎麼被打包分發。

讀完每一節自檢:這一節回答了哪個問題、用什麼機制回答的、為什麼不是另一種實現。

2. 寫進 SKILL.md

最小 Skill 只有一個檔案:SKILL.md

目錄長這樣:

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 啟用時無需逐次確認
modelSkill 啟用時臨時切模型某類任務固定需要 Opus / Haiku 時不寫 = 沿用主會話模型
effortSkill 啟用時覆蓋思考深度審計類深想、格式類低 effort不寫 = 沿用主會話 effort(詳見 05 篇
contextfork 時在子代理上下文執行不想汙染主對話時不寫 = 在主對話執行;寫 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。比如:

extract_tables.py # 辅助脚本

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 的邊界

這一步最容易和 03 篇 / 10 篇 / 09 篇 混。

四者都是"配置 Claude 行為"的方式,但職責不同。一張 4 維對照表看清:

維度CLAUDE.md03 篇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 觸發判斷。

判斷訣竅——問自己:

  1. 這條資訊每次會話都要進上下文嗎?是 → CLAUDE.md。
  2. 這條資訊只在某類任務才需要?是 → SKILL.md。
  3. 這條規則漏一次就出事?是 → Hook。
  4. 這條資訊來自外部系統(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. 檢驗你真懂了嗎

試著用自己的話回答:

  1. 有人說"Skill 就是給 Claude 裝外掛"。你能解釋為什麼這個說法不準確嗎?對應 §1 + §2。
  2. 為什麼 description 比正文第一段更像 Skill 的入口?一個太泛的 description 會造成什麼問題?對應 §3。
  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 篇)。

官方資料

接下來去哪

如果你只記一個判斷:凡是你第三次複製貼上給 Claude 的流程,就該考慮寫成 Skill。

本頁目錄