荣耀文档
80.56M · 2026-04-14
Skill 是 Claude Code 中 懒加载的 Agent 行动说明文件。它本质上是一段提示词增强,通过用户调用(/skill-name)或 LLM 主动调用(SkillTool)触发,在运行时注入到 Agent 的上下文中,指导 Agent 执行特定任务。
核心特征:
与 Tool 懒加载的对比:
ToolSearch 动态加载工具 schema,用于执行操作Claude Code 的系统提示词有 token 限制,无法在初始阶段加载所有能力。Skill 通过 按需加载 解决这个问题:
启动时:
系统提示词: [核心工具] + [SkillTool 的工具定义]
↓
Token 占用:~50k tokens
用户调用 /skill-name:
系统提示词: [核心工具] + [SkillTool] + [skill-name 的 Markdown 内容]
↓
Token 占用:~50k + skill-name 内容
关键机制: Skill 的完整内容(Markdown Body)不在初始提示词中,仅在触发时注入。
Skill 不是工具(Tool),而是 指导 Agent 如何行动的说明文档:
| 概念 | 作用 | 示例 |
|---|---|---|
| Tool | 执行特定操作 | Read(file_path) → 返回文件内容 |
| Skill | 改变 Agent 行为模式 | /tech-blog-writer → Agent 按照技术博客写作规范工作 |
类比:
read_file(path))你现在是一位技术博客专家...)Skill 有两种触发方式:
$ claude "/commit"
执行流程:
/commitcommit 的 SkillSKILL.md 文件User: 写一篇关于 Rust 所有权的技术博客
Agent: (内部推理)
- 检测到 tech-blog-writer Skill
- when_to_use: "当用户需要撰写技术博客时"
- 匹配当前任务 → 调用
[调用 SkillTool(skill: "tech-blog-writer", args: "Rust 所有权")]
区别:
when_to_use 字段判断一个完整的 Skill 目录可能包含:
~/.claude/skills/example-skill/
├── SKILL.md ← 必需:主文件(Frontmatter + Markdown)
├── helper.py ← 可选:辅助脚本
├── config.json ← 可选:配置文件
└── templates/ ← 可选:模板目录
└── template.md
核心文件: SKILL.md 是唯一必需文件,其他均为辅助资源。
---
name: example-skill
description: 示例 Skill
when_to_use: 当用户需要示例功能时
execution_context: fork
allowed_tools:
- Read
- Bash
shell:
command: python
args: ["helper.py"]
---
# Example Skill
这是 Skill 的主体内容,当 Skill 被调用时,这段文本会被 Agent 看到。
## 使用方法
...
## 示例
...
两部分:
YAML Frontmatter(--- 包裹)
Markdown Body
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
name | string | Skill 标识符(命令名称) | |
description | string | 简短描述(显示在 SkillTool 中) | |
when_to_use | string | - | 使用时机说明(指导 LLM 何时调用) |
| 字段 | 类型 | 说明 |
|---|---|---|
execution_context | 'fork' | 设为 fork 时使用子 Agent 执行 |
allowed_tools | string[] | Fork 模式下的工具白名单 |
model | 'sonnet' | 'opus' | 'haiku' | 指定使用的模型 |
| 字段 | 类型 | 说明 |
|---|---|---|
shell | object | 脚本执行配置(见下文) |
hooks | object | 钩子配置(事件触发) |
| 字段 | 类型 | 说明 |
|---|---|---|
paths | string | string[] | 路径模式,匹配时才激活此 Skill |
Skill 可以包含可执行脚本,用于:
支持的脚本语言: Python、JavaScript、Shell、任何可执行文件
Markdown 内容是 Skill 的核心,它通过 注入 Agent 上下文 生效。
机制: 将 Markdown Body 直接添加到对话历史
// src/tools/SkillTool/SkillTool.ts (简化)
async callInlineSkill(skill: Command, args?: string) {
// 1. 读取 SKILL.md
const content = await fs.readFile(skill.filePath, 'utf-8')
// 2. 提取 Markdown Body(去除 Frontmatter)
const body = extractMarkdownBody(content)
// 3. 注入到对话
this.messages.push({
role: 'user',
content: `<command-name>/${skill.name}</command-name>nn${body}nn${args || ''}`
})
// 4. Agent 在下一轮回复时会看到这段内容
}
流程图:
Before Skill After /example-skill
┌─────────────────┐ ┌─────────────────┐
│ User: 帮我写代码 │ │ User: 帮我写代码 │
├─────────────────┤ ├─────────────────┤
│ Agent: 好的... │ │ Agent: 好的... │
└─────────────────┘ ├─────────────────┤
│ User: /example-skill│
│ │
│ # Example Skill │
│ 你现在是代码专家... │
│ ... │
└─────────────────┘
→ Agent 下一轮回复会基于新增的指令
特点:
机制: 启动独立的子 Agent,Markdown 作为其系统提示词
// src/tools/SkillTool/SkillTool.ts (简化)
async callForkSkill(skill: Command, args?: string) {
// 1. 读取 Skill 内容
const body = extractMarkdownBody(await fs.readFile(skill.filePath))
// 2. 构建子 Agent 的消息
const forkMessages = [
{
role: 'user',
content: `${body}nn${args || ''}`
}
]
// 3. 启动子 Agent(独立 API 调用)
const result = await this.apiClient.createMessage({
model: skill.model || this.defaultModel,
messages: forkMessages,
tools: this.filterTools(skill.allowedTools), // 仅限白名单工具
max_tokens: 4096
})
// 4. 返回子 Agent 的输出
return result.content[0].text
}
流程图:
Main Agent Fork Agent
┌─────────────────┐
│ User: 分析代码 │
├─────────────────┤
│ Agent: 调用Skill │
│ Skill(name: │
│ "analyzer") │───────────────────→┌─────────────────┐
│ │ │ System: │
│ │ │ # Analyzer │
│ │ │ 你是代码分析专家 │
│ │ │ ... │
│ │ ├─────────────────┤
│ │ │ (执行分析任务) │
│ │ │ - Read files │
│ │ │ - Grep patterns │
│ │ └─────────────────┘
│ │←───────────────────返回分析结果
├─────────────────┤
│ 分析结果: ... │
└─────────────────┘
特点:
allowed_tools 提升安全性| 维度 | Inline | Fork |
|---|---|---|
| 注入位置 | 主对话历史 | 子 Agent 独立上下文 |
| API 调用 | 0 次(复用主对话) | 1 次(独立调用) |
| 历史可见 | 看到完整对话 | 仅看到 Skill 内容 |
| 工具访问 | 继承所有工具 | 仅限 allowed_tools |
| Token 计费 | 算入主对话 | 独立计费 |
脚本文件通过三种方式生效:
shell 字段直接执行配置:
---
name: data-processor
shell:
command: python
args: ["process.py", "--input", "data.json"]
timeout: 30000
---
执行流程:
// src/tools/SkillTool/SkillTool.ts
if (skill.shell) {
// 在 Skill 目录中执行脚本
const result = await exec({
command: skill.shell.command,
args: skill.shell.args,
cwd: path.dirname(skill.filePath), // Skill 所在目录
timeout: skill.shell.timeout || 10000
})
// 脚本输出作为 Skill 的结果
return result.stdout
}
特点:
hooks 字段响应事件配置:
---
name: auto-format
hooks:
pre-commit:
command: python
args: ["format.py"]
---
执行时机:
pre-commit:提交前自动运行post-edit:文件编辑后运行on-error:遇到错误时运行详见 Claude Code 的 hooks 系统文档。
SKILL.md 内容:
---
name: code-generator
execution_context: fork
allowed_tools:
- Bash
- Write
---
# Code Generator
当用户请求生成代码时:
1. 使用以下命令生成代码:
```bash
python generator.py --template $TEMPLATE_NAME
**执行流程:**
1. Fork Agent 读取上述 Markdown
2. Agent 根据指令调用 `Bash` 工具
3. Bash 工具执行 `python generator.py ...`
4. Agent 获取输出并继续处理
**特点:**
- 脚本不是直接执行,而是通过 **Agent 的工具调用** 执行
- 需要 `allowed_tools` 包含 `Bash`
- 适合:需要 Agent 理解脚本输出并做后续处理的场景
#### 3.2.4 三种方式对比
| 方式 | 执行者 | 适用场景 | 配置 |
|------|--------|----------|------|
| **`shell` 字段** | 系统直接执行 | 纯数据处理、外部工具调用 | `shell: {command, args}` |
| **`hooks` 字段** | 事件触发执行 | 自动化任务(格式化、检查) | `hooks: {event: {command}}` |
| **Markdown 指令** | Agent 通过 Bash 工具执行 | 需要 Agent 理解输出的场景 | `allowed_tools: [Bash]` |
---
## 4. SkillTool:LLM 的主动调用
### 4.1 SkillTool 是什么
SkillTool 是一个 **Claude Code 工具**,暴露给 LLM 调用,用于动态加载 Skill。
**工具定义:**
```typescript
{
name: "Skill",
description: `Execute a skill within the main conversation
Available skills:
- commit: Create a git commit with Claude's help
- review-pr: Review a pull request
- tech-blog-writer: 撰写技术博客文章 - 当用户请求撰写技术博客时使用
...`,
parameters: {
skill: { type: "string", description: "The skill name" },
args: { type: "string", description: "Optional arguments" }
}
}
关键点:
description 包含所有可用 Skill 的列表when_to_use 字段会被附加到描述中SkillTool 的描述是 动态生成 的,每次加载 Skill 时更新:
// src/tools/SkillTool/SkillTool.ts (简化)
function buildSkillToolDescription(skills: Command[]): string {
let desc = "Execute a skill within the main conversationnn"
desc += "Available skills:n"
for (const skill of skills) {
const whenToUse = skill.whenToUse ? ` - ${skill.whenToUse}` : ""
desc += `- ${skill.name}: ${skill.description}${whenToUse}n`
}
return desc
}
// 示例输出:
// Available skills:
// - commit: Create git commits - 当用户需要提交代码时使用
// - tech-blog-writer: 撰写技术博客 - 当用户请求撰写技术博客时使用
机制:
1. User: "写一篇技术博客"
2. LLM: (内部推理)
- 检测到 tech-blog-writer Skill
- when_to_use: "当用户请求撰写技术博客时"
- 决定调用
3. LLM 生成工具调用:
Skill({
skill: "tech-blog-writer",
args: "写一篇技术博客"
})
4. SkillTool 执行:
a. 查找 tech-blog-writer Skill
b. 读取 SKILL.md 的 Markdown Body
c. 注入到对话历史:
messages.push({
role: 'user',
content: '<command-name>/tech-blog-writer</command-name>nn[Markdown Body]nn写一篇技术博客'
})
5. LLM 继续处理(看到注入的 Skill 内容):
"根据技术博客写作规范,我将..."
1. User: "分析这个项目的代码结构"
2. LLM: (内部推理)
- 检测到 code-analyzer Skill
- execution_context: fork
- 决定调用
3. LLM 生成工具调用:
Skill({
skill: "code-analyzer",
args: "分析代码结构"
})
4. SkillTool 执行:
a. 检测到 execution_context: fork
b. 启动子 Agent:
- System: [code-analyzer 的 Markdown Body]
- User: "分析代码结构"
- Tools: [allowed_tools 中指定的工具]
c. 等待子 Agent 完成
d. 返回子 Agent 的输出
5. LLM 收到工具返回值(子 Agent 的分析结果):
"根据分析结果..."
SkillTool 根据 execution_context 字段自动选择模式:
// src/tools/SkillTool/SkillTool.ts
async call(params: { skill: string; args?: string }): Promise<string> {
const skill = this.findSkill(params.skill)
if (skill.executionContext === 'fork') {
return await this.callForkSkill(skill, params.args)
} else {
return await this.callInlineSkill(skill, params.args)
}
}
何时使用 Fork:
---
execution_context: fork
allowed_tools:
- Read
- Grep
---
何时使用 Inline:
---
# 不设置 execution_context(默认 inline)
---
机制: 通过 ToolSearch 工具动态加载工具 schema
启动时:
Tools = [Read, Edit, Write, Bash, ..., ToolSearch]
↓
延迟的工具(Deferred Tools): [NotebookEdit, WebSearch, ...]
→ 仅名称出现在 <system-reminder> 中
Agent 需要使用 NotebookEdit:
1. Agent: ToolSearch({query: "notebook jupyter"})
2. ToolSearch 返回: <functions>
<function>{"name": "NotebookEdit", "parameters": {...}}</function>
</functions>
3. Agent: NotebookEdit({notebook_path: "...", ...})
详细流程(参考 TOOL_SYSTEM_CN.md):
Round 1:
User: "编辑 Jupyter notebook"
Round 2:
Agent: 我需要 NotebookEdit 工具
ToolSearch({query: "select:NotebookEdit"})
→ 返回 NotebookEdit 的完整 JSONSchema
Round 3:
Agent: NotebookEdit({notebook_path: "...", new_source: "..."})
→ 执行操作
关键特性:
ToolSearchtool_reference 机制避免缓存失效机制: 通过 Skill 工具动态注入 Markdown 内容
启动时:
Tools = [Read, Edit, ..., Skill]
Skill 描述中包含所有可用 Skill 的名称和简介
Agent 需要使用 tech-blog-writer:
1. Agent: Skill({skill: "tech-blog-writer", args: "..."})
2. SkillTool 读取 SKILL.md 的 Markdown Body
3. 注入到对话 / 启动 Fork Agent
4. Agent 根据注入的内容调整行为
详细流程:
Round 1:
User: "写一篇技术博客"
Round 2:
Agent: 我检测到需要使用 tech-blog-writer Skill
Skill({skill: "tech-blog-writer", args: "写一篇技术博客"})
→ Inline 模式:
注入 Markdown 到对话历史
messages.push({role: 'user', content: '# Tech Blog Writern...'})
→ Fork 模式:
启动子 Agent,Markdown 作为系统提示词
Round 3:
Agent: 根据 Skill 的指导完成任务
关键特性:
Skill 工具 或 用户输入 /skill-name| 维度 | Tool 懒加载 | Skill 懒加载 |
|---|---|---|
| 目的 | 延迟加载工具 schema | 延迟加载提示词 |
| 触发方式 | LLM 调用专用工具 | LLM 调用专用工具或用户命令 |
| 初始提示词占用 | 仅工具名称(~10 tokens/工具) | 仅 Skill 名称 + 简介(~20 tokens/Skill) |
| KV Cache 友好 | (通过 tool_reference) | (追加式注入) |
| 动态发现 | 通过关键词搜索 | 通过 when_to_use 匹配 |
| 维度 | Tool 懒加载 | Skill 懒加载 |
|---|---|---|
| 延迟的内容 | JSONSchema(参数定义) | Markdown(自然语言指令) |
| 加载后的作用 | 工具变为 可调用 | Agent 行为被 重新指导 |
| 是否执行操作 | (工具执行具体操作) | (Skill 仅提供指导,操作仍通过工具) |
| 是否需要参数 schema | (严格的类型定义) | (自然语言参数) |
| 内容来源 | 代码中定义(TypeScript) | 文件系统(Markdown 文件) |
| 用户可扩展 | (需修改源码) | (添加 Markdown 文件即可) |
Tool 和 Skill 经常协同工作:
示例:tech-blog-writer Skill
---
name: tech-blog-writer
execution_context: fork
allowed_tools:
- Read ← 使用 Tool 读取代码
- Grep ← 使用 Tool 搜索代码
- Write ← 使用 Tool 写入文章
---
# Tech Blog Writer
你是技术博客专家。写作流程:
1. 使用 Read 工具读取项目代码
2. 使用 Grep 工具搜索关键实现
3. 分析代码并撰写文章
4. 使用 Write 工具保存文章
执行流程:
Main Agent:
Skill({skill: "tech-blog-writer"}) ← 懒加载 Skill
Fork Agent:
→ 读到 Skill 的指导:"使用 Read 工具..."
→ Read({file_path: "..."}) ← 使用 Tool(已预加载)
→ Grep({pattern: "..."}) ← 使用 Tool(已预加载)
→ Write({file_path: "..."}) ← 使用 Tool(已预加载)
关系:
Skill 从 5 个来源加载:
| 优先级 | 来源 | 路径 | 说明 |
|---|---|---|---|
| 1 | Managed | ~/.claude/skills/ | 官方管理的 Skill |
| 2 | User | ~/.claude/skills/ | 用户自定义的全局 Skill |
| 3 | Project | <project>/.claude/skills/ | 项目级 Skill |
| 4 | Bundled | 代码内置 | 核心 Skill(/commit, /review-pr) |
| 5 | MCP | MCP 服务器 | 远程 Skill |
去重规则: 高优先级来源覆盖低优先级来源(基于 Skill 名称)
条件激活: 通过 paths 字段实现路径匹配
---
name: cargo-helper
paths:
- "**/Cargo.toml"
- "**/*.rs"
---
仅在存在 Cargo.toml 或 .rs 文件的项目中激活。
---
name: test-skill
description: Test skill for debugging
---
# Test Skill
When invoked, respond with "Test skill loaded successfully!"
调用:
$ claude "/test-skill"
执行:
SKILL.md模式: Inline(无 execution_context)
---
name: tech-blog-writer
description: 撰写技术博客文章
when_to_use: 当用户请求撰写技术博客时使用
execution_context: fork
allowed_tools:
- Read
- Grep
- Glob
- Write
model: sonnet
---
# Tech Blog Writer
你是技术博客专家。写作流程:
1. 使用 Read/Grep 分析项目代码
2. 按照以下结构撰写:
- 摘要
- 引言
- 核心机制(带代码示例)
- 实战案例
- 设计权衡
- 总结
3. 使用 Write 保存文章
调用:
User: 写一篇关于 Speculation 的技术博客
LLM: (自动检测并调用)
Skill({skill: "tech-blog-writer", args: "Speculation"})
执行:
execution_context: fork模式: Fork(需要工具调用 + 隔离执行)
---
name: data-processor
description: 处理 JSON 数据
shell:
command: python
args: ["process.py"]
---
# Data Processor
This skill processes JSON data using the `process.py` script.
调用:
$ claude "/data-processor"
执行:
shell 字段python process.py模式: 脚本直接执行(不经过 Agent)
| 概念 | 定义 |
|---|---|
| Skill | 懒加载的 Agent 行动说明文件 |
| 懒加载 | 仅在触发时注入内容,不占用初始上下文 |
| Inline | 将 Markdown 注入主对话历史 |
| Fork | 启动子 Agent,Markdown 作为系统提示词 |
| SkillTool | LLM 可调用的工具,用于动态加载 Skill |
| 维度 | Skill | Tool |
|---|---|---|
| 本质 | 行为指南 | 可执行函数 |
| 内容 | 自然语言(Markdown) | 函数签名(JSONSchema) |
| 作用 | 改变 Agent 的工作方式 | 执行具体操作 |
| 扩展性 | 用户可自由添加 | 需修改源码 |
使用 Skill 当:
不使用 Skill 当:
Skill 系统体现了 Claude Code 的 能力分层 设计:
Layer 3: Skill(任务模式层)
↓ 指导如何组合
Layer 2: Tool(操作能力层)
↓ 提供原子操作
Layer 1: Model(推理引擎层)
| 字段 | 类型 | 必需 | 默认值 | 说明 |
|---|---|---|---|---|
name | string | - | Skill 标识符 | |
description | string | - | 简短描述 | |
when_to_use | string | - | - | 使用时机说明 |
execution_context | 'fork' | - | - | 设为 fork 使用子 Agent |
allowed_tools | string[] | - | [] | Fork 模式工具白名单 |
model | string | - | 继承 | 指定模型 |
effort | string | - | 'medium' | 预算控制 |
shell | object | - | - | 脚本执行配置 |
hooks | object | - | - | 钩子配置 |
paths | string[] | - | - | 条件激活路径 |
user-invocable | boolean | - | true | 用户是否可手动调用 |
argument_hint | string | - | - | 参数提示 |
version | string | - | - | 版本号 |
| 文件 | 说明 |
|---|---|
src/skills/loadSkillsDir.ts | Skill 加载核心逻辑 |
src/tools/SkillTool/SkillTool.ts | SkillTool 实现 |
src/skills/bundled/*.ts | 内置 Skill 定义 |
~/.claude/skills/ | 用户 Skill 目录 |