Skills 不是 markdown - claude_0x05

目录概要

  1. 从按钮到工具------视角切换
  2. Skill 是一个"文件夹"
  3. 13 字段 frontmatter:跟 Command 的异同
  4. 描述字段的"触发哲学"
  5. 渐进式揭露------Anthropic 把几百 token 砍掉的办法
  6. Anthropic 内部把 skill 分成的 9 类
  7. 写好 skill 的 9 条经验(Thariq 版)
  8. 两种 skill 调用模式回顾
  9. On-demand hooks:为什么 /careful 这种设计值得抄
  10. 如何度量你的 skill 值不值得留
  11. 踩过的坑:写得太细、拿不出手的 description、文件放错地方

1. 从按钮到工具------视角切换

上一篇把 Command 拆成了"会自动抓现场的按钮"。这一篇换个主角------Skill

按钮和工具最大的区别在于谁决定什么时候用它

graph LR subgraph Cmd[Command 按钮] U1[用户] -->|主动按| C1[/ 触发] end subgraph Skl[Skill 工具] U2[用户描述需求] --> Claude[Claude 扫描工具箱] Claude -->|识别到对应工具| S1[拿出来用] end style C1 fill:#afa style S1 fill:#aaf

按钮只会在"按下去那一刻"工作。工具不一样------工具自己会喊"这活儿我来"。工具箱里摆着十几把工具,Claude 开工前扫一眼工具箱,觉得某一把能用就拿出来。

这就是 Skill 最核心的心智模型。这篇就按"工具"这个视角展开------它长什么样、模型怎么找到它、怎么确保它被挑中、怎么让它好用。


2. Skill 是一个"文件夹"

很多人用了一周 Skill 还以为它是"单个 markdown 文件"。这是最常见的误解。

Anthropic 内部做 skills 的同学 Thariq 原话:

A common misconception is that skills are "just markdown files", but the most interesting part is that they're folders that can include scripts, assets, data, etc. --- things the agent can discover, explore, and manipulate.

Skill 的磁盘布局:

arduino 复制代码
.claude/skills/my-skill/
├── SKILL.md            ← frontmatter + 简述 + "看什么时候用"
├── references/
│   ├── api.md          ← 详细 API 文档
│   └── schema.md       ← 数据结构
├── scripts/
│   ├── validate.py     ← 可执行脚本
│   └── export.sh
├── examples/
│   ├── case_01.md
│   └── case_02.md
├── assets/
│   └── template.svg
└── config.json         ← skill 自己的配置(可选)

这不是一个 prompt 文件,这是一个带代码、带资产、带样例的小包

SKILL.md 只是这个包的"索引页"。模型最开始只看到索引页------真要用的时候再去读 references/、跑 scripts/、参考 examples/

为什么这样设计?马上讲。但先看它的 frontmatter。


3. 13 字段 frontmatter:跟 Command 的异同

Skill 的 frontmatter 也是 13 个字段------这个数字跟 Command 一样,是刻意的。Anthropic 把两者做到"字段级一致",只有几个字段的默认值和语义不同。

yaml 复制代码
---
name: my-skill
description: Do X when user asks for Y
argument-hint: [file-path]
disable-model-invocation: false
user-invocable: true
allowed-tools: Read, Grep, Glob
model: sonnet
effort: medium
context: fork
agent: general-purpose
hooks:
  PreToolUse: [...]
paths: "src/**/*.py"
shell: bash
---

跟 Command 的字段清单放一起对比:

字段 Command Skill 差异
name 缺省取文件名 缺省取目录名 Skill 是文件夹,name 来自目录
description 可选但强烈推荐 关键------模型扫描用 决定 skill 能否被模型选中
argument-hint 一致 一致 ---
disable-model-invocation 默认 false 默认 false ---
user-invocable 默认 true 预加载 skill 常设为 false 见第 8 节
allowed-tools 激活时的本地白名单 ---
model 运行时模型 ---
effort ---
context fork 切子上下文 ---
agent ---
hooks 仅 command 生命周期 仅 skill 会话周期 on-demand hooks(见第 9 节)
paths glob 激活 glob 自动激活(无需用户输入) Skill 的 paths 是自动找工具的触发点
shell bash/powershell ---

字段一致是好事------你学 Command 付出的学习成本,到 Skill 继续用。只有几处语义不同要小心:

  • user-invocable: false ------ Command 里很少用(藏起来没意义),Skill 里很常见(agent-preloaded skill 都这样)
  • paths ------ Command 只是"在补全里出现",Skill 是"自动被选中"(后者更强的触发力)

4. 描述字段的"触发哲学"

Skill 的 description 跟 Command 的表面上一样,但职责重得多。Thariq 在 Tip 6 里讲得很直白:

The description field is not a summary --- it's a description of when to trigger this skill. Write it for the model.

意思是:description 不是写给用户看的"这个 skill 是干啥的",是写给模型看的"什么情况下该用这个 skill"

4.1 一个对比

反例:

yaml 复制代码
description: A skill for formatting release notes

这是在写"我是谁"。模型扫到这段没有关键触发点------它只能靠 "release notes" 几个词被动匹配。

正例(03 篇里 release-notes-formatter 的真实 description):

yaml 复制代码
description: Formats categorized commit data into a polished
  RELEASE_NOTES_<version>.md following the project's house style. Writes
  to release-notes/RELEASE_NOTES_<version>.md and release-notes/output.md.

差别是什么?正例在告诉模型:

  1. 触发场景:有分桶好的 commit 数据要排版时
  2. 具体产出:RELEASE_NOTES 文件 + output.md 文件
  3. 路径决定性 :写到 release-notes/RELEASE_NOTES_<version>.md

模型扫到这段,看到用户说"给我排一份 release notes"------match;看到用户说"把 commit 列表整理成发布日志"------match;看到当前对话里已经有 feat/fix 分桶数据------更强 match。

4.2 一条实用经验

写 description 时的套路:

css 复制代码
动词 + 触发条件 + 产出 [+ 边界说明]
  • ❌ "Formats Python code"

  • ✅ "Formats Python code with Black configuration from pyproject.toml when user asks for formatting or before committing"

  • ❌ "Database query helper"

  • ✅ "Runs read-only SQL queries against the analytics warehouse. Use when user asks for metrics, counts, or data aggregations. Does not run DDL or writes."

第二种写法的好处:模型不仅知道能用这个 skill,还知道什么时候不该用("Does not run DDL" 是负面触发条件,避免滥用)。


5. 渐进式揭露------Anthropic 把几百 token 砍掉的办法

回到"为什么 Skill 是文件夹"这个问题。

Claude Code 启动时做一件事:把所有 skill 的 SKILL.md 扫一遍,把 description 塞到系统 prompt 里。只有 description,不是全部内容。

graph TB Start[Claude Code 启动] --> Scan[扫描所有 .claude/skills/*/SKILL.md] Scan --> Desc[只读取每个 skill 的 description] Desc --> Sys[注入系统 prompt
'你有这些 skill 可用:
- skill-a: 描述
- skill-b: 描述'] Use[模型决定用 skill-a] --> Full[读 skill-a 的完整 SKILL.md] Full --> Ref{需要更多信息?} Ref -->|需要 API 细节| R1[读 references/api.md] Ref -->|需要跑脚本| R2[exec scripts/validate.py] Ref -->|参考样例| R3[读 examples/case_01.md] style Sys fill:#afa style Full fill:#ff9 style R1 fill:#aaf style R2 fill:#aaf style R3 fill:#aaf

这套机制叫 Progressive Disclosure------渐进式揭露。

5.1 数学账

假设你有 50 个 skills,每个 skill 平均 2000 token。把全部内容都塞进系统 prompt,起步就 10 万 token 消耗。

用渐进式揭露:

  • 启动时:50 个 description × 每个 50 token ≈ 2500 token
  • 用到某个 skill:+ 2000 token 完整 SKILL.md
  • 用到某个 reference:+ ? token

节省 95% 以上。而且随着你 skill 数量的增长,这个比例只会越来越好。

5.2 三层揭露

03 篇里 release-notes-formatter 的目录是典型范例:

arduino 复制代码
.claude/skills/release-notes-formatter/
├── SKILL.md        ← 总是加载(其实只有 description 加载,正文待唤醒)
├── reference.md    ← 需要 Markdown 模板时才读
└── examples.md     ← 需要对照 OSS 样例时才读

SKILL.md 正文里引用了这两个文件:

markdown 复制代码
## Additional resources

- For Markdown template, category headers, and tone examples, see [reference.md]
- For example input/output pairs, see [examples.md]

模型看到 SKILL.md 再决定"我需要 Markdown 模板吗?"------需要就读 reference.md。不需要的话这部分 token 永远不花。

5.3 跟 Commands 的对比

Command 为什么不用这套机制?因为 Command 是用户主动按 的------用户按下 /xxx 的那一刻就肯定要用,token 该花就花,没必要搞分层。

Skill 是模型自主挑的------它只看 description 就要做决定,决定前不该让整个 skill 占满上下文。所以 Skill 有目录结构,Command 只有单文件。

这是一个典型的设计权衡------选择机制决定了成本模型。按钮是"只有按下才扫描",工具是"先扫描再决定按",扫描过程必须足够廉价。


6. Anthropic 内部把 skill 分成的 9 类

如果只看官方默认的 5 个 skill(simplify batch debug loop claude-api),你没法理解 Skill 的真正能力上限。Anthropic 内部用了几百个 skill 之后,Thariq 把它们归纳成 9 个大类:

mindmap root((9 种 skill 类型)) 1 Library & API Reference billing-lib internal-platform-cli frontend-design 2 Product Verification signup-flow-driver checkout-verifier tmux-cli-driver 3 Data Fetching & Analysis funnel-query cohort-compare grafana 4 Business Process standup-post create-ticket weekly-recap 5 Code Scaffolding new-workflow new-migration create-app 6 Code Quality & Review adversarial-review code-style testing-practices 7 CI CD Deployment babysit-pr deploy-service cherry-pick-prod 8 Runbooks service-debugging oncall-runner log-correlator 9 Infrastructure Ops resource-orphans dependency-management cost-investigation

九类里真正值得十年以上经验的架构师先投入的是哪几类?我的排序:

优先 类型 为什么值得先做
1 Library & API Reference Claude 在陌生 API 上容易瞎编,一个 skill 能立刻止血
2 Product Verification 花一周时间让 skill 会自动验证产出------Thariq 说这个 ROI 最高
3 Runbooks 把线上值班的"第一步、第二步、第三步"交给 skill,减少人肉查 wiki
4 Code Quality & Review 结合 hooks 自动跑,团队质量门禁
5 Infrastructure Ops 危险操作带 guardrail,新人误操作率大降

最被低估的是 Runbooks ------传统团队都有 wiki / confluence / notion 写 runbook,但人真去 oncall 时要么懒得翻要么翻错。Skill 的优势是主动匹配------报警一到,Claude 直接选中对应 runbook skill,人只需要审 Claude 的判断,不需要自己查文档。


7. 写好 skill 的 9 条经验(Thariq 版)

Thariq 同一份公开分享里给了 9 条 skill 编写经验。这里把每条配上"十年经验架构师视角的翻译"------哪些是"废话常识"、哪些是"非做不可"。

7.1 不要写废话

Don't State the Obvious

Claude 已经知道怎么写 React 组件、怎么用 Python pandas、怎么写 SQL。你的 skill 如果只是重复这些,负价值------既占 token 又稀释描述的信号度。

值得写进 skill 的

  • 内部库 / 私有 CLI 的用法
  • 跟"行业默认做法"相反的团队约定("我们不用 Inter 字体,不要紫色渐变")
  • Claude 经常犯错的边界条件

7.2 Gotchas 是全 skill 信号密度最高的段落

Build a Gotchas Section

Gotchas / 踩坑 / 注意事项------放在 skill 末尾。内容不是凭空想的,是实际用 Claude 时它反复踩的点

迭代逻辑:

复制代码
Claude 用 skill 出错 → 人工看原因 → 把这个原因加进 Gotchas → 下次不再踩

这是 skill 从 "v1 能跑" 到 "v10 真好用" 的核心路径。

7.3 用文件系统做渐进式揭露

第 5 节讲过了。要点重复一次:SKILL.md 简短、细节拆到子文件、模型按需读

7.4 不要给 Claude 写死步骤

Avoid Railroading Claude

新手最容易踩------写 skill 时担心 Claude 不按规矩来,就把"第 1 步、第 2 步、第 3 步"写得死死的。结果是:

  • 场景稍微变化,Claude 僵硬套模板
  • Skill 复用性急剧下降

对比两种写法:

markdown 复制代码
# 写法一(railroading,不推荐)

## Instructions
1. Read `config.yaml`
2. Extract the `database_url` field
3. Call `psql $database_url -c "SELECT * FROM users"`
4. Parse the output
5. Print as JSON
markdown 复制代码
# 写法二(goal + constraints,推荐)

## Goal
给定 config.yaml,查 users 表并返回 JSON。

## Constraints
- 数据库 URL 在 config.yaml 的 `database_url` 字段
- 只读查询,不做 DDL
- 输出 JSON schema:`{users: [{id, email, created_at}]}`

## Useful tools
- `scripts/run_query.sh` ------ 带连接重试的查询脚本

写法二让 Claude 有判断余地------config 格式变了它能跟着调整;JSON 出错它能排查。这是 skill 可持续的关键。

7.5 Setup 要先想清楚

Think through the Setup

有些 skill 需要用户配置才能跑(数据库地址、API key、dashboard ID)。配置存哪里?

Anthropic 的推荐:skill 目录下的 config.json,不存在时用 AskUserQuestion 工具让用户填一遍。

arduino 复制代码
skill/
├── SKILL.md
├── config.json         ← 存 setup 结果
└── references/...

SKILL.md 里写:

markdown 复制代码
## Setup
If config.json does not exist, use AskUserQuestion to gather:
- database_url
- default_schema

Then write to config.json and confirm with user.

第一次用 skill 触发 setup,之后永远不用重配。

7.6 description 是写给模型看的

第 4 节展开过。

7.7 Skill 可以自己存记忆

skill 可以自己维护数据文件------append-only log、JSON、甚至 SQLite。但直接存在 skill 目录里会被升级覆盖

正确做法:用 ${CLAUDE_PLUGIN_DATA} 环境变量指向稳定目录:

markdown 复制代码
## Memory
Append a line to `${CLAUDE_PLUGIN_DATA}/runs.log` every time this skill completes:
  `timestamp\tuser\toperation\tresult`

下次启动还能看到历史,skill 升级也不会丢。

7.8 把代码塞进 skill

Store Scripts & Generate Code

这是 Skill 相比 prompt-only 扩展最爆炸的能力。

LLM 擅长"组合、决策、解释 ",不擅长"重复生成复杂模板代码 "。Skill 目录里放 shell / python 脚本,Claude 去调用它们、组合它们,而不是自己写一份。

例子------一个数据查询 skill:

bash 复制代码
data-query/
├── SKILL.md
├── scripts/
│   ├── run_query.py        ← 带 auth、带 retry、带 timeout 的查询封装
│   ├── format_csv.py       ← 标准化 CSV 输出
│   └── format_markdown.py  ← 转 markdown 表格
└── references/
    └── schema.md

SKILL.md 告诉 Claude:

bash 复制代码
用户要查数据时:
1. 看 references/schema.md 找对表
2. 组合 scripts/run_query.py 的参数
3. 根据用户想要 csv 还是 markdown,pipe 到对应 format_* 脚本

Claude 的工作变成"组装 pipeline",不是"从 0 写查询"。稳定性、速度、token 消耗都好一个量级。

7.9 On-demand hooks

第 9 节展开。


8. 两种 skill 调用模式回顾

第 03 篇讲过 release-notes 生成器同时用了两种 skill 调用方式。这里从 Skill 自己的视角再说一遍,因为这是"什么时候该设 user-invocable: false"的判断依据。

模式 例子 触发 user-invocable 何时用
Agent Skill(预加载) git-log-reader Agent 启动时读入 false 隐藏 skill 是某个 agent 的"必备知识",不独立存在
Direct Skill(直接调用) release-notes-formatter Skill 工具 / /name / 模型自动选 true 或省略 skill 是"可复用的独立操作"

判定是否要 preload 的一个硬标准:

如果少了这个 skill,这个 agent 就彻底没法工作 → preload 如果 skill 能在多个 agent 间复用 → 直接调用

git-log-reader 是"怎么解析 conventional commits"------只有 release-notes-agent 用得到,没有它 agent 就瞎了,preload

release-notes-formatter 是"把分桶数据排版成 Markdown"------以后做 changelog agent、做 monthly digest agent 都能用这个 skill,直接调用

8.1 跨 skill 调用

Skill 还能引用另一个 skill:

file-upload skill 把这份 CSV 上传到 S3。

模型看到这行,知道去找 file-upload skill 并执行。没有 native 的依赖管理------靠的是 skill 名字自然语言引用。

这种自由度带来的风险是:名字改了引用就断。所以实战里我们会在 SKILL.md 顶部列一段 "Dependencies":

markdown 复制代码
## Dependencies (skills this skill calls)

- `file-upload` --- needed to push final CSV to S3
- `data-query` --- needed to fetch source data

肉眼能看到依赖,改名时可以 grep 出来。


9. On-demand hooks:为什么 /careful 这种设计值得抄

Skill 的 hooks 字段跟 Command 的 hooks 字段看起来一样,但生效时机不同

  • Command 的 hooks:command 激活期间生效
  • Skill 的 hooks:skill 被调用开始直到会话结束都生效

这个区别催生了 Anthropic 内部最好玩的两个 skill:

9.1 /careful------临时穿上防护服

yaml 复制代码
---
name: careful
description: Enable careful mode --- blocks destructive operations for this session
---

When invoked, register PreToolUse hooks that block:
- rm -rf commands
- DROP TABLE / DROP DATABASE in SQL
- git push --force / --force-with-lease
- kubectl delete
- terraform destroy

用户说 "/careful" 之后,整个会话都处于"禁毁模式"。会话结束 hook 消失。

为什么不把这个变成默认 hook?因为平时做 dev 没必要阻挡 rm -rf build/------它会频繁报错。/careful显式切入的更严格模式 ,类似 "sudo -i 进了 root 就要小心模式"。

9.2 /freeze------写入范围冻结

yaml 复制代码
---
name: freeze
description: Freeze file writes to a specific directory for this session
---

When invoked, prompt user for allowed directory (e.g., "src/api/").
Register PreToolUse hook on Edit/Write that blocks any path outside that directory.

用途:正在改某个模块,不想让 Claude "顺手也动一下" 其他地方。/freeze src/api/ 之后它就被关在笼子里了。

9.3 这个设计模式的通用性

On-demand hooks 的本质是:用户声明模式,模式改变工具行为。这跟 Vim 的 normal/insert/visual 模式、IDE 的"只读模式"是一个路数。

架构师可以借鉴的场景:

  • /prod-debug ------ 在生产调试时自动加 audit log
  • /review-mode ------ 禁止任何 Edit/Write,只能 Read/Grep
  • /deploy-window ------ 只在工作时间允许 deploy 类工具

这些都不需要改全局 settings,一个 skill 解决。下一篇讲 subagents 时会看到 subagent 也有 hooks 字段,能做更精细的 per-role 限制。


10. 如何度量你的 skill 值不值得留

写了 20 个 skill,怎么知道哪些被用、哪些是僵尸?

Thariq 分享了 Anthropic 内部做法:用 PreToolUse hook 给 skill 埋点

yaml 复制代码
# .claude/settings.json
hooks:
  PreToolUse:
    - matcher: "Skill"
      hooks:
        - type: command
          command: python3 .claude/hooks/log_skill_use.py

log_skill_use.py 记录:

  • 时间戳
  • 用户
  • 被调用的 skill 名
  • 调用上下文摘要
  • 执行时长
  • 最终是否成功

积累一两周之后看数据:

  • 高频 + 高成功率 → 明星 skill,值得继续投入
  • 高频 + 低成功率 → 需要迭代(加 Gotchas、换 description、拆目录)
  • 低频 → 要么 description 写得没辨识度、要么这个场景根本不常见
  • 零调用 → 删掉或进存档

这是 skill 生态从"个人玩具"走向"团队基础设施"的关键步骤------没有度量就没有迭代。


11. 踩过的坑

坑 1:description 写成功能描述而不是触发条件

前面展开过。再贴一条反例:

  • description: Git commit helper
  • description: Creates conventional commits from staged changes. Invoke when user asks to commit, when changes are staged without a commit message, or before a PR.

坑 2:SKILL.md 写了 500 行

很常见------想"把能说的全说了"。结果每次 skill 被激活都吃 2000 token。

正确做法:SKILL.md 保持在 100 行以内,其他都拆到 references/。

坑 3:references/ 里放的 markdown 跟 SKILL.md 重复

SKILL.md 写"API 用法见 references/api.md";翻开 references/api.md,发现前一半又抄了 SKILL.md 的简述。纯浪费。

references/ 的内容只应该是 SKILL.md 没写的细节,不要解释"这个 skill 是干啥的"。

坑 4:把 scripts/ 写成 "pseudo-code"

skill 的脚本是要执行的 ,不是写给人读的伪代码。遇到过把 validate.py 写成注释比代码还多、最后不 runnable 的。

验证办法:python3 .claude/skills/my-skill/scripts/validate.py 能直接跑通才合格。

坑 5:paths 写成正则

  • paths: "\\.py$"
  • paths: "**/*.py"

paths 接收的是 glob,不是 regex。踩这坑的人意外多。

坑 6:混用 skills: 和 Skill 工具触发

Agent 里写了 skills: [git-log-reader](预加载),结果 command 里又写 Skill(skill: "git-log-reader") 想"再调一次"。会搞乱------agent 已经把 skill 内化为知识,不是一个可调用工具。

规则:同一个 skill,要么 preload 要么 direct,不要两条路都用


把工具放回柜子

Skill 的完整图景比 Command 大一个量级------它不是"另一个按钮",是"一个会被模型主动挑选、带着脚本资产、能做渐进式揭露的工具包"。

三个最该记住的点:

  • 文件夹不是文件 ------ SKILL.md 是索引页,其他文件按需读
  • description 是触发说明书,不是功能介绍 ------ 写给模型看
  • Gotchas 是 skill 的质量标尺 ------ 真踩过的坑比理论上的注意事项值钱 100 倍

顺着"按钮 → 工具"的类比,下一个该拆的就是"员工 "------Subagent。如果 Skill 是"一把等你来拿的工具",Subagent 就是"有独立人格、自己拿工具干活、带记忆的人"。下一篇把 Subagent 的 frontmatter 15+ 字段、memory 三种作用域、isolation 的几种模式摊开讲。


Footnotes

外部链接

相关推荐
一个大蜗牛1 小时前
Hermes Agent 保姆级安装流程
人工智能
speop1 小时前
TASK09 | Reasoning Kingdom | Transformer : 动态拓扑的注意力革命
人工智能·深度学习·transformer
ting94520001 小时前
WanVideo_Cofy:AI 驱动的开源专业级视频生成平台全解析
人工智能
Black蜡笔小新1 小时前
企业私有化AI部署方案DLTM企业级AI模型工作站:零代码私有化,企业AI训练服务器新选择
运维·服务器·人工智能
Xpower 171 小时前
OpenClaw Token 优化的技术方案与实践:OpenSpace 自进化 Skill 引擎
java·开发语言·人工智能
南宫萧幕1 小时前
基于最优控制理论的 HEV 能量管理:从物理建模到 VMD-PPO 强化学习环境构建
开发语言·人工智能·matlab·simulink·控制
LONGZETECH1 小时前
教育数字化转型|汽车专业仿真教学体系搭建实操指南(含避坑+案例+FAQ)
大数据·人工智能·物联网·自动驾驶·汽车·汽车仿真教学软件·汽车教学软件
jay神1 小时前
基于YOLO26的珍稀鸟类检测系统
人工智能·深度学习·yolo·目标检测·毕业设计
虎子_layor1 小时前
Headless Chrome 该退休了?Obscura 正在给 AI Agent 换浏览器底座
前端·人工智能·后端