Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

附录 C:修复记录

本附录记录 Claude Code 泄露源码修复过程中的问题分析和解决方案。

Warning

本附录内容基于 Claude Code Haha 项目(泄露源码修复版本)的 README.md 文档整理。

C.1 泄露源码修复记录

C.1.1 修复总览

泄露的 Claude Code 源码无法直接运行,主要修复了以下问题:

问题根因修复
TUI 不启动入口脚本把无参数启动路由到了 recovery CLI恢复走 cli.tsx 完整入口
启动卡死verify skill 导入缺失的 .md 文件,Bun text loader 无限挂起创建 stub .md 文件
--print 卡死filePersistence/types.ts 缺失创建类型桩文件
--print 卡死ultraplan/prompt.txt 缺失创建资源桩文件
Enter 键无响应modifiers-napi native 包缺失,isModifierPressed() 抛异常导致 handleEnter 中断,onSubmit 永远不执行加 try-catch 容错
setup 被跳过preload.ts 自动设置 LOCAL_RECOVERY=1 跳过全部初始化移除默认设置

C.2 修复过程详解

C.2.1 TUI 不启动问题

问题现象

执行 ./bin/claude-haha 后,TUI 界面不出现,直接进入 recovery CLI 模式。

根因分析

入口脚本中的路由逻辑将无参数启动错误地路由到了 localRecoveryCli.ts,而不是完整的 cli.tsx 入口。

修复方案

修改入口脚本,恢复正确的启动路由:

// 修复:无参数启动应走 cli.tsx 完整入口
// 原代码:
// if (args.length === 0) { runRecoveryCLI() }

// 修复后:
if (args.length === 0) {
  await import('./src/entrypoints/cli.tsx')
}

C.2.2 启动卡死问题

问题现象

启动过程中程序卡住不动,无任何响应。

根因分析

verify skill 导入了缺失的 .md 文件,由于 Bun 的 text loader 无法找到文件,导致无限等待挂起。

// verify skill 导入了不存在的 .md 文件
import verificationPrompt from './prompt.md'

修复方案

创建 stub .md 文件,确保 Bun text loader 能正常加载:

# Verification Stub

This is a placeholder file for the verification skill.

同时修复其他缺失的文件:

  • filePersistence/types.ts - 创建类型桩文件
  • ultraplan/prompt.txt - 创建资源桩文件

C.2.3 Enter 键无响应问题

问题现象

在交互界面中按下 Enter 键没有任何响应,消息无法提交。

根因分析

这是一个最隐蔽的 bug:

  1. modifiers-napi 是一个 native 包,用于检测修饰键状态
  2. 泄露源码缺少这个 native 包
  3. isModifierPressed() 函数调用时抛出异常
  4. 异常中断了 handleEnter 函数的执行
  5. onSubmit 回调永远不执行,导致 Enter 键无响应
// 问题代码路径
function handleEnter() {
  if (isModifierPressed('shift')) {  // 这里抛异常
    // multiline handling
  }
  onSubmit(input)  // 永远不执行
}

修复方案

isModifierPressed() 调用处添加 try-catch 容错:

// 修复:添加 try-catch 容错
function handleEnter() {
  let isShiftPressed = false
  try {
    isShiftPressed = isModifierPressed('shift')
  } catch (e) {
    // native 包缺失,默认 false
    isShiftPressed = false
  }
  
  if (isShiftPressed) {
    // multiline handling
  }
  onSubmit(input)  // 正常执行
}

Tip

这个问题最难发现,因为:

  1. 异常发生在 native 模块调用中
  2. 没有明显错误提示
  3. UI 看起来正常,只是 Enter 键不工作

C.2.4 setup 被跳过问题

问题现象

启动初始化阶段(setup)被完全跳过,直接进入主界面。

根因分析

preload.ts 文件中错误地设置了 LOCAL_RECOVERY=1 环境变量,导致初始化流程被跳过。

// preload.ts 中的问题代码
process.env.LOCAL_RECOVERY = '1'  // 强制跳过 setup

修复方案

移除 preload.ts 中的默认设置:

// 修复:移除强制跳过设置
// process.env.LOCAL_RECOVERY = '1'  // 删除这行

// 只在需要时设置
if (process.env.CLAUDE_CODE_FORCE_RECOVERY_CLI === '1') {
  process.env.LOCAL_RECOVERY = '1'
}

C.3 修复技术要点

C.3.1 文件桩文件创建

对于缺失的资源文件,需要创建最小化的桩文件:

// 类型桩文件示例 (filePersistence/types.ts)
export type FilePersistenceState = unknown
export type PersistedFileEntry = unknown
export function createFilePersistence(): FilePersistenceState {
  return null
}

C.3.2 Native 包容错处理

对于 native 包缺失的情况,采用以下容错策略:

  1. Try-Catch 包装: 在调用处捕获异常
  2. 默认值兜底: 异常时使用安全的默认值
  3. 功能降级: 不影响核心功能运行

C.3.3 启动路由修复

入口脚本路由逻辑的修复原则:

  1. 无参数启动 -> TUI 完整入口
  2. -p/--print 参数 -> 无头模式
  3. CLAUDE_CODE_FORCE_RECOVERY_CLI=1 -> Recovery CLI

C.4 降级模式说明

如果完整 TUI 出现问题,可以使用简化版 readline 交互模式:

CLAUDE_CODE_FORCE_RECOVERY_CLI=1 ./bin/claude-haha

降级模式特点:

  • 简化的命令行交互
  • 基本的问答功能
  • 不依赖 Ink 终端渲染引擎
  • 适合问题排查和调试

Note

Windows 用户推荐使用以下方式启动 TUI:

bun --env-file=.env ./src/entrypoints/cli.tsx

</div>
</div>
这种方式绕过 shell 脚本,直接调用 Bun 运行入口文件。

C.5 Windows 平台注意事项

Windows 平台运行 Claude Code Haha 需要注意:

  1. 依赖 Git Bash: 启动脚本 bin/claude-haha 是 bash 脚本,需要 Git for Windows
  2. 推荐方式: 直接使用 PowerShell/cmd 调用 Bun
  3. 不可用功能: 语音输入、Computer Use、Sandbox 隔离等
# Windows 启动方式
bun --env-file=.env ./src/entrypoints/cli.tsx

# Windows 无头模式
bun --env-file=.env ./src/entrypoints/cli.tsx -p "your prompt"

# Windows 降级模式
bun --env-file=.env ./src/localRecoveryCli.ts