本文是 《Claude Code 从入门到高级实战》系列 第 3 篇(共 4 篇)。前两篇讲解了环境搭建、基础交互与任务执行核心;本篇进入高级扩展:Hooks、Agent Skills、SubAgents 与 Plugins。
第四部分:高级功能扩展与定制
16. Hooks:把规则变成自动执行的生命周期操作
16.1 Hook 的作用
Hook 是 Claude Code 在特定事件发生时运行的自定义动作。它适合确定性的流程,例如:
- 在修改后运行格式化;
- 修改敏感文件前阻止操作;
- 会话结束时通知开发者;
- 上下文压缩后重新注入关键约束;
- 工具调用前记录审计信息。
与纯提示词相比,Hook 的优势是它由生命周期事件触发,不需要每次祈祷模型主动记起某个步骤。
16.2 常见事件
| 事件 | 触发时机 | 用途 |
|---|---|---|
SessionStart |
会话启动或特定恢复情形 | 注入环境信息 |
UserPromptSubmit |
用户提交消息后 | 注入或检查提示信息 |
PreToolUse |
工具执行之前 | 预校验、阻止危险动作 |
PostToolUse |
工具成功使用之后 | 格式化、记录结果 |
Notification |
等待输入或通知事件 | 系统提醒 |
Stop |
Agent 准备结束响应 | 检查是否满足结束条件 |
SubagentStart / SubagentStop |
子代理启动/结束 | 观察子代理生命周期 |
具体事件类型、输入 JSON 和退出码请以官方 Hooks Reference 为准。
16.3 Windows + Node.js:保护敏感文件
与依赖 jq 的 Bash 示例不同,下面提供一个更适合 Node 项目的跨平台脚本。
创建 .claude/hooks/protect-files.cjs:
javascript
const chunks = [];
process.stdin.on('data', chunk => chunks.push(chunk));
process.stdin.on('end', () => {
try {
const input = JSON.parse(Buffer.concat(chunks).toString('utf8'));
const path = String(input.tool_input?.file_path || '')
.replace(/\\/g, '/')
.toLowerCase();
const protectedFile =
/(^|\/)\.env(?:\.[^/]*)?$/.test(path) ||
/(^|\/)\.git\//.test(path);
if (protectedFile) {
console.error(`Blocked write to protected path: ${path}`);
process.exitCode = 2;
}
} catch (error) {
console.error(`Hook input error: ${error.message}`);
process.exitCode = 2; // 解析失败时保守拒绝
}
});
在项目 .claude/settings.json 中注册:
json
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "node .claude/hooks/protect-files.cjs"
}
]
}
]
}
}
PreToolUse 的命令 Hook 退出码 2 可以阻止这次操作。调用脚本时工作目录及路径解析须结合你的实际运行环境验证;对高保障项目,应再配合 permissions.deny、系统 ACL 与隔离容器,避免通过其他工具路径绕过保护。
16.4 验证 Hook 是否生效
在 Claude Code 中:
text
/hooks
然后让 Claude 尝试在一个临时测试项目内 编辑用于测试的 .env 文件,确认操作被阻止并给出解释。不要直接用生产凭证文件做实验。
16.5 Hook 的边界
PostToolUse是"已执行之后",不适合阻止已经发生的危险操作。PreToolUse只针对匹配的事件和工具;Shell、MCP、外部应用可能有其他修改路径。- Hook 脚本有超时、退出码、标准输出与 JSON 结构约定,写错可能导致意外批准或阻塞。
- Hook 的命令执行具有本机权限;安装不可信 Hook 与运行不可信脚本一样有风险。
17. Agent Skill:封装可复用的专业流程
17.1 Skill 是什么?
Skill 本质上是一个定义了用途、触发条件和操作步骤的可复用说明包,核心文件通常是 SKILL.md。Claude 可以根据任务描述自动选用 Skill,也可以由用户显式调用。
Skill 适合解决"遇到某类任务时应该按照什么流程做",不一定需要创建独立 Agent。
17.2 Skill 的目录结构
text
.claude/ ← .claude 目录
skills/ ← 技能目录
code-review/ ← 技能名
SKILL.md ← 技能定义文件(必需)
references/ ← 参考资料(可选)
checklist.md ← 审查清单
scripts/ ← 脚本(可选)
check-diff.cjs ← 检查脚本
其中 references 和 scripts 是可选的组织方式,不是创建最小 Skill 的必需条件。
17.3 创建一个 Code Review Skill
文件:.claude/skills/code-review/SKILL.md
markdown
---
name: code-review
description: 对当前 Git 变更执行独立代码审查。用户要求 review、代码审查或检查回归风险时使用。
---
# Code Review 工作流
## 输入确认
1. 确认需求背景、验收标准和审查范围。
2. 确认 Base / Head Commit 或明确当前 Diff。
3. 检查哪些测试已有结果,哪些没有执行。
## 审查顺序
1. 功能正确性与边界场景。
2. 安全、鉴权和敏感数据。
3. 并发、状态一致性与资源泄漏。
4. 兼容性、性能与可维护性。
5. 测试覆盖与潜在回归。
## 输出要求
- 只报告可验证、与本次变更相关的问题。
- 每项包含严重级别、文件位置、复现场景、原因和建议。
- 区分确定性缺陷与有待验证的风险。
- 默认不修改代码。
之后在会话内可以尝试:
text
/code-review
或者:
对当前分支相对于 main 的修改执行 code-review Skill,只输出真实缺陷。
17.4 Skill 的调用机制
通常包括:
- Claude 在上下文里获得 Skill 的名称和描述等可发现信息;
- 用户显式调用或 Claude 判断当前任务与描述匹配;
- 对应
SKILL.md的内容按需加载; - Claude 按 Skill 的流程使用被允许的工具完成任务。
Skill 并不天然拥有单独的模型、长期运行进程或独立上下文。 Skill 可以配置为在 SubAgent 中执行,但这属于额外编排方式,不能把所有 Skill 都称作"子 Agent"。
17.5 Skill 设计建议
- 名称与描述清晰,尤其写明适用和不适用场景。
- 把步骤写成可验证的操作,而不是空泛的"请认真审查"。
- 把长规范、模板、脚本拆到辅助文件,避免无条件加载。
- 减少过多相似 Skill 之间的重叠和冲突。
- 用实际任务集测试触发准确率、输出质量、成本和耗时。
18. SubAgent:创建专职角色和独立上下文
18.1 什么是 SubAgent?
SubAgent 是由主 Agent 调用的专职执行单元,拥有独立的上下文窗口,可以配置专门的系统指令、模型、工具与权限。它完成任务后把结果交回主 Agent。
#mermaid-svg-rHA15uMmACK0uykx{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rHA15uMmACK0uykx .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rHA15uMmACK0uykx .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rHA15uMmACK0uykx .error-icon{fill:#552222;}#mermaid-svg-rHA15uMmACK0uykx .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rHA15uMmACK0uykx .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rHA15uMmACK0uykx .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rHA15uMmACK0uykx .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rHA15uMmACK0uykx .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rHA15uMmACK0uykx .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rHA15uMmACK0uykx .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rHA15uMmACK0uykx .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rHA15uMmACK0uykx .marker.cross{stroke:#333333;}#mermaid-svg-rHA15uMmACK0uykx svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rHA15uMmACK0uykx p{margin:0;}#mermaid-svg-rHA15uMmACK0uykx .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rHA15uMmACK0uykx .cluster-label text{fill:#333;}#mermaid-svg-rHA15uMmACK0uykx .cluster-label span{color:#333;}#mermaid-svg-rHA15uMmACK0uykx .cluster-label span p{background-color:transparent;}#mermaid-svg-rHA15uMmACK0uykx .label text,#mermaid-svg-rHA15uMmACK0uykx span{fill:#333;color:#333;}#mermaid-svg-rHA15uMmACK0uykx .node rect,#mermaid-svg-rHA15uMmACK0uykx .node circle,#mermaid-svg-rHA15uMmACK0uykx .node ellipse,#mermaid-svg-rHA15uMmACK0uykx .node polygon,#mermaid-svg-rHA15uMmACK0uykx .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rHA15uMmACK0uykx .rough-node .label text,#mermaid-svg-rHA15uMmACK0uykx .node .label text,#mermaid-svg-rHA15uMmACK0uykx .image-shape .label,#mermaid-svg-rHA15uMmACK0uykx .icon-shape .label{text-anchor:middle;}#mermaid-svg-rHA15uMmACK0uykx .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rHA15uMmACK0uykx .rough-node .label,#mermaid-svg-rHA15uMmACK0uykx .node .label,#mermaid-svg-rHA15uMmACK0uykx .image-shape .label,#mermaid-svg-rHA15uMmACK0uykx .icon-shape .label{text-align:center;}#mermaid-svg-rHA15uMmACK0uykx .node.clickable{cursor:pointer;}#mermaid-svg-rHA15uMmACK0uykx .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rHA15uMmACK0uykx .arrowheadPath{fill:#333333;}#mermaid-svg-rHA15uMmACK0uykx .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rHA15uMmACK0uykx .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rHA15uMmACK0uykx .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rHA15uMmACK0uykx .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rHA15uMmACK0uykx .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rHA15uMmACK0uykx .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rHA15uMmACK0uykx .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rHA15uMmACK0uykx .cluster text{fill:#333;}#mermaid-svg-rHA15uMmACK0uykx .cluster span{color:#333;}#mermaid-svg-rHA15uMmACK0uykx div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rHA15uMmACK0uykx .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rHA15uMmACK0uykx rect.text{fill:none;stroke-width:0;}#mermaid-svg-rHA15uMmACK0uykx .icon-shape,#mermaid-svg-rHA15uMmACK0uykx .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rHA15uMmACK0uykx .icon-shape p,#mermaid-svg-rHA15uMmACK0uykx .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rHA15uMmACK0uykx .icon-shape .label rect,#mermaid-svg-rHA15uMmACK0uykx .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rHA15uMmACK0uykx .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rHA15uMmACK0uykx .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rHA15uMmACK0uykx :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 开发者任务
主 Claude Agent
Reviewer SubAgent
Test SubAgent
Explore SubAgent
汇总结果、裁决并答复
它的关键价值不只是"有一个角色名字",而是:职责隔离、上下文隔离、工具限制、并行能力与任务委派。
18.2 创建 SubAgent
在会话中:
text
/agents
也可以手工创建 .claude/agents/code-reviewer.md:
markdown
---
name: code-reviewer
description: 独立审查当前代码变更,重点发现真实缺陷、安全问题和回归风险。用于代码开发完成后的质量审查。
tools: Read, Grep, Glob
model: sonnet
---
你是一名独立 Senior Code Reviewer。
1. 首先确认审查范围、需求和验收标准。
2. 只读分析代码与相关测试。
3. 优先发现有明确影响的逻辑、安全与兼容性缺陷。
4. 不把开发者的完成声明当作验证证据。
5. 输出问题级别、文件位置、复现条件、影响和修复建议。
6. 如果没有发现可验证问题,明确说明审查范围与限制。
禁止修改源文件或执行部署。
这里用 Read, Grep, Glob 给审查角色限定只读工具范围;具体是否还需要其他工具,应依据审查需求与权限策略调整。
18.3 如何使用?
text
请调用 code-reviewer 子代理,独立审查本次登录功能的修改,主会话只负责汇总结果,不要替它修改结论。
观察会话中是否真的出现该 SubAgent 的调用记录;只看到 AI 说"我扮演 Reviewer"并不能证明创建或调用了真正的 SubAgent。
18.4 模型是否继承主 Agent?
- 如果 SubAgent 没有显式指定模型,通常根据主会话模型、系统默认及相关配置决定。
- 可以在 SubAgent Frontmatter 中使用
model指定模型(例如sonnet或其他当前可用别名)。 - 部分内置 SubAgent、环境变量或全局覆盖规则有额外优先级。
- SubAgent 的工具权限可能受到父会话权限模式和组织策略约束;不要假设可以独立"降权"所有已继承的高权限模式。
因此,不能简单归纳为"所有子 Agent 永远使用主 Agent 的同一模型"。
18.5 SubAgent 与 Agent Team 不一样
| 机制 | 通信关系 | 主要用途 |
|---|---|---|
| SubAgent | 主 Agent 委派任务,子 Agent 返回结果 | 聚焦职责、压缩主上下文 |
| 多个后台会话 | 各自独立运行并可被监控 | 并行完成互不相关的工作 |
| Agent Team | 多个协作会话可在机制允许时通信与协调 | 跨任务协作、分工与同步 |
"一个主 Agent 调用三个 SubAgent"不自动等于启用了 Agent Team。是否存在真正的 Team 成员、消息传递与协作能力,要看当前功能、调用记录和会话管理界面。
18.6 使用 SubAgent 的边界
不值得给每个小步骤都创建 SubAgent。过多角色会增加上下文说明、模型调用、协调开销和结果冲突。推荐在以下情况下使用:
- 需要独立审查开发结果;
- 搜索范围大、工具输出多,适合隔离主上下文;
- 多个可独立开展的研究任务;
- 需要明确不同模型、工具或权限的专职任务。
19. Skill 与 SubAgent 的区别:最重要的架构决策
这是高级开发最容易混淆的一部分。
19.1 核心对比
| 维度 | Skill | SubAgent |
|---|---|---|
| 本质 | 工作方法与指令包 | 独立上下文中的专职 Agent |
| 主要价值 | 可复用流程、按需加载 | 职责隔离、上下文隔离、任务委派 |
| 常见文件 | skills/<name>/SKILL.md |
agents/<name>.md |
| 是否默认独立上下文 | 否 | 是 |
| 是否可单独配置模型 | 通常不是核心用途 | 是,支持按配置选择模型 |
| 是否可单独限制工具 | 可通过相关 Skill/执行配置约束 | 支持定义工具范围 |
| 适合例子 | PR 检查清单、需求拆解流程、发布规范 | 独立 Reviewer、专项 Debugger、文档研究者 |
| 成本 | 通常较轻 | 额外的模型调用与协调成本 |
19.2 一个具体例子
需求:让 Claude 对代码执行专业 Review。
方案 A:只有 Skill
text
主 Agent
→ 加载 code-review Skill
→ 按规范分析当前 Diff
优势:简单、易维护,适合大部分普通 Review。局限:Review 仍受主会话已有上下文和倾向影响。
方案 B:专职 SubAgent + Skill
text
主 Agent(开发)
→ code-reviewer SubAgent(独立上下文、只读权限)
→ 使用 code-review Skill(审查规范)
→ 返回问题列表与证据
优势:专业方法复用,同时减少开发上下文对审查的干扰。代价:需要维护角色,消耗额外模型调用,主 Agent 仍需要解释并处理结果。
19.3 选择规则
#mermaid-svg-YO0RO4YMvA6Sf6wW{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-YO0RO4YMvA6Sf6wW .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-YO0RO4YMvA6Sf6wW .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-YO0RO4YMvA6Sf6wW .error-icon{fill:#552222;}#mermaid-svg-YO0RO4YMvA6Sf6wW .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YO0RO4YMvA6Sf6wW .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-YO0RO4YMvA6Sf6wW .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YO0RO4YMvA6Sf6wW .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YO0RO4YMvA6Sf6wW .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-YO0RO4YMvA6Sf6wW .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YO0RO4YMvA6Sf6wW .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YO0RO4YMvA6Sf6wW .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YO0RO4YMvA6Sf6wW .marker.cross{stroke:#333333;}#mermaid-svg-YO0RO4YMvA6Sf6wW svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YO0RO4YMvA6Sf6wW p{margin:0;}#mermaid-svg-YO0RO4YMvA6Sf6wW .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-YO0RO4YMvA6Sf6wW .cluster-label text{fill:#333;}#mermaid-svg-YO0RO4YMvA6Sf6wW .cluster-label span{color:#333;}#mermaid-svg-YO0RO4YMvA6Sf6wW .cluster-label span p{background-color:transparent;}#mermaid-svg-YO0RO4YMvA6Sf6wW .label text,#mermaid-svg-YO0RO4YMvA6Sf6wW span{fill:#333;color:#333;}#mermaid-svg-YO0RO4YMvA6Sf6wW .node rect,#mermaid-svg-YO0RO4YMvA6Sf6wW .node circle,#mermaid-svg-YO0RO4YMvA6Sf6wW .node ellipse,#mermaid-svg-YO0RO4YMvA6Sf6wW .node polygon,#mermaid-svg-YO0RO4YMvA6Sf6wW .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YO0RO4YMvA6Sf6wW .rough-node .label text,#mermaid-svg-YO0RO4YMvA6Sf6wW .node .label text,#mermaid-svg-YO0RO4YMvA6Sf6wW .image-shape .label,#mermaid-svg-YO0RO4YMvA6Sf6wW .icon-shape .label{text-anchor:middle;}#mermaid-svg-YO0RO4YMvA6Sf6wW .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-YO0RO4YMvA6Sf6wW .rough-node .label,#mermaid-svg-YO0RO4YMvA6Sf6wW .node .label,#mermaid-svg-YO0RO4YMvA6Sf6wW .image-shape .label,#mermaid-svg-YO0RO4YMvA6Sf6wW .icon-shape .label{text-align:center;}#mermaid-svg-YO0RO4YMvA6Sf6wW .node.clickable{cursor:pointer;}#mermaid-svg-YO0RO4YMvA6Sf6wW .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-YO0RO4YMvA6Sf6wW .arrowheadPath{fill:#333333;}#mermaid-svg-YO0RO4YMvA6Sf6wW .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-YO0RO4YMvA6Sf6wW .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-YO0RO4YMvA6Sf6wW .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YO0RO4YMvA6Sf6wW .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-YO0RO4YMvA6Sf6wW .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YO0RO4YMvA6Sf6wW .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-YO0RO4YMvA6Sf6wW .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-YO0RO4YMvA6Sf6wW .cluster text{fill:#333;}#mermaid-svg-YO0RO4YMvA6Sf6wW .cluster span{color:#333;}#mermaid-svg-YO0RO4YMvA6Sf6wW div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-YO0RO4YMvA6Sf6wW .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-YO0RO4YMvA6Sf6wW rect.text{fill:none;stroke-width:0;}#mermaid-svg-YO0RO4YMvA6Sf6wW .icon-shape,#mermaid-svg-YO0RO4YMvA6Sf6wW .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YO0RO4YMvA6Sf6wW .icon-shape p,#mermaid-svg-YO0RO4YMvA6Sf6wW .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-YO0RO4YMvA6Sf6wW .icon-shape .label rect,#mermaid-svg-YO0RO4YMvA6Sf6wW .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YO0RO4YMvA6Sf6wW .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-YO0RO4YMvA6Sf6wW .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-YO0RO4YMvA6Sf6wW :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
是
否
是
否
需要新增能力
只是复用一套操作方法?
优先写 Skill
是否需要独立上下文、模型或工具隔离?
创建 SubAgent
直接由主 Agent 执行
是否存在通用流程?
SubAgent 复用 Skill
保持简单的 Agent 定义
结论:优先选择最小机制。 如果一份规范化 SKILL.md 就足够,不必为了"看起来像多 Agent 架构"再制造一层角色。只有独立上下文、并行和权限边界带来明确收益时,才值得添加 SubAgent。
20. Plugin:把扩展能力打包安装和分发
20.1 Plugin 是什么?
Plugin 是 Claude Code 的一种扩展分发形式,可以把多个 Skills、SubAgents、Hooks 和 MCP Server 配置作为一个整体安装与更新。
可以把它理解为:
Skill 是一个工作流程,SubAgent 是一个专职执行者,Hook 是一个事件触发器,MCP 是对外部工具的连接,Plugin 是这些能力的安装与分发载体。
20.2 一个典型 Plugin 目录
text
my-dev-plugin/
.claude-plugin/ ← 插件清单目录
plugin.json ← Manifest 文件
skills/ ← 技能
code-review/
SKILL.md
agents/ ← 子代理
reviewer.md
hooks/ ← 钩子
hooks.json
.mcp.json ← MCP 配置
最小 Manifest 示例:
json
{
"name": "my-dev-plugin",
"version": "1.0.0",
"description": "Reusable development workflows and review agents"
}
Manifest 和组件目录的更多合法字段、加载规则及插件开发规范以官方 Plugin 文档为准。上面目录是结构演示,并不表示每个组件都必须存在。
20.3 安装和管理
在 Claude Code 会话中:
text
/plugin
也可以通过支持的 CLI 命令安装官方或 Marketplace 中的插件,例如前文的 Figma Plugin:
powershell
claude plugin install figma@claude-plugins-official
不要未经检查就安装来源不明的插件。插件可能携带自动执行的 Hooks、MCP 服务、脚本以及广泛的工具调用能力。
20.4 什么时候需要开发 Plugin?
单项目或个人流程通常只需 .claude/skills/、.claude/agents/ 和本地 Hooks。适合开发 Plugin 的情况有:
- 需要统一分发给多个项目或团队;
- 需要组合多种扩展机制;
- 需要有版本、升级、禁用与来源管理;
- 想把一套成熟开发实践变成可安装的产品。
20.5 为什么不建议疯狂安装插件?
更多插件并不一定带来更好的结果。它们可能造成:
- 可发现的 Skill/Agent 描述占用上下文;
- 同名命令或类似功能冲突;
- MCP 服务器占用进程、网络和工具上下文;
- Hook 执行时间增加;
- 权限和供应链攻击面扩大。
应当定期检查哪些插件真正被使用,并移除或禁用多余扩展。