- 添加项目配置文件(tsconfig.json、bunfig.toml、.gitignore、.env.example) - 创建文档架构图(00runtime.png 至 08-state-data-flow.png) - 添加核心工具常量定义(FileEditTool、AgentTool、BashTool 等) - 实现基础命令框架(help、exit、config、model 等) - 添加 Ink TUI 组件库和布局引擎 - 包含内存管理、沙箱、shell 工具等基础工具类 - 设置预加载脚本和版本信息
25 KiB
Claude Code Haha 架构文档
本文档详细分析 Claude Code Haha 项目的架构设计、核心模块以及数据流动方式。
目录
1. 概述
Claude Code Haha 是基于 Claude Code 泄露源码修复的本地可运行版本,支持接入任意 Anthropic 兼容 API(如 MiniMax、OpenRouter 等)。
核心特性
- 完整的 Ink TUI 交互界面(与官方 Claude Code 一致)
--print无头模式(脚本/CI 场景)- 支持 MCP 服务器、插件、Skills
- 支持自定义 API 端点和模型
- 降级 Recovery CLI 模式
技术栈
| 类别 | 技术 |
|---|---|
| 运行时 | Bun |
| 语言 | TypeScript |
| 终端 UI | React 19 + Ink 6 |
| CLI 解析 | Commander.js |
| API | Anthropic SDK |
| 协议 | MCP、LSP |
2. 整体架构
2.1 分层架构
Claude Code Haha 采用五层分层架构,从上到下依次为:
┌─────────────────────────────────────────────────────────────┐
│ 入口层 (Entrypoints) │
│ cli.tsx → main.tsx → REPL.tsx │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 交互层 (Interaction) │
│ screens/ + components/ │
│ TUI 界面、用户输入、消息展示 │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 核心层 (Core) │
│ tools/ + commands/ + skills/ + state/ │
│ 工具系统、命令系统、Skill、状态管理 │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 服务层 (Services) │
│ services/ + bridge/ + context/ │
│ API、MCP、OAuth、分析、桥接 │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 支撑层 (Infrastructure) │
│ utils/ + hooks/ + constants/ │
│ 工具函数、React Hooks、常量定义 │
└─────────────────────────────────────────────────────────────┘
2.2 项目结构
src/
├── entrypoints/ # CLI 入口点
│ ├── cli.tsx # 主入口(参数解析、快速路径分流)
│ ├── mcp.ts # MCP 服务器入口
│ └── init.ts # 初始化入口
├── screens/ # 交互界面
│ └── REPL.tsx # 主 REPL 界面
├── components/ # UI 组件库
│ ├── App.tsx
│ ├── Message.tsx
│ ├── PromptInput/
│ └── ...
├── ink/ # Ink 终端渲染引擎
│ ├── components/ # Ink 基础组件(Box、Text、Button)
│ ├── events/ # 事件系统
│ ├── hooks/ # Ink Hooks
│ ├── layout/ # Yoga 布局引擎
│ ├── termio/ # 终端协议解析(ANSI、CSI、SGR)
│ └── ...
├── tools/ # 工具系统
│ ├── Tool.ts # 工具基类
│ ├── BashTool/ # Bash 执行工具
│ ├── FileEditTool/ # 文件编辑工具
│ ├── GrepTool/ # 搜索工具
│ ├── MCPTool/ # MCP 工具
│ └── ...
├── commands/ # 命令系统
│ ├── commit/
│ ├── review/
│ ├── help/
│ └── ...
├── skills/ # Skill 系统
│ ├── bundled/ # 内置 Skills
│ │ ├── verify/
│ │ ├── batch.ts
│ │ ├── debug.ts
│ │ ├── loop.ts
│ │ └── ...
│ └── bundledSkills.ts
├── state/ # 状态管理
│ ├── AppState.tsx
│ ├── AppStateStore.ts
│ └── store.ts
├── bridge/ # 桥接与远程控制
│ ├── bridgeMain.ts
│ ├── bridgeApi.ts
│ └── ...
├── services/ # 服务层
│ ├── api/ # API 服务
│ ├── mcp/ # MCP 服务
│ ├── oauth/ # OAuth 服务
│ ├── analytics/ # 分析服务
│ └── lsp/ # LSP 服务
├── context/ # React 上下文
├── hooks/ # React Hooks
├── constants/ # 常量定义
└── utils/ # 工具函数
3. 入口与启动
3.1 启动流程
CLI 启动 (bin/claude-haha)
↓
entrypoints/cli.tsx
- 解析命令行参数
- 处理快速路径(--version、--help)
- 特殊模式检查(--daemon-worker、bridge、remote-control)
↓
main.tsx (动态导入)
- 完整初始化
- 配置加载
- 状态初始化
↓
screens/REPL.tsx
- TUI 渲染
- 用户交互循环
3.2 快速路径优化
cli.tsx 实现了多种快速路径,避免不必要的模块加载:
| 路径 | 条件 | 优化效果 |
|---|---|---|
--version |
args.length === 1 |
零模块加载 |
--dump-system-prompt |
Feature Flag | 提前退出 |
--daemon-worker |
Feature Flag | Lean Worker |
bridge/remote-control |
Feature Flag | 桥接专用初始化 |
daemon |
Feature Flag | 守护进程模式 |
ps/logs/attach/kill |
Feature Flag | 会话管理 |
3.3 Feature Flags
项目使用 feature() 函数实现 Dead Code Elimination(代码消除):
// 启用特性
if (feature('FEATURE_NAME')) {
// 仅在启用的构建中包含
}
// 条件导入
const Module = feature('FEATURE')
? require('./feature.js')
: null
支持的 Feature Flags:
VOICE_MODE:语音模式BRIDGE_MODE:桥接模式DAEMON:守护进程BG_SESSIONS:后台会话COORDINATOR_MODE:协调模式WORKFLOW_SCRIPTS:工作流脚本
4. 交互层(TUI)
4.1 REPL 主界面
screens/REPL.tsx 是核心的 TUI 组件,负责:
- 消息展示:渲染用户消息、助手消息、系统消息
- 输入处理:PromptInput 接收用户输入
- 任务管理:后台任务的状态展示与切换
- 权限请求:工具调用的权限确认对话框
- 快捷键绑定:全局键盘事件处理
4.2 核心组件
components/
├── App.tsx # 根组件
├── Message.tsx # 单条消息渲染
├── Messages.tsx # 消息列表
├── MessageRow.tsx # 消息行
├── PromptInput/ # 输入框组件
│ ├── PromptInput.tsx
│ └── PromptInputQueuedCommands.tsx
├── Spinner.tsx # 加载动画
├── SearchBox.tsx # 搜索框
├── TaskListV2.tsx # 任务列表
└── permissions/ # 权限相关组件
4.3 输入模式
REPL 支持多种输入模式:
| 模式 | 说明 | 快捷键 |
|---|---|---|
| 标准模式 | 普通文本输入 | Enter 提交 |
| Vim 模式 | Vim 风格编辑 | Esc 进入命令模式 |
| 命令模式 | 斜杠命令输入 | / 触发 |
| 选择模式 | 消息选择/复制 | v 进入可视化模式 |
5. Ink 渲染引擎
5.1 概述
Ink 是基于 React 的终端 UI 渲染库,Claude Code 对其进行了深度定制。
5.2 架构
ink/
├── components/ # React 组件
│ ├── Box.tsx # 容器组件
│ ├── Text.tsx # 文本组件
│ ├── Button.tsx # 按钮组件
│ └── ...
├── reconciler.ts # React Reconciler
├── renderer.ts # 渲染器
├── screen.ts # 屏幕管理
├── dom.ts # DOM 抽象
└── termio/ # 终端协议
├── ansi.ts # ANSI 转义序列
├── csi.ts # Control Sequence Introducer
├── sgr.ts # Select Graphic Rendition
├── parser.ts # 协议解析器
└── tokenize.ts # Tokenizer
5.3 布局引擎
Ink 使用 Yoga(Facebook 的跨平台布局引擎)进行布局计算:
// ink/layout/yoga.ts
import Yoga from 'yoga-wasm'
// 支持的布局属性
type LayoutProps = {
width?: number | 'auto' | number
height?: number | 'auto' | number
flexDirection?: 'row' | 'column'
justifyContent?: 'flex-start' | 'center' | 'flex-end' | 'space-between'
alignItems?: 'flex-start' | 'center' | 'flex-end' | 'stretch'
padding?: number | [number, number, number, number]
margin?: number | [number, number, number, number]
}
5.4 终端协议
Ink 实现了完整的终端协议支持:
| 协议 | 说明 | 用途 |
|---|---|---|
| ANSI | 基本转义序列 | 颜色、样式 |
| CSI | 控制序列 | 光标移动、清屏 |
| SGR | 选择图形渲染 | 颜色属性 |
| OSC | 操作系统命令 | 窗口标题 |
6. 工具系统
6.1 概述
工具系统是 Claude Code 的核心能力,允许 AI Agent 执行各种操作。
6.2 工具基类
所有工具都继承自 Tool 基类:
// Tool.ts
export type Tool = {
name: string
description: string
allowedTools?: string[]
isEnabled?: () => boolean
prompt?: ToolPrompt
UI?: ToolUIComponent
execute?: (context: ToolUseContext) => Promise<ToolResult>
}
6.3 内置工具
| 工具 | 说明 | 核心文件 |
|---|---|---|
| BashTool | 执行 Shell 命令 | tools/BashTool/ |
| FileReadTool | 读取文件 | tools/FileReadTool/ |
| FileEditTool | 编辑文件 | tools/FileEditTool/ |
| FileWriteTool | 写入文件 | tools/FileWriteTool/ |
| GlobTool | 文件搜索 | tools/GlobTool/ |
| GrepTool | 内容搜索 | tools/GrepTool/ |
| WebFetchTool | HTTP 请求 | tools/WebFetchTool/ |
| WebSearchTool | 网络搜索 | tools/WebSearchTool/ |
| AgentTool | 子 Agent | tools/AgentTool/ |
| TaskStopTool | 停止任务 | tools/TaskStopTool/ |
| MCPTool | MCP 工具 | tools/MCPTool/ |
| LSPTool | LSP 工具 | tools/LSPTool/ |
| SkillTool | Skill 调用 | tools/SkillTool/ |
6.4 工具注册与过滤
// tools.ts
export function getAllBaseTools(): Tools {
return [
AgentTool,
TaskOutputTool,
BashTool,
GlobTool,
GrepTool,
ExitPlanModeV2Tool,
FileReadTool,
FileEditTool,
FileWriteTool,
// ... 更多工具
]
}
export function getTools(permissionContext: ToolPermissionContext): Tools {
const tools = getAllBaseTools()
// 权限过滤
return filterToolsByDenyRules(tools, permissionContext)
}
6.5 工具权限
工具调用需要权限确认:
// 权限类型
type ToolPermission = {
tool: string
args: Record<string, unknown>
reason?: string
autoApprove?: boolean
}
// 权限检查
function checkToolPermission(tool: string): boolean
function requestToolPermission(tool: string): Promise<boolean>
7. 命令系统
7.1 概述
命令系统处理以 / 开头的斜杠命令,提供辅助功能。
7.2 内置命令
| 命令 | 说明 | 目录 |
|---|---|---|
| /commit | Git 提交 | commands/commit/ |
| /review | 代码审查 | commands/review.js |
| /help | 帮助信息 | commands/help/ |
| /diff | 查看变更 | commands/diff/ |
| /tasks | 任务管理 | commands/tasks/ |
| /model | 模型切换 | commands/model/ |
| /config | 配置管理 | commands/config/ |
| /clear | 清除缓存 | commands/clear/ |
| /doctor | 诊断检查 | commands/doctor/ |
| /theme | 主题切换 | commands/theme/ |
| /mcp | MCP 管理 | commands/mcp/ |
| /skills | Skill 管理 | commands/skills/ |
7.3 命令注册
// commands.ts
import addDir from './commands/add-dir/index.js'
import commit from './commands/commit.js'
import help from './commands/help/index.js'
const commands: Command[] = [
addDir,
commit,
help,
// ...
]
export function getCommand(name: string): Command | undefined {
return commands.find(cmd =>
cmd.name === name || cmd.aliases?.includes(name)
)
}
7.4 命令类型
type Command = {
name: string
description: string
aliases?: string[]
type: 'prompt' | 'action' | 'navigation'
execute: (args: string, context: CommandContext) => Promise<CommandResult>
}
8. Skill 系统
8.1 概述
Skill 是封装好的任务模板,可以被 AI Agent 调用。
8.2 内置 Skills
| Skill | 说明 | 用途 |
|---|---|---|
| verify | 验证代码修改 | 自动化验证 |
| batch | 批量处理 | 批量任务执行 |
| loop | 循环执行 | 重复任务 |
| debug | 调试助手 | 问题诊断 |
| simplify | 代码简化 | 重构辅助 |
| stuck | 困境解脱 | 遇到问题时提供帮助 |
| updateConfig | 配置更新 | 配置文件修改 |
| remember | 记忆管理 | 知识库操作 |
| scheduleRemoteAgents | 远程调度 | 分布式任务 |
8.3 Skill 注册
// skills/bundledSkills.ts
export function registerBundledSkill(definition: BundledSkillDefinition): void {
const command: Command = {
type: 'prompt',
name: definition.name,
description: definition.description,
// ...
}
bundledSkills.push(command)
}
8.4 Skill 文件提取
某些 Skill 需要将文件提取到磁盘:
// 首次调用时提取
const files = await extractBundledSkillFiles(skillName, filesDefinition)
// 模型可以 Read/Grep 这些文件
9. 状态管理
9.1 AppStateStore
使用 React 的 useSyncExternalStore 实现全局状态管理:
// state/store.ts
export function createStore(
initialState: AppState,
onChange?: (newState: AppState, oldState: AppState) => void
): AppStateStore {
return {
getState: () => state,
setState: (update) => {
const newState = typeof update === 'function'
? update(state)
: update
state = newState
listeners.forEach(listener => listener())
},
subscribe: (listener) => {
listeners.add(listener)
return () => listeners.delete(listener)
}
}
}
9.2 AppState 结构
// state/AppStateStore.ts
export interface AppState {
// 主循环状态
mainLoopModel: string
task: TaskState | null
// MCP 状态
mcp: {
clients: MCPClient[]
tools: Tool[]
resources: MCPResource[]
}
// 权限状态
toolPermissionContext: ToolPermissionContext
// UI 状态
messages: Message[]
isLoading: boolean
// 配置状态
settings: Settings
config: Config
}
9.3 状态选择器
使用选择器模式避免不必要的重渲染:
// state/selectors.ts
export const selectMainLoopModel = (s: AppState) => s.mainLoopModel
export const selectMessages = (s: AppState) => s.messages
export const selectMcpTools = (s: AppState) => s.mcp.tools
9.4 React Hooks
// state/AppState.tsx
export function useAppState<T>(selector: (s: AppState) => T): T {
const store = useAppStore()
return useSyncExternalStore(
store.subscribe,
() => selector(store.getState()),
() => selector(store.getState())
)
}
export function useSetAppState(): SetAppState {
return useAppStore().setState
}
10. 桥接与远程控制
10.1 Bridge 模式
Bridge 允许远程控制本地 Claude Code 实例。
10.2 核心组件
bridge/
├── bridgeMain.ts # 主入口
├── bridgeApi.ts # API 客户端
├── bridgeUI.ts # 状态显示
├── bridgeMessaging.ts # 消息处理
├── sessionRunner.ts # 会话运行
├── jwtUtils.ts # JWT 认证
├── trustedDevice.ts # 设备信任
└── types.ts # 类型定义
10.3 认证流程
Bridge 启动
↓
检查认证状态 (getClaudeAIOAuthTokens)
↓
检查 Bridge 可用性 (getBridgeDisabledReason)
↓
验证最低版本 (checkBridgeMinVersion)
↓
检查策略限制 (isPolicyAllowed)
↓
建立桥接连接 (bridgeMain)
10.4 会话管理
// bridge/types.ts
export type SessionSpawnOpts = {
sessionId?: string
spawnMode?: 'foreground' | 'background'
spawnCount?: number
sessionTimeoutMs?: number
}
export type SessionHandle = {
sessionId: string
workSecret: string
sdkUrl: string
cleanup: () => Promise<void>
}
11. 服务层
11.1 API 服务
services/api/
├── client.ts # Anthropic API 客户端
├── claude.ts # Claude 特定逻辑
├── bootstrap.ts # 初始化
├── errors.ts # 错误处理
├── filesApi.ts # 文件 API
├── grove.ts # Grove 集成
├── logging.ts # 日志
├── usage.ts # 使用统计
└── withRetry.ts # 重试逻辑
11.2 MCP 服务
Model Context Protocol 实现:
services/mcp/
├── client.ts # MCP 客户端
├── config.ts # 配置
├── auth.ts # 认证
├── oauthPort.ts # OAuth 端口
├── types.ts # 类型定义
├── utils.ts # 工具函数
├── xaa.ts # XAA 集成
├── claudeai.ts # Claude AI 集成
└── utils.ts
11.3 OAuth 服务
services/oauth/
├── client.ts # OAuth 客户端
├── crypto.ts # 加密工具
└── index.ts # 导出
11.4 Analytics 服务
services/analytics/
├── sink.ts # 数据汇
├── datadog.js # DataDog 集成
├── growthbook.js # GrowthBook 特性开关
├── firstPartyEventLogger.js # 第一方事件日志
└── index.js
11.5 LSP 服务
Language Server Protocol 实现:
services/lsp/
├── LSPClient.ts # LSP 客户端
├── config.ts # 配置
└── manager.ts # 管理器
12. 数据流
12.1 请求生命周期
用户输入
↓
PromptInput 接收输入
↓
命令解析 (/command 或普通文本)
↓
创建 UserMessage
↓
添加消息到状态 (setAppState)
↓
调用 query() 函数
↓
构建 API 请求
↓
Anthropic API 调用
↓
流式响应处理
↓
工具调用检测
↓
执行工具 (tool use)
↓
继续响应或完成
↓
更新消息状态
↓
渲染消息
12.2 工具调用流
API 响应包含 tool_use
↓
提取工具信息 (name, input)
↓
检查权限 (toolPermissionContext)
↓
请求用户确认 (如果需要)
↓
执行工具 (tool.execute())
↓
获取工具结果
↓
添加到消息历史
↓
发送 tool_result 回到 API
↓
继续响应流
12.3 消息流
┌─────────┐ UserMessage ┌─────────┐
│ 用户 │ ───────────────→ │ 状态 │
└─────────┘ └─────────┘
↓
┌─────────┐ ┌─────────────┐
│ API │ ←───────────── │ query() │
└─────────┘ 请求 └─────────────┘
↓
┌─────────┐ ┌─────────────┐
│ 流式 │ ─────────────→ │ 状态更新 │
│ 响应 │ AssistantMsg │ + 渲染 │
└─────────┘ └─────────────┘
12.4 状态更新流
Action 触发 (用户输入、API 响应)
↓
setAppState(update)
↓
计算新状态
↓
通知所有订阅者
↓
相关组件重渲染
↓
UI 更新
13. 关键技术
13.1 Dead Code Elimination (DCE)
通过 feature() 函数和条件导入实现构建时代码消除:
// Feature Flag 定义
if (feature('FEATURE')) {
require('./feature.js')
}
// 环境变量检查
if (process.env.USER_TYPE === 'ant') {
// Ant 专用代码
}
13.2 流式响应处理
// services/api/claude.ts
const stream = await client.messages.stream({
model: params.model,
max_tokens: params.maxTokens,
messages: params.messages,
tools: params.tools,
})
for await (const event of stream) {
if (event.type === 'message_delta') {
// 处理 token
} else if (event.type === 'content_block_delta') {
// 处理增量内容
}
}
13.3 权限模型
// utils/permissions/permissionSetup.ts
export function createPermissionContext(
settings: PermissionSettings
): ToolPermissionContext {
return {
isBypassPermissionsModeAvailable: settings.bypassMode,
denyRules: settings.denyRules ?? [],
allowRules: settings.allowRules ?? [],
}
}
// 工具过滤
export function filterToolsByDenyRules(
tools: Tool[],
context: ToolPermissionContext
): Tool[] {
return tools.filter(tool => !getDenyRuleForTool(context, tool))
}
13.4 MCP 协议
// services/mcp/client.ts
export class MCPClient {
private connection: JSONRPCConnection
async initialize(): Promise<void> {
await this.connection.sendRequest('initialize', {
protocolVersion: '2024-11-05',
capabilities: { ... }
})
}
async listTools(): Promise<Tool[]> {
const response = await this.connection.sendRequest(
'tools/list',
{}
)
return response.tools
}
async callTool(name: string, args: object): Promise<ToolResult> {
return this.connection.sendRequest('tools/call', {
name,
arguments: args
})
}
}
13.5 终端渲染优化
// ink/renderer.ts
export class Renderer {
private reconciler: FiberRoot
render(element: ReactElement): void {
updateContainer(element, this.reconciler, null)
}
private framesPerSecond: number
private lastFrame: number
frame(): void {
const now = performance.now()
const delta = now - this.lastFrame
if (delta >= 1000 / this.framesPerSecond) {
this.flushUpdates()
this.lastFrame = now
}
requestAnimationFrame(() => this.frame())
}
}
附录
A. 关键文件索引
| 文件 | 说明 |
|---|---|
| cli.tsx | CLI 入口 |
| main.tsx | 主程序入口 |
| REPL.tsx | REPL 界面 |
| tools.ts | 工具系统 |
| commands.ts | 命令系统 |
| AppState.tsx | 状态管理 |
| bridgeMain.ts | 桥接主入口 |
| client.ts | API 客户端 |
B. 环境变量
| 变量 | 说明 |
|---|---|
ANTHROPIC_API_KEY |
API Key |
ANTHROPIC_BASE_URL |
API 端点 |
ANTHROPIC_MODEL |
默认模型 |
DISABLE_TELEMETRY |
禁用遥测 |
CLAUDE_CODE_SIMPLE |
简单模式 |
USER_TYPE |
用户类型 (ant/external) |
文档版本:1.0.0 最后更新:2026-04-02