跳到內容

第 1 章 skills

一句話:把每次都要重講的一套步驟寫成 SKILL.md,變成一個 /指令。

Skill 是一份 SKILL.md:上面是 YAML frontmatter——檔案開頭兩行 --- 之間、一行一個「欄位: 值」的區塊(名字、什麼時候用、要不要參數),下面是 Markdown 步驟。放進 .claude/skills/<name>/SKILL.md,你就多了一個 /name 指令,Claude 也會在對話對得上 description 時自己拿出來用。 它解決的是「同一套步驟每次都要重新講」:產 changelog、寫 MR 說明、跑固定的檢查清單。把步驟寫成 skill,每次執行都是同一份標準,而且可以進 git 給整個團隊用。 本章要你寫一個 changelog skill,從 git log 產生一段 Unreleased changelog 寫進 CHANGELOG.md,用 /changelog 叫起來。

原理:/changelog 按下去發生什麼事

Section titled “原理:/changelog 按下去發生什麼事”
你打/changelog v1.0.0Claude Code 找到skills/changelog/SKILL.md正文展開進對話$ARGUMENTS被換成 v1.0.0照步驟做git log →CHANGELOG.md
skill 不是程式,是「被展開到對話裡的說明書」——效果跟你自己貼那段字一樣,差別是每次都同一份、可以進 git 分享。

先看沒有 skill 的世界:每次要整理 changelog,你都要打一長段「看 git log、照 type 分組、寫成這個格式、放在檔案最上面、不要動舊內容……」。打三次,就會有三個略微不同的版本。 把這段話存成 SKILL.md 之後,/changelog 做的事其實很單純——Claude Code 找到那份檔案,把正文原封不動展開到對話裡,$ARGUMENTS 換成你打在後面的參數(例如 v1.0.0),然後 Claude 照著做。 所以 skill 沒有魔法:效果跟你自己把那段字貼進對話一模一樣。價值在別的地方——同一份說明書、每次都一樣、進 git 之後全團隊用的都是同一套。

  • 一套固定步驟重複做:每次 release 前整理 changelog、每次開 MR 前產說明。第二次就該是 skill。
  • 想讓 Claude 在對的時機自己用:description 寫清楚觸發條件(「使用者說要整理 changelog 時」),它會自動載入。
  • 要帶參數:/changelog v1.2.0 這種「從某個 ref 之後」的需求,用 argument-hint 加 $ARGUMENTS 就能收。

skill本章

一份步驟說明書

主對話自己照著做,
共享同一個 context

subagent第 2 章

一個獨立的執行者

自己的 context,
做完只回摘要

workflow第 3 章

一條產線

編排多個 subagent,
照腳本跑

步驟本身不需要隔離就用 skill;要隔離 context 用 subagent;要編排很多個就是 workflow。

這三張卡片先放在這裡當地圖:skill 是步驟說明書(在主對話裡執行、共享 context);subagent 是一個獨立的執行者(第 2 章);workflow 是多個 subagent 的編排(第 3 章)。現在只要記住一件事:步驟本身不需要隔離,就用 skill。

兩個都是「讓 Claude 記得事情」的地方,分界在載入時機:

  • CLAUDE.md 每次 session 都整份載入——放「每次都該知道的事實與規範」:指令、風格、慣例。它越長,Claude 越容易漏看重點,所以只放廣泛適用的。
  • skill 的正文用到才載入——放「偶爾才執行的程序」。長的參考資料放在 skill 裡,不用的時候幾乎不佔 context。

官方的判準很好記:當 CLAUDE.md 的某一段長成了「步驟」而不是「事實」,就該搬出來變 skill。

---
name: changelog
description: 從 git log 產生 CHANGELOG 段落並寫進 CHANGELOG.md
argument-hint: [since-ref]
---
正文:步驟、格式、限制。
欄位 作用
name 顯示名稱;指令名以目錄名為準,兩者保持一致最不容易搞混
description 做什麼、什麼時候用。Claude 靠它決定要不要自動載入
argument-hint 打 /changelog 時自動補全顯示的參數提示,例如 [since-ref]
disable-model-invocation 設 true 就只有你能用 /name 叫,Claude 不會自己載入。適合有副作用的步驟(deploy、送訊息——你不會想讓它自己決定要部署)
user-invocable 設 false 就只有 Claude 會自動載入、你打 / 叫不到。適合純背景知識(例如「舊系統的來龍去脈」)
allowed-tools 這個 skill 執行的那一輪可以不問就用的工具,例如 Bash(git log *)

正文裡可以用 $ARGUMENTS 拿到你打在 /name 後面的整串參數;沒寫 $ARGUMENTS 的話參數會被接在最後面。 description 的前幾個字最重要——把主要使用情境放最前面,Claude 自動選用才會準。

skill 是一個資料夾,不是一份檔。SKILL.md 保持精簡(官方建議 500 行以內),細節放旁邊的檔案,在 SKILL.md 裡連結並說明「什麼時候讀哪份」——Claude 需要時才會去讀,不用的檔案完全不佔 context:

.claude/skills/deploy/
├── SKILL.md ← 必要:總覽與導覽
├── reference.md ← 詳細參考,需要才載入
├── examples.md ← 範例集,需要才載入
└── scripts/
└── helper.py ← 讓它執行的腳本,不載入內容

本章的 changelog skill 只需要一份 SKILL.md;等你的 skill 長大,再用這個形狀拆。

/changelog 或 /changelog v1.0.0。輸入 / 會列出所有可用 skill,包含內建與 plugin 提供的。

位置 給誰用
.claude/skills/<name>/SKILL.md 這個專案,進 git 團隊共用
~/.claude/skills/<name>/SKILL.md 你的所有專案,只有你

同名時 personal 蓋過 project。團隊規則放 project,個人習慣放 personal。另外還有 plugin marketplace:把 skills 打包成 plugin 發布,一句 claude plugin install 就能裝——形狀跟這裡一樣,只是多一層包裝。

實務案例:一個「寫 MR」的 skill

Section titled “實務案例:一個「寫 MR」的 skill”

一個團隊有一個「寫 MR」的 skill(MR=GitLab 的 merge request,等於 GitHub 的 PR):frontmatter 裡的 description 列出觸發詞(「寫 MR」「建 MR」「update MR」),正文是編號步驟——先偵測改動範圍、再蒐集 diff、起草四段內文、給使用者確認、才呼叫命令列工具送出。 值得學的形狀:觸發詞寫在 description(自動載入才準)、步驟編號、副作用之前一定有確認步驟、邊界情況單獨一段。本章的 changelog skill 就是照這個形狀縮小版。

練習寫 changelog skill,用 /changelog 叫起來

  1. 起點:

    第一次做就 clone(首頁「共用步驟」做過就跳過 clone);要重做這一章,用第二段把 repo 重置回乾淨的 main。已經在 repo 目錄裡的人不要再貼 clone 這段,會多出一層巢狀目錄。

    Terminal window
    git clone https://github.com/AngusLu0731/claude-code-practice.git
    cd claude-code-practice

    已 clone/重跑(在 repo 根目錄執行):

    Terminal window
    git merge --abort 2>/dev/null
    git checkout -f main && git reset --hard origin/main
    git clean -fd && git worktree prune

    白話:這段=把 repo 恢復成剛 clone 完的乾淨狀態。它會丟掉未 commit 的改動與未追蹤檔(含你自己貼進.claude/ 的檔案),但不會動被 gitignore 的.todo.json(只影響 list 顯示的項目,想清就 rm -f .todo.json)與.claude/settings.local.json(存的是你核准過的權限,留著沒關係)。origin/main 是 GitHub 上那份 main 在你電腦裡的複本,所以reset --hard origin/main=回到跟 GitHub 一模一樣。最後的 git worktree prune 是第 5 章才用得到的清理,現在跑了沒作用也無害。

    練習 repo 也有 make reset,跟上面那段等價。

  2. 信任資料夾:CLI 路線:這個目錄還沒接受過信任對話的話,先 claude 接受再 /exit。Orca 路線:worktree 一開 agent 就自動啟動了,信任對話直接出現(新 worktree 是獨立目錄,會再問一次),選 Yes 即可。

  3. **在終端機(不是 Claude 裡)**貼這個檔案到 .claude/skills/changelog/SKILL.md(與練習 repo 的 solutions/ch1-skills/.claude/skills/changelog/SKILL.md 相同;Orca:按 Cmd-T 在這個 worktree 開一個新終端機分頁來貼):

    下面這段是 heredoc:cat > 路徑 <<'EOF' 到最後一行 EOF 是一組,把中間的內容一字不改寫進那個檔案。整段一起複製、貼到終端機、按 Enter——過程中不會有任何輸出,提示符回來、沒有錯誤就是寫好了(之後 cat .claude/skills/changelog/SKILL.md 可以確認)。不習慣的話,用你的編輯器建檔、貼中間那段內容也一樣。練習 repo 已預先建好 .claude/ 底下的 agents、hooks、skills、workflows 四個資料夾;skill 還要多一層自己的目錄,所以第一行有 mkdir -p——在自己的專案要先把這些目錄建起來。

    Terminal window
    mkdir -p .claude/skills/changelog
    cat > .claude/skills/changelog/SKILL.md <<'EOF'
    ---
    name: changelog
    description: 從 git log 產生 CHANGELOG 段落並寫進 CHANGELOG.md
    argument-hint: [since-ref]
    ---
    (changelog skill v1)從 git 歷史整理一段 Unreleased changelog,寫進 repo 根目錄的 `CHANGELOG.md`。
    ## 輸入
    - since-ref:`$ARGUMENTS`。有給就只看 `<since-ref>..HEAD`;沒給就看全部歷史。
    ## 步驟
    1. 取得 commit 清單:
    - 有 since-ref:`git log --oneline <since-ref>..HEAD`
    - 沒有:`git log --oneline`
    2. 依 commit 訊息開頭的 type 分組(`feat:`、`fix:`、`docs:`、`refactor:`、`test:`、`chore:`;沒有 type 的歸「其他」)。
    3. 用 `date +%F` 取今天日期,組成下面這段,放在 `CHANGELOG.md` 的最頂端(檔案不存在就建立;已存在就插在第一行之前,不要動舊內容):
    ```markdown
    ## Unreleased (YYYY-MM-DD)
    ### feat
    - <subject>(<短 hash>)
    ### fix
    - ...
    ```
    只列有內容的分組。
    4. 寫完後印出這段給使用者看,並提醒:這段還沒 commit。
    ## 限制
    - 只動 `CHANGELOG.md`,不改其他檔案、不 commit、不 push。
    - 不要憑空補 commit 沒寫的內容;subject 照原文。
    EOF

    這份 skill 刻意沒寫 allowed-tools:Claude 跑 git log 前可能會照你目前的權限模式問一次,選允許即可;上面表格的 allowed-tools: Bash(git log *) 是你以後想省掉這個提示時才加。

  4. 建完 .claude/ 檔案,保險起見重開一次(skills 其實有即時偵測、通常不重開也找得到;hooks 與 workflow 也多半會自動讀到,但本教材一律重開,最省事):

    claude 還開著先 /exit,然後:

    Terminal window
    claude
  5. 打 /changelog(輸入 / 時清單裡應該看得到它,旁邊有 [since-ref] 的提示)。since-ref 可以是 tag、分支名或 commit hash(A..HEAD=A 之後到現在的 commit);本章直接打 /changelog,不帶參數。

❯ /changelog
(changelog skill v1)從 git 歷史整理一段 Unreleased changelog,寫進 repo 根目錄的 CHANGELOG.md。
⏺ Bash(git log --oneline)
⏺ Write(CHANGELOG.md)
已寫入 CHANGELOG.md(尚未 commit):
## Unreleased (2026-09-01)
### feat
- add done command(a1b2c3d)
示意圖

橘色那行「(changelog skill v1)」=SKILL.md 正文被展開的證據——預設畫面通常看不到它,這是 ctrl+o 逐字稿裡的樣子;日期與條目依你的 git log 而定。

  • 送出 /changelog 後,按 ctrl+o 展開對話逐字稿(再按一次回到對話):展開的內容第一句是 「(changelog skill v1)」——那是 SKILL.md 正文被載入的證據。預設畫面通常不會直接印出這段,看不到是正常的,逐字稿裡才有。
  • Claude 跑 git log --oneline,依 type 分組,寫入 CHANGELOG.md,並把那段印給你看。
  • git status --porcelain 有兩行:?? .claude/skills/changelog/(你貼的 skill,還沒進 git)與 ?? CHANGELOG.md(??=新檔、還沒被 git 追蹤);打開 CHANGELOG.md 第一行是 ## Unreleased (今天日期),底下是 ### feat、### docs 之類的分組條目。

在乾淨的 main 上跑一次 /changelog,產出的 CHANGELOG.md 長這樣(日期是你跑的那天;條目數與短 hash 依你 clone 到的 main 的 git log 而定,這裡不承諾固定值):

## Unreleased (YYYY-MM-DD)
### feat
- <feat 類型 commit 的 subject>(<短 hash>)
### docs
- <docs 類型 commit 的 subject>(<短 hash>)
### refactor
- <refactor 類型 commit 的 subject>(<短 hash>)
### chore
- <chore 類型 commit 的 subject>(<短 hash>)

只會列出有 commit 的分組——練習 repo 的 main 目前有 feat、docs、refactor、chore 四種 type,所以你會看到四組;之後 repo 多了別種 commit,組數也會跟著變。

自檢(勾選會存在你的瀏覽器)0/3

以 Claude Code 2.1.246(2026-08-26)為準