深入理解 Claude Code 的 Skill 机制:可复用能力与上下文成本的平衡术

从一个矛盾说起

当你反复使用 Claude Code 处理工作,很快会遇到一个矛盾:

一方面,你希望 Claude 掌握越来越多的专业流程和领域知识------你们团队的 commit 规范、部署 checklist、某类文档的处理套路、某个数据库的表结构......知道得越多,它越好用。

另一方面,上下文窗口是有限且昂贵的 。如果把这些知识全塞进 CLAUDE.md(每次会话开始就整体加载的项目说明文件),那么无论这次对话用不用得上,你每一轮都在为这些内容付费。知识越多,固定开销越大,最终把上下文挤爆。

Skill 机制就是对这个矛盾的回答。 它的核心思想可以用一句话概括:

让 Claude "知道"自己拥有大量专业能力,但只在真正需要时才把对应的详细内容加载进来。

理解了这个核心矛盾,Skill 的所有设计------目录结构、description 的写法、脚本的组织方式------都会变得顺理成章。本文就从这个角度,把 Skill 讲透。


一、Skill 是什么

Skill 本质上是一个"按需加载的、可复用的指令包"------一个目录,里面装着 Claude 完成某类任务时要遵循的操作说明,以及可能用到的脚本、模板、参考文档。

它的最小形态只需要一个文件:

objectivec 复制代码
skill-name/
└── SKILL.md          (唯一必需的文件)

完整形态则可以打包各种辅助资源:

objectivec 复制代码
skill-name/
├── SKILL.md          (必需)
│   ├── YAML frontmatter   ------ 元数据,name、description 必填
│   └── Markdown 正文       ------ 具体操作指令
├── scripts/           (可选)------ 可执行代码
├── references/        (可选)------ 按需加载的参考文档
└── assets/            (可选)------ 直接用于产出物的文件

可以把一个 Skill 理解成给某个专业领域写的**"入职手册"**:它把"遇到这类任务该怎么一步步做"的流程性知识固化下来,让一个通用的 Claude 瞬间变成这个领域的专家。


二、核心设计原则:渐进式加载(Progressive Disclosure)

这是 Skill 的灵魂,必须先讲清楚,后面的结构设计才有意义。

Skill 采用三层加载模型,每一层的加载时机和成本完全不同:

层级 内容 加载时机 成本
第 1 层 name + description(元数据) 会话全程常驻 极低(约 100 词)
第 2 层 SKILL.md 正文 仅当 Skill 被触发时 中(建议 < 500 行)
第 3 层 references / scripts / assets Claude 判断需要时才按需读取 趋近于零(脚本甚至不用读进上下文就能执行)

这三层的分工是整个机制的精髓:

  • 第 1 层始终在线,是一份"能力目录"。它让 Claude 时刻知道"我有哪些技能可用",但只花极小的常驻成本。
  • 第 2 层只在触发时加载。用户的请求匹配到某个 Skill,它的正文才会被读进上下文。没触发的 Skill,正文一直躺在磁盘上,不花一分钱。
  • 第 3 层最省 。庞大的参考资料、几千行的工具脚本都放在这里,Claude 只在具体需要时才去读某一个文件;脚本更是可以直接执行而不必把源码读进上下文(后文详述)。

一个直观的成本对比

假设你有一份 50KB 的领域参考手册:

  • 写进 CLAUDE.md:每一轮对话都要多花约几万 token,哪怕这次根本没用到。
  • 做成 Skill :平时只有一句话的 description 常驻(几十 token 量级),只有当用户请求真正相关时,正文(可能仅 1000 token)才被加载,参考手册按需读取。

这就是 Skill 相比"把知识堆进 CLAUDE.md"的根本优势:把"固定开销"变成了"按需开销"


三、结构解剖:三个可选目录各司其职

scripts/references/assets/ 这三个目录最容易被混为一谈,但它们的职责界限其实非常清晰:

目录 存什么 判断标准 典型例子
scripts/ 可执行代码(Python / Bash 等) 同样的代码要被反复重写 ,或需要确定性可靠(不能靠模型每次现场推理) rotate_pdf.py(PDF 旋转,逻辑固定,没必要每次重写)
references/ 给 Claude 阅读的文档,按需加载进上下文 详细的领域知识、schema、API 文档、规范------内容多,但不是每次都用得上 api_docs.md(接口规格)、schema.md(表结构说明)
assets/ 直接用在产出物里的文件,不会被读进上下文 模板、图标、字体、样板代码------是被复制/填充,而不是被阅读理解的 template.pptx(PPT 模板)、logo.png、前端脚手架目录

一句话记住它们的区别:

scripts/ 是"帮你干活的手",references/ 是"给你看的书",assets/ 是"要塞进成品里的原料"。

这个区分背后,正是第二部分讲的渐进式加载:references 会被读进上下文(消耗 token),而 scripts 通常是被执行、assets 是被搬运------两者几乎不占上下文。

按领域组织的进阶模式

当一个 Skill 需要覆盖多个变体时,推荐让 SKILL.md 只做"路由",把细节拆进 references/

markdown 复制代码
cloud-deploy/
├── SKILL.md          (通用流程 + 判断该用哪个 reference)
└── references/
    ├── aws.md
    ├── gcp.md
    └── azure.md

这样 Claude 只会读到当前场景对应的那一个 reference 文件,而不会把三个云平台的内容全部塞进上下文。


四、SKILL.md 内部:Frontmatter 与正文的写法

4.1 Frontmatter:为什么 description 要用第三人称

SKILL.md 开头是 YAML frontmatter,严格必填的只有 namedescription 两个字段。其中 description 是整个机制里最关键的一行,它的写法有明确规范。

先看对比:

yaml 复制代码
# ❌ 不推荐
description: Use this skill when you want to create X...

# ✅ 推荐
description: This skill should be used when the user asks to "create X", "configure Y"...

为什么必须用第三人称? 这不是文风洁癖,背后有实际的工程理由。

关键在于:description 的作用不是"下达指令",而是"提供一个可比对的触发条件"。

所有 Skill 的 description 会汇成一份"能力目录"常驻在上下文里。当用户说话时,Claude 要做的是拿用户的原话,去和目录里每一条的触发条件做语义比对,看哪个最匹配。

在这个语境下:

  • 写成 "Use this skill when you want to..."(第二人称祈使句)------这个 "you" 指向模糊(是在命令 Claude,还是在转述用户?),而且很容易滑向"描述功能"而非"描述触发条件"。
  • 写成 "This skill should be used when the user asks to '...'" (第三人称客观陈述)------它强迫作者写出"用户会说什么",也就是列举具体的触发短语。而这恰恰是匹配机制最需要的信号。

换句话说,第三人称是一种"倒逼":它逼你把触发条件写成客观事实陈述,自然而然就会去列举用户的具体原话。对比一下就很清楚:

yaml 复制代码
# ❌ 差:模糊、无触发短语
description: Provides guidance for working with hooks.

# ✅ 好:第三人称、列出具体触发短语
description: This skill should be used when the user asks to "create a hook",
  "add a PreToolUse hook", "validate tool use", or mentions hook events
  (PreToolUse, PostToolUse, Stop).

还有一个实用技巧:Claude 有时会"欠触发"(明明该用某个 Skill 却没用)。为了对冲这一点,可以把 description 写得主动一些------不只描述功能,还要点明"即使用户没明说某个关键词,只要涉及某类场景就应该触发"。

4.2 正文:为什么要用祈使句而非第二人称

frontmatter 之后的 Markdown 正文,规范是用祈使句 / 动词开头的指令语气

csharp 复制代码
❌ 第二人称:You should start by reading the configuration file.
✅ 祈使语气:Start by reading the configuration file.

原因和 4.1 一脉相承,但侧重点不同:正文是写给"另一个 Claude 实例去执行的操作手册",不是给人看的说明书。祈使句 "Validate the input" 直接下达动作,比 "You should validate..." 更干脆、更省 token、也不会有代词指向的歧义。

小结这两条规则的共性:无论是 description 还是正文,都要避免用 "you" 制造指向不清的歧义 ------description 要客观陈述触发条件,正文要直接下达操作指令。

正文通常回答三个问题:这个 Skill 干什么什么时候用 (主要放在 description)、具体怎么用 。其中"怎么用"必须明确引用 所有的 scripts / references / assets,否则 Claude 根本不知道这些资源存在。常见的写法是在正文末尾放一段资源索引:

markdown 复制代码
## Additional Resources

### Reference Files
- `references/patterns.md` ------ 常见模式
- `references/advanced.md` ------ 高级用法

### Scripts
- `scripts/validate.sh` ------ 校验工具

五、Skill 是怎么被触发的

触发方式有三种,但机制的核心是同一个:

  1. 自动触发(Claude 判断) :这不是有独立的分类器或规则引擎,而是 Claude(LLM 本身)在做语义匹配 ------它像决定"要不要调用某个工具"一样,拿用户的话去和"能力目录"里每条 description 比对,匹配上就发起一次 Skill 调用,这时对应的正文才被加载进来。这正是 description 质量如此重要的原因。
  2. 用户手动触发 :直接输入 /skill-name
  3. Claude 主动触发:在工具调用循环里,Claude 判断相关就调用(可通过权限规则精细控制哪些 Skill 允许/禁止)。

有一个值得知道的细节:Claude 只会为"它自己不容易直接搞定"的任务去查阅 Skill。 像"读一下这个文件"这种一步到位的简单请求,即使某个 Skill 的描述完全匹配,也可能不会触发------因为用基础工具直接做更快。只有复杂的、多步骤的、专业化的任务,才会稳定地触发匹配的 Skill。


六、Skill 在生态中的位置:与 MCP / Subagent / Workflow 的关系

这四个概念常被放在一起比较,但它们其实不是"竞品",而是四个不同的层,可以叠加使用。用一个团队协作的比喻:

概念 类比 解决什么
MCP 给电脑装新硬件 / 新 App 让 Claude 拥有新能力------连上外部系统(代码托管平台、数据库、设计工具等)
Skill 一本操作手册 / SOP 把"遇到某类任务该怎么做"的流程与经验固化下来,复用已有能力
Subagent 一个独立员工,有自己的工位和记忆 把一件事隔离出去做,避免过程中的海量中间信息(搜索结果、文件内容)塞满主对话
Workflow 项目经理的调度脚本 按固定流程(并行 / 流水线 / 分阶段)指挥一群独立员工协作完成大规模任务

它们如何协同?以"审查一个大型改动里的所有安全问题"为例:

  1. MCP 提供"连上代码托管平台、拿到改动内容"这个底层能力------没有它,Claude 根本碰不到数据;
  2. Skill (如一个 security-review 技能)里写着"审查安全问题时,按 OWASP Top 10 逐项检查、用什么模式去搜索危险代码"------这是把最佳实践固化成可复用的步骤,而非每次现场发明;
  3. 如果这个 Skill 配置了在独立 Subagent 中运行,审查过程中翻阅的几十个文件、几百行搜索结果都留在 Subagent 自己的上下文里,不会拖垮主对话;
  4. 如果改动涉及大量文件,还可以用 Workflow 并行派发多个 Subagent 各查一部分,最后统一汇总------这就是"项目经理指挥一群员工"。

一句话记忆:

MCP = 能力从哪来;Skill = 做这件事的经验/流程;Subagent = 在哪做(隔离上下文);Workflow = 一群 Subagent 怎么协作。


七、辨析:Skill 里的 script 和 tool 有什么区别?

这是一个特别容易混淆的点,也是理解 Skill 执行机制的关键。先说结论:

script 不是 tool 的"同类替代品",而是"通过某个 tool 来运行的东西"。二者根本不在同一层。

7.1 它们分别是什么

  • tool(工具)注册给模型的一个函数接口:有名字、有参数 schema,模型可以直接发出结构化调用,由执行层去跑并返回结果。读文件、执行命令、抓取网页等都是 tool;MCP server 提供的也是 tool。

  • script(脚本) 只是磁盘上的一个代码文件 。它没有被注册到任何地方,模型不能"直接调用"它,只能借助执行命令的那个 tool 去运行它

bash 复制代码
模型  →  发起"执行命令"的工具调用  →  运行 python scripts/xxx.py  →  拿到 stdout

也就是说,script 是嵌套在一次 tool 调用内部的,它跑在 tool 之上,而非与 tool 平级。

一个类比:tool 是模型的"手"(能直接使的原语),script 是工具箱里的一个"零件/刀头"------模型得先用手把它拿起来用。

7.2 逐维度对比

维度 script(脚本) tool(含 MCP tool)
本质 磁盘上的代码文件 注册给模型的函数接口,有名字 + 参数 schema
模型怎么用 通过"执行命令"的工具去运行 直接发结构化调用,是"一等公民"动作
上下文成本 平时零成本,用到时才在 SKILL.md 里被提及 定义常驻上下文,每轮对话都占 token
模型如何知道它存在 SKILL.md 正文明确指出来 天生就在工具清单里,随时知道能调
输入/输出 命令行参数进、stdout 出------非结构化文本,需自行解析 schema 校验的结构化输入输出,有类型保障
分发/安装 跟着 Skill 目录走,自包含,无需安装、无需起服务 MCP 需要配置、运行服务器进程,可能要鉴权
状态/生命周期 一次性进程,跑完即退,无状态 MCP 是长驻进程,可保持连接、鉴权会话、状态

一个关键机制值得强调:script 通常不会被"读"进上下文,而是被"执行"。 references 里的文件要先读进上下文 Claude 才能看懂(实打实占 token),而 scripts 里的文件是被直接调用,进入上下文的只有那条执行命令和它的输出结果------脚本内部几百行代码完全不占 token。这就是为什么第三层加载被称为"理论上无限"。(例外:当脚本报错、需要打补丁或做环境适配时,Claude 才会退回去用读取/编辑工具打开源码,这时它才真正进入上下文。)

7.3 那能不能用 tool 替代 script?

可以,同一段逻辑完全能包装成一个 MCP tool。但要不要这么做,取决于场景:

  • 用 script 更合适 ------当逻辑是"某个 Skill 专属、偶发使用、自包含、确定性"的。 例:旋转 PDF 。就是个一次性的确定性转换,打包成脚本放进 Skill 里最合适。硬做成 MCP tool 反而要跑一个服务器进程、注册一个永久占用上下文 token 的工具定义,只为一个偶尔用一次的功能,性价比极低。

  • 用 tool / MCP 更合适 ------当它是"跨场景通用、需常驻可用、需保持连接/状态、需结构化接口"的能力。 例:查询数据库。需要长期保持连接和鉴权、被很多不同任务反复用到、还希望有类型化的参数和返回------这就该做成 MCP tool。

决策口诀:

偶发的、Skill 内部的、"跑一下算个结果"的活 → script (成本几乎为零,还能随 Skill 一起分发); 常驻的、跨场景的、需要状态/连接/结构化接口的能力 → tool / MCP(值得付"常驻上下文"这个固定税)。

7.4 一个把两者连起来的细节

Skill 的 frontmatter 里有个 allowed-tools 字段,正好体现了这层依赖关系。如果一个 Skill 要靠脚本干活,通常会预授权执行命令的工具,免得每次跑脚本都弹权限确认:

yaml 复制代码
---
name: pdf-tools
description: This skill should be used when the user asks to rotate, merge, or split PDF files...
allowed-tools: Bash(python *)
---

这句话的意思是:"这个 Skill 激活时,允许 Claude 无需再确认就用命令行去跑 python 脚本"。script 要跑,得先放行它所依赖的那个 tool ------这再次印证了核心关系:script 永远站在某个 tool 的肩膀上运行,不是 tool 的替代。


八、最佳实践与避坑清单

综合前面的原理,一个高质量 Skill 的经验可以归纳为:

✅ 应该做:

  • description 用第三人称,并列出具体触发短语("create X"、"configure Y"),这是自动匹配的唯一依据;写得笼统就永远不会被触发。
  • SKILL.md 正文保持精简 (目标 1500--2000 词,硬上限约 500 行),把详细内容拆到 references/
  • 正文用祈使句,把它当作"写给另一个 Claude 的操作手册"。
  • 复杂、重复、需确定性的逻辑打包成脚本 放进 scripts/,而不是写成大段 prompt 让模型每次现场推理。
  • 在正文里明确引用所有资源,否则 Claude 不知道它们存在。
  • 超过 300 行的 reference 文件加个目录,方便快速定位。

❌ 应该避免:

  • description 模糊、无触发短语、人称混乱。
  • 把所有内容塞进一个巨大的 SKILL.md(几千词全在一个文件),导致每次触发都加载一大堆平时用不到的内容。
  • 正文里用第二人称 "You should..."。
  • references / scripts 里放了文件,正文却只字未提。

⚠️ 几个已知局限:

  • Skill 内容一旦加载进上下文就固定了 ,会话中途修改 SKILL.md 不会实时生效,需重新触发或开新会话。
  • Skill 太多时,description 可能被自动截断以适配上下文预算。
  • 上下文自动压缩时,较旧的、不常用的 Skill 内容可能被丢弃,需要时得重新触发。

结语:Skill 的哲学

回到开头那个矛盾------能力广度 vs 上下文成本

Skill 给出的答案,本质上是一次巧妙的"分层":把一个能力拆成"什么该常驻 (一句话的触发描述)、什么该按需加载 (详细的操作正文和参考资料)、什么根本不该进上下文 (只用来执行或产出的脚本与素材)"三层,分别对应 descriptionSKILL.md 正文scripts / references / assets

理解了这一点,你就能超越"照着模板填空",真正判断出:一段知识该放哪一层?一个功能该做成 Skill 里的脚本,还是独立的 MCP 工具?一个流程该内联执行,还是隔离到 Subagent? 这些判断力,才是用好 Skill 乃至整个 Claude Code 能力体系的关键。

Skill 不是最重的抽象(那是 Subagent 和 Workflow),也不是最轻的(那是一次性的 prompt),它是中间那一层------比一次性提示更结构化、可复用,又比独立 Agent 更轻量。用对了地方,它能把你和团队反复打磨的专业经验,变成 Claude 随取随用、却几乎不占成本的"肌肉记忆"。

相关推荐
亦暖筑序1 小时前
AgentScope-Java 入门:保存评审状态并生成 Markdown 报告
java·人工智能·后端
Csvn1 小时前
📊 SQL 入门 Day 4:聚合函数 — COUNT / SUM / AVG / MIN / MAX
后端·sql
用户298698530142 小时前
Java 创建 CSV 文件的三种实用方法:从零构建、数组写入与 Excel 转换
java·后端·excel
玉宇夕落2 小时前
Cheerio虚拟DOM原理
后端
geovindu2 小时前
go: Recursion Algorithm
开发语言·后端·算法·golang·递归算法
用户2930750976692 小时前
深入理解 RAG 文档切割:从知识库到向量数据库的关键一步
后端
geovindu2 小时前
CSharp: Composite Pattern
开发语言·后端·c#·组合模式·结构型模式
宇图SHARE2 小时前
别再用 Python 写 Agent 前端了!Vue3 + NestJS + TypeScript 全栈方案,开发效率翻倍
前端·后端
吃饱了得干活2 小时前
Spring Cloud Gateway限流:从Redis到Sentinel的三种方案
后端·spring cloud