来源:Claude Code 技术文档 - v2.1.88 源码分析
插件与技能系统
10.1 概述
Claude Code 的扩展系统分为四个层次:
┌────────────────────────────────────────────────┐
│ 扩展系统层次 │
│ │
│ 1. 内置插件 (Builtin Plugins) │
│ └─ 代码内注册,始终可用 │
│ │
│ 2. 打包技能 (Bundled Skills) │
│ └─ 随安装包分发,按需提取 │
│ │
│ 3. 技能目录 (Skill Directories) │
│ └─ .claude/skills/ 中的自定义技能 │
│ │
│ 4. MCP 技能 (MCP Skills) │
│ └─ 通过 MCP 协议加载的外部技能 │
│ │
│ 5. 外部插件 (Plugins) │
│ └─ 第三方插件仓库 │
│ │
└────────────────────────────────────────────────┘10.2 内置插件 (builtinPlugins.ts)
10.2.1 API
// 注册内置插件
function registerBuiltinPlugin(plugin: BuiltinPlugin): void
// 获取所有内置插件
function getBuiltinPlugins(): BuiltinPlugin[]
// 获取内置插件提供的技能命令
function getBuiltinPluginSkillCommands(): Command[]10.2.2 特点
- 在代码中直接注册
- 始终可用,不需要外部加载
- 提供技能命令 (skill commands)
- 与其他命令通过统一接口集成
10.3 打包技能 (bundledSkills.ts)
10.3.1 API
// 注册打包技能
function registerBundledSkill(skill: BundledSkill): void
// 获取所有打包技能
function getBundledSkills(): BundledSkill[]
// 获取打包技能的提取目录
function getBundledSkillExtractDir(): string10.3.2 懒加载文件提取
打包技能的内容在首次使用时从安装包中提取:
首次调用打包技能
│
├─ 检查提取目录是否存在
│
├─ 不存在?
│ ├─ 创建提取目录
│ ├─ 从捆绑数据提取文件
│ │ ├─ 使用 O_NOFOLLOW (不跟随符号链接)
│ │ └─ 使用 O_EXCL (确保文件不存在)
│ └─ 设置文件权限
│
└─ 已存在?
└─ 直接使用缓存的文件10.3.3 安全提取
// 安全标志确保:
// O_NOFOLLOW — 防止符号链接注入攻击
// O_EXCL — 防止 TOCTOU (Time-of-check-to-time-of-use) 竞争10.4 技能目录 (loadSkillsDir.ts)
10.4.1 API
// 加载技能目录中的命令 (memoized)
function getSkillDirCommands(cwd: string): Promise<Command[]>
// 发现项目中的技能目录
function discoverSkillDirsForPaths(paths: string[]): Promise<SkillDir[]>
// 条件激活 — 基于项目配置决定是否加载
// 某些技能只在特定项目类型中激活10.4.2 技能目录结构
.claude/
└─ skills/
├─ my-skill/
│ ├─ skill.json # 技能配置
│ ├─ prompt.md # 提示词内容
│ └─ tools/ # 工具定义(可选)
│
└─ another-skill/
├─ skill.json
└─ prompt.md10.4.3 skill.json 配置
{
"name": "my-skill",
"description": "技能描述",
"version": "1.0.0",
"allowedTools": ["BashTool", "FileReadTool"],
"model": "claude-sonnet-4-20250514",
"context": "inline",
"argNames": ["arg1", "arg2"],
"paths": ["src/**"],
"whenToUse": "当需要 X 时使用此技能"
}10.4.4 Memoization
// getSkillDirCommands 使用 memoize 缓存
// 按 cwd 参数缓存结果
// 清除: clearCommandMemoizationCaches()10.5 MCP 技能构建器 (mcpSkillBuilders.ts)
10.5.1 API
// 注册 MCP 技能构建器
function registerMCPSkillBuilders(builders: MCPSkillBuilder[]): void
// 获取 MCP 技能构建器
function getMCPSkillBuilders(): MCPSkillBuilder[]10.5.2 循环依赖解决
mcpSkillBuilders.ts 的存在是为了解决循环依赖问题:
MCP Client → 需要构建技能命令
技能命令 → 需要 MCP Client 连接
↺ 循环依赖
解决方案:
MCP Client → registerMCPSkillBuilders() (注册构建器)
技能系统 → getMCPSkillBuilders() (获取构建器)
→ 延迟构造技能命令(避免初始化时循环)10.6 命令系统中的技能集成
10.6.1 统一加载
所有技能通过 getSkills() 统一加载:
async function getSkills(cwd: string): Promise<{
skillDirCommands: Command[] // 技能目录命令
pluginSkills: Command[] // 插件技能
bundledSkills: Command[] // 打包技能
builtinPluginSkills: Command[] // 内置插件技能
}>错误处理:每个来源的加载独立捕获错误,不影响其他来源。
10.6.2 命令源优先级
bundled-skills (最高)
↓
builtin-plugin-skills
↓
skill-dir-commands
↓
workflow-commands
↓
plugin-commands
↓
built-in-commands (最低)10.6.3 技能作为命令
技能命令是 PromptCommand 类型:
const skillCommand: PromptCommand = {
type: 'prompt',
name: 'my-skill',
description: '技能描述',
progressMessage: '正在执行技能...',
contentLength: promptContent.length,
source: 'skills', // 或 'bundled', 'plugin', 'mcp'
loadedFrom: 'skills',
async getPromptForCommand(args, context) {
// 读取 prompt.md
// 替换参数占位符
// 返回内容块
return [{ type: 'text', text: processedPrompt }]
}
}10.7 SkillTool 集成
10.7.1 SkillTool 调用流程
AI 模型决定使用技能
│
▼
SkillTool.call({ skillName, args })
│
├─ getSkillToolCommands(cwd) — 获取可用技能
├─ findCommand(skillName, commands) — 查找技能
├─ skill.getPromptForCommand(args, context) — 获取提示
│
▼
将技能提示作为新的消息注入
│
└─ 继续对话循环10.7.2 可被 SkillTool 调用的条件
// 条件:
// 1. type === 'prompt' (必须是提示类型)
// 2. source !== 'builtin' (非内置命令)
// 3. 未被模型禁用 (disableModelInvocation !== true)10.8 插件清单
10.8.1 PluginManifest
插件通过清单文件描述自身:
type PluginManifest = {
name: string // 插件名称
version: string // 版本
description: string // 描述
skills?: SkillConfig[] // 提供的技能
tools?: ToolConfig[] // 提供的工具
hooks?: HooksConfig // 提供的 Hook
// ...
}10.8.2 插件来源标注
// 命令描述中的来源标注
function formatDescriptionWithSource(cmd: Command): string
// 输出示例:
// "代码审查 (from plugin: code-review)"
// "安全扫描 (from bundled skill)"
// "自定义分析 (from skills directory)"10.9 MCP 技能命令
10.9.1 MCP 提供的提示命令
function getMcpSkillCommands(
mcpCommands: readonly Command[]
): readonly Command[] {
return mcpCommands.filter(cmd =>
cmd.type === 'prompt' &&
cmd.loadedFrom === 'mcp'
)
}10.9.2 MCP 服务器配置层
MCP 有 6 个配置层级(从高到低):
1. enterprise — 企业策略配置
2. dynamic — 运行时动态添加
3. project — 项目级配置 (.claude/mcp.json)
4. user — 用户级配置 (~/.claude/mcp.json)
5. local — 本地覆盖
6. claudeai — Claude AI 平台配置每个 MCP 服务器通过签名 (signature) 去重,同一服务器的多个配置取最高优先级。
10.10 技能缓存管理
// 清除所有命令缓存(含技能)
function clearCommandsCache(): void
// 清除:
// - loadAllCommands 缓存
// - getSkillToolCommands 缓存
// - getSlashCommandToolSkills 缓存
// - 插件缓存
// - 技能目录缓存
// 清除 memoization 缓存
function clearCommandMemoizationCaches(): void
// 仅清除:
// - loadAllCommands
// - getSkillToolCommands
// - getSlashCommandToolSkills