ClaudeCode 源码完整解读:从 60+ 模块51万行源码学习如何构建生产级 AI Agent 系统
源码泄露事件
2026 年 3 月 31 日,Claude Code 的完整源码在技术社区流出,引发了 AI 开发者圈的广泛讨论。这并非 Anthropic 主动开源,而是一次意外的代码泄露——完整的 TypeScript 源码、构建配置、内部工具实现,甚至包含部分内部注释和调试代码,全部暴露在公众视野中。
这套源码的泄露,对于 AI Agent 开发者而言,是一次难得的学习机会:
代码规模惊人:src/ 目录下 60+ 个模块,涵盖工具系统、权限管理、Agent 调度、MCP 协议实现等完整功能。这不是一个 MVP 或玩具项目,而是经过大规模用户验证的商业级产品。
架构设计精良:从工具系统的 buildTool 模式,到权限系统的多层级检查,再到 MCP 协议的适配器设计,每一处都体现了工程团队对 AI Agent 的深刻理解。
工程化程度极高:完善的错误处理、性能优化(并行预取、懒加载、缓存)、测试覆盖、类型安全……这是教科书级别的 TypeScript 项目工程实践。
安全意识强烈:源码中随处可见安全相关的代码——危险命令检测、沙箱隔离、权限剥离、敏感信息过滤。Claude Code 在让 AI 拥有强大能力的同时,也在小心翼翼地控制风险。
泄露源码包含的核心内容:
- 核心引擎:Agent 调度、消息处理、工具调用
- 40+ 内置工具:Bash、Edit、Glob、Grep、WebSearch、Agent...
- 权限系统:细粒度的工具权限控制和用户确认机制
- MCP 协议实现:动态加载外部工具的标准协议
- 多 Agent 协作:子代理、团队模式、后台任务
源码规模:
- 60+ 模块目录
- 数千个 TypeScript 文件
- 完整的构建、测试、部署流程
技术栈:
- TypeScript(严格模式)
- Bun 运行时 + Node.js 兼容
- React + Ink(终端 UI)
- Zod v4(Schema 验证)
- Anthropic SDK
本文定位声明
本文是一份技术学习文档,目的是:
- 帮助开发者理解 AI Agent 的架构设计
- 学习 TypeScript 大型项目的工程实践
- 探索 MCP 协议的设计思路
声明:仅用于学习研究目的。
📋 目录
- 项目概览
- 核心架构
- 根目录核心文件
- 模块深度分析
- 工具系统详解
- 服务模块详解
- 设计模式与最佳实践
- 如何基于源码搭建自己的 Claude Code
项目概览
技术栈
|
层级 |
技术 |
版本/说明 |
|
语言 |
TypeScript |
严格类型检查 |
|
运行时 |
Bun |
主运行时,支持原生模块 |
|
兼容 |
Node.js |
>= 18 |
|
构建 |
Bun bundle |
支持 dead code elimination |
|
UI 框架 |
React + Ink |
终端 UI |
|
状态管理 |
自定义 Store |
类似 Redux,不可变更新 |
|
API |
Anthropic SDK |
Claude 模型 API |
|
协议 |
MCP |
Model Context Protocol |
|
验证 |
Zod v4 |
Schema 验证 |
核心特性
- 多模式运行: 交互式 REPL + 非交互式 Print 模式
- 工具扩展: 40+ 内置工具 + MCP 动态加载
- Agent 系统: 支持子代理、团队协作、后台任务
- 权限管理: 细粒度的工具权限控制
- 会话持久化: 支持会话恢复、分支、teleport
核心架构
┌─────────────────────────────────────────────────────────────────┐
│ CLI Entry (main.tsx) │
│ - 命令行参数解析 (Commander) │
│ - 初始化流程 (init, setup) │
│ - 模式选择 (interactive / headless) │
└─────────────────────────────────────────────────────────────────┘
│
┌───────────────┴───────────────┐
▼ ▼
┌───────────────────────────┐ ┌───────────────────────────┐
│ Interactive Mode (REPL) │ │ Headless Mode (print) │
│ - Ink UI 渲染 │ │ - 单次查询执行 │
│ - 实时状态更新 │ │ - 流式输出支持 │
│ - 用户交互处理 │ │ - JSON Schema 输出 │
└───────────────────────────┘ └───────────────────────────┘
│ │
└───────────────┬───────────────┘
▼
┌─────────────────────────────────────────────────────────────────┐
│ Query Engine │
│ - 消息处理流程 │
│ - API 调用管理 │
│ - 工具调用调度 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Tool System │
│ - 40+ 内置工具 │
│ - MCP 动态工具 │
│ - 权限检查 │
│ - 并发控制 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ State Management │
│ - AppState (全局状态) │
│ - ToolPermissionContext │
│ - MCP 连接状态 │
│ - Task/Agent 状态 │
└─────────────────────────────────────────────────────────────────┘
根目录核心文件
main.tsx - CLI 入口
职责: 命令行解析、初始化编排、模式选择
// 核心流程
async function main() {
// 1. 安全设置
process.env.NoDefaultCurrentDirectoryInExePath = '1'
// 2. 并行预启动(性能优化)
startMdmRawRead() // MDM 设置预读
startKeychainPrefetch() // Keychain 预取
// 3. 命令行解析(60+ 选项)
const program = new CommanderCommand()
program
.option('-p, --print')
.option('--model <model>')
.option('--dangerously-skip-permissions')
// ... 更多选项
// 4. 初始化钩子
program.hook('preAction', async () => {
await init() // 加载配置、认证
runMigrations() // 数据迁移
})
// 5. 执行模式分支
if (isNonInteractiveSession) {
await runHeadless()
} else {
await launchRepl()
}
}
设计亮点:
- 并行预取减少启动时间
- Lazy Import 条件导入
- Dead code elimination(feature() 函数)
- 迁移系统保证配置兼容性
Tool.ts - 工具接口
职责: 定义工具接口、提供 buildTool 构建器
export type Tool<Input, Output, Progress> = {
// 基本信息
readonly name: string
aliases?: string[]
readonly inputSchema: ZodSchema<Input>
outputSchema?: ZodSchema<Output>
// 核心方法
call(input, context, canUseTool, parentMessage, onProgress): Promise<ToolResult<Output>>
description(input, options): Promise<string>
// 权限
checkPermissions(input, context): Promise<PermissionResult>
validateInput?(input, context): Promise<ValidationResult>
// 行为特性
isEnabled(): boolean
isConcurrencySafe(input): boolean
isReadOnly(input): boolean
isDestructive?(input): boolean
interruptBehavior?(): 'cancel' | 'block'
// UI 渲染
renderToolUseMessage(input, options): ReactNode
renderToolResultMessage?(content, progress, options): ReactNode
getToolUseSummary?(input): string | null
// Prompt
prompt(options): Promise<string>
userFacingName(input): string
}
// 构建器:填充默认值
export function buildTool<D extends ToolDef>(def: D): BuiltTool<D> {
return {
...TOOL_DEFAULTS,
userFacingName: () => def.name,
...def,
}
}
const TOOL_DEFAULTS = {
isEnabled: () => true,
isConcurrencySafe: () => false, // 安全默认值
isReadOnly: () => false,
isDestructive: () => false,
checkPermissions: () => Promise.resolve({ behavior: 'allow' }),
}
设计模式:
- Builder Pattern:buildTool 提供默认值
- Strategy Pattern:不同权限检查策略
- Observer Pattern:onProgress 回调
context.ts - 上下文管理
职责: 用户上下文、系统上下文的获取和缓存
// 用户上下文(CLAUDE.md 等)
export const getUserContext = memoize(async () => {
const claudeMd = shouldDisableClaudeMd
? null
: getClaudeMds(await getMemoryFiles())
return {
...(claudeMd && { claudeMd }),
currentDate: `Today's date is ${getLocalISODate()}.`,
}
})
// 系统上下文(Git 状态)
export const getSystemContext = memoize(async () => {
const [branch, mainBranch, status, log] = await Promise.all([
getBranch(),
getDefaultBranch(),
execFileNoThrow(gitExe(), ['status', '--short']),
execFileNoThrow(gitExe(), ['log', '--oneline', '-n', '5']),
])
return {
gitStatus: [
`Current branch: ${branch}`,
`Main branch: ${mainBranch}`,
`Status:\n${status || '(clean)'}`,
`Recent commits:\n${log}`,
].join('\n\n')
}
})
Task.ts - 任务系统
职责: 任务类型定义、任务 ID 生成、任务状态管理
export type TaskType =
| 'local_bash' // 本地 Shell 任务
| 'local_agent' // 本地 Agent 任务
| 'remote_agent' // 远程 Agent 任务
| 'in_process_teammate' // 进程内队友
| 'local_workflow' // 本地工作流
| 'monitor_mcp' // MCP 监控
| 'dream' // Dream 任务
export type TaskStatus =
| 'pending' | 'running' | 'completed' | 'failed' | 'killed'
// 任务 ID 生成(安全、唯一)
export function generateTaskId(type: TaskType): string {
const prefix = TASK_ID_PREFIXES[type] // 'b', 'a', 'r' 等
const bytes = randomBytes(8)
let id = prefix
for (let i = 0; i < 8; i++) {
id += TASK_ID_ALPHABET[bytes[i]! % 36] // 0-9a-z
}
return id // 例如: "b3k9x2m1n7p4"
}
模块深度分析
📁 assistant/ - AI 助手后台服务
职责: KAIROS/Proactive 模式的后台守护进程
|
文件 |
功能 |
深入分析 |
|
|
会话历史管理 |
记录会话 ID、时间戳、摘要,支持历史查询和恢复 |
架构设计:
┌─────────────────────────────────────────┐
│ Assistant Daemon │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Scheduler │ │ Notifier │ │
│ │ (定时任务) │ │ (推送通知) │ │
│ └─────────────┘ └─────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────────┐ │
│ │ Session History │ │
│ │ (会话记录、上下文恢复) │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────┘
📁 bootstrap/ - 启动状态管理
职责: 全局启动状态的单例管理
// state.ts 核心状态
let cwd: string // 当前工作目录
let sessionId: SessionId // 会话 ID
let mainLoopModel: ModelSetting // 主模型
let permissionMode: PermissionMode // 权限模式
let agentDefinitions: AgentDefinitionsResult // Agent 定义
let hasTrustDialogAccepted: boolean // 信任对话框
let statsStore: StatsStore // 统计存储
let registeredHooks: RegisteredHooks // 注册的 Hooks
// 状态访问器(确保单例)
export function getCwd(): string { return cwd }
export function getSessionId(): SessionId { return sessionId }
export function getMainLoopModel(): ModelSetting { return mainLoopModel }
设计要点:
- 单例模式确保全局一致性
- 状态变更通过 setter 触发副作用
- 支持状态快照和恢复
📁 bridge/ - 远程控制桥接
职责: Claude Code 与 claude.ai 的双向通信
核心文件分析:
|
文件 |
职责 |
关键实现 |
|
|
主逻辑 |
WebSocket 连接、心跳、重连 |
|
|
API 接口 |
RPC 调用封装 |
|
|
配置管理 |
环境 ID、会话 URL |
|
|
消息处理 |
序列化、路由 |
|
|
权限回调 |
远程权限审批 |
|
|
指针同步 |
光标位置共享 |
|
|
容量唤醒 |
按需激活 |
架构图:
┌─────────────────┐ ┌─────────────────┐
│ Claude Code │ │ claude.ai │
│ (本地) │ │ (云端) │
│ │ │ │
│ ┌───────────┐ │ WebSocket (WSS) │ ┌───────────┐ │
│ │ Bridge │◄─┼────────────────────┼─►│ Server │ │
│ │ Client │ │ │ │ │ │
│ └───────────┘ │ │ └───────────┘ │
│ │ │ │ │ │
│ ▼ │ │ ▼ │
│ ┌───────────┐ │ │ ┌───────────┐ │
│ │Permission │ │ 权限请求 ────────►│ │ User │ │
│ │ Manager │ │ ◄─────── 审批结果 │ │ Approval │ │
│ └───────────┘ │ │ └───────────┘ │
└─────────────────┘ └─────────────────┘
消息流:
// 权限请求流程
async function requestPermission(tool: string, input: unknown) {
// 1. 本地生成请求
const request = {
type: 'permission_request',
toolName: tool,
input: sanitize(input),
timestamp: Date.now(),
}
// 2. 发送到云端
bridge.send(request)
// 3. 等待审批
const response = await bridge.waitFor('permission_response', request.id)
return response.decision // 'allow' | 'deny' | 'ask'
}
📁 buddy/ - 伴侣精灵系统
职责: 终端右下角的动画伴侣
|
文件 |
功能 |
实现 |
|
|
核心逻辑 |
状态机、动画触发 |
|
|
React 组件 |
Ink 渲染、帧动画 |
|
|
精灵定义 |
ASCII 艺术、动画帧 |
|
|
提示词 |
伴侣行为描述 |
状态机设计:
┌─────────┐ idle ┌─────────┐
│ Idle │ ─────────►│ Think │
│ (休息) │ │ (思考) │
└─────────┘ └────┬────┘
▲ │
│ working
│ ▼
│ ┌─────────┐
└───────────────│ Work │
done │ (工作) │
└─────────┘
📁 cli/ - 命令行接口
职责: Headless/Print 模式实现
|
文件 |
功能 |
|
|
Headless 模式核心,单次查询执行 |
|
|
结构化输入输出(JSON Schema) |
|
|
远程 I/O 处理 |
|
|
退出码管理 |
|
|
各类处理器(auth、mcp、plugins) |
|
|
传输层实现 |
print.ts 核心流程:
export async function runPrintMode(options: PrintOptions) {
// 1. 解析输入
const input = await parseInput(options)
// 2. 初始化上下文
const context = await createQueryContext(options)
// 3. 执行查询(流式)
const stream = await queryModelWithStreaming({
messages: [{ role: 'user', content: input }],
model: options.model,
stream: true,
})
// 4. 输出结果
for await (const chunk of stream) {
if (chunk.type === 'content_block_delta') {
process.stdout.write(chunk.delta.text)
}
}
// 5. 清理
await cleanup()
}
📁 commands/ - Slash 命令系统
职责: 实现 /help、/login 等 Slash 命令
|
命令 |
文件 |
功能 |
|
|
|
初始化项目配置 |
|
|
|
Git 提交 |
|
|
|
代码审查 |
|
|
|
状态显示 |
|
|
|
安装插件 |
|
|
(内置) |
配置管理 |
命令注册模式:
interface Command {
name: string
aliases?: string[]
description: string
handler: (args: string[], context: CommandContext) => Promise<void>
autocomplete?: (input: string) => string[]
}
// 命令注册
const commands: Command[] = [
{
name: 'commit',
description: 'Create a git commit',
handler: async (args, ctx) => {
const message = args.join(' ')
await createCommit(message, ctx)
},
},
]
📁 components/ - React UI 组件库
职责: 终端 UI 组件(Ink 框架)
|
组件 |
功能 |
|
|
根组件 |
|
|
REPL 主界面 |
|
|
加载动画 |
|
|
API Key 批准 |
|
|
Auto 模式选择 |
|
|
桥接对话框 |
|
|
文本输入 |
组件设计原则:
// 函数式组件 + Hooks
const Spinner: React.FC<SpinnerProps> = ({ mode, text }) => {
const [frame, setFrame] = useState(0)
useEffect(() => {
const timer = setInterval(() => {
setFrame(f => (f + 1) % FRAMES.length)
}, 80)
return () => clearInterval(timer)
}, [])
return (
<Box>
<Text color="cyan">{FRAMES[frame]}</Text>
<Text> {text}</Text>
</Box>
)
}
📁 constants/ - 常量定义
职责: 全局常量集中管理
|
文件 |
内容 |
|
|
产品信息(名称、版本、URL) |
|
|
OAuth 配置(客户端 ID、端口) |
|
|
API 限制(Token、速率) |
|
|
Beta 功能开关 |
|
|
系统提示词模板 |
|
|
错误 ID 枚举 |
📁 context/ - React Context
职责: 全局状态共享
|
Context |
功能 |
|
|
通知管理 |
|
|
模态框 |
|
|
覆盖层 |
|
|
消息收发 |
|
|
语音功能 |
|
|
性能指标 |
📁 coordinator/ - 协调器模式
职责: 多 Agent 协调(Leader-Worker)
// coordinatorMode.ts
export function isCoordinatorMode(): boolean {
return process.env.CLAUDE_COORDINATOR_MODE === 'true'
}
// Leader 分发任务
export async function dispatchToWorkers(tasks: Task[]) {
const workers = getAvailableWorkers()
return Promise.all(tasks.map((task, i) => {
const worker = workers[i % workers.length]
return worker.execute(task)
}))
}
📁 hooks/ - React Hooks
职责: 可复用逻辑封装
|
Hook |
功能 |
|
|
工具权限检查 |
|
|
箭头键历史 |
|
|
闪烁动画 |
|
|
取消请求 |
|
|
剪贴板提示 |
📁 ink/ - Ink 终端 UI 框架
职责: 封装 Ink 框架,实现终端 UI
|
文件 |
功能 |
|
|
核心封装 |
|
|
ANSI 处理 |
|
|
双向文本 |
|
|
虚拟 DOM |
|
|
焦点管理 |
|
|
帧渲染 |
📁 keybindings/ - 快捷键系统
职责: 可配置的快捷键绑定
|
文件 |
功能 |
|
|
默认绑定 |
|
|
快捷键解析 |
|
|
快捷键解析 |
|
|
Hook |
📁 memdir/ - 内存目录管理
职责: CLAUDE.md 智能扫描
|
文件 |
功能 |
|
|
核心逻辑 |
|
|
查找相关记忆 |
|
|
扫描算法 |
|
|
老化机制 |
扫描策略:
当前目录/CLAUDE.md
│
├── 父目录/CLAUDE.md (向上遍历)
│
└── ~/.claude/CLAUDE.md (用户全局)
📁 migrations/ - 数据迁移
职责: 版本升级时的配置迁移
// 迁移脚本模式
export async function migrateSonnet45ToSonnet46() {
const settings = await loadSettings()
if (settings.model === 'claude-sonnet-4-5') {
settings.model = 'claude-sonnet-4-6'
await saveSettings(settings)
logEvent('migration_sonnet_45_to_46')
}
}
📁 native-ts/ - 原生模块
职责: 性能关键路径的原生实现
|
模块 |
功能 |
|
|
颜色差异计算 |
|
|
文件索引 |
|
|
布局引擎 |
📁 plugins/ - 插件系统
职责: 插件发现、加载、管理
interface Plugin {
name: string
version: string
commands?: Command[]
tools?: Tool[]
hooks?: HookDefinition[]
mcpServers?: MCPServerConfig[]
}
// 插件加载
export async function loadPlugin(pluginPath: string): Promise<Plugin> {
const manifest = await readJson(join(pluginPath, 'manifest.json'))
const plugin = await import(join(pluginPath, 'index.js'))
return {
name: manifest.name,
commands: plugin.commands ?? [],
tools: plugin.tools ?? [],
}
}
📁 query/ - 查询引擎
职责: 核心查询处理
|
文件 |
功能 |
|
|
查询配置 |
|
|
依赖管理 |
|
|
停止钩子 |
|
|
Token 预算 |
📁 remote/ - 远程会话管理
职责: CCR 远程会话
|
文件 |
功能 |
|
|
会话生命周期 |
|
|
权限桥接 |
|
|
WebSocket 管理 |
📁 screens/ - 页面组件
职责: 全屏页面
|
文件 |
功能 |
|
|
主界面 |
|
|
诊断页面 |
|
|
恢复会话 |
📁 server/ - 服务器模式
职责: 直接连接服务
|
文件 |
功能 |
|
|
创建会话 |
|
|
管理器 |
📁 skills/ - Skills 系统
职责: 可扩展技能包
|
文件 |
功能 |
|
|
加载技能 |
|
|
MCP 构建 |
|
|
内置技能 |
📁 state/ - 状态管理
职责: 全局状态管理
// AppState 完整结构
export type AppState = {
// 设置
settings: SettingsJson
verbose: boolean
mainLoopModel: ModelSetting
// 权限
toolPermissionContext: ToolPermissionContext
// MCP
mcp: {
clients: MCPServerConnection[]
tools: Tool[]
commands: Command[]
resources: Record<string, ServerResource[]>
}
// Agent
agentDefinitions: AgentDefinitionsResult
agentNameRegistry: Map<string, AgentId>
// 任务
tasks: { [taskId: string]: TaskState }
// 团队
teamContext?: TeamContext
// 更多...
}
// Store 实现
export class Store<State> {
private state: State
private listeners = new Set<(state: State) => void>()
getState(): State { return this.state }
setState(updater: (prev: State) => State): void {
const next = updater(this.state)
if (next !== this.state) {
this.state = next
this.listeners.forEach(l => l(this.state))
}
}
subscribe(listener: (state: State) => void): () => void {
this.listeners.add(listener)
return () => this.listeners.delete(listener)
}
}
📁 tasks/ - 任务系统
职责: 后台任务管理
|
目录 |
任务类型 |
|
|
Shell 命令任务 |
|
|
Agent 任务 |
|
|
远程 Agent |
|
|
进程内队友 |
|
|
Dream 任务 |
任务生命周期:
pending → running → completed/failed/killed
│ │
│ ├── 输出持久化
│ └── 通知入队
│
└── 超时/取消 → killed
📁 types/ - 类型定义
职责: TypeScript 类型集中管理
|
文件 |
内容 |
|
|
消息类型 |
|
|
权限类型 |
|
|
工具类型 |
|
|
Hooks 类型 |
|
|
ID 类型 |
📁 upstreamproxy/ - 上游代理
职责: CCR 上游代理支持
|
文件 |
功能 |
|
|
代理核心 |
|
|
CONNECT 中继 |
📁 utils/ - 工具函数
职责: 通用工具函数(100+ 文件)
|
子目录 |
功能 |
|
|
权限处理 |
|
|
设置管理 |
|
|
模型相关 |
|
|
Bash 工具 |
|
|
Shell 提供者 |
|
|
遥测 |
|
|
Git 操作 |
|
|
沙箱 |
|
|
插件工具 |
📁 vim/ - Vim 模式
职责: Vim 风格键盘导航
|
文件 |
功能 |
|
|
移动命令 |
|
|
操作符 |
|
|
文本对象 |
📁 voice/ - 语音模式
职责: 语音输入/输出
|
文件 |
功能 |
|
|
启用判断 |
工具系统详解
工具分类总览
工具 (40+)
├── 文件操作
│ ├── FileReadTool # 读取文件
│ ├── FileEditTool # 编辑文件
│ ├── FileWriteTool # 写入文件
│ ├── GlobTool # 文件搜索
│ └── GrepTool # 内容搜索
│
├── Shell 执行
│ ├── BashTool # Bash 命令
│ └── PowerShellTool # PowerShell
│
├── 网络
│ ├── WebFetchTool # 网页抓取
│ └── WebSearchTool # 网页搜索
│
├── Agent/Task
│ ├── AgentTool # 子代理
│ ├── TaskOutputTool # 任务输出
│ └── TaskStopTool # 停止任务
│
├── 协作
│ ├── TeamCreateTool # 创建团队
│ ├── TeamDeleteTool # 删除团队
│ └── SendMessageTool # 发送消息
│
├── 计划
│ ├── EnterPlanModeTool
│ └── ExitPlanModeTool
│
├── MCP
│ ├── MCPTool
│ ├── ListMcpResourcesTool
│ └── ReadMcpResourceTool
│
└── 其他
├── SkillTool
├── TodoWriteTool
├── ConfigTool
└── ...
BashTool 深入分析
// BashTool.tsx 核心实现
export const BashTool = buildTool({
name: 'Bash',
inputSchema: z.object({
command: z.string(),
timeout: z.number().optional(),
description: z.string().optional(),
}),
async call(input, context, canUseTool, parentMessage, onProgress) {
const { command, timeout } = input
// 1. 安全解析
const parsed = parseForSecurity(command)
// 2. 只读检查
const isReadOnly = checkReadOnlyConstraints(command)
// 3. 沙箱判断
const useSandbox = shouldUseSandbox(command, context)
// 4. 执行
const result = await exec(command, {
timeout: timeout ?? getDefaultTimeoutMs(),
sandbox: useSandbox,
cwd: getCwd(),
})
// 5. 大输出持久化
if (result.stdout.length > PREVIEW_SIZE_BYTES) {
const outputPath = getTaskOutputPath(taskId)
await writeTextContent(outputPath, result.stdout)
return {
data: {
output: generatePreview(result.stdout),
outputPath,
}
}
}
return { data: { output: result.stdout } }
},
isSearchOrReadCommand(input) {
return isSearchOrReadBashCommand(input.command)
},
})
FileEditTool 深入分析
// FileEditTool.ts 核心实现
export const FileEditTool = buildTool({
name: 'Edit',
async call(input, context) {
const { file_path, old_string, new_string } = input
// 1. 读取文件
const content = await readFile(file_path)
// 2. 查找并替换
const newContent = content.replace(old_string, new_string)
// 3. 写入
await writeFile(file_path, newContent)
// 4. 返回 diff
return {
data: {
path: file_path,
diff: generateDiff(content, newContent),
}
}
},
async checkPermissions(input, context) {
return checkWritePermissionForTool(input.file_path, context)
},
})
WebSearchTool 深入分析
// WebSearchTool.ts 核心实现
export const WebSearchTool = buildTool({
name: 'WebSearch',
async call(input, context) {
const { query, allowed_domains, blocked_domains } = input
// 使用 Claude 内置的 Web Search 工具
const toolSchema = {
type: 'web_search_20250305',
name: 'web_search',
allowed_domains,
blocked_domains,
max_uses: 8,
}
const result = await queryModelWithStreaming({
tools: [toolSchema],
messages: [{ role: 'user', content: query }],
})
return parseSearchResults(result)
},
})
服务模块详解
📁 services/mcp/ - MCP 协议实现
职责: MCP 客户端、工具发现、服务器管理
|
文件 |
功能 |
|
|
MCP 客户端实现 |
|
|
类型定义 |
|
|
配置管理 |
|
|
认证 |
|
|
Headers 处理 |
MCP 客户端核心:
// client.ts
export async function connectMCPServer(config: MCPServerConfig): Promise<MCPServerConnection> {
// 1. 创建传输层
let transport: Transport
switch (config.type) {
case 'stdio':
transport = new StdioClientTransport({
command: config.command,
args: config.args,
env: { ...process.env, ...config.env },
})
break
case 'sse':
transport = new SSEClientTransport(new URL(config.url))
break
case 'http':
transport = new StreamableHTTPClientTransport(new URL(config.url))
break
}
// 2. 创建客户端
const client = new Client({ name: 'claude-code', version: VERSION }, {
capabilities: { tools: {}, resources: {} },
})
// 3. 连接
await client.connect(transport)
// 4. 发现工具
const { tools } = await client.request(ListToolsResultSchema, {})
// 5. 转换为 Tool 对象
const mcpTools = tools.map(tool => createMCPTool(client, tool))
return { client, tools: mcpTools, config }
}
📁 services/analytics/ - 分析遥测
职责: GrowthBook 集成、事件追踪
|
文件 |
功能 |
|
|
GrowthBook SDK |
|
|
分析入口 |
|
|
1P 事件日志 |
GrowthBook 集成:
// growthbook.ts
export async function initializeGrowthBook(user: UserAttributes) {
const client = new GrowthBook({
apiHost: 'https://cdn.growthbook.io',
clientKey: getGrowthBookClientKey(),
attributes: {
id: user.id,
sessionId: getSessionId(),
platform: process.platform,
userType: user.userType,
},
trackingCallback: (experiment, result) => {
logEvent('experiment_viewed', {
experimentId: experiment.key,
variationId: result.variationId,
})
},
})
await client.loadFeatures()
return client
}
// 功能开关检查
export function isFeatureEnabled(featureKey: string): boolean {
return client?.isOn(featureKey) ?? false
}
// 动态配置获取
export function getFeatureValue<T>(key: string, defaultValue: T): T {
return client?.getFeatureValue(key, defaultValue) ?? defaultValue
}
📁 services/api/ - API 客户端
职责: Anthropic API 封装
|
文件 |
功能 |
|
|
Claude API 客户端 |
|
|
HTTP 客户端 |
|
|
用量追踪 |
|
|
错误处理 |
|
|
日志记录 |
API 调用核心:
// claude.ts
export async function queryModelWithStreaming(options: QueryOptions) {
const { messages, model, tools, stream } = options
const client = new Anthropic({
apiKey: await getApiKey(),
baseURL: getApiBaseUrl(),
})
const response = await client.messages.create({
model: model ?? 'claude-sonnet-4-20250514',
max_tokens: 8192,
messages,
tools,
stream,
})
if (stream) {
return response as AsyncIterable<MessageStreamEvent>
}
return response as Message
}
📁 services/lsp/ - LSP 集成
职责: 语言服务器协议集成
|
文件 |
功能 |
|
|
LSP 管理器 |
|
|
LSP 客户端 |
|
|
类型定义 |
📁 services/oauth/ - OAuth 客户端
职责: OAuth 认证流程
|
文件 |
功能 |
|
|
OAuth 客户端 |
|
|
类型定义 |
📁 services/remoteManagedSettings/ - 远程管理设置
职责: 企业远程配置管理
|
文件 |
功能 |
|
|
入口 |
|
|
同步缓存 |
设计模式与最佳实践
1. 模块化工具系统
模式: Builder + Strategy
// 工具定义
const MyTool = buildTool({
name: 'MyTool',
inputSchema: z.object({ input: z.string() }),
async call(input, context) {
// 实现逻辑
return { data: 'result' }
},
checkPermissions(input, context) {
return { behavior: 'allow' }
},
})
// buildTool 自动填充默认值
// - isEnabled: true
// - isConcurrencySafe: false
// - isReadOnly: false
2. 状态管理模式
模式: Flux-like 单向数据流
// Store
const store = new Store<AppState>(getDefaultAppState())
// 读取
const state = store.getState()
// 更新(不可变)
store.setState(prev => ({
...prev,
tasks: {
...prev.tasks,
[taskId]: { ...prev.tasks[taskId], status: 'completed' },
},
}))
// 订阅
const unsubscribe = store.subscribe(state => {
console.log('State updated:', state)
})
3. 权限系统模式
模式: Chain of Responsibility
// 权限检查链
async function checkPermission(tool: Tool, input: unknown, context: Context) {
// 1. 工具特定检查
const toolResult = await tool.checkPermissions(input, context)
if (toolResult.behavior !== 'allow') return toolResult
// 2. 全局拒绝规则
if (matchDenyRules(tool.name, context)) {
return { behavior: 'deny' }
}
// 3. 全局允许规则
if (matchAllowRules(tool.name, context)) {
return { behavior: 'allow' }
}
// 4. 需要用户确认
return { behavior: 'ask' }
}
4. 任务系统模式
模式: State Machine
// 任务状态机
type TaskStatus = 'pending' | 'running' | 'completed' | 'failed' | 'killed'
const transitions: Record<TaskStatus, TaskStatus[]> = {
pending: ['running', 'killed'],
running: ['completed', 'failed', 'killed'],
completed: [], // 终态
failed: [], // 终态
killed: [], // 终态
}
function canTransition(from: TaskStatus, to: TaskStatus): boolean {
return transitions[from].includes(to)
}
5. MCP 协议模式
模式: Adapter
// MCP 工具适配器
function createMCPTool(client: MCPClient, toolDef: MCPToolDefinition): Tool {
return {
name: `mcp__${toolDef.name}`,
inputSchema: convertMCPSchemaToZod(toolDef.inputSchema),
async call(input, context) {
const result = await client.callTool(toolDef.name, input)
return { data: result.content }
},
isMcp: true,
mcpInfo: { toolName: toolDef.name },
}
}
6. 缓存策略
模式: Memoization + LRU
// 带缓存的函数
export const getGitStatus = memoize(async () => {
const [branch, status] = await Promise.all([
getBranch(),
execFileNoThrow('git', ['status', '--short']),
])
return { branch, status }
})
// LRU 缓存
const cache = new LRUCache<string, FileState>({
max: 1000,
maxAge: 1000 * 60 * 5, // 5 分钟
})
export const getFileState = memoizeWithLRU(
(path: string) => readFileState(path),
path => path,
50, // 最大缓存数量
)
7. 并发控制
模式: Semaphore + Queue
// 并发限制
const MAX_CONCURRENT_TOOLS = 10
const semaphore = new Semaphore(MAX_CONCURRENT_TOOLS)
async function executeTool(tool: Tool, input: unknown) {
await semaphore.acquire()
try {
return await tool.call(input, context)
} finally {
semaphore.release()
}
}
8. 错误处理
模式: Result Type
// 结果类型
type Result<T, E = Error> =
| { ok: true; value: T }
| { ok: false; error: E }
async function safeCall<T>(fn: () => Promise<T>): Promise<Result<T>> {
try {
const value = await fn()
return { ok: true, value }
} catch (error) {
return { ok: false, error: toError(error) }
}
}
如何基于源码搭建自己的 Claude Code
方案一:Fork 修改
步骤:
- 获取源码
- 安装依赖
bun install
- 修改配置
-
src/constants/product.ts- 产品名称
-
src/constants/oauth.ts- OAuth 配置
-
src/utils/auth.ts- 认证逻辑
- 添加自定义工具
// src/tools/MyTool/MyTool.ts
import { buildTool } from '../Tool.js'
import { z } from 'zod/v4'
export const MyTool = buildTool({
name: 'MyTool',
inputSchema: z.object({
input: z.string().describe('Input parameter'),
}),
async call(input, context) {
// 实现你的逻辑
return { data: 'result' }
},
async description(input) {
return 'My custom tool description'
},
})
- 注册工具
// src/tools.ts
import { MyTool } from './tools/MyTool/MyTool.js'
export function getAllBaseTools(): Tools {
return [
...existingTools,
MyTool,
]
}
- 构建运行
bun run build
bun run start
方案二:从零开始构建
核心架构:
your-claude-code/
├── src/
│ ├── index.ts # 入口
│ ├── cli.ts # CLI 解析
│ ├── agent/
│ │ ├── engine.ts # 核心引擎
│ │ ├── context.ts # 上下文
│ │ └── message.ts # 消息处理
│ ├── tools/
│ │ ├── base.ts # 工具基类
│ │ ├── registry.ts # 工具注册
│ │ └── implementations/
│ ├── mcp/
│ │ ├── client.ts
│ │ └── server.ts
│ ├── permissions/
│ │ ├── manager.ts
│ │ └── rules.ts
│ └── state/
│ ├── store.ts
│ └── types.ts
├── package.json
└── tsconfig.json
核心实现代码:
// 1. 工具系统 (tools/base.ts)
export interface Tool<Input, Output> {
name: string
inputSchema: z.ZodType<Input>
call(input: Input, context: Context): Promise<Output>
checkPermissions?(input: Input): Promise<PermissionResult>
}
// 2. 工具注册 (tools/registry.ts)
export class ToolRegistry {
private tools = new Map<string, Tool>()
register(tool: Tool) {
this.tools.set(tool.name, tool)
}
get(name: string) {
return this.tools.get(name)
}
list() {
return Array.from(this.tools.values())
}
}
// 3. Agent 引擎 (agent/engine.ts)
export class AgentEngine {
constructor(
private client: Anthropic,
private tools: ToolRegistry,
private permissions: PermissionManager,
) {}
async query(messages: Message[]): Promise<Response> {
while (true) {
const response = await this.client.messages.create({
model: 'claude-sonnet-4',
messages,
tools: this.getToolDefinitions(),
})
if (response.stop_reason === 'tool_use') {
const results = await Promise.all(
response.content
.filter(block => block.type === 'tool_use')
.map(block => this.executeTool(block))
)
messages.push(
{ role: 'assistant', content: response.content },
{ role: 'user', content: results }
)
continue
}
return response
}
}
private async executeTool(block: ToolUseBlock) {
const tool = this.tools.get(block.name)
const permission = await this.permissions.check(tool, block.input)
if (permission.denied) {
return { type: 'tool_result', tool_use_id: block.id, content: 'Denied' }
}
const result = await tool.call(block.input, this.context)
return { type: 'tool_result', tool_use_id: block.id, content: result }
}
}
// 4. 权限管理 (permissions/manager.ts)
export class PermissionManager {
private rules: PermissionRule[] = []
addRule(rule: PermissionRule) {
this.rules.push(rule)
}
async check(tool: Tool, input: unknown): Promise<PermissionResult> {
for (const rule of this.rules) {
if (rule.matches(tool.name, input)) {
return { denied: rule.behavior === 'deny', reason: rule.reason }
}
}
return { denied: false, askUser: true }
}
}
// 5. MCP 客户端 (mcp/client.ts)
export class MCPClient {
async connect(config: MCPServerConfig) {
const transport = this.createTransport(config)
const client = new MCPClientSDK({ name: 'my-claude-code', version: '1.0' })
await client.connect(transport)
const { tools } = await client.listTools()
return this.convertToTools(tools)
}
private createTransport(config: MCPServerConfig): Transport {
switch (config.type) {
case 'stdio':
return new StdioClientTransport({
command: config.command,
args: config.args,
})
case 'http':
return new StreamableHTTPClientTransport(new URL(config.url))
default:
throw new Error(`Unknown transport: ${config.type}`)
}
}
}
关键决策点
|
决策点 |
选项 |
建议 |
|
模型 |
Anthropic API / 兼容 API |
Anthropic API 质量最高 |
|
UI |
终端 (Ink) / Web / Desktop |
终端最轻量,Web 最通用 |
|
认证 |
API Key / OAuth / 自定义 |
API Key 最简单,OAuth 最安全 |
|
存储 |
本地文件 / 云端同步 |
本地文件最简单 |
|
MCP |
支持 / 不支持 |
支持可无限扩展 |
总结
Claude Code 是一个设计精良的 AI 编程助手,其核心设计亮点包括:
- 模块化架构: 清晰的职责划分,易于扩展
- 工具系统: buildTool 模式,默认值 + 覆盖
- 权限系统: 多层级检查,安全可控
- Agent 系统: 支持子代理、团队协作
- MCP 协议: 动态加载外部工具
- 性能优化: 并行预取、懒加载、死代码消除
通过深入分析源码,可以学习到:
- 大型 TypeScript 项目的组织方式
- CLI 工具的设计模式
- 终端 UI 的实现技巧
- AI Agent 的架构设计
- 权限系统的实现方案
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)