本章概述
系列目录:Claude Code 源码分析系列索引
Skills 技能系统是 Claude Code 实现可复用 AI 工作流的核心机制,它允许用户定义和调用预配置的 AI 行为模式。
你将学到
- ✅ 技能系统的架构设计
- ✅ 技能定义与加载
- ✅ 技能触发机制
- ✅ 技能执行流程
- ✅ 内置技能分析
技能系统概览
flowchart TB
subgraph SkillSystem["技能系统"]
A[技能定义] --> B[技能加载]
B --> C[技能注册]
C --> D[技能触发]
D --> E[技能执行]
end
subgraph Sources["技能来源"]
F[内置技能] --> G[bundled/]
H[本地技能] --> I[.claude/skills/]
J[远程技能] --> K[Marketplace]
end
subgraph Trigger["触发机制"]
L[显式调用] --> M[/skill-name]
N[自动触发] --> O[关键词匹配]
P[Hook 触发] --> Q[事件监听]
end
A --> F
D --> L
核心文件结构
src/
├── skills/ # 技能系统
│ ├── bundled/ # 内置技能
│ │ ├── index.ts
│ │ ├── commitSkill.ts
│ │ ├── initSkill.ts
│ │ └── ...
│ └── AGENTS.md
├── utils/skills/ # 技能工具
│ ├── skillChangeDetector.ts
│ └── ...
├── commands/skills/ # /skills 命令
│ └── index.ts
└── tools/SkillTool/ # SkillTool 实现
└── SkillTool.ts
技能定义
技能结构
// types/command.ts - Skill 类型
export type PromptCommand = {
type: 'prompt'
name: string
description: string
progressMessage: string
source: 'builtin' | 'skills' | 'plugin' | 'bundled'
// 提示词生成
getPromptForCommand(
args: string,
context: ToolUseContext
): Promise<ContentBlockParam[]>
// 可选配置
allowedTools?: string[]
model?: string
effort?: EffortValue
hooks?: HooksSettings
paths?: string[]
context?: 'inline' | 'fork'
agent?: string
}
技能定义文件
技能通常定义在 Markdown 文件中,包含 YAML frontmatter:
---
name: commit
description: Create a git commit with a descriptive message
model: sonnet
allowedTools:
- Bash(git add:*)
- Bash(git status:*)
- Bash(git commit:*)
---
## Context
Current git status: !`git status`
Current git diff: !`git diff HEAD`
## Task
Create a git commit with a descriptive message following conventional commits format.
技能加载
技能发现
// utils/skills/skillLoader.ts
export async function discoverSkills(): Promise<Skill[]> {
const skills: Skill[] = [];
// 1. 加载内置技能
const bundledSkills = await loadBundledSkills();
skills.push(...bundgedSkills);
// 2. 加载本地技能
const localSkills = await loadLocalSkills();
skills.push(...localSkills);
// 3. 加载插件技能
const pluginSkills = await loadPluginSkills();
skills.push(...pluginSkills);
return skills;
}
async function loadLocalSkills(): Promise<Skill[]> {
const skillsDir = path.join(process.cwd(), '.claude', 'skills');
if (!existsSync(skillsDir)) {
return [];
}
const files = await glob('**/*.md', { cwd: skillsDir });
const skills: Skill[] = [];
for (const file of files) {
const skill = await parseSkillFile(path.join(skillsDir, file));
if (skill) {
skills.push(skill);
}
}
return skills;
}
技能解析
// utils/skills/skillParser.ts
export async function parseSkillFile(filePath: string): Promise<Skill | null> {
const content = await readFile(filePath, 'utf-8');
// 解析 frontmatter
const { data: frontmatter, content: body } = matter(content);
// 验证必需字段
if (!frontmatter.name || !frontmatter.description) {
logError(`Invalid skill file: ${filePath}`);
return null;
}
return {
name: frontmatter.name,
description: frontmatter.description,
model: frontmatter.model,
allowedTools: frontmatter.allowedTools,
hooks: frontmatter.hooks,
source: 'skills',
getPromptForCommand: async (args, context) => {
// 处理技能模板
const processedBody = await processSkillTemplate(body, context);
return [{
type: 'text',
text: processedBody
}];
}
};
}
技能触发机制
显式触发
// 用户通过 /skill-name 调用
/skills/my-skill arg1 arg2
// SkillTool 处理
export async function callSkill(params: SkillParams) {
const skill = findSkill(params.skillName);
if (!skill) {
throw new Error(`Skill ${params.skillName} not found`);
}
const prompt = await skill.getPromptForCommand(params.args, context);
return await callClaudeAPI({
messages: prompt,
model: skill.model,
tools: skill.allowedTools
? filterTools(skill.allowedTools)
: getAllTools()
});
}
自动触发(关键词)
// utils/skills/autoTrigger.ts
const TRIGGER_KEYWORDS: Record<string, string[]> = {
'commit': ['commit', 'git commit', 'create commit'],
'test': ['test', 'run tests', 'pytest'],
'review': ['review', 'code review', 'pr review']
};
export function shouldAutoTrigger(
input: string
): string | null {
const lowerInput = input.toLowerCase();
for (const [skill, keywords] of Object.entries(TRIGGER_KEYWORDS)) {
for (const keyword of keywords) {
if (lowerInput.includes(keyword)) {
return skill;
}
}
}
return null;
}
// 在对话中检测
export function detectSkillInConversation(
messages: Message[]
): string | null {
const lastMessage = messages[messages.length - 1];
if (lastMessage?.role === 'user') {
return shouldAutoTrigger(lastMessage.content);
}
return null;
}
Hook 触发
// utils/hooks/registerFrontmatterHooks.ts
export async function registerFrontmatterHooks(
skill: Skill
): Promise<void> {
if (!skill.hooks) {
return;
}
for (const [event, command] of Object.entries(skill.hooks)) {
registerHook(event as HookEvent, async (context) => {
// 执行 hook 命令
await executeBashCommand(command, context);
});
}
}
// Hook 事件类型
type HookEvent =
| 'pre_tool_use'
| 'post_tool_use'
| 'pre_edit'
| 'post_edit'
| 'session_start'
| 'session_end'
技能执行流程
sequenceDiagram
participant User as 用户
participant CLI as Commander
participant SkillTool as SkillTool
participant Parser as 技能解析
participant Claude as Claude API
User->>CLI: /skill-name args
CLI->>SkillTool: call({skillName, args})
SkillTool->>SkillTool: 查找技能
alt 找到技能
SkillTool->>Parser: getPromptForCommand(args, context)
Parser->>Parser: 解析模板
Parser->>Parser: 执行嵌入命令
Parser-->>SkillTool: 提示词
SkillTool->>Claude: 调用 API
Claude-->>SkillTool: 响应
alt 包含工具调用
loop 工具调用循环
SkillTool->>SkillTool: 执行工具
SkillTool->>Claude: 发送结果
Claude-->>SkillTool: 响应
end
end
SkillTool-->>CLI: 最终结果
CLI-->>User: 显示结果
else 未找到
SkillTool-->>CLI: 错误
end
内置技能分析
Commit 技能
// skills/bundled/commitSkill.ts
export const commitSkill: Skill = {
name: 'commit',
description: 'Create a git commit with a descriptive message',
progressMessage: 'creating commit',
source: 'bundled',
allowedTools: [
'Bash(git add:*)',
'Bash(git status:*)',
'Bash(git commit:*)'
],
async getPromptForCommand(args, context) {
const gitStatus = await context.executeTool('Bash', {
command: 'git status'
});
const gitDiff = await context.executeTool('Bash', {
command: 'git diff HEAD'
});
return [{
type: 'text',
text: `## Git Context
Status:
${gitStatus}
Changes:
${gitDiff}
## Task
Create a commit with a message following conventional commits format.
Focus on the "why" not the "what".
${args ? `Additional context: ${args}` : ''}`
}];
}
};
Init 技能
// skills/bundled/initSkill.ts
export const initSkill: Skill = {
name: 'init',
description: 'Initialize Claude Code in a project',
progressMessage: 'initializing',
source: 'bundled',
allowedTools: ['*'],
async getPromptForCommand(args, context) {
return [{
type: 'text',
text: `## Task
Set up a minimal CLAUDE.md for this repository.
Steps:
1. Explore the codebase structure
2. Identify build/test/lint commands
3. Create CLAUDE.md with:
- Project overview
- Common commands
- Architecture notes
- Testing approach
Be concise - only include what Claude would get wrong without it.`
}];
}
};
Superpowers 集成
Superpowers 技能
Claude Code 支持 Superpowers 技能框架,这是一套预定义的 AI 工作流:
// skills/bundled/superpowers/
export const superpowersSkills = [
{
name: 'brainstorming',
description: 'Brainstorm before writing code',
trigger: 'before_coding'
},
{
name: 'writing-plans',
description: 'Create implementation plans',
trigger: 'before_implementation'
},
{
name: 'test-driven-development',
description: 'Enforce TDD workflow',
trigger: 'before_testing'
},
{
name: 'systematic-debugging',
description: 'Debug systematically',
trigger: 'on_bug'
}
];
技能链
// utils/skills/skillChain.ts
export async function executeSkillChain(
chain: Skill[],
context: SkillContext
): Promise<SkillResult> {
let result: SkillResult = { success: true };
for (const skill of chain) {
// 检查前置条件
if (!checkPrerequisites(skill, result)) {
return {
success: false,
error: `Prerequisites not met for ${skill.name}`
};
}
// 执行技能
result = await executeSkill(skill, context);
// 失败中断
if (!result.success) {
return result;
}
}
return result;
}
技能最佳实践
1. 技能设计原则
// ✅ 好的技能设计
const goodSkill = {
name: 'test',
description: 'Run project tests',
// 清晰的任务描述
getPromptForCommand: async (args, context) => {
// 收集上下文
const testConfig = await detectTestFramework();
return {
type: 'text',
text: `Run tests using ${testConfig.command}
Context:
- Framework: ${testConfig.framework}
- Config: ${testConfig.configPath}
${args ? `Filter: ${args}` : ''}`
};
}
};
2. 上下文收集
// ✅ 充分的上下文
async function collectContext(context: ToolUseContext) {
return {
git: {
branch: await getBranch(),
status: await getStatus()
},
project: {
root: getProjectRoot(),
language: detectLanguage()
},
env: {
node: process.version,
pwd: process.cwd()
}
};
}
3. 错误处理
// ✅ 健壮的技能
async function executeSkill(skill: Skill, context: Context) {
try {
const prompt = await skill.getPromptForCommand(context);
return await callClaudeAPI(prompt);
} catch (error) {
if (error instanceof PermissionError) {
return {
success: false,
error: 'Permission denied'
};
}
throw error;
}
}
小结
本章分析了 Claude Code 的 Skills 技能系统:
核心概念
| 概念 | 说明 | 应用场景 |
|---|---|---|
| Skill | 技能定义 | 可复用 AI 工作流 |
| Trigger | 触发机制 | 自动/手动调用 |
| Hook | 事件钩子 | 工具事件响应 |
| Chain | 技能链 | 多技能组合 |
架构优势
- 可复用 - 预定义工作流
- 可扩展 - 自定义技能
- 灵活 - 多种触发方式
- 可组合 - 技能链执行
学习收获
- 🎯 技能设计 - 可复用 AI 工作流
- 🔄 触发机制 - 自动/手动调用
- 🔗 技能组合 - 链式执行
- 📋 模板处理 - 动态提示词生成
系列导航:
- ← 上一篇:第7章:State 状态管理与持久化
- 返回:系列索引