# claude-code-web
**Repository Path**: uthelei/claude-code-web
## Basic Information
- **Project Name**: claude-code-web
- **Description**: claude-code, 告别cli,带web前端,体验感爆表
- **Primary Language**: TypeScript
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2026-04-16
- **Last Updated**: 2026-04-18
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Claude Code Web
基于 Claude Code 泄露源码修复的**本地可运行版本**,支持接入任意 Anthropic 兼容 API(如 MiniMax,qianwen等)。
> 原始泄露源码无法直接运行。本仓库修复了启动链路中的多个阻塞问题,使完整的 Ink TUI 交互界面可以在本地工作。
> 并添加web gui前端交互方式,类似deepseek网页版交互,用户体验感更好,告别CMD。
## 功能
- 完整的Web交互界面(自研),方便用户使用
- 完整的 Ink TUI 交互界面(与官方 Claude Code 一致)
- `--print` 无头模式(脚本/CI 场景)
- 支持 MCP 服务器、插件、Skills
- 支持自定义 API 端点和模型
- 降级 Recovery CLI 模式
---
## 架构概览
浏览器 ↔ WebSocket,子进程 ↔ 标准输入/输出(stdio)。主程序(bin/claude-haha)只认 stdin 上的 stream-json 行,不认 WS。
1. 整体数据流
浏览器 --WebSocket--> Bun server --stdin 管道--> claude-haha 子进程
<--WebSocket-- <--stdout 管道--
下行(你发消息):WS 收到 JSON → server.ts 拼成一行 NDJSON → proc.stdin.write(line + '\n')。
上行(模型/事件):子进程往 stdout 打 NDJSON → server 按行 JSON.parse → send(ws, { type: 'event', event })。
也就是说:和主程序交互的是子进程的 stdin,不是 WebSocket。
2. server.ts 里具体在哪儿接 WS、在哪儿写给主程序
把浏览器消息写进子进程 stdin(用户输入、权限回复、取消等):
```
switch (msg.type) {
case 'user': {
try {
const line = JSON.stringify({
type: 'user',
session_id: '',
message: { role: 'user', content: msg.content },
parent_tool_use_id: null,
});
if (proc.stdin && typeof proc.stdin !== 'number') proc.stdin.write(line + '\n');
} catch {
// ignore
}
break;
}
case 'control_response': {
try {
const response = msg.allow
? { behavior: 'allow', updatedInput: {} }
: { behavior: 'deny', message: 'Rejected by user', interrupt: true };
const line = JSON.stringify({
type: 'control_response',
response: {
request_id: msg.requestId,
subtype: 'success',
response,
},
});
if (proc.stdin && typeof proc.stdin !== 'number') proc.stdin.write(line + '\n');
break;
}
}
```
子进程 stdout → 再转成 WS 发给浏览器:
```
function flushStdoutLines(ws: any, session: Session) {
for (;;) {
const idx = session.stdoutBuffer.indexOf('\n');
if (idx === -1) break;
const line = session.stdoutBuffer.slice(0, idx).trimEnd();
session.stdoutBuffer = session.stdoutBuffer.slice(idx + 1);
if (!line) continue;
try {
const event = JSON.parse(line);
send(ws, { type: 'event', event });
```
3. 主程序「在哪儿接收」这些消息?
主程序是 --input-format=stream-json 启动的 CLI。入口里在非 TTY 且为 stream-json 时,输入源就是 process.stdin(即上面管道接到的那一端):
```
async function getInputPrompt(prompt: string, inputFormat: 'text' | 'stream-json'): Promise> {
if (!process.stdin.isTTY &&
// Input hijacking breaks MCP.
!process.argv.includes('mcp')) {
if (inputFormat === 'stream-json') {
return process.stdin;
```
后面 StructuredIO 会按行读这个流,解析成 user / control_response 等(与 server.ts 写入的 JSON 格式对应)。没有任何「在主程序里监听 WebSocket」的逻辑;WS 只存在于 web/server.ts 的 Bun serve 里。
4. 总结
层级 作用
Bun web/server.ts WebSocket ↔ 浏览器;把 WS 消息转成 stdin 行 喂给子进程;把子进程 stdout 行 转回 WS。
claude-haha 子进程 只从 process.stdin 读 stream-json,往 stdout 写 stream-json(print.ts / structuredIO 等)。
---
## 快速开始
### 1. 安装依赖
需要 [Bun](https://bun.sh) >= 1.1 和 Node.js >= 18。
```bash
npm install
```
### 2. 配置环境变量
复制示例文件并填入你的 API Key:
```bash
cp .env.example .env
```
编辑 `.env`:
```env
# API 认证(二选一)
ANTHROPIC_API_KEY=sk-xxx # 标准 API Key(x-api-key 头)
ANTHROPIC_AUTH_TOKEN=sk-xxx # Bearer Token(Authorization 头)
# API 端点(可选,默认 Anthropic 官方)
ANTHROPIC_BASE_URL=https://api.minimaxi.com/anthropic
# 模型配置
ANTHROPIC_MODEL=MiniMax-M2.7-highspeed
ANTHROPIC_DEFAULT_SONNET_MODEL=MiniMax-M2.7-highspeed
ANTHROPIC_DEFAULT_HAIKU_MODEL=MiniMax-M2.7-highspeed
ANTHROPIC_DEFAULT_OPUS_MODEL=MiniMax-M2.7-highspeed
# 超时(毫秒)
API_TIMEOUT_MS=3000000
# 禁用遥测和非必要网络请求
DISABLE_TELEMETRY=1
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1
```
### 3. 启动
```bash
# Web模式(完整界面)
windows ./bin/claude-haha-web.cmd
并在浏览器请求 http://127.0.0.1:8787/
# 交互 TUI 模式(完整界面)
windows ./bin/claude-haha-cmd
linux ./bin/claude-haha
# 无头模式(单次问答)
./bin/claude-haha -p "your prompt here"
# 管道输入
echo "explain this code" | ./bin/claude-haha -p
# 查看所有选项
./bin/claude-haha --help
```
---
## 环境变量说明
| 变量 | 必填 | 说明 |
|------|------|------|
| `ANTHROPIC_API_KEY` | 二选一 | API Key,通过 `x-api-key` 头发送 |
| `ANTHROPIC_AUTH_TOKEN` | 二选一 | Auth Token,通过 `Authorization: Bearer` 头发送 |
| `ANTHROPIC_BASE_URL` | 否 | 自定义 API 端点,默认 Anthropic 官方 |
| `ANTHROPIC_MODEL` | 否 | 默认模型 |
| `ANTHROPIC_DEFAULT_SONNET_MODEL` | 否 | Sonnet 级别模型映射 |
| `ANTHROPIC_DEFAULT_HAIKU_MODEL` | 否 | Haiku 级别模型映射 |
| `ANTHROPIC_DEFAULT_OPUS_MODEL` | 否 | Opus 级别模型映射 |
| `API_TIMEOUT_MS` | 否 | API 请求超时,默认 600000 (10min) |
| `DISABLE_TELEMETRY` | 否 | 设为 `1` 禁用遥测 |
| `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` | 否 | 设为 `1` 禁用非必要网络请求 |
---
## 降级模式
如果完整 TUI 出现问题,可以使用简化版 readline 交互模式:
```bash
CLAUDE_CODE_FORCE_RECOVERY_CLI=1 ./bin/claude-haha
```
---
## 相对于原始泄露源码的修复
泄露的源码无法直接运行,主要修复了以下问题:
| 问题 | 根因 | 修复 |
|------|------|------|
| 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` 跳过全部初始化 | 移除默认设置 |
---
## 项目结构
```
claude-code-web/
├── .git/
├── bin/ # 可执行入口脚本
├── docs/ # 文档与配图
├── node_modules/ # 依赖(略)
├── src/ # 主源码
├── stubs/ # 类型/构建桩
├── .env / .env.example
├── package.json
├── bun.lock / bunfig.toml
├── tsconfig.json
├── preload.ts
├── README.md
└── …
```
src/
```
src/
├── main.tsx
├── QueryEngine.ts
├── commands.ts / tools.ts / …
├── assistant/
├── bootstrap/
├── bridge/
├── buddy/
├── cli/
├── commands/ # 大量子命令(子目录很多)
├── components/
├── entrypoints/ # web.ts / cli.tsx / mcp.ts / sdk/ …
├── services/
├── utils/
├── web/ # 本地 Web UI(见下)
└── … # 其它业务目录(体量很大)
```
src/web/(当前 Web 相关,完整展开)
```
src/web/
├── protocol.ts
├── server.ts
├── sessionList.ts
├── transcript.ts
└── ui/
├── app.js
├── index.html
├── styles.css
├── marked.min.js
└── xss.min.js
```
src/entrypoints/
```
entrypoints/
├── web.ts
├── cli.tsx
├── mcp.ts
├── init.ts
├── agentSdkTypes.ts
├── sandboxTypes.ts
└── sdk/ # 各类 generated / 类型定义
```
---
## 技术栈
| 类别 | 技术 |
|------|----------------------------------------------------|
| 运行时 | [Bun](https://bun.sh) |
| 语言 | TypeScript/Html/Js |
| 终端 UI | React + [Ink](https://github.com/vadimdemedes/ink) |
| CLI 解析 | Commander.js |
| API | Anthropic SDK |
| 协议 | MCP, LSP |
---
## Disclaimer
本仓库基于 2026-03-31 从 Anthropic npm registry 泄露的 Claude Code 源码。所有原始源码版权归 [Anthropic](https://www.anthropic.com) 所有。仅供学习和研究用途。