开发者指南
想改 Claude Code 的源码?先把这篇看完。不然你大概率会被 4684 行的 main.tsx 劝退。
环境准备
必需工具
- Bun(最新版)— 运行时 + 构建工具 + 包管理器,三合一
- Node.js 18+ — 部分原生模块还是需要 Node 编译
- Git 2.x — 不解释
bash
# 确认版本
bun --version # >= 1.x
node --version # >= 18
git --version # >= 2.x项目结构
claude-code/
├── src/
│ ├── entrypoints/ # CLI、MCP、SDK 入口
│ ├── main.tsx # 主启动文件(4684 行,是的)
│ ├── tools/ # 40+ 工具实现
│ ├── commands/ # 70+ 斜杠命令
│ ├── services/ # 后台服务
│ ├── components/ # 200+ React/Ink 组件
│ ├── hooks/ # 100+ 自定义 Hook
│ └── utils/ # 300+ 工具函数
├── vendor/ # 原生模块源码
└── docs/ # 文档代码模式
1. React Compiler 自动 memo
项目用了 React Compiler,不需要手写 useMemo 或 useCallback。编译器会自动分析依赖并插入缓存。
如果你习惯性地加 useMemo,在这个项目里反而是多余的。
2. Feature Gate 模式
条件功能通过编译时门控实现:
typescript
if (feature('SOME_FEATURE')) {
// 未启用时整个分支在构建产物中不存在
}3. 延迟 Import
大型模块一律动态加载:
typescript
// 不要这样
import { heavyModule } from './heavy'
// 要这样
const { heavyModule } = await import('./heavy')这是启动速度快的关键。
4. useSyncExternalStore 模式
绕过 React Context 的延迟问题,实现高性能状态订阅。当状态更新频繁时,Context 的 re-render 成本太高,用 useSyncExternalStore 直接订阅外部 store 更高效。
5. Ref 缓存模式
避免回调重建导致的不必要重渲染:
typescript
const callbackRef = useRef(callback)
callbackRef.current = callback
// 传给子组件的是 ref,不会触发重渲染6. 工具调用模式
工具的 call() 方法返回 Promise<ToolResult<Output>>,不是 AsyncGenerator。
关键类型
Tool 接口
大约 55 个成员。核心的几个:
typescript
interface Tool {
name: string
description: string
inputSchema: ZodSchema
call(input, context): Promise<ToolResult>
isEnabled?(context): boolean
requiresPermission?(input): boolean
// ...还有 50 个
}AppState
80+ 字段的全局状态。从模型选择到权限配置,从任务列表到历史记录,全在这一个对象里。
ToolUseContext
工具执行时的运行时上下文,提供文件系统访问、状态读写、权限检查等能力。
调试技巧
环境变量
| 变量 | 作用 |
|---|---|
CLAUDE_CODE_DEBUG=1 | 启用调试日志 |
CLAUDE_CODE_DEBUG_REPAINTS=1 | Ink 重绘调试 |
CLAUDE_CODE_SHELL | 覆盖默认 Shell |
CLAUDE_CODE_COORDINATOR_MODE=1 | 协调器模式 |
日志
会话日志在 ~/.claude/logs/,实时查看:
bash
tail -f ~/.claude/logs/*.log添加新工具
- 在
src/tools/下创建目录 - 实现
index.ts(工具逻辑)、prompt.ts(描述)、UI.tsx(渲染) - 在
tools.ts中注册
添加新命令
- 在
src/commands/下创建目录 - 实现
LocalCommand接口 - 在
commands.ts中导入
两者的区别记住一句话:工具给 AI 调,命令给人用。