深入理解 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 随取随用、却几乎不占成本的"肌肉记忆"。

相关推荐
程序员cxuan3 小时前
速度太快了!本地可以跑 DeepSeek-V4-Flash 了
人工智能·后端·程序员
阿祖zu4 小时前
芝士就是力量!开源私有化部署与 GitHub 双向同步的个人知识笔记 App
前端·后端·ios
不才不才不不才4 小时前
Spring 源码系列(16): doDispatch 全流程——一次请求的主干链路
java·后端·spring
IT_陈寒4 小时前
SpringBoot自动配置失效?这个隐藏配置坑了我一整晚
前端·人工智能·后端
搜狐技术产品小编20234 小时前
告别“黑盒”与误判:如何用“多智能体对抗辩论”重构内容安全审核系统
后端·多agent
DantyWei5 小时前
controller注册及调用时机
后端
edwarddamon5 小时前
Spring Cloud 配置热更新与 Bean 代理机制梳理
java·后端
码事漫谈5 小时前
我用 Seed Evolving 做了个 AI 小说写作工具
后端
Raas1006 小时前
MAIGateway,魔芋企业级AI网关的FinAPI成本竞争力设计
java·后端·网关·api网关·魔芋ai·finapi·mai gateway
计算机魔术师6 小时前
传统基础架构 - 微服务
大数据·后端·微服务·架构·开发工具·编程语言