乐于分享
好东西不私藏

Claude Code 源码解析 – SKILL 运行机制

Claude Code 源码解析 – SKILL 运行机制

想象你是一个刚入职的程序员。现在让你去修空调,你一脸懵——你会写代码,但不会修空调。

但如果有人给你一本《空调维修手册》,你就能照着手册修了。

Claude Code 的 Skill 系统就是这本技能手册:让 AI 能快速掌握新能力,不需要重新训练模型。

一、Skill 架构:Markdown 即技能

Claude Code 的 Skill 和 Agent 一样,用 Markdown 写配置。这延续了 Claude Code「配置即代码」的设计哲学。

为什么用 Markdown?因为 Markdown 本身就是一种结构化文档格式。它的 frontmatter 可以放元数据,正文可以放指令和示例。天然适合定义技能。

一个 Skill 就是一个 Markdown 文件。文件头部是 frontmatter,定义技能的名字、描述;正文是 instruction,告诉 AI 这个技能怎么用。

---
name: my-skill
description: 当你需要 XXX 时使用这个技能
instruction: 执行步骤...
---


# My Skill

这个技能可以帮助你...

1.1 Skill 与 Agent 的区别

虽然 Skill 和 Agent 都用 Markdown 定义,但它们有本质区别。

Agent 是独立的工作单元。它有自己独立的对话循环、独立的上下文。像一个独立的员工,被派去完成一个完整的子任务。

Skill 是技能的增强。它运行在当前对话中,不创建独立的对话循环。像员工学的一门技能,让员工能做新的事,但员工还是员工。

Agent Skill
用途 独立的工作单元 增强工具能力
粒度 粗粒度(完整的子任务) 细粒度(单一功能)
调用方式 /agent 或 Agent tool /my-skill 或 Skill tool
运行模式 独立对话循环 在当前对话中执行

简单说:Agent 是独立员工,Skill 是员工学的技能

二、Skill 定义结构

从代码层面看,Skill 的定义和 Agent 非常相似,但更轻量。

Skill 最核心的三个属性是:namedescriptioninstruction。名字是唯一标识,描述说明什么时候用,指令说明怎么用。

可选属性用来控制 Skill 的行为:toolsdisallowedTools 控制可用工具,arguments 定义接受的参数,subskills 让技能可以包含子技能。

// src/skills/loadSkillsDir.ts
type SkillDefinition = {
  namestring              // 技能名称(唯一标识)
  descriptionstring       // 何时使用
  instructionstring       // 执行步骤
  category?: string         // 分类
  arguments?: SkillArgument[]  // 参数定义
  subskills?: SkillDefinition[]  // 子技能
  
  // 执行控制
  maxTurns?: number         // 最大回合数
  effort?: EffortValue      // 努力程度
  tools?: string[]          // 允许使用的工具
  disallowedTools?: string[]  // 禁止使用的工具
  
  // 来源追踪
  source'skills' | 'plugin' | 'managed' | 'bundled'
}

Skill 和 Agent 的一个关键区别是:Skill 没有独立的 system prompt。Skill 的指令(instruction)只是追加到当前对话的文本,不会替换 system prompt。

三、Skill 加载:多来源聚合

Claude Code 从多个来源加载 Skill,就像一个图书馆从不同渠道采购书籍。

内置 Skill(bundled) 是 Claude Code 官方提供的,比如 claude-code-guide,教用户怎么用 Claude Code。

插件 Skill(plugin) 是第三方插件提供的。

托管 Skill(managed) 是企业管理员统一管理的。

用户 Skill(skills) 是用户自己创建的,存放在 ~/.claude/skills/<project>/.claude/skills/

// Skill 来源优先级
const SKILL_SOURCES = [
  'bundled',    // 内置技能
  'plugin',     // 插件提供
  'managed',    // 托管配置
  'skills',     // 用户自定义
]

多个来源的同名 Skill 会合并,后加载的覆盖先加载的。

3.1 内置 Skill

Claude Code 自带一些内置 Skill,帮助用户上手:

claude-code-guide 是交互式教程,带你了解 Claude Code 的基本用法。

这些 Skill 是 Claude Code 的一部分,开箱即用。

3.2 用户 Skill

用户可以创建自己的 Skill。Skill 文件存放在特定目录:

~/.claude/skills/          # 用户级别,所有项目可见
<project>/.claude/skills/   # 项目级别,只有该项目可见

创建一个 Skill 只需要一个 Markdown 文件。这就是 Claude Code 的设计哲学:门槛低,能力深

四、Skill 执行流程

当用户调用 /my-skill 时,Claude Code 经历以下步骤:

解析:识别技能名称和参数。

加载:从磁盘或缓存读取 Skill 定义。

参数验证:如果 Skill 定义了参数,验证用户提供的参数是否合法。

执行:把 instruction 追加到当前对话,让 AI 按指令执行。

返回:Skill 执行完成后,返回结果给用户。

用户调用 /my-skill
       ↓
  解析 Skill 名称
       ↓
  加载 Skill 定义
       ↓
  验证参数(如果有)
       ↓
  在当前对话执行 instruction
       ↓
  返回执行结果

4.1 解析与参数替换

Skill 可以接受参数。比如 /deploy --env production --service api

参数用 {{variable}} 语法在 instruction 中标记。执行时,系统会用实际参数替换这些占位符。

// Skill 可以接受参数
// /deploy --env production --service api

function parseSkillArgs(skillSkillDefinitionrawArgsstring) {
  // 1. 解析参数名
  const argNames = parseArgumentNames(skill.arguments)
  
  // 2. 替换指令中的 {{arg}}
  const instruction = substituteArguments(skill.instruction, argNames)
  
  return instruction
}

4.2 子技能调用

复杂的 Skill 可以包含子技能。比如一个 full-stack-deploy Skill 可以包含 buildtestdeploy 三个子技能。

子技能让 Skill 可以模块化,便于复用和维护。

// Skill 可以调用子技能
const skill = {
  name'full-stack-deploy',
  subskills: [
    { name'build'instruction'...' },
    { name'test'instruction'...' },
    { name'deploy'instruction'...' },
  ]
}

五、Skill 与工具的集成

5.1 SkillTool

Skill 通过 SkillTool 和系统集成。当用户输入 /my-skill 时,实际调用的是 SkillTool。

SkillTool 的 handler 负责加载 Skill 定义并执行它。

// src/tools/SkillTool/SkillTool.ts
const SkillTool = {
  name'Skill',
  description'Execute a skill',
  
  inputSchema: {
    name'skill',      // Skill 名称
    arguments: {}       // 可选参数
  },
  
  handlerasync (input) => {
    const skill = await loadSkill(input.name)
    return await executeSkill(skill, input.arguments)
  }
}

5.2 Skill 作为增强

Skill 可以增强现有工具的能力。比如一个 git-helper Skill 告诉 AI 怎么用 git 命令。

Skill 不是替代工具,而是指导 AI 更好地使用工具

六、MCP Skill:外部系统集成

MCP(Model Context Protocol)Skill 允许调用外部系统的工具。

通过 MCP Skill,AI 可以用自然语言操作外部系统——数据库、API、监控系统等。

// MCP Skill 的构建
function buildMcpSkill(serverstringtoolstring): SkillDefinition {
  return {
    name`${server}:${tool}`,
    description`MCP tool: ${server}/${tool}`,
    instruction`调用 MCP 服务器 ${server} 的 ${tool} 工具...`,
    source'mcp'
  }
}

MCP Skill 让 Claude Code 的能力边界变得无限——只要有 MCP 服务器,就能操作任何系统。

七、Skill 的执行上下文

7.1 上下文隔离

Skill 运行在当前对话的上下文中,但不等于完全共享。

Skill 可以声明自己需要的工具和记忆范围。系统会根据 Skill 的声明,配置它的执行环境。

// Skill 执行时的上下文
const skillContext = {
  // 继承主对话的上下文
  systemPrompt: parentContext.systemPrompt,
  
  // Skill 特定的工具限制
  toolsresolveSkillTools(skill),
  
  // Skill 特定的记忆
  memory: skill.memory,
  
  // 隔离的工作目录(可选)
  cwd: skill.isolation ? createIsolatedDir() : parentContext.cwd
}

7.2 资源限制

Skill 有执行资源限制,防止它占用太多系统资源。

每个 Skill 有最大回合数限制(maxTurns)。超过限制会自动停止。

还有 token 预算和超时设置。

// Skill 的资源限制
const skillLimits = {
  maxTurns: skill.maxTurns ?? 10,
  maxTokens: skill.maxTokens ?? 5000,
  timeout: skill.timeout ?? 60000,  // 60 秒超时
}

八、Skill 与 Agent 的选择

什么时候用 Skill,什么时候用 Agent?

用 Agent 当你需要:

  • 完整的独立工作循环
  • 复杂的上下文隔离
  • 多个工具协作完成子任务

用 Skill 当你需要:

  • 单一功能的增强
  • 在当前对话中快速执行
  • 按步骤指引 AI
需要完整的工作循环?→ Agent
需要单一功能增强?→ Skill

需要独立的上下文?→ Agent
需要在当前对话中执行?→ Skill

需要多个工具协作?→ Agent
只需要按步骤执行?→ Skill

九、设计思想:技能即模块

Claude Code 的 Skill 系统体现了模块化的思想。

可复用性。一个 Skill 可以被多个 Agent 共享,就像一个人学的技能可以被多个项目使用。

渐进式能力。新能力不需要重新训练模型,只需要写一个 Skill。门槛低,迭代快。

组合性。复杂任务可以分解为多个 Skill 的组合。简单技能的叠加产生复杂能力。

总结

Claude Code 的 Skill 系统告诉我们:能力不等于模型,能力等于模块

  • Skill 用 Markdown 定义,门槛低
  • Skill 可以组合,复杂能力来自简单技能的叠加
  • Skill 有执行上下文隔离,安全可控
  • Skill 与 Agent 互补,粒度选择更灵活

如果你想让 AI 掌握新能力,先问:需要独立的子 Agent,还是只是一个 Skill?


源码索引

功能 文件
Skill 加载 src/skills/loadSkillsDir.ts
内置 Skill src/skills/bundledSkills.ts
Skill 工具 src/tools/SkillTool/SkillTool.ts
MCP Skill src/skills/mcpSkillBuilders.ts
参数解析 src/utils/argumentSubstitution.ts