Claude Code 源码泄露的背后,到底与Codex,Gemini 有啥不一样?

目录

  1. [从现象出发:Claude Code 是什么?](#从现象出发:Claude Code 是什么? "#1-%E4%BB%8E%E7%8E%B0%E8%B1%A1%E5%87%BA%E5%8F%91claude-code-%E6%98%AF%E4%BB%80%E4%B9%88")
  2. 项目结构:模块化的插件仓库
  3. 整体架构:可扩展的能力注册系统
  4. 记忆系统:三层记忆架构
  5. 上下文管理:动态压缩与快照
  6. [通信协议:流式 API 与实时交互](#通信协议:流式 API 与实时交互 "#6-%E9%80%9A%E4%BF%A1%E5%8D%8F%E8%AE%AE%E6%B5%81%E5%BC%8F-api-%E4%B8%8E%E5%AE%9E%E6%97%B6%E4%BA%A4%E4%BA%92")
  7. [UI 层:Ink 驱动的终端渲染](#UI 层:Ink 驱动的终端渲染 "#7-ui-%E5%B1%82ink-%E9%A9%B1%E5%8A%A8%E7%9A%84%E7%BB%88%E7%AB%AF%E6%B8%B2%E6%9F%93")
  8. 核心模块一:Commands(命令系统)
  9. 核心模块二:Agents(智能代理)
  10. 核心模块三:Skills(技能系统)
  11. 核心模块四:Hooks(钩子与治理)
  12. [MCP 协议:连接外部世界](#MCP 协议:连接外部世界 "#12-mcp-%E5%8D%8F%E8%AE%AE%E8%BF%9E%E6%8E%A5%E5%A4%96%E9%83%A8%E4%B8%96%E7%95%8C")
  13. 工具系统:执行引擎
  14. [实战案例:Feature-Dev 插件剖析](#实战案例:Feature-Dev 插件剖析 "#14-%E5%AE%9E%E6%88%98%E6%A1%88%E4%BE%8Bfeature-dev-%E6%8F%92%E4%BB%B6%E5%89%96%E6%9E%90")
  15. [CLI 使用方式与最佳实践](#CLI 使用方式与最佳实践 "#15-cli-%E4%BD%BF%E7%94%A8%E6%96%B9%E5%BC%8F%E4%B8%8E%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5")
  16. [总结:Markdown 驱动的 AI 应用新范式](#总结:Markdown 驱动的 AI 应用新范式 "#16-%E6%80%BB%E7%BB%93markdown-%E9%A9%B1%E5%8A%A8%E7%9A%84-ai-%E5%BA%94%E7%94%A8%E6%96%B0%E8%8C%83%E5%BC%8F")
  17. [三足鼎立:Claude Code vs Codex vs Gemini CLI](#三足鼎立:Claude Code vs Codex vs Gemini CLI "#17-%E4%B8%89%E8%B6%B3%E9%BC%8E%E7%AB%8Bclaude-code-vs-codex-vs-gemini-cli")

1. 从现象出发:Claude Code 是什么?

1.1 大白话解释

如果说传统的 AI 编程助手(如 GitHub Copilot)是一个"智能的代码补全工具",那么 Claude Code 就是一个住在你终端里的全职程序员

它不仅能写代码,还能:

  • 🔍 理解项目结构:自动分析代码库架构
  • 🤖 自主执行任务:通过工具调用完成复杂操作(git commit、运行测试、创建 PR)
  • 🧠 记住上下文:跨会话记住项目规范和待办事项
  • 🔌 连接外部服务:通过 MCP 协议集成数据库、API 等外部资源
  • 🛡️ 安全治理:通过 Hook 系统拦截危险操作

1.2 核心差异

特性 GitHub Copilot Claude Code
交互模式 代码补全(被动) 对话式 + 自主执行(主动)
执行能力 可执行 Bash、读写文件、调用 API
记忆系统 无状态 项目级配置(CLAUDE.md)+ 会话历史
可扩展性 固定功能 插件系统,用户可自定义
安全机制 Hook 系统拦截 + 权限控制

1.3 应用场景

graph LR User[开发者] -->|"实现登录功能"| Claude[Claude Code] Claude -->|"1. 探索代码"| Explore[Code Explorer Agent] Claude -->|"2. 设计架构"| Architect[Code Architect Agent] Claude -->|"3. 编写代码"| Implement[实现模块] Claude -->|"4. 代码审查"| Review[Code Reviewer Agent] Claude -->|"5. 提交代码"| Git[Git 操作] style Claude fill:#f9f,stroke:#333,stroke-width:4px

2. 项目结构:模块化的插件仓库

2.1 目录树与功能划分

通过逆向分析 claude-code 项目,我们发现这是一个插件仓库 而非核心引擎代码库。核心引擎是 Bun 编译的闭源 CLI 工具(源码可通过逆向提取到 extracted/src/),而这个仓库提供了 13+ 官方插件。核心引擎的源码包含 30+ 内置工具、插件加载器、Hook 执行引擎、MCP 客户端等完整实现。

perl 复制代码
claude-code/
├── .claude/                    # 根级别命令定义
│   └── commands/              # 全局 Slash 命令
│       ├── commit-push-pr.md  # Git 工作流
│       ├── oncall-triage.md   # Issue 分类
│       └── dedupe.md          # 重复检测
├── .claude-plugin/            # 插件市场配置
│   └── marketplace.json       # 13 个插件的注册清单
├── plugins/                   # 插件目录(核心)
│   ├── feature-dev/          # 功能开发工作流
│   ├── code-review/          # 代码审查
│   ├── hookify/              # 用户自定义规则引擎
│   ├── security-guidance/    # 安全警告
│   ├── plugin-dev/           # 插件开发工具包
│   └── ...                   # 其他 8 个插件
├── examples/                  # 示例配置
├── scripts/                   # 自动化脚本
└── doc/                       # 文档

2.2 插件类型分类

graph TB subgraph DevTools["🛠️ 开发工具插件 (4)"] FD[feature-dev
7阶段功能开发] PD[plugin-dev
插件脚手架] ASD[agent-sdk-dev
SDK项目生成] MIG[claude-opus-4-5-migration
模型迁移] end subgraph Productivity["⚡ 生产力插件 (3)"] CR[code-review
自动PR审查] PRT[pr-review-toolkit
6种专业审查] CC[commit-commands
Git提交工作流] end subgraph Learning["📚 学习增强插件 (2)"] EO[explanatory-output-style
教学模式] LO[learning-output-style
互动学习] end subgraph Security["🔐 安全治理插件 (2)"] HF[hookify
自定义行为规则] SG[security-guidance
安全模式拦截] end subgraph Design["🎨 设计辅助插件 (1)"] FE[frontend-design
UI/UX设计指导] end subgraph Other["🔮 其他插件 (1)"] RW[ralph-wiggum
自引用迭代] end Core["🎯 Claude Code 核心引擎
插件注册中心"] Core -.加载.-> DevTools Core -.加载.-> Productivity Core -.加载.-> Learning Core -.加载.-> Security Core -.加载.-> Design Core -.加载.-> Other
类别 插件名称 核心功能
开发工具 feature-dev 7 阶段功能开发工作流
plugin-dev 插件开发脚手架
agent-sdk-dev Claude Agent SDK 项目生成
claude-opus-4-5-migration 模型迁移工具
生产力 code-review 自动化 PR 审查
pr-review-toolkit 6 种专业审查 Agent
commit-commands Git 提交工作流
学习增强 explanatory-output-style 教学模式
learning-output-style 互动学习
安全治理 hookify 用户自定义行为规则
security-guidance 安全模式拦截
设计辅助 frontend-design UI/UX 设计指导
其他 ralph-wiggum 自引用迭代循环

3. 整体架构:可扩展的能力注册系统

3.1 架构分层

Claude Code 采用微内核 + 插件的架构模式。核心引擎负责:

  • 🧠 LLM 交互(流式请求、上下文管理)
  • 🔧 工具执行(Bash, Read, Write, Edit 等)
  • 🔌 MCP 客户端(连接外部服务)
  • 📦 插件加载器(动态发现和注册)

业务逻辑全部由插件提供。

flowchart TB subgraph Layer1["🖥️ 用户交互层 - User Interface Layer"] direction LR CLI["💻 CLI 终端
命令行交互"] VSCode["📝 VSCode 扩展
IDE 集成"] GitHub["🤖 GitHub Bot
CI/CD 自动化"] end subgraph Layer2["⚙️ 核心引擎层 - Core Engine Layer (闭源)"] direction TB subgraph Router_Group["🎯 请求路由模块"] Router["Intent Router
智能意图识别"] end subgraph Context_Group["🧠 上下文管理模块"] Context["Context Manager
记忆压缩·注入"] PluginLoader["Plugin Loader
动态插件发现"] end subgraph Execution_Group["⚡ 执行引擎模块"] ToolEngine["Tool Execution Engine
工具调用·沙箱隔离"] MCPClient["MCP Client
外部服务桥接"] end end subgraph Layer3["🧩 插件生态层 - Plugin Ecosystem Layer (开源)"] direction TB Registry["📋 Capability Registry
能力注册中心"] subgraph Plugin_Types["插件能力矩阵"] direction LR Commands["⚡ Commands
显式调用"] Agents["🤖 Agents
自主决策"] Skills["📚 Skills
隐式注入"] Hooks["🪝 Hooks
行为拦截"] end end subgraph Layer4["🌐 外部服务层 - External Services Layer"] direction LR LLM["🧠 Claude API
Sonnet 4.6/Opus 4.6/Haiku 4.5"] MCP["🔌 MCP Servers
GitHub·DB·FS"] OS["💾 Operating System
文件系统·Shell"] end %% 交互层到核心层 CLI ==>|stdin/stdout| Router VSCode ==>|MCP SDK Protocol| Router GitHub ==>|Webhooks| Router %% 核心层内部流转 Router -->|分发请求| Context Router -->|触发加载| PluginLoader Context -.实时同步.-> PluginLoader PluginLoader ==>|注册能力| Registry %% 插件层到执行引擎 Registry -->|路由| Plugin_Types Commands ==>|Tool Calls| ToolEngine Agents ==>|Tool Calls| ToolEngine Skills -.Prompt注入.-> Context Hooks -.拦截.-> ToolEngine %% 执行引擎到外部服务 Context ==>|API 请求| LLM ToolEngine ==>|MCP 协议| MCPClient ToolEngine ==>|系统调用| OS MCPClient ==>|stdio/SSE/HTTP| MCP

3.2 插件发现与加载流程

核心引擎通过约定优于配置 的方式自动发现插件。实际源码中并不存在独立的 "Capability Registry" 类或 "Intent Router" 类------插件的各组件(Commands、Agents、Skills、Hooks)分别由对应的加载器(loadPluginCommandsloadPluginAgentsloadSkillsDirloadPluginHooks)加载后,通过 React hooks(useMergedCommandsuseMergedTools)在 REPL 运行时合并到工具池和命令列表中:

sequenceDiagram participant Boot as 启动入口 (cli.tsx) participant Init as init() participant Loader as pluginLoader.ts participant FS as File System participant Hooks as useMergedTools/Commands Boot->>Init: 1. 初始化配置、认证、遥测 Init->>Loader: 2. loadAllPlugins() Loader->>FS: 3. 读取 settings.json 中已安装插件列表 loop 遍历每个已启用插件 Loader->>FS: 4. 解析 plugin.json 清单 Loader->>FS: 5. loadPluginCommands (commands/*.md) Loader->>FS: 6. loadPluginAgents (agents/*.md) Loader->>FS: 7. loadSkillsDir (skills/*/SKILL.md) Loader->>FS: 8. loadPluginHooks (hooks/hooks.json) end Loader-->>Hooks: 9. 插件组件注入到 REPL 运行时 Hooks-->>Boot: 10. 合并到工具池 (assembleToolPool)

3.3 核心数据结构

typescript 复制代码
// 实际源码中的插件元数据结构(src/types/plugin.ts + src/utils/plugins/schemas.ts)
// 通过 Zod Schema 验证
interface PluginManifest {
  name: string;              // 插件名称
  version?: string;          // 版本号(可选)
  description?: string;      // 描述
  author?: {                 // 作者信息
    name: string;
    email?: string;
  };
  mcpServers?: {             // MCP 服务器配置
    [serverName: string]: MCPServerConfig;
  };
}

// 实际加载结果类型(src/types/plugin.ts)
interface LoadedPlugin {
  name: string;
  dir: string;
  manifest: PluginManifest;
  components: PluginComponent[];       // 包含 commands, agents, skills, hooks
  source: {
    type: 'marketplace' | 'session' | 'builtin';
    marketplace?: string;
  };
}

// ⚠️ 注意:源码中没有独立的 "CapabilityRegistry" 类
// 插件组件加载后分别存入不同系统:
// - Commands/Skills → 通过 useMergedCommands() 合并到命令列表
// - Agents → 通过 loadPluginAgents() 注册到 AgentDefinitionsResult
// - Hooks → 通过 loadPluginHooks() 注入到 getAllHooks() 结果
// - Tools → 通过 useMergedTools() + assembleToolPool() 合并到工具池

4. 记忆系统:三层记忆架构

4.1 大白话解释

Claude Code 的记忆就像人脑一样分层存储:

  • 🧬 长期记忆(硬盘):用户全局偏好,永久保存
  • 📚 中期记忆(项目文件):项目规范和待办事项,跨会话持久化
  • 💭 短期记忆(RAM):当前对话历史,会话结束即清空

这种设计让 AI 既能记住你的编码习惯,又能适应每个项目的特殊规范。

4.2 三层记忆架构图

flowchart TB subgraph Disk["💾 持久化存储层 - Persistent Storage (Disk)"] direction TB L3["🌍 L3: Global Memory
~/.claude/config.json
📌 用户偏好 · API配置 · 模型设置"] subgraph ProjectLevel["📁 项目级存储"] direction LR L2["📜 L2-A: Project Constitution
CLAUDE.md
🎯 代码规范 · 架构原则"] L2T["✅ L2-B: Todo List
.claude/todos.json
📋 任务队列 · 断点续传"] end end subgraph RAM["⚡ 运行时内存层 - Runtime Memory (RAM)"] direction TB L1["🧬 L1: System Prompt
核心身份定义
🛠️ 工具定义 · Skill SOP · 安全策略"] L0["💭 L0: Session History
对话上下文
💬 用户消息 · AI响应 · 工具调用结果"] end subgraph Pipeline["🔄 上下文处理流水线 - Context Pipeline"] direction TB subgraph Injection["📥 注入阶段"] Injector["Prompt Injector
多源上下文融合器"] end subgraph Compression["📦 压缩阶段"] Monitor["Token Monitor
Token 使用率监控
⚠️ 90%阈值触发"] Compressor["Context Compressor
智能压缩引擎
📸 Summary + Snapshot"] end end FinalContext["🎯 Final Context
最终上下文包
📤 发送给 Claude API"] %% 数据流 - 持久化层到注入器 L3 ==>|"① 用户偏好注入"| Injector L2 ==>|"② 项目规范注入"| Injector L2T ==>|"③ 待办事项注入"| Injector %% 数据流 - 运行时层 L1 ==>|"④ 系统提示词(基座)"| Injector L0 -->|"⑤ 实时监控"| Monitor %% 压缩流程 Monitor -.->|"超过90%"| Compressor Compressor ==>|"压缩结果"| L0 L0 ==>|"⑥ 历史对话"| Injector %% 最终输出 Injector ==>|"⑦ 组装完成"| FinalContext

4.3 记忆层级详解

L3: Global Memory(全局偏好)

存储位置

  • ~/.claude/CLAUDE.md:全局记忆文档(Markdown 格式,跨项目指令)
  • ~/.claude/settings.json:配置文件(JSON 格式,模型、权限规则等)

作用 :跨项目的通用配置和全局指令。CLAUDE.md 类似 Shell 的 .bashrc,而 settings.json 管理结构化配置。

json 复制代码
// ~/.claude/settings.json 结构示例
{
  "model": "claude-sonnet-4-6",
  "permissions": {
    "allow": ["Bash(git *)"],
    "deny": []
  },
  "hooks": {
    "PreToolUse": [...]
  },
  "plugins": {
    "code-review@claude-code-marketplace": { "enabled": true }
  }
}
markdown 复制代码
<!-- ~/.claude/CLAUDE.md 示例 -->
# 全局偏好
- 使用中文回复
- 代码风格:简洁
- 提交信息遵循 Conventional Commits

生命周期 :永久存储。CLAUDE.md 通过 loadMemoryPrompt() 在每次 API 请求时注入 System Prompt;settings.json 通过 enableConfigs() 在启动时加载。

L2: Project Memory(项目规范)

存储位置

  • CLAUDE.md:项目规范文档
  • .claude/todos.json:待办事项队列

CLAUDE.md 示例

markdown 复制代码
# 项目规范:MyApp

## 代码风格
- TypeScript 严格模式
- 使用 Prettier + ESLint
- 组件命名:PascalCase

## 架构原则
- 每个组件单一职责
- 所有函数必须有类型定义
- 错误使用 Result 类型而非异常

## 禁止操作
- ❌ 不要使用 `any` 类型
- ❌ 不要直接修改 package.json
- ❌ 不要提交 .env 文件

## Git 规范
遵循 Conventional Commits:
- feat: 新功能
- fix: Bug 修复
- docs: 文档更新

todos.json 示例

json 复制代码
{
  "version": 1,
  "todos": [
    {
      "content": "实现用户登录功能",
      "status": "in_progress",
      "activeForm": "实现用户登录功能",
      "createdAt": "2026-01-11T10:00:00Z"
    },
    {
      "content": "编写单元测试",
      "status": "pending",
      "activeForm": "编写单元测试",
      "createdAt": "2026-01-11T10:01:00Z"
    }
  ]
}

作用:这是项目的"宪法",AI 必须遵守这些规则。每次会话启动时重新读取。

L1 & L0: Session Memory(会话记忆)

存储位置:内存中的消息数组

数据结构

typescript 复制代码
// 实际源码中的消息类型(src/types/message.ts)
// 注意:不使用简单的 role 字段,而是使用 discriminated union
type Message =
  | UserMessage           // 用户输入 + 工具结果
  | AssistantMessage      // LLM 响应(文本 + 工具调用)
  | ProgressMessage       // 工具执行进度(Hook进度等)
  | AttachmentMessage     // 附件(记忆注入、Hook结果)
  | SystemMessage         // 系统消息(本地命令输出等)
  | ToolUseSummaryMessage // 工具使用摘要
  | TombstoneMessage      // 已删除消息占位

// AssistantMessage 的核心结构
interface AssistantMessage {
  type: 'assistant';
  uuid: string;
  message: {
    content: Array<TextBlock | ToolUseBlock>;  // 可同时包含文本和工具调用
    stop_reason: 'end_turn' | 'tool_use' | 'max_tokens';
  };
  costUsd: number;
  durationMs: number;
}

// UserMessage 承载用户输入和工具结果
interface UserMessage {
  type: 'user';
  uuid: string;
  message: {
    content: Array<TextBlock | ToolResultBlock>;
  };
}

生命周期 :仅在当前 CLI 进程存活。消息数组存储在 ToolUseContext.messages 中,一旦 Token 超限(90% 阈值),触发自动压缩机制(autoCompact)。

4.4 上下文组装逻辑

核心引擎在每次调用 Claude API 前,通过 getSystemPrompt()query() 函数组装完整上下文:

typescript 复制代码
// 实际源码逻辑(src/constants/prompts.ts + src/query.ts 精简)
async function getSystemPrompt(tools: Tools, model: string): Promise<SystemPrompt> {
  const sections: SystemPromptSection[] = [];

  // 1. 核心身份(模型名称、版本、能力说明)
  sections.push(systemPromptSection('core_identity', getCoreIdentity(model)));

  // 2. 工具定义(30+ 工具的 prompt 文本)
  for (const tool of tools) {
    sections.push(systemPromptSection(`tool_${tool.name}`, await tool.prompt(ctx)));
  }

  // 3. Skill 元数据(名称 + 描述,供 LLM 判断是否调用)
  const skills = getSkillToolCommands(commands);
  if (skills.length > 0) {
    sections.push(systemPromptSection('skills', buildSkillSection(skills)));
  }

  // 4. 安全规则
  sections.push(systemPromptSection('security', CYBER_RISK_INSTRUCTION));

  // 5. 输出样式(如果安装了 output-style 插件)
  const outputStyle = getOutputStyleConfig();
  if (outputStyle) {
    sections.push(systemPromptSection('output_style', outputStyle.instructions));
  }

  // 6. MCP 服务器指令
  for (const client of mcpClients) {
    if (client.instructions) {
      sections.push(systemPromptSection(`mcp_${client.name}`, client.instructions));
    }
  }

  return resolveSystemPromptSections(sections);
}

// CLAUDE.md 通过 loadMemoryPrompt() 在 query() 中作为 attachment 注入
// 不是作为 system message,而是通过 AttachmentMessage 机制
async function loadMemoryPrompt(): Promise<string | null> {
  const parts: string[] = [];
  // 1. ~/.claude/CLAUDE.md(全局)
  // 2. ./CLAUDE.md(项目)
  // 3. 向上遍历到 $HOME 的所有 CLAUDE.md
  return parts.join('\n\n');
}

纠正 :原文描述将 CLAUDE.md 作为 <project_rules> 标签注入 system message。实际源码中,CLAUDE.md 的内容通过 loadMemoryPrompt()(位于 src/memdir/memdir.ts)加载,并作为 AttachmentMessage 附加到消息列表中,由 query()normalizeMessagesForAPI() 时合并。

4.5 核心洞察

Claude Code 的"记忆"是一种错觉

它并没有真正的数据库,而是通过每次请求前疯狂读取文件 并塞入 System Prompt,来模拟一个"记得项目背景"的 AI。这种 Stateless to Stateful 的转换技巧,是其架构的精髓。

优势

  • ✅ 简单:无需维护数据库
  • ✅ 透明:记忆内容就是文件内容
  • ✅ 可控:用户可直接编辑 CLAUDE.md

劣势

  • ⚠️ 每次启动都要重新读取
  • ⚠️ 无法存储超大历史记录
  • ⚠️ 依赖文件系统

5. 上下文管理:动态压缩与快照

5.1 为什么需要上下文压缩?

LLM 的 Context Window 是稀缺资源。Claude Sonnet 4.6 的默认上下文为 200K tokens(1M context 版本可扩展到 1M),看似很多,但在实际开发中:

diff 复制代码
一次完整的功能开发对话可能消耗:
- System Prompt: 5K tokens
- CLAUDE.md: 2K tokens
- 代码文件读取: 20K tokens
- 工具调用结果: 10K tokens
- 对话历史: 每轮 2-5K tokens

假设 30 轮对话 = 5K + 2K + 20K + 10K + (30 × 3K) = 127K tokens

当超过 **90% 阈值(180K tokens)**时,必须压缩,否则下一轮对话会失败。

5.2 压缩策略流程图

sequenceDiagram participant Engine as 核心引擎 participant Monitor as Token 监控器 participant LLM as Claude API participant Compressor as 压缩器 Engine->>Monitor: 1. 每轮对话后检查 Token 使用 Monitor->>Monitor: 2. 计算当前 Token 占用 alt Token < 90% Monitor-->>Engine: 继续正常对话 else Token >= 90% Monitor->>Compressor: 3. 触发压缩流程 Compressor->>LLM: 4. 调用 LLM 生成对话摘要 Note over Compressor,LLM: Prompt: "总结之前的对话,
保留关键信息和决策" LLM-->>Compressor: 5. 返回摘要(Summary) Compressor->>Compressor: 6. 生成环境快照(Snapshot)
- Git 状态
- 文件树
- 待办事项 Compressor->>Compressor: 7. 丢弃旧对话历史
保留最近 5 轮 Compressor->>Engine: 8. 重构 Context:
[Summary] + [Snapshot] + [Recent 5] Engine->>Monitor: 9. 重置 Token 计数器 Monitor-->>Engine: 继续对话 end

5.3 压缩器核心实现

typescript 复制代码
// [伪代码] Context Compressor
class ContextCompressor {
  private readonly THRESHOLD = 0.9; // 90% 阈值
  private readonly CONTEXT_LIMIT = 200000; // 200K tokens
  private readonly KEEP_RECENT = 5; // 保留最近 5 轮对话

  // 检查是否需要压缩
  async checkAndCompress(history: Message[]): Promise<Message[]> {
    const currentTokens = this.estimateTokens(history);

    if (currentTokens < this.CONTEXT_LIMIT * this.THRESHOLD) {
      return history; // 无需压缩
    }

    console.log(`Token 使用达到 ${(currentTokens / this.CONTEXT_LIMIT * 100).toFixed(1)}%,触发压缩...`);

    // 1. 生成对话摘要
    const summary = await this.generateSummary(history);

    // 2. 生成环境快照
    const snapshot = await this.generateSnapshot();

    // 3. 保留最近的对话
    const recentMessages = history.slice(-this.KEEP_RECENT * 2); // 每轮包含 user + assistant

    // 4. 重构上下文
    return [
      {
        role: 'system',
        content: `<conversation_summary>\n${summary}\n</conversation_summary>`
      },
      {
        role: 'system',
        content: `<environment_snapshot>\n${snapshot}\n</environment_snapshot>`
      },
      ...recentMessages
    ];
  }

  // 生成对话摘要(调用 LLM)
  private async generateSummary(history: Message[]): Promise<string> {
    const summaryPrompt = `
请总结之前的对话内容,保留以下关键信息:
1. 用户的核心需求和目标
2. 已经完成的工作和决策
3. 遇到的问题和解决方案
4. 待完成的任务

保持简洁,突出重点。

<previous_conversation>
${this.formatHistoryForSummary(history)}
</previous_conversation>
    `;

    const response = await this.llm.chat([
      { role: 'user', content: summaryPrompt }
    ], {
      model: 'haiku', // 使用 Haiku 降低成本
      maxTokens: 2000
    });

    return response.content;
  }

  // 生成环境快照
  private async generateSnapshot(): Promise<string> {
    const parts: string[] = [];

    // Git 状态
    try {
      const gitStatus = await exec('git status --short');
      const gitBranch = await exec('git branch --show-current');
      parts.push(`## Git 状态\n分支:${gitBranch}\n变更:\n${gitStatus}`);
    } catch (e) {
      // 非 Git 项目
    }

    // 文件树(简化)
    try {
      const tree = await exec('tree -L 2 -I "node_modules|.git"');
      parts.push(`## 项目结构\n${tree}`);
    } catch (e) {
      // tree 命令不存在
    }

    // 待办事项
    const todos = await loadTodos('.claude/todos.json');
    if (todos.length > 0) {
      const todoList = todos.map((t, i) =>
        `${i + 1}. [${t.status}] ${t.content}`
      ).join('\n');
      parts.push(`## 待办事项\n${todoList}`);
    }

    return parts.join('\n\n');
  }

  // 估算 Token 数量(简化版)
  private estimateTokens(messages: Message[]): number {
    let total = 0;
    for (const msg of messages) {
      const content = typeof msg.content === 'string'
        ? msg.content
        : JSON.stringify(msg.content);
      // 粗略估算:1 token ≈ 4 字符
      total += Math.ceil(content.length / 4);
    }
    return total;
  }
}

5.4 压缩前后对比

压缩前(180K tokens):

css 复制代码
[System Prompt: 5K]
[CLAUDE.md: 2K]
[Todos: 1K]
[第1轮对话: 3K]
[第2轮对话: 4K]
...
[第30轮对话: 5K]
总计:~180K tokens

压缩后(40K tokens):

css 复制代码
[System Prompt: 5K]
[CLAUDE.md: 2K]
[Todos: 1K]
[对话摘要: 2K]          ← 替代前 25 轮对话
[环境快照: 3K]          ← Git/文件树/待办
[第26轮对话: 3K]        ← 保留最近 5 轮
[第27轮对话: 4K]
[第28轮对话: 3K]
[第29轮对话: 5K]
[第30轮对话: 5K]
总计:~40K tokens

压缩比:77.8%(节省 140K tokens)

5.5 用户触发的手动压缩

用户可以通过 /compact 命令手动触发压缩:

bash 复制代码
# 感觉 AI 反应变慢或开始产生幻觉时
/compact

这会强制执行压缩流程,让 AI"清醒"过来。


6. 通信协议:流式 API 与实时交互

6.1 为什么使用流式 API?

传统的 Request-Response 模式会让用户等待很久才看到结果,而流式 API可以边生成边显示:

css 复制代码
传统模式:
用户提问 → [等待 10 秒] → 完整回答一次性显示

流式模式:
用户提问 → [0.5秒] → "我" → [0.5秒] → "会" → [0.5秒] → "帮" → ...

6.2 通信流程图

sequenceDiagram participant User as 用户输入 participant CLI as CLI 主进程 participant API as Claude API participant UI as UI 渲染器 User->>CLI: 1. 输入问题 CLI->>CLI: 2. 构建 Context CLI->>API: 3. POST /v1/messages
stream=true loop 流式返回 API-->>CLI: 4. SSE chunk: text CLI->>UI: 5. 更新显示 UI-->>User: 实时渲染文本 API-->>CLI: 6. SSE chunk: tool_use CLI->>UI: 7. 显示 "正在执行工具..." CLI->>CLI: 8. 执行工具调用 CLI->>API: 9. 继续对话(附带结果) API-->>CLI: 10. SSE chunk: more text CLI->>UI: 11. 继续渲染 end API-->>CLI: 12. SSE: stop_reason=end_turn CLI->>UI: 13. 对话完成

6.3 流式 API 调用实现

typescript 复制代码
// [伪代码] Streaming API Client
class ClaudeStreamClient {
  async chat(
    messages: Message[],
    options: {
      model?: string;
      maxTokens?: number;
      onChunk?: (chunk: StreamChunk) => void;
    }
  ): Promise<string> {
    const response = await fetch('https://api.anthropic.com/v1/messages', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-API-Key': this.apiKey,
        'anthropic-version': '2023-06-01',
        // 注意:CLI 不使用 anthropic-dangerous-direct-browser-access 头
      },
      body: JSON.stringify({
        model: options.model || 'claude-sonnet-4-6-20250514',
        max_tokens: options.maxTokens || 8192,
        messages,
        stream: true, // 关键:启用流式
        tools: this.getToolDefinitions() // 工具定义
      })
    });

    const reader = response.body.getReader();
    const decoder = new TextDecoder();
    let fullText = '';
    let buffer = '';

    while (true) {
      const { done, value } = await reader.read();
      if (done) break;

      // 解析 SSE 格式
      buffer += decoder.decode(value, { stream: true });
      const lines = buffer.split('\n');
      buffer = lines.pop() || ''; // 保留不完整的行

      for (const line of lines) {
        if (line.startsWith('data: ')) {
          const data = line.slice(6);
          if (data === '[DONE]') continue;

          try {
            const chunk = JSON.parse(data);

            // 处理不同类型的 chunk
            switch (chunk.type) {
              case 'content_block_start':
                // 新的内容块开始
                if (chunk.content_block.type === 'text') {
                  // 文本块
                } else if (chunk.content_block.type === 'tool_use') {
                  // 工具调用块
                  options.onChunk?.({
                    type: 'tool_use_start',
                    toolName: chunk.content_block.name
                  });
                }
                break;

              case 'content_block_delta':
                // 内容增量更新
                if (chunk.delta.type === 'text_delta') {
                  const text = chunk.delta.text;
                  fullText += text;
                  options.onChunk?.({
                    type: 'text',
                    text
                  });
                }
                break;

              case 'content_block_stop':
                // 内容块结束
                break;

              case 'message_stop':
                // 消息结束
                options.onChunk?.({
                  type: 'done',
                  stopReason: chunk.stop_reason
                });
                break;
            }
          } catch (e) {
            console.error('Parse SSE error:', e);
          }
        }
      }
    }

    return fullText;
  }
}

6.4 SSE (Server-Sent Events) 协议

Claude API 使用 SSE 协议进行流式传输:

css 复制代码
事件格式:
data: {"type": "content_block_start", ...}

data: {"type": "content_block_delta", "delta": {"type": "text_delta", "text": "Hello"}}

data: {"type": "content_block_delta", "delta": {"type": "text_delta", "text": " World"}}

data: {"type": "message_delta", "delta": {"stop_reason": "end_turn"}}

data: {"type": "message_stop"}

关键事件类型

事件类型 说明
message_start 消息开始
content_block_start 内容块开始(文本或工具调用)
content_block_delta 内容增量更新
content_block_stop 内容块结束
message_delta 元数据更新(如 Token 使用)
message_stop 消息结束

6.5 错误处理与重试

typescript 复制代码
class StreamErrorHandler {
  async retryWithBackoff<T>(
    fn: () => Promise<T>,
    maxRetries: number = 3
  ): Promise<T> {
    for (let i = 0; i < maxRetries; i++) {
      try {
        return await fn();
      } catch (error) {
        if (i === maxRetries - 1) throw error;

        // 指数退避
        const delayMs = Math.pow(2, i) * 1000;
        console.log(`请求失败,${delayMs}ms 后重试...`);
        await sleep(delayMs);
      }
    }
    throw new Error('Max retries exceeded');
  }

  handleStreamError(error: any): void {
    if (error.status === 429) {
      console.error('⚠️ API 速率限制,请稍后再试');
    } else if (error.status === 500) {
      console.error('⚠️ API 服务器错误,请稍后再试');
    } else if (error.message.includes('overloaded')) {
      console.error('⚠️ API 负载过高,请稍后再试');
    } else {
      console.error(`❌ 通信错误: ${error.message}`);
    }
  }
}

7. UI 层:Ink 驱动的终端渲染

7.1 为什么选择 Ink?

传统 CLI 工具使用 console.log() 线性打印,无法实现:

  • ❌ 动态更新(如进度条、Spinner)
  • ❌ 彩色输出和格式化
  • ❌ 交互式选择(如多选菜单)

重要纠正 :Claude Code 并非直接使用 ink npm 包,而是基于 react-reconciler 自建了一套完整的终端渲染引擎(位于 src/ink/ 目录,包含 40+ 个文件)。它借鉴了 Ink 的设计理念,但包含自定义的 Yoga 布局引擎(src/ink/layout/)、ANSI 渲染器、滚动容器、超链接支持等。用 JSX 编写 CLI 界面的概念相同:

tsx 复制代码
// 传统方式
console.log('Loading...');
// 无法更新这行文本

// Ink 方式
<Text color="cyan">
  <Spinner /> Loading...
</Text>
// 可以实时更新 Spinner 动画

7.2 Ink 架构原理

graph LR subgraph "React Layer (src/components/)" JSX[JSX 组件
Box, Text, ScrollBox] VirtualDOM[Virtual DOM] end subgraph "Custom Ink Engine (src/ink/)" Reconciler[react-reconciler
自定义 Reconciler] Layout[Yoga Layout Engine
src/ink/layout/] Renderer[render-node-to-output.ts
渲染到缓冲区] end subgraph "Terminal Layer" ANSI[ANSI Escape Codes
chalk + 自定义 colorize.ts] Stdout[stdout] end JSX -->|"渲染"| VirtualDOM VirtualDOM -->|"Diff 计算"| Reconciler Reconciler -->|"布局计算"| Layout Layout -->|"生成渲染指令"| Renderer Renderer -->|"转换为"| ANSI ANSI -->|"render-to-screen.ts"| Stdout style Reconciler fill:#61dafb style Layout fill:#4caf50

7.3 核心 UI 组件

tsx 复制代码
// [伪代码] Claude Code 的主 UI 组件
// 注意:Box、Text 等组件来自 src/ink/components/,不是 npm 的 ink 包
import { Box, Text } from '../ink/components';
import { Spinner } from '../components/Spinner';
import { useState, useEffect } from 'react';

function ClaudeCodeUI() {
  const [messages, setMessages] = useState<Message[]>([]);
  const [isThinking, setIsThinking] = useState(false);
  const [toolStatus, setToolStatus] = useState<string | null>(null);

  return (
    <Box flexDirection="column">
      {/* 对话历史 */}
      {messages.map((msg, i) => (
        <Message key={i} message={msg} />
      ))}

      {/* 工具执行状态 */}
      {toolStatus && (
        <Box marginTop={1}>
          <Text color="cyan">
            <Spinner type="dots" /> {toolStatus}
          </Text>
        </Box>
      )}

      {/* AI 思考状态 */}
      {isThinking && (
        <Box marginTop={1}>
          <Text color="yellow">
            <Spinner type="simpleDotsScrolling" /> Claude 正在思考...
          </Text>
        </Box>
      )}
    </Box>
  );
}

// 消息组件
function Message({ message }: { message: Message }) {
  if (message.role === 'user') {
    return (
      <Box marginTop={1}>
        <Text bold color="green">You: </Text>
        <Text>{message.content}</Text>
      </Box>
    );
  } else if (message.role === 'assistant') {
    return (
      <Box marginTop={1}>
        <Text bold color="blue">Claude: </Text>
        <MarkdownText>{message.content}</MarkdownText>
      </Box>
    );
  }
  return null;
}

// Markdown 渲染组件
function MarkdownText({ children }: { children: string }) {
  // 简化版:实际会解析 Markdown 并应用样式
  const lines = children.split('\n');
  return (
    <>
      {lines.map((line, i) => {
        // 代码块
        if (line.startsWith('```')) {
          return <Text key={i} color="gray" backgroundColor="black">{line}</Text>;
        }
        // 标题
        if (line.startsWith('#')) {
          return <Text key={i} bold>{line}</Text>;
        }
        // 普通文本
        return <Text key={i}>{line}</Text>;
      })}
    </>
  );
}

7.4 乐观更新(Optimistic UI)

Claude Code 使用乐观更新策略,在工具实际执行前就显示"正在执行"状态:

tsx 复制代码
// [伪代码] 工具调用的乐观更新
function ToolCallHandler() {
  const [toolCalls, setToolCalls] = useState<ToolCall[]>([]);

  // 当 LLM 返回 tool_use 时立即更新 UI
  useEffect(() => {
    claudeAPI.on('tool_use_start', (toolCall) => {
      // 立即显示"正在执行"
      setToolCalls(prev => [...prev, {
        ...toolCall,
        status: 'pending'
      }]);

      // 异步执行工具
      executeToolAsync(toolCall).then(result => {
        // 完成后更新状态
        setToolCalls(prev => prev.map(tc =>
          tc.id === toolCall.id
            ? { ...tc, status: 'completed', result }
            : tc
        ));
      });
    });
  }, []);

  return (
    <Box flexDirection="column">
      {toolCalls.map(tc => (
        <Box key={tc.id} marginTop={1}>
          {tc.status === 'pending' && (
            <Text color="cyan">
              <Spinner /> 执行中: {tc.name}
            </Text>
          )}
          {tc.status === 'completed' && (
            <Text color="green">
              ✓ 完成: {tc.name}
            </Text>
          )}
        </Box>
      ))}
    </Box>
  );
}

7.5 实时性能优化

Ink 使用 React Fiber 架构,可以优先渲染重要的更新:

tsx 复制代码
// 高优先级:用户输入反馈
<Text color="green">{userInput}</Text>

// 中优先级:工具执行状态
<Spinner /> Executing git status...

// 低优先级:日志输出
<Text dimColor>{debugLog}</Text>

7.6 ANSI 颜色与样式

Ink 底层使用 ANSI Escape Codes 实现终端样式:

typescript 复制代码
// ANSI 颜色代码
const ANSI = {
  RESET: '\x1b[0m',
  BOLD: '\x1b[1m',
  RED: '\x1b[31m',
  GREEN: '\x1b[32m',
  YELLOW: '\x1b[33m',
  BLUE: '\x1b[34m',
  CYAN: '\x1b[36m',
};

// 示例输出
console.log(`${ANSI.BOLD}${ANSI.GREEN}✓ Success${ANSI.RESET}`);
// 显示为:粗体绿色的 "✓ Success"

Ink 封装了这些复杂的转义码,提供声明式的 API:

tsx 复制代码
<Text bold color="green">✓ Success</Text>

8. 核心模块一:Commands(命令系统)

8.1 什么是 Command?

重要说明 :在 v2.1.88 的源码中,commands/ 目录已被标记为 commands_DEPRECATED(见 src/skills/loadSkillsDir.ts),新的推荐方式是使用 skills/ 目录。两者的 Frontmatter 格式相同,但 Skills 提供了更丰富的元数据(whenToUsemodelversion 等)。为保持文档的历史连贯性,本章仍以 Command 术语描述。

Command(现称 Skill) 是用户通过 Slash 命令 (如 /commit/review)直接调用的预定义 Prompt。它类似于 ChatGPT 的"自定义指令",但更强大:

  • ✅ 可以预授权工具权限(无需每次确认)
  • ✅ 支持参数传递(/feature-dev 实现登录功能
  • ✅ 可以调用其他 Agent
  • ✅ 支持 $ARGUMENTS 和索引参数 $0, $1 等变量替换

8.2 Command 文件格式

所有 Command 都是 Markdown + YAML Frontmatter 格式:

markdown 复制代码
---
description: 创建 Git 提交并推送到远程分支
argument-hint: 可选的提交信息
allowed-tools: [Bash(*), Read, TodoWrite]
---

# Commit Push PR 工作流

你是一个 Git 工作流专家。用户想要提交代码并创建 PR。

## 执行步骤

1. 运行 `git status` 查看变更文件
2. 运行 `git diff` 查看具体改动
3. 根据改动生成符合 Conventional Commits 规范的提交信息
4. 执行 `git add .` 和 `git commit -m "..."`
5. 推送到远程:`git push`
6. 使用 `gh pr create` 创建 Pull Request

## 注意事项

- 提交信息必须包含 `Co-Authored-By:` 行(模型名称根据实际使用的模型动态生成,见 `src/utils/commitAttribution.ts`)
- 不要提交 `.env`、`credentials.json` 等敏感文件

8.3 Command 调用流程

sequenceDiagram participant User as 用户 participant Router as Intent Router participant Registry as Command Registry participant LLM as Claude API participant Tools as Tool Engine User->>Router: 输入 "/commit 修复登录bug" Router->>Registry: 1. 查找 "commit" 命令 Registry-->>Router: 2. 返回 Command 定义 Router->>Router: 3. 读取 Markdown 内容 Router->>Router: 4. 替换 $ARGUMENTS = "修复登录bug" Router->>LLM: 5. 注入 System Prompt + Command LLM-->>Router: 6. 返回工具调用 (Bash: git status) Router->>Tools: 7. 执行 git status Tools-->>Router: 8. 返回执行结果 Router->>LLM: 9. 继续对话循环 LLM-->>User: 10. 显示最终结果

8.4 核心代码逆向还原

typescript 复制代码
// [伪代码] Command 解析器
class CommandParser {
  // 解析 Markdown 文件
  parse(filePath: string): CommandDefinition {
    const content = fs.readFileSync(filePath, 'utf-8');
    const { attributes, body } = parseFrontmatter(content);

    return {
      name: path.basename(filePath, '.md'),
      description: attributes.description,
      argumentHint: attributes['argument-hint'],
      allowedTools: attributes['allowed-tools'] || [],
      prompt: body, // Markdown 正文作为 Prompt
    };
  }

  // 生成最终 System Prompt
  buildSystemPrompt(command: CommandDefinition, userArgs: string): string {
    // 替换 $ARGUMENTS 变量
    let prompt = command.prompt.replace(/\$ARGUMENTS/g, userArgs);

    // 添加工具权限说明
    if (command.allowedTools.length > 0) {
      prompt += `\n\n## 可用工具\n${command.allowedTools.join(', ')}`;
    }

    return prompt;
  }
}

// 调用示例
const parser = new CommandParser();
const commitCommand = parser.parse('plugins/commit-commands/commands/commit.md');
const systemPrompt = parser.buildSystemPrompt(commitCommand, '修复登录bug');
// 发送到 LLM...

9. 核心模块二:Agents(智能代理)

9.1 什么是 Agent?

Agent 是一个自主执行的 AI 实体,拥有独立的:

  • 🎯 目标(Goal)
  • 🧰 工具集(Tools)
  • 🎨 人格(Model + Color)
  • 🔒 隔离上下文(不污染主对话)

Agent 与 Command/Skill 的区别:

特性 Command/Skill Agent
触发方式 用户 /command 调用或 LLM 调用 SkillTool LLM 调用 AgentTool 派生
执行模式 在主上下文运行 隔离的子上下文运行
工具权限 需要在 frontmatter 声明 同样需要声明
返回结果 对话式输出 返回结果摘要到主上下文
并行能力 支持多 Agent 并行(同一消息多个 AgentTool 调用)
实际工具名 SkillTool AgentTool (src/tools/AgentTool/)

9.2 Agent 文件格式

markdown 复制代码
---
name: code-explorer
description: 深度分析现有代码库功能,追踪执行路径和架构层次
tools: [Glob, Grep, Read, TodoWrite, WebFetch]
model: sonnet
color: yellow
---

你是一个代码分析专家,专注于追踪和理解功能实现。

## 核心任务

提供完整的功能理解,从入口点到数据存储,贯穿所有抽象层。

## 分析方法

**1. 功能发现**
- 找到入口点(API、UI 组件、CLI 命令)
- 定位核心实现文件
- 绘制功能边界和配置

**2. 代码流程追踪**
- 跟随调用链从输入到输出
- 追踪每一步的数据转换
- 识别所有依赖和集成

**3. 架构分析**
- 绘制抽象层(展示层 → 业务逻辑 → 数据层)
- 识别设计模式和架构决策
- 记录组件间的接口

## 输出要求

提供包含以下内容的全面分析:
- 入口点(文件:行号)
- 逐步执行流程和数据转换
- 关键组件及其职责
- 架构洞察:模式、分层、设计决策
- **必须包含:最关键的 5-10 个文件列表**

9.3 Agent 派生与调度

graph TD MainContext[主上下文] -->|"LLM 调用 Agent 工具"| AgentTool[AgentTool
src/tools/AgentTool/] AgentTool -->|"createSubagentContext()"| SubContext1[Sub-Agent 1
code-explorer] AgentTool -->|"createSubagentContext()"| SubContext2[Sub-Agent 2
code-architect] AgentTool -->|"createSubagentContext()"| SubContext3[Sub-Agent 3
code-reviewer] SubContext1 -->|"独立执行"| Result1[分析报告 1] SubContext2 -->|"独立执行"| Result2[设计方案 2] SubContext3 -->|"独立执行"| Result3[审查报告 3] Result1 --> Merge[合并结果] Result2 --> Merge Result3 --> Merge Merge -->|"返回主上下文"| MainContext style TaskTool fill:#4ecdc4 style Merge fill:#ffd93d

9.4 核心代码:Agent 调度器

typescript 复制代码
// [伪代码] Agent 调度器
class AgentScheduler {
  // 派生子 Agent
  async spawnAgent(
    agentName: string,
    task: string,
    options: {
      fork?: boolean,    // 是否隔离上下文
      model?: 'sonnet' | 'opus' | 'haiku',
      maxTurns?: number, // 最大对话轮数
    }
  ): Promise<AgentResult> {
    // 1. 从注册表加载 Agent 定义
    const agentDef = this.registry.getAgent(agentName);
    if (!agentDef) throw new Error(`Agent not found: ${agentName}`);

    // 2. 构建子上下文
    const subContext = options.fork
      ? this.createIsolatedContext()  // 隔离上下文(不继承主对话)
      : this.cloneContext();          // 克隆上下文(继承历史)

    // 3. 注入 Agent 的 System Prompt
    subContext.addSystemMessage(agentDef.prompt);
    subContext.addUserMessage(task);

    // 4. 设置工具权限
    subContext.setAllowedTools(agentDef.tools);

    // 5. 执行 Agent Loop(类似主循环)
    let turns = 0;
    while (turns < (options.maxTurns || 20)) {
      // 注意:实际源码中 temperature 固定为 1(API 要求开启思考时必须为 1)
      const response = await this.llm.chat(subContext, {
        model: options.model || agentDef.model || 'sonnet',
        temperature: 1,
      });

      // 如果完成任务,返回结果
      if (response.stopReason === 'end_turn') {
        return {
          agentName,
          transcript: subContext.messages,
          summary: response.content,
        };
      }

      // 执行工具调用
      if (response.toolCalls) {
        const results = await this.toolEngine.execute(response.toolCalls);
        subContext.addToolResults(results);
      }

      turns++;
    }

    // 超时返回
    return { agentName, error: 'Max turns exceeded' };
  }

  // 并行执行多个 Agent
  async spawnParallel(tasks: Array<{agent: string, task: string}>): Promise<AgentResult[]> {
    return Promise.all(
      tasks.map(t => this.spawnAgent(t.agent, t.task, { fork: true }))
    );
  }
}

9.5 实际应用:Feature-Dev 的 7 阶段工作流

feature-dev 插件通过多 Agent 协作实现复杂的功能开发流程:

flowchart TD Start[用户: /feature-dev 实现登录功能] --> Phase1[Phase 1: Discovery
理解需求] Phase1 --> Phase2[Phase 2: Codebase Exploration
派生 3 个 code-explorer Agents] Phase2 --> ReadFiles[读取 Agents 推荐的关键文件] ReadFiles --> Phase3[Phase 3: Clarifying Questions
询问未明确的细节] Phase3 --> Phase4[Phase 4: Architecture Design
派生 3 个 code-architect Agents] Phase4 --> UserApproval{用户批准方案?} UserApproval -->|否| Phase4 UserApproval -->|是| Phase5[Phase 5: Implementation
编写代码] Phase5 --> Phase6[Phase 6: Quality Review
派生 3 个 code-reviewer Agents] Phase6 --> FixIssues{需要修复?} FixIssues -->|是| Phase5 FixIssues -->|否| Phase7[Phase 7: Summary
总结完成] style Phase2 fill:#ffcccb style Phase4 fill:#add8e6 style Phase6 fill:#90ee90

10. 核心模块三:Skills(技能系统)

10.1 什么是 Skill?

Skill 是一种可被 LLM 自主调用的 SOP(标准操作流程) 。Skill 的元数据(name、description)始终在 System Prompt 中,LLM 根据用户意图判断是否通过 SkillTool 调用某个 Skill。

重要纠正:原文描述 Skill 是"通过触发短语自动激活"的隐式注入。实际源码中,Skill 的触发方式有两种:

  1. LLM 主动调用 :Skill 元数据列在 System Prompt 中,LLM 判断相关时调用 SkillTool(src/tools/SkillTool/
  2. 用户显式调用 :用户输入 /skill-name 直接调用

并不存在基于关键词的自动匹配引擎。

类比:

  • 旧版 Command = 用户 /commit 显式调用
  • Skill = LLM 看到元数据后自主决策是否调用(半隐式);也可由用户 /skill-name 显式调用

10.2 Skill 文件格式

markdown 复制代码
---
name: Frontend Design
description: 当用户提到 "design", "UI", "frontend", "用户界面" 时触发。提供高质量前端实现指导。
version: 0.1.0
---

# 前端设计技能

## 触发场景

当检测到以下关键词时自动激活:
- "设计登录页面"
- "优化 UI 性能"
- "实现响应式布局"

## 设计原则

### 1. 组件化思维
- 单一职责原则
- Props 接口清晰
- 避免 Prop Drilling

### 2. 性能优化
- 使用 React.memo 避免不必要渲染
- 代码分割(React.lazy + Suspense)
- 图片懒加载

### 3. 可访问性(a11y)
- 语义化 HTML
- ARIA 标签
- 键盘导航支持

## 代码规范

```tsx
// ✅ 好的实践
function LoginButton({ onClick, disabled, children }: ButtonProps) {
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      aria-label="登录"
      className="btn btn-primary"
    >
      {children}
    </button>
  );
}

// ❌ 避免的做法
function Button(props) {  // 缺少类型定义
  return <div onClick={props.click}>click me</div>;  // 非语义化标签
}

审查清单

  • 组件是否可复用?
  • 是否有 TypeScript 类型定义?
  • 是否处理了加载和错误状态?
  • 是否支持深色模式?
  • 是否通过了 a11y 测试?
less 复制代码
### 10.3 Skill 渐进式加载

Skill 采用**三层加载策略**,平衡 Token 消耗与知识可用性:

```mermaid
graph BT
    subgraph Level3["Level 3: References (磁盘)"]
        Refs["详细文档<br/>代码示例<br/>API 参考"]
        note3["超高 Token 成本<br/>仅在需要时 Read"]
    end

    subgraph Level2["Level 2: SOP Body (上下文)"]
        Body["设计原则<br/>代码规范<br/>审查清单"]
        note2["中等 Token 成本<br/>触发时注入"]
    end

    subgraph Level1["Level 1: Metadata (内存)"]
        Meta["Name<br/>Description<br/>触发短语"]
        note1["极低 Token 成本<br/>常驻内存"]
    end

    Meta -->|"关键词命中"| Body
    Body -->|"需要细节"| Refs

    style Meta fill:#90ee90
    style Body fill:#add8e6
    style Refs fill:#ffcccb

10.4 Skill 注入逻辑

typescript 复制代码
// 实际源码逻辑(src/skills/loadSkillsDir.ts + src/tools/SkillTool/)

// 1. 启动时:加载所有 Skill 的 frontmatter 元数据
async function loadSkillsFromDir(dir: string): Promise<Command[]> {
  const skillDirs = await readdir(dir);
  const skills: Command[] = [];

  for (const skillName of skillDirs) {
    const skillPath = join(dir, skillName, 'SKILL.md');
    if (!await pathExists(skillPath)) continue;

    const content = await readFile(skillPath, 'utf-8');
    const { attributes, body } = parseFrontmatter(content);

    skills.push({
      type: 'prompt',
      name: attributes.name || skillName,
      description: coerceDescriptionToString(attributes.description),
      // 完整内容懒加载 --- 调用时才读取 body
      getContent: () => body,
      allowedTools: parseSlashCommandToolsFromFrontmatter(attributes),
      model: parseUserSpecifiedModel(attributes.model),
    });
  }
  return skills;
}

// 2. System Prompt 中列出所有 Skill 元数据,供 LLM 决策
// (在 src/constants/prompts.ts 的 getSystemPrompt 中)

// 3. LLM 决定调用时 → SkillTool.call() 读取完整内容
// ⚠️ 注意:没有关键词匹配引擎,是 LLM 自主决策

// 实际的 Skill 调用流程:
// 用户: "帮我设计一个登录页面"
// LLM 看到 System Prompt 中有: "- Frontend Design: 提供高质量前端实现指导"
// LLM 决定调用: SkillTool({ skill: "Frontend Design", args: "登录页面" })
// SkillTool.call() → 读取 SKILL.md 完整内容 → 替换 $ARGUMENTS
//                   → 返回 Skill SOP 作为用户消息注入后续对话
// LLM 后续回答遵循 Skill 中的设计原则

10.5 Skill vs Command vs Agent:三大能力对比

核心区别 :这三者代表了 Claude Code 中不同的知识传递模式

graph TB subgraph User["👤 用户意图层"] Intent["用户输入:设计一个登录页面"] end subgraph Detection["🔍 意图识别层"] Router["Intent Router
路由引擎"] end subgraph Capabilities["🧩 能力执行层"] direction LR subgraph CommandFlow["⚡ Command 流程
显式调用"] C1["用户输入:
/feature-dev 登录功能"] C2["🎯 精确匹配命令"] C3["📋 执行固定流程
7阶段 SOP"] C4["✅ 完成任务"] C1 --> C2 --> C3 --> C4 end subgraph SkillFlow["📚 Skill 流程
隐式注入"] S1["用户输入:
设计登录页面"] S2["🔎 关键词匹配
design/UI/frontend"] S3["💉 注入 Skill SOP
前端设计最佳实践"] S4["🧠 AI自主执行
遵循设计原则"] S1 --> S2 --> S3 --> S4 end subgraph AgentFlow["🤖 Agent 流程
自主决策"] A1["Command调用:
/feature-dev"] A2["🚀 启动 Agent
code-explorer"] A3["🔄 自主规划
搜索→分析→总结"] A4["📊 返回报告"] A1 --> A2 --> A3 --> A4 end end Intent --> Router Router -.检测Command.-> CommandFlow Router -.检测关键词.-> SkillFlow Router -.调用Agent.-> AgentFlow

对比表格

维度 🎯 Skill (用户调用型) 📚 Skill (LLM 调用型) 🤖 Agent
触发方式 /skill-name 用户显式调用 LLM 通过 SkillTool 自主调用 LLM 通过 AgentTool 调用
执行主体 主线程 Core Engine 主线程 Core Engine 独立子上下文 AI 实例
Token 成本 中等(SOP注入) 低(元数据常驻 + 按需加载正文) 高(独立上下文)
适用场景 固定流程任务 通用质量保证、知识注入 复杂自主任务
用户感知 ✅ 明确知道调用 ⚠️ 半感知(会显示 Skill 工具调用) ✅ 明确知道调用
工具权限 allowed-tools 预定义 allowed-tools 预定义(可选) tools 预定义
典型例子 /commit 提交代码 前端设计最佳实践 code-explorer 分析

纠正 :原文将 Command 和 Skill 描述为完全不同的概念。实际源码中,Command 已被 Skill 统一(commands_DEPRECATED)。Skill 本质上就是更强大的 Command,支持用户显式调用和 LLM 隐式调用两种模式。

10.6 Skill 完整生命周期

sequenceDiagram autonumber participant User as 👤 用户 participant Engine as ⚙️ Core Engine participant Router as 🔍 Skill Router participant Index as 📇 Skill Index
(内存) participant FS as 💾 File System participant LLM as 🧠 Claude API Note over Engine,Index: ═══ Phase 1: 启动时索引构建 ═══ Engine->>+Router: 初始化 Skill 系统 Router->>+FS: 扫描 plugins/*/skills/*/SKILL.md FS-->>-Router: 返回所有 Skill 文件路径 loop 每个 Skill 文件 Router->>+FS: 读取 SKILL.md 的 frontmatter FS-->>-Router: 返回 { name, description } Router->>Router: 从 description 提取触发短语 Router->>Index: 存储到内存索引 end Router-->>-Engine: Skill 索引构建完成 Note over User,LLM: ═══ Phase 2: 运行时触发与注入 ═══ User->>+Engine: 输入:帮我设计一个登录界面 Engine->>+Router: 检测触发的 Skills Router->>Index: 遍历所有 Skill metadata Index-->>Router: 匹配到: frontend-design
(关键词: 设计, 界面) Router->>+FS: 读取 frontend-design/SKILL.md 完整内容 FS-->>-Router: 返回 SOP 内容 Router->>Engine: 返回触发的 Skill 列表 Engine->>Engine: 将 Skill SOP 注入 System Prompt Note over Engine: System Prompt 组成:
① Core System Prompt
② 用户偏好 (L3)
③ 项目规范 (L2)
④ Skill SOP (frontend-design) Engine->>+LLM: 发送请求 (携带注入后的上下文) LLM-->>-Engine: AI响应(遵循 Skill 中的设计原则) Engine-->>-User: 输出高质量前端代码 Note over User,LLM: ═══ Phase 3: Skill 持续生效 ═══ User->>+Engine: 后续消息: 加一个密码强度提示 Note over Engine: Skill SOP 仍在上下文中
无需重新注入 Engine->>+LLM: 发送请求 LLM-->>-Engine: 继续遵循前端设计原则 Engine-->>-User: 输出符合 a11y 标准的实现

10.7 Skill 设计哲学:渐进式披露

Claude Code 的 Skill 系统采用**渐进式披露(Progressive Disclosure)**设计模式,这是一个经典的 UX 设计原则,应用在了 AI 系统中。

🎯 核心理念

按需加载,恰到好处

不要一次性把所有知识塞给 AI,而是:

  1. Level 1(元数据):启动时加载,极低成本,用于快速匹配
  2. Level 2(SOP 主体):触发时注入,中等成本,提供核心知识
  3. Level 3(详细文档):需要时 Read,高成本,提供深度参考

📊 Token 成本对比

假设某个 Skill 的完整知识库包含:

  • Metadata: 100 tokens(name, description, triggers)
  • SOP Body: 2000 tokens(设计原则、代码规范)
  • References: 10000 tokens(详细 API 文档、示例代码)

传统方式(全量加载):

  • 启动时加载所有 10 个 Skill = 10 × (100 + 2000 + 10000) = 121,000 tokens
  • 每次对话都携带这些 tokens
  • 即使用户根本不需要某些 Skill

渐进式方式(Claude Code 实现):

  • 启动时加载元数据 = 10 × 100 = 1,000 tokens
  • 触发 1 个 Skill 时注入 SOP = 1 × 2000 = 2,000 tokens
  • 需要详细文档时再 Read = 0-10,000 tokens(按需)

节省比例(121,000 - 3,000) / 121,000 ≈ 97.5% 🎉

10.8 实战案例:Skill 如何改变 AI 行为

场景:用户要求实现一个前端表单

❌ 无 Skill 加持的输出

tsx 复制代码
// 用户输入:帮我实现一个登录表单
function LoginForm() {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');

  const handleSubmit = () => {
    // 直接发送请求,没有验证
    fetch('/api/login', {
      method: 'POST',
      body: JSON.stringify({ username, password })
    });
  };

  return (
    <div>
      <input value={username} onChange={e => setUsername(e.target.value)} />
      <input value={password} onChange={e => setPassword(e.target.value)} />
      <button onClick={handleSubmit}>登录</button>
    </div>
  );
}

问题

  • ❌ 没有类型定义
  • ❌ input 缺少 label(不符合 a11y)
  • ❌ 密码框没有设置 type="password"
  • ❌ 没有错误处理
  • ❌ 没有加载状态
  • ❌ 非语义化标签(应该用 form)

✅ 有 Skill 加持的输出 (自动触发 frontend-design Skill)

tsx 复制代码
// 用户输入:帮我实现一个登录表单
// [Skill Injected: frontend-design]

interface LoginFormProps {
  onSuccess?: () => void;
  onError?: (error: Error) => void;
}

interface FormData {
  username: string;
  password: string;
}

interface FormErrors {
  username?: string;
  password?: string;
}

function LoginForm({ onSuccess, onError }: LoginFormProps) {
  const [formData, setFormData] = useState<FormData>({
    username: '',
    password: ''
  });
  const [errors, setErrors] = useState<FormErrors>({});
  const [isLoading, setIsLoading] = useState(false);

  const validateForm = (): boolean => {
    const newErrors: FormErrors = {};

    if (!formData.username.trim()) {
      newErrors.username = '请输入用户名';
    }

    if (formData.password.length < 6) {
      newErrors.password = '密码至少6位';
    }

    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    if (!validateForm()) return;

    setIsLoading(true);

    try {
      const response = await fetch('/api/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(formData)
      });

      if (!response.ok) throw new Error('登录失败');

      onSuccess?.();
    } catch (error) {
      const err = error as Error;
      onError?.(err);
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <form onSubmit={handleSubmit} aria-label="登录表单">
      <div className="form-group">
        <label htmlFor="username">
          用户名
          <span className="required" aria-label="必填">*</span>
        </label>
        <input
          id="username"
          type="text"
          value={formData.username}
          onChange={e => setFormData({ ...formData, username: e.target.value })}
          aria-invalid={!!errors.username}
          aria-describedby={errors.username ? "username-error" : undefined}
          disabled={isLoading}
        />
        {errors.username && (
          <span id="username-error" role="alert" className="error">
            {errors.username}
          </span>
        )}
      </div>

      <div className="form-group">
        <label htmlFor="password">
          密码
          <span className="required" aria-label="必填">*</span>
        </label>
        <input
          id="password"
          type="password"
          value={formData.password}
          onChange={e => setFormData({ ...formData, password: e.target.value })}
          aria-invalid={!!errors.password}
          aria-describedby={errors.password ? "password-error" : undefined}
          disabled={isLoading}
        />
        {errors.password && (
          <span id="password-error" role="alert" className="error">
            {errors.password}
          </span>
        )}
      </div>

      <button
        type="submit"
        disabled={isLoading}
        aria-busy={isLoading}
      >
        {isLoading ? '登录中...' : '登录'}
      </button>
    </form>
  );
}

export default LoginForm;

改进点

  • ✅ 完整的 TypeScript 类型定义
  • ✅ 表单验证(前端验证)
  • ✅ 错误处理和状态管理
  • ✅ 加载状态(防止重复提交)
  • ✅ 完整的 ARIA 标签(a11y)
  • ✅ 语义化 HTML(form, label)
  • ✅ Props 接口设计(回调函数)
  • ✅ 错误提示与用户体验

可视化对比

graph LR subgraph Without["❌ 无 Skill"] W1["用户输入"] --> W2["AI 基础知识"] W2 --> W3["低质量输出
缺少最佳实践"] style W3 fill:#dc2626,stroke:#fca5a5,color:#fff end subgraph With["✅ 有 Skill"] S1["用户输入"] --> S2["AI 基础知识"] S2 --> S3["+ Skill SOP"] S3 --> S4["高质量输出
遵循最佳实践"] style S3 fill:#7c3aed,stroke:#c4b5fd,color:#fff style S4 fill:#16a34a,stroke:#86efac,color:#fff end

10.9 Skill 的核心价值

Skill 系统解决了 AI 辅助编程中的一个根本性问题:

如何让 AI 在不明确指示的情况下,自动遵循项目最佳实践?

传统方案

  • ❌ 每次都在 prompt 中重复:"请使用 TypeScript,注意 a11y,处理错误..."
  • ❌ 依赖 AI 的"通用知识",质量不稳定
  • ❌ 无法针对特定项目定制规范

Skill 方案

  • ✅ 一次定义,自动应用
  • ✅ 团队统一标准,质量可预测
  • ✅ 针对项目特点定制 SOP
  • ✅ 新成员无需培训,AI 自动遵循

类比 :Skill 就像团队里的高级工程师在旁边 Code Review,在你写代码时自动提醒最佳实践,而不需要你每次都问。


11. 核心模块四:Hooks(钩子与治理)

11.1 什么是 Hook?

Hook 是一个拦截器系统,在关键时刻介入 AI 的执行流程:

  • 🛡️ 安全防护 :阻止危险命令(如 rm -rf /
  • 📊 审计日志:记录所有工具调用
  • 🎯 行为定制:根据项目规则修改 AI 行为
  • ⚠️ 警告提示:在敏感操作前提醒用户

11.2 Hook 类型与事件

graph LR subgraph "Hook 事件类型(v2.1.88 完整列表)" E1[PreToolUse
工具执行前] E2[PostToolUse
工具执行后] E2b[PostToolUseFailure
工具执行失败后] E3[UserPromptSubmit
用户输入提交前] E4[Stop
对话结束前] E4b[StopFailure
结束检查失败] E5[SessionStart
会话开始] E6[SessionEnd
会话结束] E7a[SubagentStart
子 Agent 启动] E7b[SubagentStop
子 Agent 结束] E8[PreCompact
上下文压缩前] E8b[PostCompact
上下文压缩后] E9[Notification
通知事件] E10[PermissionRequest
权限请求] E11[PermissionDenied
权限拒绝] end E1 -.->|"可以阻止"| Decision1{允许执行?} E2 -.->|"可以修改"| Decision2{修改结果?} E3 -.->|"可以修改"| Decision3{修改输入?} E4 -.->|"可以阻止"| Decision4{允许退出?} style E1 fill:#ff6b6b style E2 fill:#4ecdc4 style E3 fill:#ffe66d style E4 fill:#a8dadc

源码出处 :完整的 Hook 事件列表定义在 src/entrypoints/sdk/coreTypes.tsHOOK_EVENTS 常量中。

11.3 Hook 配置格式

实际支持四种 Hook 类型commandpromptagenthttp),以及 if 条件匹配:

json 复制代码
{
  "description": "Security Guidance Hook - 拦截危险操作",
  "hooks": {
    "PreToolUse": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/security_reminder_hook.py",
            "timeout": 10
          }
        ],
        "matcher": "Edit|Write|MultiEdit"
      },
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "检查这个 Bash 命令是否安全:$ARGUMENTS",
            "if": "Bash(rm *)"
          }
        ],
        "matcher": "Bash"
      },
      {
        "hooks": [
          {
            "type": "agent",
            "prompt": "验证此代码变更不会引入安全漏洞",
            "timeout": 30
          }
        ],
        "matcher": "Edit|Write"
      },
      {
        "hooks": [
          {
            "type": "http",
            "url": "https://security-api.example.com/check",
            "timeout": 15
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/posttooluse.py",
            "timeout": 10
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/stop.py",
            "timeout": 10
          }
        ]
      }
    ]
  }
}

四种 Hook 类型说明 (源码:src/utils/hooks/hooksSettings.ts):

  • command:启动子进程执行脚本,通过 stdin 传入 JSON,退出码 0=放行、2=阻止
  • prompt:将 prompt 文本直接注入当前对话作为系统消息
  • agent:启动子 Agent(使用 Haiku 模型),通过 SyntheticOutputTool 返回 {ok, reason} 结构化结果
  • http:发送 HTTP 请求到指定 URL,请求体为工具调用信息的 JSON
python 复制代码
### 11.4 实战案例:Security Guidance Hook

这是一个真实的安全拦截器,检测 XSS、命令注入等漏洞:

```python
#!/usr/bin/env python3
"""
Security Reminder Hook for Claude Code
检查文件编辑中的安全模式并发出警告
"""

import json
import sys
from datetime import datetime

# 安全模式配置
SECURITY_PATTERNS = [
    {
        "ruleName": "github_actions_workflow",
        "path_check": lambda path: ".github/workflows/" in path
                                  and (path.endswith(".yml") or path.endswith(".yaml")),
        "reminder": """⚠️ 你正在编辑 GitHub Actions 工作流。注意以下安全风险:

1. **命令注入**:不要直接使用 ${{ github.event.issue.title }}
2. **使用环境变量**:通过 env: 传递用户输入
3. **参考指南**:https://github.blog/security/...

❌ 不安全模式:
run: echo "${{ github.event.issue.title }}"

✅ 安全模式:
env:
  TITLE: ${{ github.event.issue.title }}
run: echo "$TITLE"
"""
    },
    {
        "ruleName": "eval_injection",
        "substrings": ["eval("],
        "reminder": "⚠️ eval() 会执行任意代码,存在重大安全风险。考虑使用 JSON.parse() 或其他安全方案。"
    },
    {
        "ruleName": "react_dangerously_set_html",
        "substrings": ["dangerouslySetInnerHTML"],
        "reminder": "⚠️ dangerouslySetInnerHTML 可能导致 XSS 漏洞。确保内容经过 DOMPurify 等库的清理。"
    },
    {
        "ruleName": "innerHTML_xss",
        "substrings": [".innerHTML =", ".innerHTML="],
        "reminder": "⚠️ 直接设置 innerHTML 可能导致 XSS。对于纯文本使用 textContent,HTML 使用 DOMPurify。"
    }
]

def check_patterns(file_path: str, content: str):
    """检查文件路径或内容是否匹配安全模式"""
    normalized_path = file_path.lstrip("/")

    for pattern in SECURITY_PATTERNS:
        # 检查路径模式
        if "path_check" in pattern and pattern["path_check"](normalized_path):
            return pattern["ruleName"], pattern["reminder"]

        # 检查内容模式
        if "substrings" in pattern and content:
            for substring in pattern["substrings"]:
                if substring in content:
                    return pattern["ruleName"], pattern["reminder"]

    return None, None

def main():
    # 读取 Hook 输入(JSON 格式)
    try:
        input_data = json.loads(sys.stdin.read())
    except json.JSONDecodeError:
        sys.exit(0)  # 解析失败,放行

    tool_name = input_data.get("tool_name", "")
    tool_input = input_data.get("tool_input", {})

    # 只检查文件编辑工具
    if tool_name not in ["Edit", "Write", "MultiEdit"]:
        sys.exit(0)

    # 提取文件路径和内容
    file_path = tool_input.get("file_path", "")
    content = tool_input.get("content") or tool_input.get("new_string", "")

    # 检查安全模式
    rule_name, reminder = check_patterns(file_path, content)

    if rule_name and reminder:
        # 输出警告到 stderr
        print(reminder, file=sys.stderr)
        # 退出码 2 = 阻止执行
        sys.exit(2)

    # 放行
    sys.exit(0)

if __name__ == "__main__":
    main()

11.5 Hookify:用户自定义规则引擎

hookify 插件提供了一个可视化的规则编辑器,让用户无需写代码就能定义拦截规则:

yaml 复制代码
# .hookify.rules.md (用户配置文件)

## 规则 1:禁止删除 node_modules
- **名称**:prevent-delete-node-modules
- **启用**:是
- **事件**:bash
- **条件**:
  - 字段:command
  - 操作符:regex_match
  - 模式:`rm.*node_modules`
- **动作**:block
- **消息**:🚫 不要删除 node_modules!请使用 npm clean-install 重新安装。

## 规则 2:Git 提交前提醒
- **名称**:commit-reminder
- **启用**:是
- **事件**:bash
- **条件**:
  - 字段:command
  - 操作符:contains
  - 模式:`git commit`
- **动作**:warn
- **消息**:⚠️ 提交前确认:是否已运行测试?是否更新了文档?

Hookify 架构

graph LR Config[.hookify.rules.md
Markdown 配置] -->|"解析"| Loader[Config Loader
YAML to Python] Loader --> Rules[Rule Objects
数据结构] Input[Hook 输入
JSON] --> Engine[Rule Engine
规则引擎] Rules --> Engine Engine --> Matcher{匹配规则?} Matcher -->|"否"| Allow[允许执行] Matcher -->|"是"| Action{动作类型?} Action -->|"block"| Block[阻止 + 显示消息] Action -->|"warn"| Warn[警告 + 继续执行] style Config fill:#ffe66d style Engine fill:#4ecdc4 style Block fill:#ff6b6b style Warn fill:#ffa500

12. MCP 协议:连接外部世界

12.1 什么是 MCP?

MCP (Model Context Protocol) 是 Anthropic 推出的标准化的 AI-服务连接协议。它类似于:

  • 🔌 USB 协议:统一的接口标准
  • 🌐 GraphQL:声明式的能力描述
  • 🐳 Docker:封装复杂服务为简单工具

通过 MCP,Claude Code 可以连接:

  • 🗄️ 数据库(PostgreSQL, MongoDB)
  • 📁 文件系统(本地、S3、Google Drive)
  • 🐙 GitHub API(Issues, PRs, Code Search)
  • 📊 Asana, Notion(项目管理)
  • 🔍 搜索引擎(Google, Brave Search)

12.2 MCP 服务器类型

graph TD subgraph "MCP Server Types" T1[stdio
本地进程] T2[SSE
服务器推送] T3[HTTP
REST API] T4[WebSocket
双向实时] end subgraph "Use Cases" U1[本地工具
文件系统, Git] U2[云服务
GitHub, Asana] U3[API 后端
自定义服务] U4[实时数据
股票行情] end T1 --> U1 T2 --> U2 T3 --> U3 T4 --> U4

12.3 MCP 配置示例

方式 1:独立 .mcp.json 文件

json 复制代码
{
  "filesystem": {
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects"],
    "env": {
      "LOG_LEVEL": "info"
    }
  },
  "github": {
    "type": "sse",
    "url": "https://mcp.github.com/sse"
  },
  "database": {
    "command": "${CLAUDE_PLUGIN_ROOT}/servers/db-server",
    "args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"],
    "env": {
      "DB_URL": "${DATABASE_URL}"
    }
  }
}

方式 2:内嵌在 plugin.json

json 复制代码
{
  "name": "my-plugin",
  "version": "1.0.0",
  "mcpServers": {
    "api-service": {
      "type": "http",
      "url": "https://api.example.com/mcp",
      "headers": {
        "Authorization": "Bearer ${API_TOKEN}"
      }
    }
  }
}

12.4 MCP 工具命名规范

MCP 提供的工具会自动加上前缀:

markdown 复制代码
mcp__plugin_<插件名>_<服务器名>__<工具名>

示例:
- mcp__plugin_asana_asana__asana_create_task
- mcp__plugin_github_github__github_search_issues
- mcp__plugin_db_database__execute_query

在 Command 中使用

markdown 复制代码
---
description: 创建 Asana 任务
allowed-tools: [
  "mcp__plugin_asana_asana__asana_create_task",
  "mcp__plugin_asana_asana__asana_search_tasks"
]
---

# 任务管理

使用 Asana API 创建和管理任务。

步骤:
1. 询问用户任务标题和描述
2. 调用 mcp__plugin_asana_asana__asana_create_task
3. 确认创建成功

12.5 MCP 生命周期

sequenceDiagram participant Plugin as 插件加载器 participant MCP as MCP Client participant Server as MCP Server participant LLM as Claude Plugin->>MCP: 1. 读取 .mcp.json 配置 MCP->>Server: 2. 启动 stdio 进程 / 建立 SSE 连接 Server-->>MCP: 3. 返回工具清单 (tools/list) MCP->>MCP: 4. 注册工具到能力表 LLM->>MCP: 5. 调用 mcp__plugin_x_y__tool MCP->>Server: 6. 发送 JSON-RPC 请求 Server-->>MCP: 7. 返回执行结果 MCP-->>LLM: 8. 格式化结果 Note over MCP,Server: 连接保持活跃,支持多次调用 Plugin->>MCP: 9. 会话结束 MCP->>Server: 10. 关闭连接 / 终止进程

13. 工具系统:执行引擎

13.1 内置工具清单

Claude Code 提供了 30+ 内置工具 (源码 src/tools/ 目录下每个子目录对应一个工具),覆盖常见开发场景:

类别 工具名称 源码位置 功能描述
文件操作 Read FileReadTool/ 读取文件内容(支持行号范围、PDF、图片)
Write FileWriteTool/ 创建或覆盖文件
Edit FileEditTool/ 精确字符串替换编辑
NotebookEdit NotebookEditTool/ 编辑 Jupyter Notebook
Glob GlobTool/ 文件模式匹配查找
Grep GrepTool/ 正则搜索文件内容(基于 ripgrep)
Shell 操作 Bash BashTool/ 执行 Shell 命令(支持后台、超时、沙箱)
PowerShell PowerShellTool/ Windows PowerShell 执行
代理管理 Agent AgentTool/ 派生子 Agent(隔离上下文)
SendMessage SendMessageTool/ 向已有 Agent 发送消息
TaskCreate TaskCreateTool/ 创建后台任务
TaskGet TaskGetTool/ 获取任务状态
TaskList TaskListTool/ 列出所有任务
TaskOutput TaskOutputTool/ 获取任务输出
TaskStop TaskStopTool/ 停止任务
TaskUpdate TaskUpdateTool/ 更新任务
TodoWrite TodoWriteTool/ 管理待办事项列表
模式切换 EnterPlanMode EnterPlanModeTool/ 进入计划模式(只读)
ExitPlanMode ExitPlanModeTool/ 退出计划模式
EnterWorktree EnterWorktreeTool/ 进入 Git Worktree 隔离环境
ExitWorktree ExitWorktreeTool/ 退出 Worktree
用户交互 AskUserQuestion AskUserQuestionTool/ 询问用户选择
Skill SkillTool/ 调用 Skill
ToolSearch ToolSearchTool/ 搜索延迟加载的工具定义
网络请求 WebFetch WebFetchTool/ 获取网页内容
WebSearch WebSearchTool/ 执行网络搜索
定时调度 RemoteTrigger RemoteTriggerTool/ 远程触发代理
ScheduleCron ScheduleCronTool/ 创建定时任务
MCP 工具 mcp__* MCPTool/ MCP 服务器提供的动态工具
实验性 Sleep SleepTool/ 等待指定时间
REPL REPLTool/ 交互式代码执行

纠正:原文列出 "MultiEdit"、"KillShell"、"Task" 等工具名,这些在实际源码中不存在。正确名称分别是 Edit(支持 replace_all)、TaskStop、Agent。

13.2 工具执行流程

sequenceDiagram participant LLM as Claude API participant Router as Tool Router participant Hooks as Hook System participant Executor as Tool Executor participant OS as Operating System LLM->>Router: 1. 返回 tool_calls: [Bash, Read, Grep] Router->>Router: 2. partitionToolCalls() 分区 Note over Router: 智能并行策略:
连续只读工具 → 并行批次
写入工具 → 串行批次 loop 遍历每个批次 alt 只读批次(Read, Grep 等) par 并行执行 Router->>Hooks: 3a. PreToolUse Hook Hooks-->>Router: 放行 Router->>Executor: 4a. Read 执行 Router->>Executor: 4b. Grep 执行 end else 写入批次(Bash, Edit 等) Router->>Hooks: 3b. PreToolUse Hook alt Hook 阻止 Hooks-->>LLM: 拦截并返回错误消息 else Hook 放行 Router->>Executor: 4c. 串行执行 alt 内置工具 Executor->>OS: 5a. 调用系统 API OS-->>Executor: 返回结果 else MCP 工具 Executor->>MCP: 5b. JSON-RPC 调用 MCP Server MCP-->>Executor: 返回结果 end end end Executor->>Hooks: 6. PostToolUse Hook(可修改结果) Executor-->>Router: 7. 返回工具结果 end Router-->>LLM: 8. 汇总所有结果,继续对话循环

13.3 工具权限控制

每个 Command 和 Agent 都必须声明允许使用的工具:

markdown 复制代码
---
# 明确列出工具
allowed-tools: [Read, Glob, Grep, TodoWrite]

# 使用通配符 --- 允许所有参数的 Bash 调用
allowed-tools: [Bash(*), Edit, Write]

# 使用参数匹配 --- 仅允许 git 开头的 Bash 命令
allowed-tools: ["Bash(git *)"]

# 允许特定 MCP 工具
allowed-tools: [
  "mcp__plugin_github_github__github_search_code",
  "mcp__plugin_github_github__github_create_issue"
]
---

补充allowed-tools 中的通配符语法 Bash(git *)src/tools/BashTool/bashPermissions.ts 中的 matchWildcardPattern 函数实现,支持 glob 风格匹配。

权限检查逻辑

typescript 复制代码
// [伪代码] 工具权限检查器
class ToolPermissionChecker {
  // 检查工具调用是否被允许
  isAllowed(toolName: string, allowedTools: string[]): boolean {
    // 1. 精确匹配
    if (allowedTools.includes(toolName)) {
      return true;
    }

    // 2. 通配符匹配(如 "Bash(*)" 允许所有 Bash 调用)
    for (const pattern of allowedTools) {
      if (pattern.endsWith('(*)')) {
        const baseTool = pattern.replace('(*)', '');
        if (toolName === baseTool) {
          return true;
        }
      }

      // 3. MCP 工具通配符(如 "mcp__plugin_x_y__*")
      if (pattern.endsWith('*')) {
        const prefix = pattern.slice(0, -1);
        if (toolName.startsWith(prefix)) {
          return true;
        }
      }
    }

    return false;
  }

  // 拦截未授权的工具调用
  async checkAndExecute(toolCall: ToolCall, context: Context): Promise<ToolResult> {
    const allowedTools = context.getAllowedTools();

    if (!this.isAllowed(toolCall.name, allowedTools)) {
      return {
        error: `工具 ${toolCall.name} 未被授权。允许的工具:${allowedTools.join(', ')}`
      };
    }

    // 执行工具
    return await this.toolExecutor.execute(toolCall);
  }
}

14. 实战案例:Feature-Dev 插件剖析

14.1 插件文件结构

bash 复制代码
plugins/feature-dev/
├── .claude-plugin/
│   └── plugin.json           # 插件元数据
├── commands/
│   └── feature-dev.md        # /feature-dev 命令
├── agents/
│   ├── code-explorer.md      # 代码探索 Agent
│   ├── code-architect.md     # 架构设计 Agent
│   └── code-reviewer.md      # 代码审查 Agent
└── README.md                 # 使用文档

14.2 命令定义(feature-dev.md 节选)

markdown 复制代码
---
description: 引导式功能开发,包含代码库理解和架构聚焦
argument-hint: 可选的功能描述
---

# Feature Development

你正在帮助开发者实现新功能。遵循系统化方法:深入理解代码库,识别并询问所有未明确的细节,设计优雅的架构,然后实现。

## 核心原则

- **提出澄清性问题**:识别所有歧义、边界情况和未明确的行为。提出具体、实际的问题而非假设。在实现前等待用户回答。在理解代码库后、设计架构前尽早提问。
- **先理解再行动**:首先阅读和理解现有代码模式
- **阅读 Agent 识别的文件**:启动 Agent 时,要求它们返回最重要文件的列表。Agent 完成后,阅读这些文件以建立详细上下文再继续。
- **简单优雅**:优先考虑可读性、可维护性、架构合理性
- **使用 TodoWrite**:全程跟踪所有进度

---

## Phase 1: Discovery

**目标**:理解需要构建什么

初始请求:$ARGUMENTS

**行动**:
1. 创建包含所有阶段的待办列表
2. 如果功能不清楚,询问用户:
   - 他们要解决什么问题?
   - 功能应该做什么?
   - 有哪些约束或需求?
3. 总结理解并与用户确认

---

## Phase 2: Codebase Exploration

**目标**:在高层和低层理解相关的现有代码和模式

**行动**:
1. 并行启动 2-3 个 code-explorer Agent。每个 Agent 应该:
   - 全面追踪代码,专注于全面理解抽象、架构和控制流
   - 针对代码库的不同方面(如类似功能、高层理解、架构理解、用户体验等)
   - 包含 5-10 个关键文件的列表

   **Agent Prompt 示例**:
   - "找到类似 [功能] 的特性并全面追踪其实现"
   - "绘制 [功能区域] 的架构和抽象,全面追踪代码"
   - "分析 [现有功能/区域] 的当前实现,全面追踪代码"
   - "识别与 [功能] 相关的 UI 模式、测试方法或扩展点"

2. Agent 返回后,请阅读 Agent 识别的所有文件以建立深入理解
3. 展示全面的发现总结和发现的模式

---

## Phase 3: Clarifying Questions

**目标**:在设计前填补空白并解决所有歧义

**关键**:这是最重要的阶段之一。不要跳过。

**行动**:
1. 审查代码库发现和原始功能请求
2. 识别未明确的方面:边界情况、错误处理、集成点、范围边界、设计偏好、向后兼容性、性能需求
3. **以清晰、有组织的列表向用户展示所有问题**
4. **在进入架构设计前等待答案**

如果用户说"你认为最好的方式",提供你的建议并获得明确确认。

---

## Phase 4: Architecture Design

**目标**:设计具有不同权衡的多种实现方法

**行动**:
1. 并行启动 2-3 个 code-architect Agent,具有不同的关注点:最小变更(最小改动,最大复用)、清晰架构(可维护性,优雅抽象)或务实平衡(速度 + 质量)
2. 审查所有方法并形成你对哪个最适合此特定任务的看法(考虑:小修复 vs 大功能,紧急性,复杂性,团队背景)
3. 向用户展示:每种方法的简要总结、权衡比较、**你的建议及理由**、具体实现差异
4. **询问用户更喜欢哪种方法**

---

## Phase 5: Implementation

**目标**:构建功能

**未获用户批准不要开始**

**行动**:
1. 等待明确的用户批准
2. 阅读前面阶段识别的所有相关文件
3. 按照选定的架构实现
4. 严格遵循代码库约定
5. 编写清晰、文档良好的代码
6. 在进展时更新待办事项

---

## Phase 6: Quality Review

**目标**:确保代码简单、DRY、优雅、易读且功能正确

**行动**:
1. 并行启动 3 个 code-reviewer Agent,具有不同关注点:简单性/DRY/优雅、错误/功能正确性、项目约定/抽象
2. 整合发现并识别你建议修复的最高严重性问题
3. **向用户展示发现并询问他们想做什么**(现在修复、稍后修复或按原样继续)
4. 根据用户决定解决问题

---

## Phase 7: Summary

**目标**:记录完成的工作

**行动**:
1. 标记所有待办事项完成
2. 总结:
   - 构建了什么
   - 做出的关键决策
   - 修改的文件
   - 建议的后续步骤

14.3 Agent 定义示例(code-explorer.md

markdown 复制代码
---
name: code-explorer
description: 通过追踪执行路径、绘制架构层、理解模式和抽象、记录依赖关系来深度分析现有代码库功能
tools: [Glob, Grep, Read, TodoWrite, WebFetch]
model: sonnet
color: yellow
---

你是一个代码分析专家,专注于追踪和理解功能实现。

## 核心任务

从入口点到数据存储,贯穿所有抽象层,提供功能的完整理解。

## 分析方法

**1. 功能发现**
- 找到入口点(API、UI 组件、CLI 命令)
- 定位核心实现文件
- 绘制功能边界和配置

**2. 代码流程追踪**
- 跟随从输入到输出的调用链
- 追踪每一步的数据转换
- 识别所有依赖和集成
- 记录状态变化和副作用

**3. 架构分析**
- 绘制抽象层(展示 → 业务逻辑 → 数据)
- 识别设计模式和架构决策
- 记录组件间的接口
- 注意横切关注点(认证、日志、缓存)

**4. 实现细节**
- 关键算法和数据结构
- 错误处理和边界情况
- 性能考虑
- 技术债务或改进领域

## 输出指导

提供全面的分析,帮助开发者深入理解功能,足以修改或扩展它。包括:

- 带文件:行号引用的入口点
- 带数据转换的逐步执行流程
- 关键组件及其职责
- 架构洞察:模式、分层、设计决策
- 依赖关系(外部和内部)
- 关于优势、问题或机会的观察
- **你认为绝对必要的文件列表,以理解所讨论的主题**

以最大的清晰度和实用性组织你的响应。始终包含具体的文件路径和行号。

14.4 工作流演示

sequenceDiagram participant User as 用户 participant Main as Main Context participant Explorer as Code Explorer Agent participant Architect as Code Architect Agent participant Reviewer as Code Reviewer Agent User->>Main: /feature-dev 实现用户登录 Main->>Main: Phase 1: 理解需求 Main->>User: 确认功能范围 User->>Main: 确认:支持邮箱/密码登录 Main->>Main: Phase 2: 探索代码库 par 并行探索 Main->>Explorer: "找到类似的认证实现" Main->>Explorer: "分析当前的用户系统" Main->>Explorer: "识别 API 路由模式" end Explorer-->>Main: 返回关键文件列表 Main->>Main: 读取推荐文件 Main->>User: Phase 3: 询问澄清问题
- 密码加密方式?
- Token 存储位置?
- 支持第三方登录吗? User->>Main: 回答问题 Main->>Main: Phase 4: 设计架构 par 并行设计 Main->>Architect: "最小变更方案" Main->>Architect: "清晰架构方案" Main->>Architect: "务实平衡方案" end Architect-->>Main: 返回 3 种设计方案 Main->>User: 展示方案 + 推荐 User->>Main: 批准"务实平衡方案" Main->>Main: Phase 5: 实现功能
(编写代码) Main->>Main: Phase 6: 质量审查 par 并行审查 Main->>Reviewer: "检查简单性/DRY" Main->>Reviewer: "检查功能正确性" Main->>Reviewer: "检查项目约定" end Reviewer-->>Main: 返回审查报告 Main->>User: 展示问题列表 User->>Main: 修复高优先级问题 Main->>Main: Phase 7: 总结完成 Main-->>User: ✅ 功能完成

15. CLI 使用方式与最佳实践

15.1 核心命令清单

命令 功能 使用场景
claude 启动交互式会话 日常开发对话
claude "快速任务" 单次执行 CI/CD 脚本、自动化
claude --debug 调试模式 排查插件问题、查看 MCP 连接
/help 查看帮助 了解可用命令
/init 初始化项目 首次使用,生成 CLAUDE.md
/commit 智能提交 自动生成提交信息
/review 代码审查 提交前质量检查
/compact 压缩上下文 感觉 AI 反应慢时
/clear 清空会话 切换任务时
/cost 查看成本 监控 Token 消耗
/mcp 查看 MCP 服务器 调试外部服务连接

15.2 项目配置:CLAUDE.md

这是 Claude Code 的"项目宪法",定义 AI 的行为准则:

markdown 复制代码
# 项目规范:MyApp

## 代码风格

- **语言**:TypeScript(严格模式)
- **格式化**:Prettier + ESLint
- **命名**:
  - 组件:PascalCase (`UserProfile.tsx`)
  - 函数:camelCase (`getUserById`)
  - 常量:UPPER_SNAKE_CASE (`MAX_RETRY_COUNT`)

## 架构原则

- **组件化**:每个组件单一职责
- **类型安全**:所有函数必须有类型定义
- **错误处理**:使用 Result 类型而非异常
- **测试**:核心逻辑覆盖率 > 80%

## 禁止操作

- ❌ 不要使用 `any` 类型
- ❌ 不要直接修改 `package.json`(使用 npm install)
- ❌ 不要提交 `.env` 文件

## Git 规范

遵循 Conventional Commits:

feat: 新功能 fix: Bug 修复 docs: 文档更新 refactor: 重构 test: 测试 chore: 构建/工具变更

bash 复制代码
## 测试命令

```bash
npm test              # 运行所有测试
npm run test:watch    # 监视模式
npm run test:e2e      # E2E 测试

部署流程

  1. 运行 npm run build
  2. 确保所有测试通过
  3. 创建 PR 到 main 分支
  4. 等待 CI 通过
  5. 合并后自动部署到 staging
ini 复制代码
### 15.3 最佳实践

#### 1. 使用 TodoWrite 跟踪任务

```markdown
# 用户
实现用户注册功能

# Claude
我会使用 TodoWrite 来跟踪这个任务:

1. [pending] 设计数据库 schema
2. [pending] 实现 API 端点
3. [pending] 编写单元测试
4. [pending] 添加前端表单
5. [pending] 集成验证码

现在开始第一步...

2. 善用 Plan Mode(Shift+Tab)

Plan Mode 会禁用所有写操作,只允许读取和分析。适合:

  • 🔍 探索不熟悉的代码库
  • 📋 制定实现计划
  • 🤔 架构设计讨论

3. 自定义 Hookify 规则

yaml 复制代码
# .hookify.rules.md

## 规则:生产环境保护
- **启用**:是
- **事件**:bash
- **条件**:
  - 字段:command
  - 操作符:regex_match
  - 模式:`kubectl.*delete|helm.*uninstall`
- **动作**:block
- **消息**:🚫 生产环境操作已被阻止!请联系 DevOps 团队。

## 规则:大文件警告
- **启用**:是
- **事件**:file
- **条件**:
  - 字段:file_path
  - 操作符:regex_match
  - 模式:`\.png$|\.jpg$|\.mp4$`
- **动作**:warn
- **消息**:⚠️ 你正在提交二进制文件。考虑使用 Git LFS 或 CDN。

16. 总结:Markdown 驱动的 AI 应用新范式

16.1 核心设计哲学

Claude Code 的插件生态系统证明了一个重要理念:

用 Markdown 定义能力,用 LLM 执行逻辑,用 Hook 保障安全。

这种范式的优势:

传统代码 Claude Code 插件
用 Python/JS 编写逻辑 用 Markdown 描述意图
硬编码的 if-else LLM 动态推理
需要编译/部署 热加载(无需重启)
学习曲线陡峭 接近自然语言
难以维护 易于修改和理解

16.2 技术架构精髓

mindmap root((Claude Code
插件生态)) 分层设计 微内核 插件扩展 能力注册 声明式能力 Commands Agents Skills 治理机制 Hooks 权限控制 安全拦截 外部连接 MCP 协议 stdio/SSE/HTTP 多服务集成 开发者体验 Markdown 驱动 热加载 调试友好

16.3 适用场景与限制

适用场景

  • ✅ 自动化开发工作流(commit, review, PR)
  • ✅ 代码库探索和文档生成
  • ✅ 定制化开发助手(企业内部规范)
  • ✅ 连接外部服务(数据库、API、CI/CD)

当前限制

  • ⚠️ 核心引擎闭源(无法深度定制)
  • ⚠️ 依赖网络(需要 Claude API)
  • ⚠️ Token 成本(大型项目可能昂贵)
  • ⚠️ Hook 调试较困难(需要 --debug 模式)

16.4 未来展望

基于当前架构,我们可以预见:

  1. 更多官方插件:数据库管理、DevOps、测试生成
  2. 插件市场:类似 VS Code Extensions
  3. 本地模型支持:降低成本,提高隐私
  4. 可视化编辑器:拖拽式创建 Command/Agent
  5. 企业版:SSO、审计日志、合规性控制

附录:快速参考

A. 文件格式速查

Command 格式

markdown 复制代码
---
description: 描述
argument-hint: 参数提示
allowed-tools: [工具列表]
---

# Prompt 内容
$ARGUMENTS 会被替换为用户输入

Agent 格式

markdown 复制代码
---
name: agent-name
description: 描述
tools: [工具列表]
model: sonnet|opus|haiku
color: yellow|blue|green
---

# Agent 指令
详细的执行逻辑...

Skill 格式(新版统一格式,替代旧版 Command):

markdown 复制代码
---
name: Skill Name
description: 功能描述(LLM 根据此判断何时调用)
version: 1.0.0
model: sonnet                         # 可选:指定模型
allowed-tools: [Read, Glob, Grep]     # 可选:预授权工具
argument-hint: 可选的参数提示           # 可选
---

# SOP 内容
标准操作流程...

$ARGUMENTS 会被替换为用户输入
也支持索引参数:$0, $1, $ARGUMENTS[0]

Hook 格式

json 复制代码
{
  "hooks": {
    "PreToolUse": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python3 script.py",
            "timeout": 10
          }
        ],
        "matcher": "Edit|Write"
      }
    ]
  }
}

B. 环境变量

  • ${CLAUDE_PLUGIN_ROOT} - 插件根目录(必须使用)
  • ${API_KEY} - 自定义 API 密钥
  • ${DATABASE_URL} - 数据库连接字符串
  • ENABLE_SECURITY_REMINDER - 启用/禁用安全提示(0/1)

C. 调试技巧

bash 复制代码
# 启用调试日志
claude --debug

# 查看 MCP 服务器状态
/mcp

# 查看插件列表
/help

# 强制压缩上下文
/compact

# 查看 Token 使用
/cost

# 清空会话重新开始
/clear

D. Bun 适配层(源码运行必备)

Claude Code 核心引擎使用 Bun 编译,依赖 bun:bundlebun:ffi 两个 Bun-only 模块。通过 extracted/ 中的 shim 层可在 Node.js 下运行:

less 复制代码
extracted/
├── loader.mjs           # ESM Loader Hook --- 拦截 bun:bundle/bun:ffi 导入
├── shims/
│   ├── register.ts      # 入口:注册 MACRO 全局常量
│   ├── macro.ts         # MACRO.VERSION 等构建时常量
│   ├── bun-bundle.ts    # feature() 函数 shim --- 所有特性开关默认 false
│   └── bun-ffi.ts       # FFI 桩 --- dlopen/ptr 空实现
└── stubs/               # Anthropic 内部包的空壳 (@ant/*, @anthropic-ai/mcpb)

feature() 函数 是核心适配点 --- Bun 编译期将 feature('FLAG') 替换为字面量实现 Dead Code Elimination(DCE),Node 运行时通过 shim 返回 false

typescript 复制代码
// shims/bun-bundle.ts
const FEATURE_FLAGS: Record<string, boolean> = {};
export function feature(flag: string): boolean {
  return FEATURE_FLAGS[flag] ?? false;  // 默认全部关闭
}

E. 源码校正勘误表

原文内容 纠正 依据源码位置
"Sonnet 4.5/Opus 4.5" 当前版本为 Sonnet 4.6/Opus 4.6 src/constants/prompts.ts:118-123
"CapabilityRegistry 类" 不存在该类,组件分散合并 src/hooks/useMergedTools.ts
"Intent Router" 不存在该模块 直接由 processUserInput() 处理
"Skill 通过关键词自动激活" LLM 通过 SkillTool 自主调用 src/tools/SkillTool/
"commands/ 目录" 已标记为 commands_DEPRECATED src/skills/loadSkillsDir.ts:68
"MultiEdit 工具" 不存在,Edit 支持 replace_all src/tools/FileEditTool/
"KillShell 工具" 不存在,使用 TaskStop src/tools/TaskStopTool/
"Task 工具" 实际名为 Agent (AgentTool) src/tools/AgentTool/
"使用 ink npm 包" 自建 Ink 引擎 (40+ 文件) src/ink/
"temperature: 0.7" 固定为 1(思考模式要求) src/services/api/claude.ts:1693
"config.json 存偏好" 全局偏好在 ~/.claude/CLAUDE.md src/memdir/memdir.ts
Hook 事件仅 9 种 实际 15 种(含 PermissionDenied 等) src/entrypoints/sdk/coreTypes.ts
Hook 仅 command 类型 支持 command/prompt/agent/http 四种 src/utils/hooks/hooksSettings.ts

17. 三足鼎立:Claude Code vs Codex vs Gemini CLI

基于 Claude Code v2.1.88、OpenAI Codex(开源版)、Gemini CLI v0.21.0 的源码对比分析。

17.1 基础画像

维度 Claude Code OpenAI Codex Gemini CLI
开发商 Anthropic OpenAI Google
核心语言 TypeScript (Bun 编译) Rust + TypeScript TypeScript
运行时 Bun(发布)/ Node(兼容) Rust 原生二进制 Node.js 20+
UI 框架 自建 Ink 引擎 (react-reconciler) Rust TUI (ratatui) Ink (npm 包)
代码规模 ~800 文件,闭源核心 + 开源插件 45+ Rust 模块,完全开源 ~200 文件,完全开源
后端模型 Claude Sonnet/Opus 4.6 GPT-4 系列 Gemini 2.5 Pro/Flash
许可证 核心闭源,插件 MIT Apache 2.0 Apache 2.0

17.2 架构哲学对比

三者看似功能相同,但架构哲学截然不同:

objectivec 复制代码
Claude Code:  Markdown 驱动 + 微内核插件
               "用文档定义能力,让 LLM 执行逻辑"

Codex:        Rust 系统级 + 沙箱隔离优先
               "安全第一,性能极致,系统级隔离"

Gemini CLI:   TypeScript 全栈 + 最简设计
               "清晰分层,标准 React 模式,易于理解"

Claude Code --- 微内核 + 插件生态

scss 复制代码
┌──────────────────────────────────────────┐
│         Markdown 插件生态层               │
│  Skills(*.md) │ Agents(*.md) │ Hooks     │
├──────────────────────────────────────────┤
│         微内核引擎(闭源 Bun 编译)         │
│  query() 主循环 │ 30+ 内置工具 │ MCP      │
├──────────────────────────────────────────┤
│         自建 Ink 渲染引擎                  │
│  react-reconciler + Yoga Layout          │
└──────────────────────────────────────────┘
核心理念:业务逻辑全部外化到 Markdown 文件

Codex --- Rust 系统级安全优先

复制代码
┌──────────────────────────────────────────┐
│         TypeScript SDK 层                │
│  开发者 API │ 嵌入式集成                    │
├──────────────────────────────────────────┤
│         Rust 核心引擎                     │
│  SQ/EQ 异步队列 │ 工具注册表 │ MCP         │
├──────────────────────────────────────────┤
│         多平台沙箱隔离层                    │
│  macOS Seatbelt │ Linux Landlock+Seccomp │
│  Windows RestrictedToken                 │
└──────────────────────────────────────────┘
核心理念:系统级沙箱隔离,Rust 内存安全保障

Gemini CLI --- TypeScript 全栈最简

scss 复制代码
┌──────────────────────────────────────────┐
│         CLI UI 层 (Ink + React 19)       │
│  Composer │ MessageDisplay │ Themes      │
├──────────────────────────────────────────┤
│         Core 业务逻辑层                   │
│  GeminiClient │ ToolScheduler │ Hooks    │
├──────────────────────────────────────────┤
│         Gemini API + MCP                 │
│  REST + SSE │ Stdio/HTTP 传输            │
└──────────────────────────────────────────┘
核心理念:清晰的两包分层(cli + core),标准 React 模式

17.3 核心机制深度对比

工具系统

特性 Claude Code Codex Gemini CLI
工具数量 30+ 内置 8 内置 10 内置
工具定义 Zod Schema + prompt() 函数 Rust trait ToolHandler 类继承 BaseDeclarativeTool
并行执行 只读工具并行,写入串行 顺序执行 顺序执行
权限控制 Hook + canUseTool 多层 Starlark 策略引擎 shouldConfirmExecute()
沙箱 可选沙箱(特定命令) 系统级强制沙箱 无沙箱
独有工具 Agent(子代理)、Skill、PlanMode、Worktree apply_patch(diff 补丁) memory(AI 自动写入记忆)
typescript 复制代码
// Claude Code --- buildTool 工厂 + isReadOnly 影响并行策略
export const BashTool = buildTool({
  name: 'Bash',
  inputSchema: z.object({ command: z.string(), timeout: z.number().optional() }),
  isReadOnly(input) { return isReadOnlyCommand(input.command); },
  async call(input, ctx) { return await exec(input.command); },
});
rust 复制代码
// Codex --- Rust trait 实现,编译期类型安全
pub trait ToolHandler: Send + Sync {
    async fn handle(&self, invocation: ToolInvocation) -> Result<ToolOutput, ToolError>;
}
typescript 复制代码
// Gemini CLI --- 类继承 + 声明式 schema
class ReadFileTool extends BaseDeclarativeTool {
  readonly kind = 'Read';
  readonly requiresConfirmation = false;
  async execute(signal: AbortSignal): Promise<ToolResult> { ... }
}

记忆系统

特性 Claude Code Codex Gemini CLI
全局记忆 ~/.claude/CLAUDE.md ~/.codex/instructions.md ~/.gemini/GEMINI.md
项目记忆 ./CLAUDE.md(多级向上查找) ./AGENTS.md ./GEMINI.md(多级 + @import
AI 自动记忆 无(只读) (MemoryTool 自动写入)
注入方式 Attachment 消息 System Prompt System Prompt
会话持久化 session storage ~/.codex/sessions/ 支持 --resume

关键差异 :Gemini CLI 是唯一支持 AI 自动写入记忆 的工具 --- LLM 可以调用 MemoryTool 将事实保存到 GEMINI.md## Gemini Added Memories 部分。Claude Code 和 Codex 的记忆文件都是用户手动维护的。

上下文压缩

特性 Claude Code Codex Gemini CLI
触发阈值 90% 上下文窗口 接近上下文限制 50% 上下文窗口
保留策略 保留最近 N 轮 保留头尾,删除中间 保留最近 30%
快照格式 Summary + Snapshot 摘要 + 环境差异 XML 结构化(含文件操作记录)
手动触发 /compact 命令
xml 复制代码
Gemini CLI 压缩最激进 --- 50% 就触发,但快照最结构化:
<state_snapshot>
  <user_goal>实现用户认证</user_goal>
  <file_operations>READ: login.ts, MODIFIED: jwt.ts</file_operations>
  <progress>1. [DONE] JWT 生成  2. [IN PROGRESS] 修复测试</progress>
</state_snapshot>

Claude Code 最保守 --- 90% 才触发,但支持手动 /compact。
Codex 独有环境差异策略 --- 只发送 <environment_context_diff>。

Hook / 安全系统

特性 Claude Code Codex Gemini CLI
Hook 事件 15 种 无 Hook 系统 11 种
Hook 类型 command / prompt / agent / http --- command(shell 脚本)
安全核心 Hook → 权限 → 可选沙箱 策略引擎 + 强制沙箱 工具确认 + Hook
策略语言 JSON Starlark (.codexpolicy) JSON
AI 验证 agent 类型 Hook
独有事件 PermissionDenied, SubagentStart --- BeforeModel, AfterModel

Claude Code 的 Hook 最丰富(15 种事件 + 4 种执行方式);Codex 没有 Hook 但有最强系统级沙箱;Gemini CLI 独有 AI 模型调用生命周期钩子(BeforeModel/AfterModel)。

插件/扩展系统

特性 Claude Code Codex Gemini CLI
插件系统 完整插件生态(Marketplace)
扩展方式 Skills/Agents/Hooks + MCP MCP + AGENTS.md MCP + GEMINI.md + Hooks
技能注入 Skill 渐进式加载
子代理 AgentTool(隔离上下文,可并行)

这是 Claude Code 最大的差异化优势 --- 唯一拥有完整插件生态的工具。

17.4 通信与异步模型

特性 Claude Code Codex Gemini CLI
API 通信 Anthropic SDK(流式) OpenAI Responses API(流式) Google GenAI SDK (REST+SSE)
异步模型 AsyncGenerator (query 主循环) SQ/EQ 队列 (Rust channels) AsyncGenerator (Turn)
后台任务 TaskCreate/TaskStop
并发工具 最多 10 个只读工具并行 顺序 顺序

17.5 性能与安全权衡

css 复制代码
安全性    Codex ████████████ > Claude Code ████████ > Gemini CLI █████
          系统级沙箱             多层 Hook            工具确认

扩展性    Claude Code ████████████ > Gemini CLI ████████ > Codex █████
          插件+Skill+Agent+Hook   MCP+Hook+记忆        MCP only

性能      Codex ████████████ > Claude Code ████████ > Gemini CLI ██████
          Rust 原生               Bun 编译             Node.js

易读性    Gemini CLI ████████████ > Claude Code ████████ > Codex ██████
          纯 TS,清晰分层          TS 但闭源编译         Rust 高门槛

开放性    Codex ████████████ = Gemini CLI ████████████ > Claude Code ████
          Apache 2.0 全开源       Apache 2.0 全开源     核心闭源

17.6 谁适合谁?

场景 推荐 原因
企业级团队协作 Claude Code 插件生态 + Skill SOP 统一团队标准
安全敏感环境 Codex 系统级沙箱 + Starlark 策略引擎
快速上手/学习 Gemini CLI 代码最清晰,纯 TS,Google 免费额度
CI/CD 自动化 Codex Rust 性能 + codex exec 非交互模式
自定义 AI 行为 Claude Code Markdown 驱动的 Skill + Agent 扩展
源码学习/二开 Gemini CLI / Codex 完全开源,社区活跃

17.7 本质差异总结

三个工具解决同一个问题 --- 让 LLM 在终端里执行编程任务 --- 但各自的"灵魂"完全不同:

graph LR subgraph Claude["Claude Code 的灵魂"] CC1["Markdown 驱动的知识注入"] CC2["用文档定义能力"] CC3["插件生态 + 子 Agent 并行"] CC1 --> CC2 --> CC3 style CC1 fill:#7c3aed,stroke:#c4b5fd,color:#fff style CC2 fill:#7c3aed,stroke:#c4b5fd,color:#fff style CC3 fill:#7c3aed,stroke:#c4b5fd,color:#fff end subgraph Codex["Codex 的灵魂"] CX1["系统级安全隔离"] CX2["Rust 性能 + 沙箱"] CX3["Starlark 策略引擎"] CX1 --> CX2 --> CX3 style CX1 fill:#059669,stroke:#6ee7b7,color:#fff style CX2 fill:#059669,stroke:#6ee7b7,color:#fff style CX3 fill:#059669,stroke:#6ee7b7,color:#fff end subgraph Gemini["Gemini CLI 的灵魂"] GM1["最小可行 AI Agent"] GM2["清晰分层 + 纯 TS"] GM3["AI 自动记忆 + 结构化压缩"] GM1 --> GM2 --> GM3 style GM1 fill:#dc2626,stroke:#fca5a5,color:#fff style GM2 fill:#dc2626,stroke:#fca5a5,color:#fff style GM3 fill:#dc2626,stroke:#fca5a5,color:#fff end
  • Claude Code 本质上是一个知识管理系统 --- Skills 渐进式加载用最少 Token 给 AI 最多知识,子 Agent 并行让多个 AI 实例分工协作
  • Codex 本质上是一个安全执行环境 --- 跨平台沙箱(Seatbelt/Landlock/Seccomp)确保 AI 操作不会伤害系统
  • Gemini CLI 本质上是一个极简 Agent 框架 --- 200 文件覆盖全功能,AI 能主动学习用户偏好,适合学习和快速定制

参考资料

致谢 :本文基于 claude-code 官方仓库和逆向提取的核心引擎源码分析。v2.0 版本基于实际源码校正了多处不准确描述,并新增了与 Codex/Gemini CLI 的三方对比。


相关推荐
攀登的牵牛花2 小时前
程序员失业论,被 SWE-CI 一组数据打醒:真正先被替代的是低质量交付
前端·github
BumBle2 小时前
Vue项目中实现路由守卫自动取消Pending请求
前端
机器之心2 小时前
京东卷出新高度!硬刚「复杂指令」长时长、自由态数字人直播终于丝滑了
人工智能·openai
机器之心2 小时前
龙虾太难养?发布的SOLO独立端,可能是你要的AI生产力
人工智能·openai
gCode Teacher 格码致知2 小时前
Javascript提高:get和post等请求,对于汉字和空格信息进行编码的原则-由Deepseek产生
开发语言·前端·javascript·node.js·jquery
竹林8182 小时前
从ethers.js迁移到Viem:我在一个DeFi项目前端重构中踩过的坑
前端·javascript
与虾牵手3 小时前
Claude Tool Use 怎么用?从零到生产的完整教程(2026)
ai编程·claude
像我这样帅的人丶你还3 小时前
从交稿到甩锅预防:AI 前端流水线
前端·ai编程
想想弹幕会怎么做3 小时前
如何构建一颗可交互的ui树?
前端