Skip to content

10.1 单代理的极限

想象一个大型重构任务:将一个单体应用拆分为微服务。

Claude Code作为单个AI代理,可以:

  1. 分析现有代码结构
  2. 设计拆分方案
  3. 逐个拆分模块
  4. 修改配置和依赖
  5. 运行测试验证

但如果这个应用有50个模块呢?200个模块呢?

单个代理面临的挑战是:

  • 上下文窗口限制:即使有Prompt Caching,一个超大型项目的全部上下文仍然可能超出模型的处理能力
  • 串行效率:单代理只能一个一个任务地处理,无法并行
  • 专业性局限:一个通用的AI模型可能不如针对特定任务优化的专门模型

这些挑战的答案,就是多代理协作

10.2 Claude Code的多代理架构

Claude Code实现了完整的多代理协作框架。从sdk-tools.d.ts中可以看到核心的类型定义。

10.2.1 AgentInput:生成一个代理的指令

typescript
interface AgentInput {
  description: string;  // 任务简述(3-5个词)
  prompt: string;       // 完整任务指令
  subagent_type?: string;  // 专门代理类型
  model?: "sonnet" | "opus" | "haiku";  // 模型选择
  run_in_background?: boolean;  // 后台运行
  name?: string;  // 代理名称(用于寻址)
  team_name?: string;  // 团队名
  mode?: "acceptEdits" | "bypassPermissions" | "default" | "dontAsk" | "plan";
  isolation?: "worktree";  // 隔离模式
}

这个接口的每一个字段都蕴含着深意。让我们逐一解析。

10.2.2 任务描述与指令

description是3-5个词的简述,prompt是完整指令。这种双层描述模式遵循了抽象层次分离原则:

  • description用于人类快速识别任务("Refactor auth module")
  • prompt用于代理完整理解任务("Refactor the authentication module from session-based to JWT...")

这在多代理场景下特别重要——团队领导者可能需要快速扫描数十个子代理的任务描述。

10.2.3 模型选择:子代理不一定要和父代理相同

typescript
model?: "sonnet" | "opus" | "haiku";

这是一个极具战略意义的设计。不同的任务可能需要不同级别的模型:

  • Opus:复杂的架构决策、困难的调试、需要深度推理的任务
  • Sonnet:平衡性能与成本的通用任务(代码编写、文件修改)
  • Haiku:简单快速的任务(格式化、简单查询、轻量操作)
父代理(Opus)──→ 分析任务 ──→ 拆分为子任务

                              ├─→ 子代理A(Haiku)──→ 格式化代码
                              ├─→ 子代理B(Sonnet)──→ 重构模块
                              └─→ 子代理C(Haiku)──→ 运行测试

这种分层模型策略实现了成本与能力的动态平衡。将昂贵的Opus用于需要深度推理的任务,将便宜的Haiku用于机械性任务。

10.2.4 后台运行与异步代理

typescript
run_in_background?: boolean;

当设置为true时,代理在后台异步运行。这允许:

  1. 并行执行:启动多个后台代理同时工作
  2. 非阻塞:父代理不需要等待子代理完成就可以继续其他工作
  3. 进度检查:通过outputFile定期检查子代理的进度

10.2.5 隔离模式:Worktree

typescript
isolation?: "worktree";

这是一个关键的安全特性。当设置为worktree时,子代理在一个临时的Git Worktree中工作:

主仓库 /project
    ├── .git/
    ├── src/
    └── ...

子代理Worktree /project/.git/worktrees/agent-xxx
    ├── src/        ← 独立的副本
    └── ...

Git Worktree提供了一个轻量级的项目副本——它共享同一个Git仓库(.git目录),但工作目录是独立的。这意味着:

  1. 子代理的修改不会影响主仓库
  2. 子代理可以自由创建文件、修改代码、运行测试
  3. 父代理可以审查子代理的修改后决定是否合并
  4. 如果子代理搞砸了,直接删除Worktree即可

这种"沙箱"机制让多代理协作变得安全可控。

10.3 AgentOutput:代理的执行结果

typescript
type AgentOutput =
  | {
      agentId: string;
      agentType?: string;
      content: { type: "text"; text: string }[];
      totalToolUseCount: number;
      totalDurationMs: number;
      totalTokens: number;
      usage: {
        input_tokens: number;
        output_tokens: number;
        cache_creation_input_tokens: number | null;
        cache_read_input_tokens: number | null;
        server_tool_use: { web_search_requests: number; web_fetch_requests: number } | null;
        service_tier: ("standard" | "priority" | "batch") | null;
        cache_creation: {
          ephemeral_1h_input_tokens: number;
          ephemeral_5m_input_tokens: number;
        } | null;
      };
      status: "completed";
      prompt: string;
    }
  | {
      status: "async_launched";
      agentId: string;
      description: string;
      prompt: string;
      outputFile: string;
      canReadOutputFile?: boolean;
    };

AgentOutput有两种形态:

  1. completed:同步代理或已完成的后台代理的完整结果
  2. async_launched:刚启动的后台代理的元信息

10.3.1 丰富的执行元数据

completed形态包含了大量执行元数据:

  • totalToolUseCount:代理调用了多少次工具
  • totalDurationMs:总执行时间
  • totalTokens:总token消耗
  • usage:详细的token使用分解

这些数据不仅用于展示,还用于:

  1. 成本控制:估算多代理协作的总成本
  2. 性能分析:识别瓶颈代理
  3. 自适应调度:根据历史数据选择最优模型

10.3.2 异步代理的进度追踪

对于后台代理,async_launched形态提供了:

  • outputFile:输出文件路径,可以读取检查进度
  • canReadOutputFile:父代理是否有权限读取输出文件

Claude Code可以通过定期读取outputFile来检查后台代理的进度,实现"发起后定期检查"的模式。

10.4 Team通信协议:代理间的消息传递

多个代理需要协调工作。Claude Code实现了结构化的通信协议。

10.4.1 SendMessage:点对点消息

typescript
SendMessage({
  type: "message",
  recipient: "agent-name",  // 按名称寻址
  content: "请审查这个PR",
  summary: "PR审查请求"      // 5-10词摘要
});

每个代理可以被赋予一个name(通过AgentInput的name字段),其他代理可以通过这个名称向它发送消息。这种"命名寻址"模式让代理间通信变得直观——就像邮件系统中的收件人地址。

10.4.2 Broadcast:广播消息

typescript
SendMessage({
  type: "broadcast",
  content: "数据库schema已更新,请重新加载",
  summary: "Schema更新通知"
});

广播消息会发送给团队中的所有代理。适用于"全局通知"场景,如配置变更、任务状态更新等。

10.4.3 Shutdown协议

typescript
// 请求关闭
SendMessage({
  type: "shutdown_request",
  recipient: "agent-name"
});

// 响应关闭请求
SendMessage({
  type: "shutdown_response",
  recipient: "requester-name",
  approve: true
});

Claude Code的关闭协议遵循"两阶段关闭"模式——请求者先发送shutdown_request,被请求者确认后执行关闭。这避免了代理正在处理关键任务时被意外终止。

10.4.4 计划审批

typescript
SendMessage({
  type: "plan_approval_response",
  recipient: "agent-name",
  approve: true
});

当子代理在"plan"模式下工作时,它提出的执行计划需要经过审批才能执行。这种审批机制确保了即使代理有执行权限,关键的架构决策仍然需要人工或父代理的确认。

10.5 Teammate模式:三种进程隔离策略

Claude Code支持三种Teammate模式,每种模式有不同的隔离级别和性能特征:

10.5.1 tmux模式:进程隔离

在tmux模式下,每个Teammate运行在独立的tmux会话中:

tmux session "claude-team"
    ├── window "main" (tmux pane)
    │   └── claude (父代理)
    ├── window "agent-a" (tmux pane)
    │   └── claude (子代理A)
    └── window "agent-b" (tmux pane)
        └── claude (子代理B)

优点

  • 完全的进程隔离——一个代理崩溃不影响其他代理
  • 每个代理有独立的终端,可以手动查看
  • 资源隔离——CPU、内存使用相互独立

缺点

  • 通信延迟较高(通过文件系统或socket通信)
  • 进程启动开销较大

10.5.2 in-process模式:低延迟

在in-process模式下,所有Teammate运行在同一个Node.js进程中:

Node.js Process
    ├── 事件循环
    ├── 父代理(异步上下文)
    ├── 子代理A(异步上下文)
    └── 子代理B(异步上下文)

优点

  • 极低的通信延迟(内存共享)
  • 无进程启动开销
  • 共享缓存和连接池

缺点

  • 一个代理的崩溃可能影响整个进程
  • 内存和CPU不隔离
  • 调试困难(多个代理共享同一个进程)

10.5.3 auto模式:智能选择

auto模式根据当前环境自动选择最优策略:

javascript
function chooseTeammateMode(context) {
  // 简单任务 + 少量代理 → in-process
  if (context.taskComplexity === "low" && context.teamSize <= 2) {
    return "in-process";
  }
  
  // 复杂任务 + 多代理 → tmux
  if (context.taskComplexity === "high" || context.teamSize > 5) {
    return "tmux";
  }
  
  // 默认:in-process
  return "in-process";
}

这种智能选择策略在通信效率故障隔离之间找到了平衡点。

10.6 动态团队上下文

Claude Code为每个代理维护了丰富的运行时上下文:

javascript
const agentContext = {
  agentId: "agent-xxx",
  agentName: "backend-refactorer",
  teamName: "microservice-migration",
  agentColor: "#FF5733",        // 用于UI中的视觉区分
  planModeRequired: false,      // 是否需要计划审批
  parentSessionId: "session-yyy" // 父会话ID
};

10.6.1 视觉标识:agentColor

agentColor为每个代理分配一个颜色,用于在终端UI中区分不同代理的输出。这是一种低技术但高效的UX设计——用户可以一眼识别出当前输出来自哪个代理。

10.6.2 父子关系:parentSessionId

parentSessionId建立了代理间的层级关系。这确保了:

  1. 权限继承:子代理继承父代理的权限配置
  2. 成本归属:子代理的资源消耗可以追溯到父代理
  3. 生命周期绑定:父代理关闭时,子代理也会被关闭

10.7 Agent Definition:定义代理的专业能力

Claude Code支持通过Agent Definition文件来定义专门的代理角色:

markdown
<!-- agents/code-reviewer.md -->
---
name: Code Reviewer
model: sonnet
description: 专门审查代码质量的AI代理
tools: [FileRead, Grep, Glob]
mode: plan
---

# 角色

你是一个专业的代码审查员。你的任务是:

1. 检查代码风格一致性
2. 识别潜在的安全漏洞
3. 评估代码可维护性
4. 提出改进建议

## 审查标准

- 命名规范
- 错误处理完整性
- 测试覆盖率
- 文档充分性

10.7.1 并行加载:commands + agents

Agent Definition文件和commands(自定义命令)是并行加载的:

javascript
async function loadProjectConfig(projectDir) {
  const [commands, agents] = await Promise.all([
    loadCommands(projectDir),
    loadAgents(projectDir)
  ]);
  return { commands, agents };
}

这种并行加载策略减少了Claude Code的启动时间。

10.7.2 subagent_type:专业化分工

typescript
subagent_type?: string;

subagent_type指向一个预定义的Agent Definition。这使得父代理可以快速生成具有特定专业能力的子代理:

javascript
// 父代理生成一个代码审查子代理
spawnAgent({
  description: "Review auth module",
  prompt: "Review the authentication module for security issues",
  subagent_type: "code-reviewer",
  model: "sonnet"
});

10.8 多代理协作的实际工作流

让我们通过一个完整的例子来看看多代理协作如何在实际场景中工作。

场景:大型重构 — 从Session认证迁移到JWT

第一阶段:分析(父代理,Opus)

父代理:
1. 读取现有认证代码
2. 分析所有Session使用点
3. 生成迁移计划
4. 将计划拆分为独立子任务

第二阶段:并行执行(子代理团队)

子代理A(Sonnet)──→ 重构认证中间件
    isolation: worktree
    
子代理B(Sonnet)──→ 更新API端点
    isolation: worktree
    
子代理C(Haiku)──→ 更新测试用例
    run_in_background: true
    
子代理D(Haiku)──→ 更新文档
    run_in_background: true

第三阶段:协调与合并

父代理:
1. 检查各子代理的outputFile
2. 审查子代理的代码变更
3. 解决潜在的冲突
4. 合并各Worktree的修改
5. 运行集成测试

通信模式

在上述过程中,代理间可能发生如下通信:

子代理B → 子代理A:
"我在更新API端点时发现,auth middleware的接口签名需要调整"

父代理 → 子代理C:
"子代理A修改了中间件接口,请更新相关测试"

子代理D → 广播:
"文档已更新完成,包含新的JWT配置说明"

父代理 → 子代理A:
"请暂停修改,子代理B提出了一个接口变更建议,需要先讨论"

权限模式

注意每个子代理的权限模式:

子代理A:mode = "default"  → 可以执行文件操作,需要确认Bash命令
子代理B:mode = "default"  → 同上
子代理C:mode = "bypassPermissions" → 可以自由执行(测试修改是低风险操作)
子代理D:mode = "default"  → 文档修改需要确认

10.9 后台代理的生命周期管理

10.9.1 启动

typescript
// 启动后台代理
const result = await agent.spawn({
  description: "Run full test suite",
  prompt: "Run the full test suite and report results",
  run_in_background: true
});

// result.status === "async_launched"
// result.agentId === "agent-xxx"
// result.outputFile === "/tmp/claude-agent-xxx-output"

10.9.2 进度检查

父代理可以通过读取outputFile来检查进度:

javascript
// 定期检查后台代理进度
function checkAgentProgress(agent) {
  if (agent.canReadOutputFile) {
    const output = fs.readFileSync(agent.outputFile, 'utf-8');
    // 解析进度信息
    return parseProgress(output);
  }
  return null;
}

10.9.3 完成通知

当后台代理完成时,Claude Code会向父代理发送通知:

后台代理C已完成:
  - 总耗时:12.5秒
  - 总Token:3,200
  - 工具调用:8次
  - 状态:成功
  - 输出:23个测试通过,2个需要更新

10.9.4 超时处理

后台代理也有超时机制。如果代理在指定时间内未完成,Claude Code会:

  1. 发送shutdown_request
  2. 等待代理响应
  3. 如果未响应,强制终止

10.10 成本优化:智能模型调度

多代理协作的一个核心挑战是成本控制。如果所有代理都使用最强大的Opus模型,成本会急剧上升。

Claude Code的智能模型调度策略:

任务复杂度评估

     ├─→ 高(架构设计、复杂调试)→ Opus

     ├─→ 中(代码编写、重构)→ Sonnet

     └─→ 低(格式化、简单查询)→ Haiku

历史数据反馈

     └─→ 如果Sonnet在类似任务上的成功率 > 95%
         └─→ 下次直接使用Sonnet,跳过复杂度评估

AgentOutput中的usage数据为这种调度提供了反馈信号:

javascript
// 成本分析(概念)
function analyzeAgentCost(agentOutput) {
  const costPerToken = {
    opus: { input: 15, output: 75 },
    sonnet: { input: 3, output: 15 },
    haiku: { input: 0.25, output: 1.25 }
  };
  
  const model = agentOutput.model;
  const totalCost = 
    agentOutput.usage.input_tokens * costPerToken[model].input +
    agentOutput.usage.output_tokens * costPerToken[model].output;
  
  return totalCost;
}

10.11 设计哲学:协作而非中心化

Claude Code的多代理架构遵循协作优先的设计哲学:

  1. 代理是平等的:虽然存在父子关系,但每个代理都是一个完整的AI实例,拥有独立的推理能力
  2. 通过消息协调:代理间通过结构化消息通信,而不是共享内存或直接调用
  3. 渐进式信任:子代理的权限可以逐级放宽(plan → default → bypassPermissions)
  4. 可观察性:每个代理的完整执行记录(包括token使用、工具调用、通信记录)都被记录

这种架构与传统的"中心调度器+执行器"模式有本质区别。在传统模式中,中心调度器做出所有决策,执行器只是被动执行。而在Claude Code的多代理架构中,每个代理都是自主的——它可以根据自己的理解和判断做出局部决策。

10.12 本章小结

Claude Code的多代理协作系统是一个复杂而精巧的工程实现:

  • AgentInput/Output:类型化的代理创建和结果接口
  • 模型分层:Opus/Sonnet/Haiku的智能调度
  • 后台执行:run_in_background + outputFile进度追踪
  • Worktree隔离:Git Worktree实现安全的代码沙箱
  • Team通信:SendMessage/Broadcast/Shutdown的结构化协议
  • Teammate模式:tmux/in-process/auto的智能选择
  • Agent Definition:专业化代理角色的声明式定义
  • 动态上下文:agentId/agentName/teamName/agentColor的运行时标识
  • 成本优化:基于历史数据的自适应模型调度

这个系统的核心洞察是:复杂任务不是由一个超级智能体完成的,而是由多个适度智能体通过精心设计的协作协议完成的。这和人类社会的组织方式如出一辙——一个大型项目的成功,不取决于某个超级天才,而取决于团队成员之间的有效协作。

在下一章中,我们将看到Claude Code的另一个重要子系统——插件系统,它是构建可扩展生态的工程框架。


第11章:插件系统 — 生态构建的工程框架

11.1 从工具到生态

如果一个AI编程工具只有内置功能,它的上限就是开发团队的能力边界。

Claude Code的内置工具已经非常强大——文件操作、命令执行、代码搜索、Web搜索、MCP协议。但这些工具覆盖的是通用场景。在特定的行业、公司、项目中,总有内置工具无法满足的需求:

  • 金融公司需要连接内部的风控系统
  • 游戏公司需要和Unity/Unreal编辑器集成
  • 医疗公司需要符合HIPAA规范的数据处理
  • 每家公司都有自己的CI/CD系统、部署流程、代码规范

Claude Code的插件系统就是为了解决这个"长尾需求"而设计的。它不仅仅是一个"添加功能"的机制——它是一个完整的生态构建框架

11.2 插件的生命周期

Claude Code的插件有完整的生命周期管理:

11.2.1 安装前:Validate

在安装插件之前,Claude Code会执行验证:

用户请求安装插件


validate(plugin)

     ├─→ 格式检查:目录结构、必要文件是否存在
     ├─→ 安全检查:是否包含危险脚本
     ├─→ 依赖检查:所需的运行时是否可用
     └─→ 兼容性检查:是否与当前版本兼容


验证通过 → 进入安装流程
验证失败 → 报告具体错误

验证是安全的第一道防线。Claude Code需要确保用户不会安装一个包含恶意代码的插件。

11.2.2 安装:Install

安装过程:

  1. 从来源(Git URL / 本地路径 / Marketplace)获取插件代码
  2. 将插件放置到作用域对应的目录
  3. 安装插件依赖
  4. 注册插件的工具、命令、MCP Server
  5. 触发插件的初始化钩子

11.2.3 列表:List

bash
claude plugin list

列出当前所有已安装的插件,包括:

  • 插件名称
  • 版本
  • 状态(enabled/disabled)
  • 作用域
  • 来源

11.2.4 启用/禁用:Enable/Disable

bash
claude plugin enable <name>
claude plugin disable <name>

禁用一个插件不会卸载它,只是暂时不加载它的功能。这类似于浏览器扩展的启用/禁用——用户可能需要在某些场景下关闭某个插件,但不希望完全删除它。

11.2.5 卸载:Uninstall

bash
claude plugin uninstall <name>

完全移除插件及其所有数据。

11.2.6 更新:Update

bash
claude plugin update <name>

从原始来源拉取最新版本并更新。

11.3 作用域系统

Claude Code的插件支持三种作用域(scope),由e0数组管理:

11.3.1 user(用户级)

~/.claude/plugins/
    ├── my-custom-tools/
    └── company-standards/

用户级插件对所有项目生效。适用于:

  • 个人偏好的工具增强
  • 公司级别的编码规范
  • 通用的MCP Server

11.3.2 project(项目级)

/project/.claude/plugins/
    └── project-specific-tools/

项目级插件仅对当前项目生效。适用于:

  • 项目特定的构建工具
  • 项目特定的代码生成器
  • 项目特定的部署流程

11.3.3 local(本地级)

/project/.claude/plugins.local/
    └── experimental-tools/

本地级插件类似于.gitignore中的本地规则——它们不应该被提交到版本控制。适用于:

  • 个人在本项目中的实验性工具
  • 临时调试用的插件
  • 尚未准备好分享的工具

11.3.4 作用域优先级

local > project > user

当多个作用域中存在同名插件时,更具体的作用域优先。这确保了项目级别的配置可以覆盖用户级别的配置。

11.4 Marketplace:插件的分发中心

Claude Code内置了一个插件Marketplace,支持插件的发现、安装和管理。

11.4.1 添加插件

bash
# 从Git URL添加
claude plugin marketplace add https://github.com/user/claude-plugin

# 从本地路径添加
claude plugin marketplace add /path/to/plugin

11.4.2 Git Sparse-Checkout

对于Git来源的插件,Claude Code使用sparse-checkout来优化下载:

bash
git clone --filter=blob:none --sparse <repo-url>
cd <repo>
git sparse-checkout set <plugin-dir>

sparse-checkout允许只下载仓库中插件相关的部分,而不是整个仓库。这对于大型仓库(如monorepo)特别重要——用户不应该为了安装一个小插件而下载几个GB的仓库。

11.4.3 Marketplace操作

bash
claude plugin marketplace list     # 列出可用的插件
claude plugin marketplace remove   # 从Marketplace移除
claude plugin marketplace update   # 更新插件

11.4.4 插件MCP:插件提供外部能力

一个重要但容易被忽视的设计是:插件可以提供MCP Server

这意味着插件不仅可以通过Claude Code的内部API扩展功能,还可以通过MCP协议提供标准化的外部能力:

json
{
  "name": "my-database-plugin",
  "version": "1.0.0",
  "mcpServers": {
    "my-db": {
      "command": "node",
      "args": ["./mcp-server.js"],
      "env": {
        "DB_URL": "${DATABASE_URL}"
      }
    }
  }
}

这使得插件的能力可以超越Claude Code本身的边界——其他MCP客户端也可以使用插件提供的MCP Server。

11.4.5 插件MCP与claude.ai Connector的去重

当插件提供的MCP Server与claude.ai Connector提供的MCP Server同名时,Claude Code需要去重:

javascript
// 去重逻辑(概念)
function deduplicateMcpServers(pluginServers, claudeServers) {
  const allServers = [...pluginServers, ...claudeServers];
  const deduped = new Map();
  
  for (const server of allServers) {
    const key = `${server.name}@${server.version}`;
    if (!deduped.has(key)) {
      deduped.set(key, server);
    }
  }
  
  return deduped;
}

这里的关键是基于名称+版本的去重,而不是仅仅基于名称。同名但不同版本的MCP Server被视为不同的服务。

11.5 Hook系统:插件的事件驱动扩展

11.5.1 registerHookCallbacks

Claude Code的Hook系统允许插件注册回调函数,在特定事件发生时执行自定义逻辑:

javascript
// 插件注册Hook
registerHookCallbacks({
  "before:tool:execute": async (toolName, args) => {
    // 在工具执行前进行拦截/修改
    if (toolName === "Bash" && args.command.includes("rm -rf")) {
      return { blocked: true, reason: "Dangerous command detected" };
    }
    return { allowed: true };
  },
  
  "after:tool:execute": async (toolName, result) => {
    // 在工具执行后进行后处理
    if (toolName === "FileWrite") {
      await runLinter(result.filePath);
    }
  },
  
  "on:session:start": async (session) => {
    // 会话开始时的初始化
    await loadProjectContext(session.projectDir);
  },
  
  "on:session:end": async (session) => {
    // 会话结束时的清理
    await saveTelemetry(session);
  }
});

11.5.2 Plugin Hooks vs Non-Plugin Hooks

Claude Code将Hook分为两类:

  1. Plugin Hooks:由插件注册的Hook
  2. Non-Plugin Hooks:由项目配置或用户配置注册的Hook

这种分离的原因是权限控制

  • Plugin Hooks在沙箱环境中执行,无法访问敏感资源
  • Non-Plugin Hooks在宿主环境中执行,拥有完整权限
Hook执行优先级:
1. Non-Plugin Hooks(先执行,可以block plugin hooks)
2. Plugin Hooks(后执行,权限受限)

11.5.3 Hook的可用事件

Claude Code的Hook系统支持多种事件:

事件触发时机典型用途
before:tool:execute工具执行前安全检查、参数修改、审计日志
after:tool:execute工具执行后结果处理、副作用触发、通知
on:session:start会话开始初始化、加载上下文
on:session:end会话结束清理、保存数据
on:error错误发生错误处理、告警
on:permission:request权限请求时自定义权限策略

这种事件驱动的设计使得插件可以在不修改Claude Code核心代码的情况下,深刻地影响Claude Code的行为。

11.6 --cowork:协作开发模式

Claude Code支持--cowork模式,这是一个专门为多人协作开发设计的功能。

11.6.1 cowork_plugins目录

--cowork模式下,Claude Code会加载cowork_plugins目录中的插件:

/project/.claude/cowork_plugins/
    ├── code-review-rules/
    └── team-standards/

cowork_plugins中的插件在团队成员之间共享——当团队成员使用--cowork模式启动Claude Code时,这些插件会自动加载。这确保了整个团队使用相同的工具集、编码规范和质量标准。

11.6.2 协作场景

--cowork模式的典型使用场景:

  1. 代码审查规则:团队统一的代码审查标准
  2. 编码规范:自动化的编码规范检查和修复
  3. 部署流程:标准化的部署前检查
  4. 通知机制:代码变更时自动通知相关团队成员

11.7 安全模型:多层次的信任体系

插件系统的安全性是Claude Code最关注的问题之一。一个不受限制的插件系统等同于给恶意代码开后门。

11.7.1 allowedSettingSources

allowedSettingSources定义了插件可以修改的设置范围:

javascript
const allowedSettingSources = {
  // 插件可以修改的设置
  allow: [
    "theme",
    "editor.fontSize",
    "tools.preferredShell"
  ],
  
  // 插件不能修改的设置(需要用户手动修改)
  deny: [
    "mcpServers",
    "permissions",
    "apiKey"
  ]
};

这种白名单机制确保了插件无法篡改安全相关的设置。

11.7.2 Development Channels隔离

Claude Code通过--dangerously-load-development-channels标志来隔离开发环境中的插件:

生产插件(正式安装的插件)

    ├── 完整权限
    ├── 经过安全审计
    └── 稳定版本
    
开发插件(development channels中的插件)

    ├── 受限权限
    ├── 未经过审计(可能包含安全漏洞)
    └── 开发版本

dangerously前缀的设计意图是心理安全——通过命名约定提醒用户,他们正在加载可能不安全的代码。

11.7.3 插件沙箱

Claude Code的插件在沙箱环境中执行:

  1. 文件系统隔离:插件只能访问特定的目录
  2. 网络限制:插件的出站网络请求被限制
  3. 资源限制:插件的CPU和内存使用被限制
  4. 权限最小化:插件默认没有任何敏感权限

11.7.4 插件验证的安全层

Claude Code的多层插件安全验证:

第1层:格式验证
    └─→ 目录结构、必要文件、配置格式

第2层:静态分析
    └─→ 代码扫描、危险模式检测

第3层:权限声明
    └─→ 插件必须声明所需的权限

第4层:运行时监控
    └─→ 行为监控、异常检测

第5层:用户确认
    └─→ 敏感操作需要用户确认

11.8 插件与MCP的协同

Claude Code的插件系统和MCP协议是互补的两个扩展维度:

11.8.1 插件扩展Claude Code本身

插件可以直接扩展Claude Code的行为:

  • 添加新的内置工具
  • 注册Hook回调
  • 修改UI渲染
  • 自定义权限策略

11.8.2 MCP扩展AI的外部能力

MCP扩展的是AI模型可以调用的外部能力:

  • 连接数据库
  • 调用API
  • 读取外部数据源

11.8.3 插件可以提供MCP Server

当插件提供MCP Server时,它同时利用了两个扩展维度:

插件(Plugin)

    ├── 内部扩展:自定义工具、Hook回调

    └── MCP扩展:MCP Server

                    ├── 工具(Tools)
                    └── 资源(Resources)

这种"插件包装MCP"的模式使得插件开发者可以:

  1. 将外部系统封装为MCP Server
  2. 通过Hook添加领域特定的安全检查
  3. 通过自定义工具提供快捷操作
  4. 通过Marketplace分发给其他用户

11.9 插件系统的架构设计模式

11.9.1 插件发现与加载

javascript
async function loadPlugins(scopes) {
  // e0数组:收集所有作用域的插件
  const e0 = [];
  
  for (const scope of scopes) {
    const plugins = await discoverPlugins(scope);
    e0.push(...plugins);
  }
  
  // 去重(同名插件取最高优先级的作用域版本)
  const deduped = deduplicatePlugins(e0);
  
  // 验证
  const validated = deduped.filter(p => validatePlugin(p));
  
  // 加载
  const loaded = validated.map(p => loadPlugin(p));
  
  return loaded;
}

11.9.2 插件注册表

Claude Code维护一个运行时插件注册表:

javascript
const pluginRegistry = {
  tools: new Map(),        // 插件注册的工具
  hooks: new Map(),        // 插件注册的Hook
  mcpServers: new Map(),   // 插件提供的MCP Server
  commands: new Map(),     // 插件提供的命令
  settings: new Map(),     // 插件修改的设置
};

当Claude Code需要调用一个工具时,它会先检查内置工具,然后检查插件注册表中的工具,最后检查MCP工具。这个优先级顺序确保了内置工具始终可用,而插件和MCP提供了额外的能力。

11.9.3 插件间的依赖管理

虽然Claude Code的插件系统相对轻量,但它支持基本的依赖管理:

json
{
  "name": "my-plugin",
  "version": "1.0.0",
  "dependencies": {
    "claude-plugin-utils": "^1.2.0"
  }
}

插件依赖通过npm管理,这利用了JavaScript生态中成熟的包管理基础设施。

11.10 生态构建的工程考量

11.10.1 版本兼容性

Claude Code的插件需要处理版本兼容性问题:

  • 向前兼容:新版本的Claude Code应该能运行旧版本的插件
  • 向后兼容:旧版本的Claude Code应该尽可能运行新版本的插件

Claude Code通过API版本化来管理兼容性:

json
{
  "name": "my-plugin",
  "claudeApiVersion": "2.1",
  "version": "1.0.0"
}

11.10.2 插件的测试策略

插件开发者可以使用Claude Code提供的测试框架来验证插件行为:

  1. 单元测试:测试插件的各个组件
  2. 集成测试:测试插件与Claude Code的交互
  3. 端到端测试:模拟用户使用插件完成完整任务

11.10.3 插件的文档标准

Claude Code鼓励(但不强制)插件开发者遵循文档标准:

  • README.md:插件概述、安装说明、基本用法
  • CHANGELOG.md:版本变更记录
  • EXAMPLES.md:使用示例
  • SECURITY.md:安全策略(特别是插件需要访问敏感资源时)

11.11 设计哲学:开放但受控

Claude Code的插件系统体现了"开放但受控"的设计哲学:

11.11.1 开放

  • 任何人都可以开发插件
  • Marketplace提供公开的分发渠道
  • 插件可以提供任意能力(包括MCP Server)
  • Hook系统允许深度定制行为

11.11.2 受控

  • 多层安全验证
  • 白名单式的权限控制
  • 沙箱执行环境
  • development channels的隔离
  • 用户确认机制

这种平衡是所有生态系统的核心挑战——如何在不扼杀创新的同时保护用户安全?Claude Code的选择是:通过技术手段(沙箱、权限、验证)而非行政手段(审核、审批)来实现安全

11.12 与其他生态的对比

11.12.1 VS Code扩展

VS Code的扩展系统是IDE生态的标杆。Claude Code的插件系统与之有相似之处,也有显著不同:

特性VS CodeClaude Code
分发MarketplaceMarketplace
权限声明式权限声明式权限 + 运行时限制
API完整的Extension API工具 + Hook + MCP
沙箱Electron沙箱文件系统 + 网络沙箱
外部能力不支持MCP原生MCP支持

Claude Code的一个独特优势是MCP的原生支持——插件可以提供MCP Server,这使得插件的能力可以超越Claude Code本身的边界。

11.12.2 npm包

npm是JavaScript生态的包管理器。Claude Code的插件系统借鉴了npm的一些理念:

  • 依赖通过npm管理
  • 版本语义化(semver)
  • 作用域(@scope/package-name)

但Claude Code的插件更侧重于AI增强能力,而npm包更侧重于代码复用

11.12.3 Docker插件

Docker也支持插件机制(Docker Plugins),但与Claude Code的定位不同:

  • Docker插件扩展的是容器运行时能力
  • Claude Code插件扩展的是AI开发能力

两者共同的理念是:核心引擎保持精简,通过插件实现可扩展性

11.13 本章小结

Claude Code的插件系统是一个完整的生态构建框架:

  • 生命周期管理:validate → list → install → enable/disable → uninstall → update
  • 三层作用域:user / project / local(e0数组管理)
  • Marketplace:Git sparse-checkout优化的分发中心
  • 插件MCP:插件可以提供MCP Server,实现双向扩展
  • Hook系统:registerHookCallbacks事件驱动,plugin hooks与non-plugin hooks分离
  • --cowork:团队级协作插件共享
  • 安全模型:allowedSettingSources + development channels隔离 + 沙箱执行
  • 版本兼容性:API版本化确保向前/向后兼容
  • 设计哲学:开放但受控

Claude Code的插件系统与MCP协议、多代理协作系统共同构成了一个三层扩展架构:

第1层:MCP协议 ──── 扩展AI的外部能力(数据库、API、文档...)
第2层:多代理协作 ──── 扩展AI的工作模式(并行、专业化、团队...)
第3层:插件系统 ──── 扩展Claude Code本身(工具、Hook、UI...)

这三层扩展架构让Claude Code不再是一个封闭的"工具箱",而是一个开放的"平台"。在这个平台上,任何人都可以贡献能力,任何场景都可以被适配,任何工作流都可以被自动化。

这正是"编程思想"的终极体现——不是通过编写更多的代码来解决问题,而是通过设计更好的架构,让问题不需要被解决。


卷三终

我们从SSE流式处理的字节级实现开始,穿越了MCP协议的标准化接口,深入了多代理协作的团队通信协议,最终抵达了插件系统的生态构建框架。这四个子系统共同回答了一个根本问题:如何让一个AI编程工具具有无限的可扩展性?

答案不是更多的内置功能,而是精心设计的协议、接口和约定。Claude Code的选择是——让系统成为平台,让社区成为引擎

卷四:多态与抽象(高级篇)

基于 MIT 许可发布