280 lines
8.0 KiB
Markdown
280 lines
8.0 KiB
Markdown
# 插件与技能系统
|
||
|
||
Claude Code 提供了强大的插件系统和技能系统来扩展功能。本文档详细介绍这两个系统的架构和实现。
|
||
|
||
## 1. 插件系统 (plugins/)
|
||
|
||
### 1.1 插件加载机制
|
||
|
||
Claude Code 的插件系统支持内置插件和第三方插件。
|
||
|
||
**关键文件:**
|
||
- `/src/plugins/builtinPlugins.ts` - 内置插件注册表
|
||
- `/src/utils/plugins/pluginLoader.ts` - 插件加载器
|
||
- `/src/utils/plugins/loadPluginHooks.ts` - 插件钩子加载
|
||
|
||
**插件结构:**
|
||
```typescript
|
||
interface LoadedPlugin {
|
||
name: string // 插件名称
|
||
manifest: { // 插件清单
|
||
name: string
|
||
description: string
|
||
version: string
|
||
}
|
||
path: string // 插件路径
|
||
source: string // 来源标识
|
||
repository: string // 仓库地址
|
||
enabled: boolean // 是否启用
|
||
isBuiltin: boolean // 是否为内置插件
|
||
hooksConfig?: HooksSettings // 钩子配置
|
||
mcpServers?: MCPServer[] // MCP 服务器配置
|
||
}
|
||
```
|
||
|
||
### 1.2 内置插件 (builtinPlugins.ts)
|
||
|
||
内置插件是与 Claude Code CLI 一起打包的插件,可以通过 `/plugin` UI 启用/禁用。
|
||
|
||
**与 Bundled Skills 的区别:**
|
||
| 特性 | 内置插件 | Bundled Skills |
|
||
|------|----------|----------------|
|
||
| 出现位置 | `/plugin` UI 的 "Built-in" 部分 | `/skills` 列表 |
|
||
| 用户控制 | 可启用/禁用(持久化到用户设置) | 始终可用 |
|
||
| 组件类型 | 可提供多种组件(skills, hooks, MCP servers) | 仅 skills |
|
||
|
||
**插件 ID 格式:**
|
||
- 内置插件:`{name}@builtin`
|
||
- 市场插件:`{name}@{marketplace}`
|
||
|
||
**核心函数:**
|
||
```typescript
|
||
// 注册内置插件
|
||
registerBuiltinPlugin(definition: BuiltinPluginDefinition): void
|
||
|
||
// 检查是否为内置插件
|
||
isBuiltinPluginId(pluginId: string): boolean
|
||
|
||
// 获取所有内置插件(分启用/禁用)
|
||
getBuiltinPlugins(): { enabled: LoadedPlugin[]; disabled: LoadedPlugin[] }
|
||
|
||
// 获取内置插件提供的技能命令
|
||
getBuiltinPluginSkillCommands(): Command[]
|
||
```
|
||
|
||
### 1.3 插件注册和执行流程
|
||
|
||
**注册流程:**
|
||
1. 在启动时调用 `initBuiltinPlugins()` 注册所有内置插件
|
||
2. 插件定义包含:`name`, `description`, `version`, `isAvailable()`, `defaultEnabled`, `skills`, `hooks`, `mcpServers`
|
||
|
||
**加载流程 (loadPluginHooks.ts):**
|
||
```typescript
|
||
export const loadPluginHooks = memoize(async (): Promise<void> => {
|
||
const { enabled } = await loadAllPluginsCacheOnly()
|
||
// 转换插件钩子配置为匹配器
|
||
const pluginMatchers = convertPluginHooksToMatchers(plugin)
|
||
// 清除旧钩子并注册新钩子(原子操作)
|
||
clearRegisteredPluginHooks()
|
||
registerHookCallbacks(allPluginHooks)
|
||
})
|
||
```
|
||
|
||
**钩子事件类型:**
|
||
- `PreToolUse` - 工具执行前
|
||
- `PostToolUse` - 工具执行后
|
||
- `PermissionDenied` - 权限被拒绝
|
||
- `SessionStart/SessionEnd` - 会话开始/结束
|
||
- `SubagentStart/SubagentStop` - 子智能体启动/停止
|
||
- `TaskCreated/TaskCompleted` - 任务创建/完成
|
||
|
||
### 1.4 第三方插件支持
|
||
|
||
第三方插件通过市场安装,支持以下功能:
|
||
- 自定义 skills
|
||
- 钩子系统
|
||
- MCP 服务器
|
||
|
||
## 2. 技能系统 (skills/)
|
||
|
||
### 2.1 技能定义和格式
|
||
|
||
**技能定义结构 (BundledSkillDefinition):**
|
||
```typescript
|
||
type BundledSkillDefinition = {
|
||
name: string // 技能名称
|
||
description: string // 技能描述
|
||
aliases?: string[] // 别名
|
||
whenToUse?: string // 使用建议
|
||
argumentHint?: string // 参数提示
|
||
allowedTools?: string[] // 允许的工具
|
||
model?: string // 模型覆盖
|
||
disableModelInvocation?: boolean // 禁用模型调用
|
||
userInvocable?: boolean // 用户可调用
|
||
isEnabled?: () => boolean // 启用检查函数
|
||
hooks?: HooksSettings // 钩子设置
|
||
context?: 'inline' | 'fork' // 执行上下文
|
||
agent?: string // 代理类型
|
||
files?: Record<string, string> // 参考文件
|
||
getPromptForCommand: (args: string, context: ToolUseContext) => Promise<ContentBlockParam[]>
|
||
}
|
||
```
|
||
|
||
### 2.2 技能执行机制 (SkillTool)
|
||
|
||
**关键文件:** `/src/tools/SkillTool/SkillTool.ts`
|
||
|
||
**执行模式:**
|
||
|
||
1. **Inline 模式(内联执行)**
|
||
- 技能内容直接注入对话
|
||
- 使用 `processPromptSlashCommand` 处理
|
||
- 支持 `!command` 和 `$ARGUMENTS` 扩展
|
||
|
||
2. **Fork 模式(分叉执行)**
|
||
- 在独立子智能体中运行技能
|
||
- 拥有独立 token 预算
|
||
- 通过 `executeForkedSkill` 实现
|
||
|
||
**SkillTool 输入/输出:**
|
||
```typescript
|
||
// 输入
|
||
input: {
|
||
skill: string // 技能名称,如 "commit", "review-pr"
|
||
args?: string // 可选参数
|
||
}
|
||
|
||
// 输出
|
||
output: {
|
||
success: boolean
|
||
commandName: string
|
||
status: 'inline' | 'forked'
|
||
agentId?: string // fork 模式下的子智能体 ID
|
||
result?: string // fork 模式下的执行结果
|
||
}
|
||
```
|
||
|
||
**权限检查:**
|
||
- 技能执行需要权限检查
|
||
- 支持规则匹配(前缀匹配如 `review:*`)
|
||
- 自动允许安全属性的技能
|
||
|
||
### 2.3 内置技能
|
||
|
||
**位置:** `/src/skills/bundled/`
|
||
|
||
**内置技能列表:**
|
||
| 技能名 | 描述 |
|
||
|--------|------|
|
||
| `remember` | 记忆技能 |
|
||
| `loremIpsum` | 生成占位文本 |
|
||
| `verify` | 验证技能 |
|
||
| `loop` | 循环执行技能 |
|
||
| `claudeApi` | Claude API 相关 |
|
||
| `debug` | 调试技能 |
|
||
| `stuck` | 处理卡住情况 |
|
||
| `batch` | 批量处理 |
|
||
| `updateConfig` | 更新配置 |
|
||
| `keybindings` | 快捷键 |
|
||
| `simplify` | 简化代码 |
|
||
| `skillify` | 技能化 |
|
||
|
||
### 2.4 用户自定义技能
|
||
|
||
用户可以在 `~/.claude/skills/` 目录下创建自定义技能。
|
||
|
||
**技能文件结构:**
|
||
```
|
||
~/.claude/skills/
|
||
└── my-skill/
|
||
└── SKILL.md # 技能定义文件
|
||
```
|
||
|
||
**注册流程:**
|
||
```typescript
|
||
// 注册技能
|
||
registerBundledSkill(definition: BundledSkillDefinition): void
|
||
|
||
// 获取所有已注册技能
|
||
getBundledSkills(): Command[]
|
||
|
||
// 技能文件提取(用于有参考文件的技能)
|
||
async function extractBundledSkillFiles(
|
||
skillName: string,
|
||
files: Record<string, string>
|
||
): Promise<string | null>
|
||
```
|
||
|
||
### 2.5 技能与命令的转换
|
||
|
||
技能在内部被转换为 `Command` 对象:
|
||
|
||
```typescript
|
||
function skillDefinitionToCommand(definition: BundledSkillDefinition): Command {
|
||
return {
|
||
type: 'prompt',
|
||
name: definition.name,
|
||
description: definition.description,
|
||
source: 'bundled',
|
||
loadedFrom: 'bundled',
|
||
hooks: definition.hooks,
|
||
context: definition.context,
|
||
agent: definition.agent,
|
||
// ...
|
||
}
|
||
}
|
||
```
|
||
|
||
## 3. 插件与技能的协同
|
||
|
||
### 3.1 插件提供技能
|
||
|
||
插件可以通过内置技能机制提供技能:
|
||
```typescript
|
||
// 插件定义
|
||
const myPlugin: BuiltinPluginDefinition = {
|
||
name: 'my-plugin',
|
||
description: 'My custom plugin',
|
||
skills: [skill1, skill2],
|
||
// ...
|
||
}
|
||
```
|
||
|
||
### 3.2 钩子在技能执行中的应用
|
||
|
||
技能执行时会触发各种钩子:
|
||
- `PreToolUse` - 检查技能是否允许使用特定工具
|
||
- `PostToolUse` - 记录技能执行结果
|
||
- `Stop` - 技能执行完成
|
||
|
||
## 4. MCP 集成
|
||
|
||
技能系统支持 MCP (Model Context Protocol) 技能构建器:
|
||
|
||
```typescript
|
||
// 位置:/src/skills/mcpSkillBuilders.ts
|
||
export function createMcpSkill(
|
||
serverName: string,
|
||
toolName: string
|
||
): BundledSkillDefinition
|
||
```
|
||
|
||
## 5. 权限与安全
|
||
|
||
### 5.1 技能白名单
|
||
|
||
`SAFE_SKILL_PROPERTIES` 定义了安全属性列表,只包含以下属性的技能会自动获得权限:
|
||
- `type`, `progressMessage`, `contentLength`, `argNames`, `model`, `effort`
|
||
- `source`, `pluginInfo`, `disableNonInteractive`, `skillRoot`, `context`, `agent`
|
||
- `getPromptForCommand`, `frontmatterKeys`
|
||
- `name`, `description`, `hasUserSpecifiedDescription`, `isEnabled`, `isHidden`
|
||
- `aliases`, `isMcp`, `argumentHint`, `whenToUse`, `paths`, `version`
|
||
- `disableModelInvocation`, `userInvocable`, `loadedFrom`, `immediate`, `userFacingName`
|
||
|
||
### 5.2 远程技能 (实验性)
|
||
|
||
启用 `EXPERIMENTAL_SKILL_SEARCH` 后支持远程技能:
|
||
- 技能定义存储在远程服务器
|
||
- 通过 `_canonical_<slug>` 格式引用
|
||
- 支持 GCS、HTTP/HTTPS、S3 等协议
|