---
title: "06 · 把重複的話寫成檔案"
description: "Skills 不是給 Claude 裝新能力，而是把你反覆說的流程寫成檔案。description 決定何時觸發，正文決定怎麼做。"
canonical: "https://xiangyugongzuoliu.com/tag/claude-code"
verifiedAt: "2026-05-08"
---

Aaron有一段時間每天都跟 Claude Code 說同樣的話：處理 PDF 先提取文本，再處理表格；掃描件走 OCR；表格結果轉 CSV；最後給一份可複核摘要。說了十幾遍以後突然意識到——這不是提示詞技巧，這是一個應該寫進檔案的工作流。——Aaron

> [!NOTE]
> **這一篇用 15 分鐘換什麼**：前 5 篇分別講了位置、上下文、記憶、提示詞和思考深度。現在進入第一個"複用層"：**Skills（技能）**。讀完你會知道，什麼該寫進 `CLAUDE.md`，什麼該寫成 `SKILL.md`，什麼時候讓 Claude 自動觸發，什麼時候必須你手動輸入 `/skill-name`。

## 1. 你每天重複的不是"知識"，是"流程"

先看一個具體場景。

你讓 Claude 處理一個 PDF：

> [!NOTE]
> **👤 你**：幫我把這個 PDF 裡的表格提出來。

Claude 能做嗎？能。第 1 篇講過，Claude Code 住在你電腦上。你電腦裝了 `pdfplumber`、OCR 工具、Python 指令碼，它就能讀檔案、跑命令、改指令碼。

但第一次結果常常不穩。它可能先嚐試普通文本提取，漏掉掃描頁；也可能把表格當段落處理；還可能直接給你總結，沒有留下 CSV。

你只好補一句：

```text
处理 PDF 时先判断是不是扫描件。普通 PDF 用 pdfplumber 提取文本和表格。
扫描件先 OCR。表格转 CSV，保留页码，最后输出摘要和异常页列表。
```

第二天又來一個 PDF。你再說一遍。

第三天又說一遍。

這時要停下來判斷：你重複的不是"PDF 是什麼"，也不是"pdfplumber 怎麼安裝"。Claude 大機率知道這些。你重複的是**你的處理流程**。

> [!IMPORTANT]
> **第一性原理**：Skill 解決的不是"Claude 不會什麼"，而是"Claude 不知道你遇到某類任務時希望它按什麼流程做"。

這句話很關鍵。很多人寫 Skill 寫偏，就是因為把 Skill 當成百科詞條，開始解釋 PDF、CSV、OCR 的定義。真正該寫的是：

- 先判斷什麼
- 用哪個工具
- 遇到什麼異常怎麼分支
- 輸出什麼格式
- 做完怎麼驗收

這些才是你每天反覆說的東西。

> [!IMPORTANT]
> **這一篇要回答的三個核心問題**
>
> 寫一個 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`。

目錄長這樣：

```files
pdf-workflow/
  SKILL.md
```

檔案可以這樣寫：

```md
---
description: 从 PDF 中抽取文本和表格。用户提到处理 PDF、抽表格、跑 OCR、把 PDF 数据转成 CSV 时使用。
---

## 工作流程

1. 先检查 PDF 本身，判断每页是文本型还是扫描图像。
2. 文本型页面用 pdfplumber 抽取文本和表格。
3. 扫描页面先跑 OCR 再抽取。
4. 提取出来的表格按页码存成 CSV。
5. 返回摘要：包含产出文件、跳过的页、置信度偏低的 OCR 段落。
```

注意它**沒有**寫"PDF 是 Portable Document Format"。也沒有寫"OCR 是光學字元識別"。這些不是你的流程，是百科。

它寫的是：**遇到 PDF 任務時，Claude 應該怎麼做**。

> [!TIP]
> **一句話理解**：`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](https://code.claude.com/docs/en/skills#create-your-first-skill)。

所以 `description` 不是簡介文案，它是**觸發索引**。

壞寫法：

```yaml
---
description: 处理文件相关的任务。
---
```

這個描述太泛。PDF 是檔案，圖片是檔案，程式碼也是檔案。Claude 無法判斷它什麼時候該觸發。

好寫法：

```yaml
---
description: 从 PDF 中抽取文本和表格。用户提到处理 PDF、抽表格、跑 OCR、把 PDF 数据转成 CSV 时使用。
---
```

這裡有四類觸發詞：PDF、抽表格、OCR、CSV。使用者說"把這個掃描 PDF 裡的發票表格轉成 CSV"，Claude 就容易匹配上。

```mermaid
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](/zh-Hant/docs/claude-code/understanding/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`，你可以直接輸入：

```text
/pdf-workflow 处理 invoice.pdf
```

官方文件也明確說，custom commands 已經合併進 Skills：`.claude/commands/deploy.md` 和 `.claude/skills/deploy/SKILL.md` 都能建立 `/deploy`，現有 `.claude/commands/` 還可用，但 Skills 支援 supporting files、frontmatter 控制自動觸發等更多能力。

> [!WARNING]
> **關鍵點**：不要把 Skill 理解成"只能自動觸發"。它同時有兩種入口：Claude 覺得相關時**自動載入**；你也可以用 `/skill-name` **手動呼叫**。

## 4. 什麼時候自動，什麼時候手動

這一步很容易混。

不是所有 Skill 都應該讓 Claude 自動觸發。

PDF **提取**這種流程，自動觸發沒問題。使用者說 PDF、OCR、表格，Claude 自動用它，符合預期。

但 PDF **自動覆蓋原檔案 / 處理完直接發郵件給客戶**這種有副作用的流程，不能讓 Claude 自己看起來"時機合適"就執行。

這時用 `disable-model-invocation: true`：

```yaml
---
name: pdf-archive-and-email
description: 处理 PDF 后用结果覆盖原文件并发邮件给收件人。
disable-model-invocation: true
---
```

意思是：Claude 不會自動呼叫，只有你輸入 `/pdf-archive-and-email` 才會觸發。

另一個方向也存在：有些 Skill 只是背景知識，不適合人手動呼叫。比如：

```yaml
---
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 讀，不給人當命令用。

> [!CAUTION]
> **關鍵原則**：只要一個 Skill 會產生**真實外部副作用**（覆蓋檔案 / 發訊息 / 呼叫付費 API / 刪資料），就不要讓它自動觸發。自動觸發適合"指導 Claude 怎麼思考和處理"，不適合"替你決定何時釋出、提交或通知別人"。

**為什麼 Anthropic 設計成"預設允許 + 高危 opt-out"而不是反過來**：

如果預設全部禁止自動觸發，所有 Skill 都要 `/skill-name` 手動調——失去 Skill 最大價值"按需自動載入"。如果預設全部允許自動，副作用 Skill 危險。Anthropic 選了"預設允許 + 高危顯式 opt-out"——**把"什麼算危險"的判斷權交給 Skill 作者**，因為：

- 平臺不知道每個 Skill 實際做什麼（覆蓋檔案？只讀分析？）
- 靜態掃描判斷"是否有副作用" 太弱（指令碼里調外部 API 難自動識別）
- 讓作者宣告意圖，比讓平臺猜更準確

代價：**壞作者可以寫"自動覆蓋"還不加 opt-out**。這就是 [12 篇 Plugin](/zh-Hant/docs/claude-code/understanding/12-plugins) 強調"外掛是 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](/zh-Hant/docs/claude-code/understanding/11-permissions)）；列了 = 這些工具在 Skill 啟用時無需逐次確認 |
| `model` | Skill 啟用時臨時切模型 | 某類任務固定需要 Opus / Haiku 時 | 不寫 = 沿用主會話模型 |
| `effort` | Skill 啟用時覆蓋思考深度 | 審計類深想、格式類低 effort | 不寫 = 沿用主會話 effort（詳見 [05 篇](/zh-Hant/docs/claude-code/understanding/05-thinking-depth)）|
| `context` | `fork` 時在子代理上下文執行 | 不想汙染主對話時 | 不寫 = 在主對話執行；寫 `fork` = 啟動 SubAgent（[07 篇](/zh-Hant/docs/claude-code/understanding/07-subagents)）|
| `disable-model-invocation` | 禁止自動觸發 | 副作用 Skill | 預設 false（允許自動）|
| `user-invocable` | 使用者能否手動呼叫 | 後臺知識 Skill | 預設 true（使用者可 `/cmd`）|

第 5 篇剛講過 effort。這裡它開始進入工程配置。

比如 PDF **審查** Skill 需要深度推理：

```yaml
---
name: pdf-content-review
description: 审查 PDF 中的合同条款是否存在风险点。
effort: xhigh
allowed-tools: Read Grep Glob
---
```

這說明：這個 Skill 主要讀檔案、搜文本，不應該隨便改檔案；同時合同審查需要更深推理，所以 effort 提高。

再比如 PDF **格式潤色** Skill 路徑很直，不需要高 effort：

```yaml
---
name: pdf-extracted-text-polish
description: 润色已抽取的 PDF 文本格式（断行 / 表头 / 标点），不改事实。
effort: low
---
```

> [!IMPORTANT]
> **邊界要講清**：`allowed-tools` 是預批准工具，**不是唯一可用工具**。官方文件說明，它讓列出的工具在 Skill 啟用時無需逐次確認；其它工具仍受你的 [11 篇許可權設定](/zh-Hant/docs/claude-code/understanding/11-permissions) 約束。不要把它當成完整沙箱。

**新手最常漏寫的欄位是 `argument-hint`**：寫了一個 `/pdf-workflow` Skill 但不寫 hint，使用者在終端打 `/pdf-workflow` 後不知道下一步該輸什麼——是空格加路徑？還是帶引號？還是直接Enter？hint 一行就解決：`argument-hint: "[PDF 路徑]"`。

## 6. 支援檔案：別把正文寫成儲存庫

很多人第一次寫 Skill，會把所有東西都塞進 `SKILL.md`：

- 20 個示例
- 詳細 API 文件
- 專案模板
- 完整檢查清單
- 大段背景說明

這樣很快失控。**3000 行 SKILL.md** 觸發後會一次性注入主對話——主任務上下文直接被擠壓，Claude 還沒幹活就已經"滿桌子"，跟 [02 篇上下文](/zh-Hant/docs/claude-code/understanding/02-context-window) 講的"桌子要乾淨"原則反著幹。

官方建議 `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。比如：

```files
pdf-workflow/
  SKILL.md
  reference.md          # 表格抽取边界情况、OCR 置信度判定阈值
  templates/
    extraction-report.md  # 输出报告模板
  examples/
    invoice-summary.md    # 发票类示例
    contract-summary.md   # 合同类示例
  scripts/
    extract_tables.py     # 辅助脚本
```

`SKILL.md` 只寫導航：

```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 正文都塞進上下文。它更像三層索引：

```mermaid
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/` | 詳細資料按需讀取，不常駐 |

把"漸進式載入"攤到一次真實會話的時間線上，更直觀：

```mermaid
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 篇](/zh-Hant/docs/claude-code/understanding/02-context-window) 的桌子原則一致。
- **supporting files 是真的"按需"**：只有 Claude 顯式 Read 才進上下文，這就是為什麼 500 行的硬資料外接最划算——你寫 100 個示例放 examples/，Claude 大多數任務只讀 1-2 個。

> [!TIP]
> **一句話理解**：`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 篇](/zh-Hant/docs/claude-code/understanding/12-plugins)）|
| 企業級 | managed settings | 公司統一下發的合規 PDF 審查 Skill |

如果同名 Skill 出現在多個層級，**企業級 > 個人級 > 專案級**。外掛 Skill 會帶外掛名稱空間（詳見 [12 篇](/zh-Hant/docs/claude-code/understanding/12-plugins)），避免和普通 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 篇](/zh-Hant/docs/claude-code/understanding/03-memory) / [10 篇](/zh-Hant/docs/claude-code/understanding/10-operation-control) / [09 篇](/zh-Hant/docs/claude-code/understanding/09-mcp) 混。

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

| 維度 | `CLAUDE.md`（[03 篇](/zh-Hant/docs/claude-code/understanding/03-memory)）| **`SKILL.md`（本篇）** | Hook（[10 篇](/zh-Hant/docs/claude-code/understanding/10-operation-control)）| MCP（[09 篇](/zh-Hant/docs/claude-code/understanding/09-mcp)）|
|------|------|------|------|------|
| **載入時機** | 每次會話啟動**全量注入** | 觸發後才注入正文 | 事件點自動執行 | 工具被呼叫時連線 |
| **上下文成本** | 全量常駐（建議 ≤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`。

<details>
<summary>📌 看答案</summary>

- **A → CLAUDE.md**：是專案級"用什麼庫"約定，每次會話都要知道，不需要觸發。
- **B → SKILL.md**：是反覆出現的工作流，只在 PDF 任務時才需要。
- **C → Hook（PostToolUse）**：是"動作完成後自動執行"的規則，不依賴 Claude 觸發判斷。

判斷訣竅——問自己：
1. 這條資訊**每次會話**都要進上下文嗎？是 → CLAUDE.md。
2. 這條資訊**只在某類任務**才需要？是 → SKILL.md。
3. 這條規則**漏一次就出事**？是 → Hook。
4. 這條資訊**來自外部系統**（GitHub / 資料庫 / SaaS）？是 → MCP。

</details>

## 10. 一個合格 Skill 長什麼樣

回到 PDF 例子。一個更完整的版本可以這樣寫：

```md
---
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` 和任務複雜度匹配
- 正文寫流程，不寫百科
- 輸出格式明確

再對照一個壞版本：

```md
---
description: 帮忙处理文档。
---

PDF 是 Adobe 推出的文件格式。OCR 指光学字符识别。
请使用工具处理文件，并返回有用的结果。
```

壞在哪裡？

- description 太泛：容易誤觸發，或該觸發時不觸發。
- 寫百科知識：占上下文，不改變執行質量。
- 沒有流程：Claude 還是要猜先後順序。
- 沒有輸出契約：每次結果格式不穩定。
- 沒有邊界：可能動不該動的檔案或命令。

這就是 Skill 寫作的核心：**描述要窄，流程要清，輸出要定，參考資料要外接**。

理解 Skill 的所有設計選擇，可以壓成一張決策矩陣——這一篇所有"為什麼"彙總：

```mermaid
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 篇](/zh-Hant/docs/claude-code/understanding/07-subagents)）。這裡先提前接一條線：Skill 可以在主會話裡執行，也可以在 forked subagent context（分叉子代理上下文）裡執行。

為什麼需要這個？

還是 PDF 例子。普通 PDF 提取，主會話直接做就行。

但如果你讓 Claude **批次處理 200 個 PDF**，中間會讀大量檔案、跑很多命令、產出許多日誌。這些過程會汙染主會話上下文。

這時可以讓 Skill 在子代理裡跑：

```yaml
---
name: pdf-batch-workflow
description: 批量处理一整个目录的 PDF，返回抽取出的文本、CSV 文件和异常报告。
context: fork
agent: general-purpose
effort: medium
---
```

主會話只拿回結果摘要，具體處理過程留在子代理上下文裡。

實際何時升級到 SubAgent，按這張決策樹判斷：

```mermaid
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 篇](/zh-Hant/docs/claude-code/understanding/07-subagents) 講的"SubAgent 不是任務拆分儀式" 是同一邏輯。

回到 PDF：

- 單個 PDF 處理 → Skill（主對話）
- 200 個 PDF 批次處理 → Skill + `context: fork`（SubAgent）
- 200 個 PDF + 財務 / 法務 / 技術多角色審查 + 互相確認 → 不用 Skill，開 Agent Teams（[08 篇](/zh-Hant/docs/claude-code/understanding/08-multi-agent)）

> [!TIP]
> **提前劇透**：當一個 Skill 的執行過程很長、會讀很多檔案、會跑很多命令時，就開始接近 SubAgent 的使用場景。

## 12. 檢驗你真懂了嗎

試著用自己的話回答：

1. 有人說"Skill 就是給 Claude 裝外掛"。你能解釋為什麼這個說法不準確嗎？對應 §1 + §2。
2. 為什麼 `description` 比正文第一段更像 Skill 的入口？一個太泛的 description 會造成什麼問題？對應 §3。
3. **動手題** ⭐：現在開啟一個真實專案，寫一個 Skill 的 `description` 欄位（≤80 字），讓 Claude 在使用者說"掃描發票轉表格"時**觸發**，但在使用者說"開啟這個 PDF 讓我看看" 時**不觸發**。寫完檢查：觸發詞覆蓋了"掃描"、"發票"、"表格" 三類輸入嗎？有沒有把"PDF" 單字作為唯一錨點（這會讓"看這個 PDF" 也命中）？

> [!TIP]
> **過關標準**：能用一句話說清——**Skill 是按需載入的工作流檔案：description 負責觸發，正文負責流程，supporting files 負責深層資料；長期事實進 CLAUDE.md，任務流程進 SKILL.md。** 加上動手題真寫過一遍 description，你才算真會。

## 13. 還沒回答的問題

為了不把本篇撐爆，幾個進階問題被推到後面或官方文件：

- **多個 Skill 命名衝突時怎麼辦？** → §6 名稱空間已點；完整規則在 [12 篇 Plugin](/zh-Hant/docs/claude-code/understanding/12-plugins) 的 namespace 章節
- **Skill 內部能不能 `@import` 引用其它 markdown？** → 行為類似 [03 篇 CLAUDE.md](/zh-Hant/docs/claude-code/understanding/03-memory) 的 import；具體限制看 [Anthropic skills 文件](https://code.claude.com/docs/en/skills) 當前版本
- **Skill 能不能跨會話保留狀態？** → 不能直接保留；要持久化用 [03 篇 Auto Memory](/zh-Hant/docs/claude-code/understanding/03-memory) 或自己寫檔案
- **Skill 跟 Permissions / Hooks 怎麼聯動？** → Skill frontmatter `allowed-tools` 是 Permission 的預批准入口；Skill 觸發後仍受 [10 篇 Hooks](/zh-Hant/docs/claude-code/understanding/10-operation-control) 攔截
- **Skill 怎麼版本化分發？** → 單倉 Skill 跟 git 走；要打包給團隊 / 社群，看 [12 篇 Plugin](/zh-Hant/docs/claude-code/understanding/12-plugins) 的 marketplace 章節
- **Skill description 實際匹配的演算法是什麼？** → 當前實現是模型基於 system prompt 決策（詳見 §3），具體調權細節官方未公開

把這些標記出來不是寫不全，是想讓你知道：**Skill 是個完整子系統，但它依賴 CLAUDE.md / Permission / Hook / Plugin 這些相鄰系統**。理解 Skill 的最大槓桿，是搞清楚它跟誰聯動、誰負責什麼——本篇 §9 對照表和 §11 決策樹就是這層聯動的入口。

<details id="glossary">
<summary><b>📖 本篇術語速查表</b></summary>

- **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 篇](/zh-Hant/docs/claude-code/understanding/07-subagents)）。

</details>

## 官方資料

- [Extend Claude with skills](https://code.claude.com/docs/en/skills)
- [Commands](https://code.claude.com/docs/en/commands)

## 接下來去哪

<Cards>
  <Card title="07 · 派助手去幹活" href="/zh-Hant/docs/claude-code/understanding/07-subagents">
    Skill 解決"流程複用"。下一篇講 SubAgents：怎麼把長任務放到另一張桌子上，不汙染主會話。
  </Card>
  <Card title="05 · AI 怎麼決定想多深（上一篇）" href="/zh-Hant/docs/claude-code/understanding/05-thinking-depth">
    複習 effort：很多 Skill 應該把思考深度寫進 frontmatter，而不是每次臨場手調。
  </Card>
  <Card title="03 · 怎麼記住你的習慣" href="/zh-Hant/docs/claude-code/understanding/03-memory">
    分不清 CLAUDE.md 和 SKILL.md 時，回到記憶篇：長期身份和規則進記憶，任務流程進 Skill。
  </Card>
</Cards>

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