目录
- 从现象出发:Claude Code 是什么?
- 项目结构:模块化的插件仓库
- 整体架构:可扩展的能力注册系统
- 记忆系统:三层记忆架构
- 上下文管理:动态压缩与快照
- 通信协议:流式 API 与实时交互
- UI 层:Ink 驱动的终端渲染
- 核心模块一:Commands(命令系统)
- 核心模块二:Agents(智能代理)
- 核心模块三:Skills(技能系统)
- 核心模块四:Hooks(钩子与治理)
- MCP 协议:连接外部世界
- 工具系统:执行引擎
- 实战案例:Feature-Dev 插件剖析
- CLI 使用方式与最佳实践
- 总结:Markdown 驱动的 AI 应用新范式
- 三足鼎立:Claude 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 客户端等完整实现。
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<br/>7阶段功能开发]
PD[plugin-dev<br/>插件脚手架]
ASD[agent-sdk-dev<br/>SDK项目生成]
MIG[claude-opus-4-5-migration<br/>模型迁移]
end
subgraph Productivity["⚡ 生产力插件 (3)"]
CR[code-review<br/>自动PR审查]
PRT[pr-review-toolkit<br/>6种专业审查]
CC[commit-commands<br/>Git提交工作流]
end
subgraph Learning["📚 学习增强插件 (2)"]
EO[explanatory-output-style<br/>教学模式]
LO[learning-output-style<br/>互动学习]
end
subgraph Security["🔐 安全治理插件 (2)"]
HF[hookify<br/>自定义行为规则]
SG[security-guidance<br/>安全模式拦截]
end
subgraph Design["🎨 设计辅助插件 (1)"]
FE[frontend-design<br/>UI/UX设计指导]
end
subgraph Other["🔮 其他插件 (1)"]
RW[ralph-wiggum<br/>自引用迭代]
end
Core["🎯 Claude Code 核心引擎<br/>插件注册中心"]
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 终端<br/><small>命令行交互</small>"]
VSCode["📝 VSCode 扩展<br/><small>IDE 集成</small>"]
GitHub["🤖 GitHub Bot<br/><small>CI/CD 自动化</small>"]
end
subgraph Layer2["⚙️ 核心引擎层 - Core Engine Layer <small>(闭源)</small>"]
direction TB
subgraph Router_Group["🎯 请求路由模块"]
Router["Intent Router<br/><small>智能意图识别</small>"]
end
subgraph Context_Group["🧠 上下文管理模块"]
Context["Context Manager<br/><small>记忆压缩·注入</small>"]
PluginLoader["Plugin Loader<br/><small>动态插件发现</small>"]
end
subgraph Execution_Group["⚡ 执行引擎模块"]
ToolEngine["Tool Execution Engine<br/><small>工具调用·沙箱隔离</small>"]
MCPClient["MCP Client<br/><small>外部服务桥接</small>"]
end
end
subgraph Layer3["🧩 插件生态层 - Plugin Ecosystem Layer <small>(开源)</small>"]
direction TB
Registry["📋 Capability Registry<br/><small>能力注册中心</small>"]
subgraph Plugin_Types["插件能力矩阵"]
direction LR
Commands["⚡ Commands<br/><small>显式调用</small>"]
Agents["🤖 Agents<br/><small>自主决策</small>"]
Skills["📚 Skills<br/><small>隐式注入</small>"]
Hooks["🪝 Hooks<br/><small>行为拦截</small>"]
end
end
subgraph Layer4["🌐 外部服务层 - External Services Layer"]
direction LR
LLM["🧠 Claude API<br/><small>Sonnet 4.6/Opus 4.6/Haiku 4.5</small>"]
MCP["🔌 MCP Servers<br/><small>GitHub·DB·FS</small>"]
OS["💾 Operating System<br/><small>文件系统·Shell</small>"]
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)分别由对应的加载器(loadPluginCommands、loadPluginAgents、loadSkillsDir、loadPluginHooks)加载后,通过 React hooks(useMergedCommands、useMergedTools)在 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 核心数据结构
// 实际源码中的插件元数据结构(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 <small>(Disk)</small>"]
direction TB
L3["🌍 L3: Global Memory<br/><small>~/.claude/config.json</small><br/>📌 用户偏好 · API配置 · 模型设置"]
subgraph ProjectLevel["📁 项目级存储"]
direction LR
L2["📜 L2-A: Project Constitution<br/><small>CLAUDE.md</small><br/>🎯 代码规范 · 架构原则"]
L2T["✅ L2-B: Todo List<br/><small>.claude/todos.json</small><br/>📋 任务队列 · 断点续传"]
end
end
subgraph RAM["⚡ 运行时内存层 - Runtime Memory <small>(RAM)</small>"]
direction TB
L1["🧬 L1: System Prompt<br/><small>核心身份定义</small><br/>🛠️ 工具定义 · Skill SOP · 安全策略"]
L0["💭 L0: Session History<br/><small>对话上下文</small><br/>💬 用户消息 · AI响应 · 工具调用结果"]
end
subgraph Pipeline["🔄 上下文处理流水线 - Context Pipeline"]
direction TB
subgraph Injection["📥 注入阶段"]
Injector["Prompt Injector<br/><small>多源上下文融合器</small>"]
end
subgraph Compression["📦 压缩阶段"]
Monitor["Token Monitor<br/><small>Token 使用率监控</small><br/>⚠️ 90%阈值触发"]
Compressor["Context Compressor<br/><small>智能压缩引擎</small><br/>📸 Summary + Snapshot"]
end
end
FinalContext["🎯 Final Context<br/><small>最终上下文包</small><br/>📤 发送给 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 管理结构化配置。
// ~/.claude/settings.json 结构示例
{
"model": "claude-sonnet-4-6",
"permissions": {
"allow": ["Bash(git *)"],
"deny": []
},
"hooks": {
"PreToolUse": [...]
},
"plugins": {
"code-review@claude-code-marketplace": { "enabled": true }
}
}
<!-- ~/.claude/CLAUDE.md 示例 -->
# 全局偏好
- 使用中文回复
- 代码风格:简洁
- 提交信息遵循 Conventional Commits
生命周期:永久存储。CLAUDE.md 通过 loadMemoryPrompt() 在每次 API 请求时注入 System Prompt;settings.json 通过 enableConfigs() 在启动时加载。
L2: Project Memory(项目规范)
存储位置:
-
CLAUDE.md:项目规范文档
-
.claude/todos.json:待办事项队列
CLAUDE.md 示例:
# 项目规范:MyApp
## 代码风格
- TypeScript 严格模式
- 使用 Prettier + ESLint
- 组件命名:PascalCase
## 架构原则
- 每个组件单一职责
- 所有函数必须有类型定义
- 错误使用 Result 类型而非异常
## 禁止操作
- ❌ 不要使用 `any` 类型
- ❌ 不要直接修改 package.json
- ❌ 不要提交 .env 文件
## Git 规范
遵循 Conventional Commits:
- feat: 新功能
- fix: Bug 修复
- docs: 文档更新
todos.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(会话记忆)
存储位置:内存中的消息数组
数据结构:
// 实际源码中的消息类型(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() 函数组装完整上下文:
// 实际源码逻辑(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),看似很多,但在实际开发中:
一次完整的功能开发对话可能消耗:
- 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: "总结之前的对话,<br/>保留关键信息和决策"
LLM-->>Compressor: 5. 返回摘要(Summary)
Compressor->>Compressor: 6. 生成环境快照(Snapshot)<br/>- Git 状态<br/>- 文件树<br/>- 待办事项
Compressor->>Compressor: 7. 丢弃旧对话历史<br/>保留最近 5 轮
Compressor->>Engine: 8. 重构 Context:<br/>[Summary] + [Snapshot] + [Recent 5]
Engine->>Monitor: 9. 重置 Token 计数器
Monitor-->>Engine: 继续对话
end
5.3 压缩器核心实现
// [伪代码] 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):
[System Prompt: 5K]
[CLAUDE.md: 2K]
[Todos: 1K]
[第1轮对话: 3K]
[第2轮对话: 4K]
...
[第30轮对话: 5K]
总计:~180K tokens
压缩后(40K tokens):
[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 命令手动触发压缩:
# 感觉 AI 反应变慢或开始产生幻觉时
/compact
这会强制执行压缩流程,让 AI"清醒"过来。
6. 通信协议:流式 API 与实时交互
6.1 为什么使用流式 API?
传统的 Request-Response 模式会让用户等待很久才看到结果,而流式 API可以边生成边显示:
传统模式:
用户提问 → [等待 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<br/>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 调用实现
// [伪代码] 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 协议进行流式传输:
事件格式:
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 错误处理与重试
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 界面的概念相同:
// 传统方式
console.log('Loading...');
// 无法更新这行文本
// Ink 方式
<Text color="cyan">
<Spinner /> Loading...
</Text>
// 可以实时更新 Spinner 动画
7.2 Ink 架构原理
graph LR
subgraph "React Layer (src/components/)"
JSX[JSX 组件<br/>Box, Text, ScrollBox]
VirtualDOM[Virtual DOM]
end
subgraph "Custom Ink Engine (src/ink/)"
Reconciler[react-reconciler<br/>自定义 Reconciler]
Layout[Yoga Layout Engine<br/>src/ink/layout/]
Renderer[render-node-to-output.ts<br/>渲染到缓冲区]
end
subgraph "Terminal Layer"
ANSI[ANSI Escape Codes<br/>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 组件
// [伪代码] 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 使用乐观更新策略,在工具实际执行前就显示"正在执行"状态:
// [伪代码] 工具调用的乐观更新
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 架构,可以优先渲染重要的更新:
// 高优先级:用户输入反馈
<Text color="green">{userInput}</Text>
// 中优先级:工具执行状态
<Spinner /> Executing git status...
// 低优先级:日志输出
<Text dimColor>{debugLog}</Text>
7.6 ANSI 颜色与样式
Ink 底层使用 ANSI Escape Codes 实现终端样式:
// 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:
<Text bold color="green">✓ Success</Text>
8. 核心模块一:Commands(命令系统)
8.1 什么是 Command?
重要说明:在 v2.1.88 的源码中,commands/ 目录已被标记为 commands_DEPRECATED(见 src/skills/loadSkillsDir.ts),新的推荐方式是使用 skills/ 目录。两者的 Frontmatter 格式相同,但 Skills 提供了更丰富的元数据(whenToUse、model、version 等)。为保持文档的历史连贯性,本章仍以 Command 术语描述。
Command(现称 Skill) 是用户通过 Slash 命令(如 /commit、/review)直接调用的预定义 Prompt。它类似于 ChatGPT 的"自定义指令",但更强大:
- ✅ 可以预授权工具权限(无需每次确认)
- ✅ 支持参数传递(
/feature-dev 实现登录功能)
- ✅ 可以调用其他 Agent
- ✅ 支持
$ARGUMENTS 和索引参数 $0, $1 等变量替换
8.2 Command 文件格式
所有 Command 都是 Markdown + YAML Frontmatter 格式:
---
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 核心代码逆向还原
// [伪代码] 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 文件格式
---
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<br/>src/tools/AgentTool/]
AgentTool -->|"createSubagentContext()"| SubContext1[Sub-Agent 1<br/>code-explorer]
AgentTool -->|"createSubagentContext()"| SubContext2[Sub-Agent 2<br/>code-architect]
AgentTool -->|"createSubagentContext()"| SubContext3[Sub-Agent 3<br/>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 调度器
// [伪代码] 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<br/>理解需求]
Phase1 --> Phase2[Phase 2: Codebase Exploration<br/>派生 3 个 code-explorer Agents]
Phase2 --> ReadFiles[读取 Agents 推荐的关键文件]
ReadFiles --> Phase3[Phase 3: Clarifying Questions<br/>询问未明确的细节]
Phase3 --> Phase4[Phase 4: Architecture Design<br/>派生 3 个 code-architect Agents]
Phase4 --> UserApproval{用户批准方案?}
UserApproval -->|否| Phase4
UserApproval -->|是| Phase5[Phase 5: Implementation<br/>编写代码]
Phase5 --> Phase6[Phase 6: Quality Review<br/>派生 3 个 code-reviewer Agents]
Phase6 --> FixIssues{需要修复?}
FixIssues -->|是| Phase5
FixIssues -->|否| Phase7[Phase 7: Summary<br/>总结完成]
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 的触发方式有两种:
-
LLM 主动调用:Skill 元数据列在 System Prompt 中,LLM 判断相关时调用 SkillTool(
src/tools/SkillTool/)
-
用户显式调用:用户输入
/skill-name 直接调用
并不存在基于关键词的自动匹配引擎。
类比:
-
旧版 Command = 用户
/commit 显式调用
-
Skill = LLM 看到元数据后自主决策是否调用(半隐式);也可由用户
/skill-name 显式调用
10.2 Skill 文件格式
---
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 测试?
### 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 注入逻辑
// 实际源码逻辑(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<br/>路由引擎"]
end
subgraph Capabilities["🧩 能力执行层"]
direction LR
subgraph CommandFlow["⚡ Command 流程<br/><small>显式调用</small>"]
C1["用户输入:<br/>/feature-dev 登录功能"]
C2["🎯 精确匹配命令"]
C3["📋 执行固定流程<br/>7阶段 SOP"]
C4["✅ 完成任务"]
C1 --> C2 --> C3 --> C4
end
subgraph SkillFlow["📚 Skill 流程<br/><small>隐式注入</small>"]
S1["用户输入:<br/>设计登录页面"]
S2["🔎 关键词匹配<br/>design/UI/frontend"]
S3["💉 注入 Skill SOP<br/>前端设计最佳实践"]
S4["🧠 AI自主执行<br/>遵循设计原则"]
S1 --> S2 --> S3 --> S4
end
subgraph AgentFlow["🤖 Agent 流程<br/><small>自主决策</small>"]
A1["Command调用:<br/>/feature-dev"]
A2["🚀 启动 Agent<br/>code-explorer"]
A3["🔄 自主规划<br/>搜索→分析→总结"]
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<br/>(内存)
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<br/>(关键词: 设计, 界面)
Router->>+FS: 读取 frontend-design/SKILL.md 完整内容
FS-->>-Router: 返回 SOP 内容
Router->>Engine: 返回触发的 Skill 列表
Engine->>Engine: 将 Skill SOP 注入 System Prompt
Note over Engine: System Prompt 组成:<br/>① Core System Prompt<br/>② 用户偏好 (L3)<br/>③ 项目规范 (L2)<br/>④ 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 仍在上下文中<br/>无需重新注入
Engine->>+LLM: 发送请求
LLM-->>-Engine: 继续遵循前端设计原则
Engine-->>-User: 输出符合 a11y 标准的实现
10.7 Skill 设计哲学:渐进式披露
Claude Code 的 Skill 系统采用**渐进式披露(Progressive Disclosure)**设计模式,这是一个经典的 UX 设计原则,应用在了 AI 系统中。
🎯 核心理念
按需加载,恰到好处
不要一次性把所有知识塞给 AI,而是:
-
Level 1(元数据):启动时加载,极低成本,用于快速匹配
-
Level 2(SOP 主体):触发时注入,中等成本,提供核心知识
-
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 加持的输出
// 用户输入:帮我实现一个登录表单
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)
// 用户输入:帮我实现一个登录表单
// [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["低质量输出<br/>缺少最佳实践"]
style W3 fill:#dc2626,stroke:#fca5a5,color:#fff
end
subgraph With["✅ 有 Skill"]
S1["用户输入"] --> S2["AI 基础知识"]
S2 --> S3["+ Skill SOP"]
S3 --> S4["高质量输出<br/>遵循最佳实践"]
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<br/>工具执行前]
E2[PostToolUse<br/>工具执行后]
E2b[PostToolUseFailure<br/>工具执行失败后]
E3[UserPromptSubmit<br/>用户输入提交前]
E4[Stop<br/>对话结束前]
E4b[StopFailure<br/>结束检查失败]
E5[SessionStart<br/>会话开始]
E6[SessionEnd<br/>会话结束]
E7a[SubagentStart<br/>子 Agent 启动]
E7b[SubagentStop<br/>子 Agent 结束]
E8[PreCompact<br/>上下文压缩前]
E8b[PostCompact<br/>上下文压缩后]
E9[Notification<br/>通知事件]
E10[PermissionRequest<br/>权限请求]
E11[PermissionDenied<br/>权限拒绝]
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.ts 的 HOOK_EVENTS 常量中。
11.3 Hook 配置格式
实际支持四种 Hook 类型(command、prompt、agent、http),以及 if 条件匹配:
{
"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
### 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 插件提供了一个可视化的规则编辑器,让用户无需写代码就能定义拦截规则:
# .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<br/>Markdown 配置] -->|"解析"| Loader[Config Loader<br/>YAML to Python]
Loader --> Rules[Rule Objects<br/>数据结构]
Input[Hook 输入<br/>JSON] --> Engine[Rule Engine<br/>规则引擎]
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<br/>本地进程]
T2[SSE<br/>服务器推送]
T3[HTTP<br/>REST API]
T4[WebSocket<br/>双向实时]
end
subgraph "Use Cases"
U1[本地工具<br/>文件系统, Git]
U2[云服务<br/>GitHub, Asana]
U3[API 后端<br/>自定义服务]
U4[实时数据<br/>股票行情]
end
T1 --> U1
T2 --> U2
T3 --> U3
T4 --> U4
12.3 MCP 配置示例
方式 1:独立 .mcp.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
{
"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 提供的工具会自动加上前缀:
mcp__plugin_<插件名>_<服务器名>__<工具名>
示例:
- mcp__plugin_asana_asana__asana_create_task
- mcp__plugin_github_github__github_search_issues
- mcp__plugin_db_database__execute_query
在 Command 中使用:
---
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: 智能并行策略:<br/>连续只读工具 → 并行批次<br/>写入工具 → 串行批次
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 都必须声明允许使用的工具:
---
# 明确列出工具
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 风格匹配。
权限检查逻辑:
// [伪代码] 工具权限检查器
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 插件文件结构
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 节选)
---
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)
---
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: 询问澄清问题<br/>- 密码加密方式?<br/>- Token 存储位置?<br/>- 支持第三方登录吗?
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: 实现功能<br/>(编写代码)
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 的行为准则:
# 项目规范: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
npm test # 运行所有测试
npm run test:watch # 监视模式
npm run test:e2e # E2E 测试
部署流程
- 运行
npm run build
- 确保所有测试通过
- 创建 PR 到
main 分支
- 等待 CI 通过
- 合并后自动部署到 staging
### 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 规则
# .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<br/>插件生态))
分层设计
微内核
插件扩展
能力注册
声明式能力
Commands
Agents
Skills
治理机制
Hooks
权限控制
安全拦截
外部连接
MCP 协议
stdio/SSE/HTTP
多服务集成
开发者体验
Markdown 驱动
热加载
调试友好
16.3 适用场景与限制
适用场景:
- ✅ 自动化开发工作流(commit, review, PR)
- ✅ 代码库探索和文档生成
- ✅ 定制化开发助手(企业内部规范)
- ✅ 连接外部服务(数据库、API、CI/CD)
当前限制:
- ⚠️ 核心引擎闭源(无法深度定制)
- ⚠️ 依赖网络(需要 Claude API)
- ⚠️ Token 成本(大型项目可能昂贵)
- ⚠️ Hook 调试较困难(需要 --debug 模式)
16.4 未来展望
基于当前架构,我们可以预见:
-
更多官方插件:数据库管理、DevOps、测试生成
-
插件市场:类似 VS Code Extensions
-
本地模型支持:降低成本,提高隐私
-
可视化编辑器:拖拽式创建 Command/Agent
-
企业版:SSO、审计日志、合规性控制
附录:快速参考
A. 文件格式速查
Command 格式:
---
description: 描述
argument-hint: 参数提示
allowed-tools: [工具列表]
---
# Prompt 内容
$ARGUMENTS 会被替换为用户输入
Agent 格式:
---
name: agent-name
description: 描述
tools: [工具列表]
model: sonnet|opus|haiku
color: yellow|blue|green
---
# Agent 指令
详细的执行逻辑...
Skill 格式(新版统一格式,替代旧版 Command):
---
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 格式:
{
"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. 调试技巧
# 启用调试日志
claude --debug
# 查看 MCP 服务器状态
/mcp
# 查看插件列表
/help
# 强制压缩上下文
/compact
# 查看 Token 使用
/cost
# 清空会话重新开始
/clear
D. Bun 适配层(源码运行必备)
Claude Code 核心引擎使用 Bun 编译,依赖 bun:bundle 和 bun:ffi 两个 Bun-only 模块。通过 extracted/ 中的 shim 层可在 Node.js 下运行:
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:
// 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 架构哲学对比
三者看似功能相同,但架构哲学截然不同:
Claude Code: Markdown 驱动 + 微内核插件
"用文档定义能力,让 LLM 执行逻辑"
Codex: Rust 系统级 + 沙箱隔离优先
"安全第一,性能极致,系统级隔离"
Gemini CLI: TypeScript 全栈 + 最简设计
"清晰分层,标准 React 模式,易于理解"
Claude Code — 微内核 + 插件生态
┌──────────────────────────────────────────┐
│ 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 全栈最简
┌──────────────────────────────────────────┐
│ 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 自动写入记忆) |
// 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); },
});
// Codex — Rust trait 实现,编译期类型安全
pub trait ToolHandler: Send + Sync {
async fn handle(&self, invocation: ToolInvocation) -> Result<ToolOutput, ToolError>;
}
// 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 命令 |
无 |
无 |
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 性能与安全权衡
安全性 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 的三方对比。
