claudecode学习 第 10 章 · Skills

4 阅读10分钟

目标:讲清 Claude Code 的 Skills 系统——三种来源、渐进式加载(三级)、触发机制(自动///Skill 工具)、inline 与 fork 两种执行模式、写作规范、ProposeSkills 反向提议、安全与用量追踪。这是插件体系中最核心的扩展机制。 受众:专业程序员。本机版本 2.1.220


10.1 Skills 不是什么

在讲 Skills 是什么之前,先排除三个容易混淆的概念:

概念是什么Skills 不是它
Slash Command用户手动敲 /xxx 触发的指令Skill 可以被模型自动触发,不需要你敲 /
Subagent独立上下文、独立运行的后台 agentSkill 可以inline 执行,不一定要 fork
CLAUDE.md启动时全量注入的静态指令Skill 是按需加载的——正文只在触发时才进上下文

心智模型:

Skill = 给 Claude 的"入职指南"。 它把一个通用 agent 变成某个领域的专家,装上它自身不具备的程序性知识。

从二进制看 Skill 如何被调用:

model-invoked skills are `"name":"Skill"` with the skill name in `input.skill`

Skill(大写 S)是和 Bash、Read、Write 并列的内置工具。模型在 Agent 循环中判断"这个任务需要某个 skill",就调 Skill 工具加载。


10.2 三种来源

Skills 按存放位置分三种作用域:

Personal:    ~/.claude/skills/<name>/SKILL.md    ← 跟你走,所有项目通用
Project:     ./.claude/skills/<name>/SKILL.md    ← 跟项目走,可提交 git
Plugin:      plugin-name/skills/<name>/SKILL.md  ← 跟插件走,安装即生效

二进制确认:

- **Personal** (`~/.claude/skills/<name>/SKILL.md`) — follows you across all repos
- **This repo** (`.claude/skills/<name>/SKILL.md`) — for workflows specific to this project

自动发现:runtime 扫描这些目录,找到含 SKILL.md 的子目录就注册。和 CLAUDE.md 一样——路径即契约,不需要配置文件声明。

/skills 命令列出所有可用 skill。已注册但从未被调用的 skill 会有提示:

loaded but never invoked. Each one adds to the system prompt every turn. Disable in /skills, or remove from .claude/skills.


10.3 解剖一个 Skill

skill-name/
├── SKILL.md          ← 必需。YAML frontmatter + Markdown 正文
├── scripts/          ← 可执行代码(Python/Bash),可直接运行而不进上下文
├── references/       ← 参考文档,Claude 按需用 Read 读取
├── assets/           ← 产出物模板(HTML、图片、字体),不进上下文,被复制使用
└── examples/         ← 可运行的完整示例,供用户复制改编

SKILL.md 的 frontmatter

只有两个必填字段:

---
name: frontend-design
description: Guidance for distinctive, intentional visual design when building new UI...
---

没有 allowed-tools、没有 model——这些是 slash command 的前置 matter,Skill 不需要。

四个可选子目录的语义

目录内容何时用是否进上下文
scripts/可执行代码同一段逻辑被反复重写,或需要确定性可靠执行否(可直接执行)
references/参考文档SKILL.md 放不下的详细内容(schema、API 文档、策略)是(按需用 Read 读)
assets/模板、图片、字体产出物需要的模板文件和静态资源否(被复制使用)
examples/可运行示例完整的、可复制改编的示例是(按需读)

10.4 渐进式加载——Skills 设计的核心

这是 Skills 最重要的设计原则。三级加载,按需升级:

Level 1: Metadata(name + description)
         ├─ 始终在 context 中(~100 词/个)
         ├─ 每个已注册 skill 一行,列在 system prompt 里
         └─ 开销极低——注册 20 个也才 ~2,000 词

Level 2: SKILL.md 正文
         ├─ 触发时才加载(推荐 1,500~2,000 词,上限 < 5,000 词)
         └─ 注入当前轮次的 context

Level 3: Bundled resources(references/、examples/)
         ├─ Claude 自己判断何时需要,用 Read 工具读
         └─ scripts/ 甚至可以不进上下文,直接用 Bash 执行

二进制中一句话点睛:

(dash = not in the current listing, costs nothing; full SKILL.md loads only when it runs)

dash = 没加载,不花钱。 对比 CLAUDE.md:一个 500 行的 CLAUDE.md 每次对话都全量占着上下文。Skill 把元数据和正文分离,信息密度高但常驻开销低。

什么放在 SKILL.md vs references/

放 SKILL.md(正文)放 references/(按需加载)
核心概念和概述详细模式和实践
基本流程和工作流完整 API 文档
快速参考表迁移指南
指向 references/examples/scripts 的指针边缘情况和故障排除
最常见的用例大量示例和走查

原则:如果信息 > 10,000 词,在 SKILL.md 里写 grep 搜索模式,让 Claude 知道如何在 references/ 中找到具体内容。


10.5 触发机制

三种触发路径:

路径一:自动触发(description 匹配)

模型读 system prompt 中每个 skill 的 description,自己判断当前任务是否匹配。Description 的质量直接决定 skill 能否被正确触发。

# ✅ 正确:第三人称 + 引号触发短语
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.

# ❌ 错误
description: Use this skill when working with hooks.       # 不是第三人称
description: Load when user needs hook help.               # 没有触发短语
description: Provides hook guidance.                       # 太模糊

路径二:Slash 命令

/frontend-design

/ 加 skill name,和 slash command 完全一样的调用体验。

二进制描述:

Packaged instructions Claude invokes automatically when a task matches, or that you trigger with a slash command (e.g. /frontend-design, /commit-push-pr).

路径三:Skill 工具显式调用

模型在 Agent 循环中主动调 Skill 工具:

{"type": "tool_use", "name": "Skill", "input": {"skill": "hook-development", "args": "[hooks-only] Constructing a PostToolUse hook..."}}

Skill 工具的 input schema(从二进制还原):

skill: string   ← skill name,来自 available-skills 列表。不要猜名字。
args:  string   ← 可选参数,传递给 skill

10.6 两种执行模式:Inline vs Fork

Skill 工具内部有两条完全不同的执行路径(从二进制混淆代码还原):

Inline(内联执行)

  • Skill 正文直接注入当前对话的 messages
  • 后续指令在当前上下文执行
  • 适合:需要用户中途介入、和用户交互的任务
  • 工具返回 {status: "inline", success: true}

Fork(分支执行)

  • 启动一个 subagent,给它独立的上下文
  • Skill 正文注入子 agent 的 system prompt
  • 主会话收到通知:Running in the background as @agent-name
  • 适合:自包含、不需要中途介入的任务
  • 工具返回 {status: "forked", agentId: "...", background: true}

二进制中的 fork 启动日志:

SkillTool executing forked skill {name} with agent {agentType}

防递归

如果一个 skill 已经在 fork 上下文里执行,模型不能再调 Skill 工具去 fork 同一个 skill:

Skill {name} is already executing in this forked context — you are the subagent
running it. Execute the instructions in the skill body directly instead of
re-invoking the Skill tool.

Re-invocation 去重

如果同一个 skill 已经被加载且指令未变,再次调用不会重复注入:

Skill /{name} is already loaded above; instructions unchanged.
SkillTool eliding byte-identical re-invocation of skill {name}

10.7 Fork 的来源追踪(Provenance)

Fork 出来的子 agent 携带来源标记,用于安全追踪:

.forked-skill.json           ← skill 的 fork 作用域记录
.forked-skill.marker.json    ← 来源标记见证

恢复会话时的安全校验(二进制中多条拒绝逻辑):

  • "carries a forked-skill provenance marker but its scoping record is missing; refusing to resume it without the skill's permission scoping."
  • "declares forked-skill scoping record that does not match its task record; refusing to resume it."
  • "has a forked-skill scoping record with no matching provenance-marker witness; refusing to resume it on a cold path without a corroborated fork identity."
  • "has a malformed forked-skill scoping record; refusing to resume it without the skill's permission scoping."

这些保护确保 fork 链的完整性——你不会在不知情的情况下恢复一个来源不明的子 agent。


10.8 消息归属

Skill 产生的每条消息都标记来源。二进制中消息结构携带:

attributionSkill    ← 哪条消息是哪个 skill 产生的
attributionAgent    ← 哪个 agent
attributionPlugin   ← 哪个插件
attributionMcpServer ← 哪个 MCP 服务器
attributionMcpTool  ← 哪个 MCP 工具

这让用量统计和调试都能追溯到具体 skill。


10.9 写作规范

从 skill-development/SKILL.md 中提炼的六条核心规则:

1. Description:第三人称 + 触发短语

# ✅
description: This skill should be used when the user asks to "create a hook", ...

# ❌
description: Use this skill when you want to create a hook...
description: Load this skill when user asks...
description: Provides hook guidance.

2. 正文:祈使/不定式(不是第二人称)

# ✅
Parse the frontmatter using sed.
Validate values before use.
To create a hook, define the event type.

# ❌
You should parse the frontmatter...
You can use grep to search...
Claude should extract fields...

原因:SKILL.md 是给 Claude 的指令,不是给用户看的。第二人称增加理解开销。

3. 正文长度:严格控制

推荐:1,500~2,000 词
上限:< 5,000 词
超过 → 拆到 references/

插件开发 skill 自身的 SKILL.md 是 1,651 词,agent-development 是 1,438 词——典范。

4. 指向 references/ 的指针

正文中显式声明 references 的存在:

## Additional Resources

### Reference Files
- **`references/patterns.md`** — Detailed patterns
- **`references/advanced.md`** — Advanced techniques

### Examples
- **`examples/script.sh`** — Working example

不声明 = Claude 不知道 references/ 存在 = 永远不会被读。

5. 信息不重复

同一信息不应该同时出现在 SKILL.md 和 references/ 中。详细内容优先放 references/,正文只保留核心流程。这避免了"正文已经够用,references/ 永远不会被读"的问题。

6. 验证清单

skill-development/SKILL.md 的完整 checklist:

  • 目录结构正确(SKILL.md 在 skills/<name>/ 下)
  • Frontmatter 含 namedescription
  • Description 第三人称 + 引号触发短语
  • 正文祈使语气,非第二人称
  • 正文控制在 1,500~2,000 词
  • 详细内容在 references/ 中
  • 正文声明了 references/ 的路径
  • 示例完整且可运行
  • 脚本可执行且有文档

10.10 ProposeSkills:agent 反向提议创建 Skill

这是 Skills 体系最巧妙的设计——Claude 在工作中发现值得封装成 skill 的重复模式,主动向用户提议创建。

sdk-tools.d.ts 中的类型定义:

interface ProposeSkillsInput {
  proposals: [{
    name: string;           // kebab-case skill slug
    kind: "new" | "improvement";
    target?: string;        // 改进已有 skill 时指定
    description: string;    // 一行摘要,显示在提议卡片上
    evidence?: string[];    // memory 文件路径,记录观察来源
    skillMd: string;        // 完整的 SKILL.md 草稿(frontmatter + 正文)
  }];
  // 一次最多 3 个提案
}

这和 memory 系统的 push 模式一脉相承(第 7 章):agent 不被动等指令,还主动观察工作模式,把值得封装的流程提请用户确认。


10.11 安全与用量

安全模式

(custom skills are disabled in safe mode)

--safe-mode 下所有自定义 skill 不可用。

Fork 来源链

10.7 节详述的 provenance marker 机制——子 agent 的完整 fork 链必须可验证,否则拒绝恢复。

用量追踪

skillUsage: {
  name → { usageCount, lastUsedAt }
}

usageCount = LIFETIME total since install(永不清零)
lastUsedAt = 只在实际 dispatch 时写入
7d tokens = skill 在过去 7 天的 token 消耗

遥测事件:tengu_skill_tool_invocation,携带 command_nameexecution_context(inline/fork)、invocation_triggerquery_depth 等字段。

/plugin stats 显示 skill 使用数据和上下文成本。


10.12 Skills vs Commands vs Agents 对比

维度SkillSlash CommandSubagent
触发方式自动 / / / Skill 工具用户手动 /Task 工具
加载方式渐进式(三级)调用时一次性注入独立上下文
文件结构目录 + SKILL.md单个 .md 文件单个 .md 文件
可附带资源scripts/references/assets/examples
谁写人 / agent(ProposeSkills)
核心 frontmattername + descriptiondescription + allowed-tools + model + argument-hintdescription + capabilities
执行模式inline 或 forkinline独立进程
是否可自动触发部分(agent 匹配 task)

什么时候用哪个

用户需要手动触发、传参数 → Slash Command
需要模型自动识别场景并介入 → Skill  
需要独立上下文、后台执行 → Subagent
需要在 Skill 运行前让用户确认参数 → Slash Command 包裹 Skill

10.13 本章核心带走

  1. Skill 是渐进式加载的领域工作流。 不是 command(无法自动触发),不是 subagent(独立上下文),不是 CLAUDE.md(全量注入)。metadata 常驻、正文按需、资源可选。

  2. 三级渐进加载:Level 1 metadata 常驻(~100 词),Level 2 SKILL.md 触发时加载(<5k 词),Level 3 resources 按需读取。信息密度高但上下文开销低。dash = 不花钱。

  3. 三种来源 + 自动发现:Personal (~/.claude/skills/)、Project (.claude/skills/)、Plugin (skills/)。路径即契约——放对位置就自动注册。

  4. 两种执行模式:inline(注入当前会话,适合需用户交互的任务)和 fork(独立 subagent + provenance 追踪,适合自包含任务)。

  5. Description 是 Skill 的接口。 第三人称 + 引号触发短语 = 决定模型何时识别并加载。写得不好 Skill 永远不会被触发。

  6. 正文写作规范严格:祈使语气(非第二人称)、1,500~2,000 词、超量内容拆到 references/、显式声明 references 路径。

  7. ProposeSkills 让 agent 反向提议创建 skill——和 memory 系统一样,agent 在工作中主动观察、主动建议。

  8. Fork 安全链完整:provenance marker → scoping record → 恢复时验证完整性,缺一环就拒绝。