Skip to content

Commit 9d71b8e

Browse files
committed
2 parents eaeefaf + 079986d commit 9d71b8e

152 files changed

Lines changed: 4162 additions & 981 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/publish-npm.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ name: Publish to npm
33
on:
44
push:
55
tags:
6-
- 'v*'
6+
- "v*"
77
workflow_dispatch:
88
inputs:
99
version:
10-
description: '版本号 (例如: v1.9.0)'
10+
description: "版本号 (例如: v1.9.0)"
1111
required: true
1212
type: string
1313

CLAUDE.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,9 @@ bun run docs:dev
7878

7979
- **Runtime**: Bun (not Node.js). All imports, builds, and execution use Bun APIs.
8080
- **Build**: `build.ts` 执行 `Bun.build()` with `splitting: true`,入口 `src/entrypoints/cli.tsx`,输出 `dist/cli.js` + chunk files。Build 默认启用 19 个 feature(见下方 Feature Flag 段)。构建后自动替换 `import.meta.require` 为 Node.js 兼容版本(产物 bun/node 都可运行)。构建时会将 `vendor/audio-capture/``src/utils/vendor/ripgrep/` 复制到 `dist/vendor/` 下。
81-
- **Build (Vite)**: `vite.config.ts` + `scripts/post-build.ts`,chunk 输出到 `dist/chunks/`。post-build 同样复制 vendor 文件到 `dist/vendor/`
82-
- **Vendor 路径解析**: 构建后 chunk 文件位于 `dist/``dist/chunks/` 下,vendor 二进制在 `dist/vendor/``src/utils/ripgrep.ts``packages/audio-capture-napi/src/index.ts` 均通过 `import.meta.url` 路径中 `lastIndexOf('dist')` 定位 dist 根目录,再拼接 `vendor/` 子路径,确保不同构建产物层级下路径一致。
81+
- **Build (Vite)**: `vite.config.ts` + `scripts/post-build.ts`,代码分割模式,chunk 输出到 `dist/chunks/`。post-build 遍历 `dist/``dist/chunks/` 下所有 `.js` 文件做 `globalThis.Bun` 解构 patch,复制 vendor 文件到 `dist/vendor/`
82+
- **Vendor 路径解析**: 构建后 chunk 文件位于 `dist/``dist/chunks/` 下,vendor 二进制在 `dist/vendor/``src/utils/distRoot.ts` 提供共享的 `distRoot` 函数,通过 `import.meta.url` 路径中 `lastIndexOf('dist')``lastIndexOf('src')` 定位根目录。`ripgrep.ts``computerUse/setup.ts``claudeInChrome/setup.ts``updateCCB.ts` 均使用 `distRoot` 而非内联 `import.meta.url` 路径推算。`packages/audio-capture-napi/src/index.ts` 有独立的 `lastIndexOf('dist')` 逻辑,功能等价。
83+
- **为什么 Vite 必须代码分割**: Bun/JSC 会全量解析单个大 JS 文件的 bytecode 和 JIT,单文件 17MB 产物导致 RSS 暴涨至 ~1GB(Node/V8 懒解析仅需 ~220MB)。代码分割为 600+ 小 chunk 后 Bun 按需加载,`--version` RSS 从 966MB 降至 35MB,完整加载从 1GB+ 降至 ~500MB。
8384
- **Dev mode**: `scripts/dev.ts` 通过 Bun `-d` flag 注入 `MACRO.*` defines,运行 `src/entrypoints/cli.tsx`。默认启用全部 feature。
8485
- **Module system**: ESM (`"type": "module"`), TSX with `react-jsx` transform.
8586
- **Monorepo**: Bun workspaces — 17 个 workspace packages + 若干辅助目录 in `packages/` resolved via `workspace:*`

README.md

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,11 @@
1010

1111
> Which Claude do you like? The open source one is the best.
1212
13-
牢 A (Anthropic) 官方 [Claude Code](https://docs.anthropic.com/en/docs/claude-code) CLI 工具的源码反编译/逆向还原项目。目标是将 Claude Code 大部分功能及工程化能力复现 (问就是老佛爷已经付过钱了)。虽然很难绷, 但是它叫做 CCB(踩踩背)... 而且, 我们实现了企业版或者需要登陆 Claude 账号才能使用的特性, 实现技术普惠
13+
牢 A (Anthropic) 官方 [Claude Code](https://docs.anthropic.com/en/docs/claude-code) 完整复原的工程化项目。虽然很难绷, 但是它叫做 CCB(踩踩背)... 而且, 我们实现了企业版或者需要登陆 Claude 账号才能使用的特性, 并在此基础上扩展了更多好玩的特性。
1414

15-
> 我们将会在五一期间进行整个代码仓库的 lint 规范化, 这个期间提交的 PR 可能会有非常多的冲突, 所以大的功能请尽量在这之前提交哈
16-
17-
[文档在这里, 支持投稿 PR](https://ccb.agent-aura.top/) | [留影文档在这里](./Friends.md) | [Discord 群组](https://discord.gg/uApuzJWGKX)
15+
[Peri Code](https://github.com/KonghaYao/peri):Claude Code 兼容的 Rust Agent,多年大模型经验匠心制作,国内大模型(DeepSeek/GLM)精调,CPU/内存极致优化,在开发版/树莓派上也能跑 CC 一样的体验。
1816

17+
[文档在这里](https://ccb.agent-aura.top/) | [留影文档在这里](./Friends.md) | [Discord 群组,群主在线答疑](https://discord.gg/uApuzJWGKX)
1918

2019
| 特性 | 说明 | 文档 |
2120
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
@@ -158,9 +157,13 @@ bun run build
158157
- **Ollama 深度集成**: 可直接在 CLI 中查看已安装模型,或输入模型名(如 `llama3.1`)一键拉取(Pull)。支持模型列表交互切换和硬件状态自动检测。
159158
- 自动检测本地运行状态和默认端口。
160159

161-
#### /login 字段说明 (云端模式):
162-
163-
> ℹ️ 支持所有 Anthropic API 兼容服务(如 OpenRouter、AWS Bedrock 代理等),只要接口兼容 Messages API 即可。
160+
| 📌 字段 | 📝 说明 | 💡 示例 |
161+
| ------------ | ------------- | ---------------------------- |
162+
| Base URL | API 服务地址 | `https://api.example.com/v1` |
163+
| API Key | 认证密钥 | `sk-xxx` |
164+
| Haiku Model | 快速模型 ID | `claude-haiku-4-5-20251001` |
165+
| Sonnet Model | 均衡模型 ID | `claude-sonnet-4-6` |
166+
| Opus Model | 高性能模型 ID | `claude-opus-4-6` |
164167

165168
### 🩺 系统诊断 /doctor
166169

contributors.svg

Lines changed: 43 additions & 35 deletions
Loading

docs/performance-reporter.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# 内存占用 1G 调研报告
2+
3+
> 诊断 session `a3593062` RSS 达 1.09 GB,定位 Bun 运行时内存膨胀根因
4+
5+
## 数据收集
6+
7+
- **诊断数据**: RSS 1,118 MB,V8 heap 84 MB,原生内存缺口 1,034 MB(92%)
8+
- **构建方式**: `bun run build:vite` → Vite/Rollup 单文件构建,产物 17MB `dist/cli.js`
9+
- **Vite 配置**: `codeSplitting: false``vite.config.ts:97`),所有代码内联为单文件
10+
- **Node.js 对比**: 相同 17MB 产物,Node.js RSS 仅 223 MB(`--version`)/ 340 MB(完整加载)
11+
12+
## 探索与验证
13+
14+
### 已确认
15+
16+
| 问题 | 位置 | 说明 |
17+
|------|------|------|
18+
| **根因: Vite 单文件构建 + Bun 解析大文件内存效率低** | `vite.config.ts:97` | `codeSplitting: false` 产出 17MB 单文件,Bun/JSC 解析时 RSS 暴涨至 966MB |
19+
| Node.js 对同等 17MB 文件仅需 223MB | 实测 | V8 对大文件解析的内存效率远优于 JSC |
20+
| Bun.build 代码分割可解决问题 | 实测 | `bun run build`(代码分割 → 627 chunk)Bun RSS 仅 30MB(`--version`)/ 318MB(完整加载) |
21+
22+
### 已否认
23+
24+
- 不是 feature flags 数量问题 — 全部 35 features 开启时,代码分割构建内存正常
25+
- 不是内存泄漏 — `detachedContexts: 0``activeHandles: 0`
26+
- 不是原生 addon 问题 — vendor 文件仅 2.7MB
27+
- 不是 TypeScript 源码体量问题 — `bun run dev`(直接加载 TS)完整路径仅 345MB
28+
29+
## 结论
30+
31+
**根因是 Vite 构建配置 `codeSplitting: false`,产出 17MB 单文件,Bun/JSC 解析单文件大 JS 时内存效率极差(966MB vs Node 的 223MB)。**
32+
33+
实测对比矩阵:
34+
35+
| 构建方式 | 产物结构 | Bun RSS | Node RSS | Bun/Node |
36+
|----------|----------|---------|----------|----------|
37+
| `build:vite` | 17MB 单文件 | **966 MB** | 223 MB | 4.3x |
38+
| `build:vite` pipe mode | 同上 | **1,088 MB** | 340 MB | 3.2x |
39+
| `build` (Bun) | 627 chunk | 30 MB | 42 MB | 0.7x |
40+
| `build` (Bun) pipe mode | 同上 | 318 MB | 253 MB | 1.3x |
41+
| `bun run dev` TS 源码 | 动态加载 | 42 MB |||
42+
| `bun run dev` pipe mode | 动态加载 | 345 MB |||
43+
44+
核心差异:
45+
- **Node/V8** 解析 17MB 文件只需 223MB — V8 的懒解析(lazy parsing)只编译入口需要的部分
46+
- **Bun/JSC** 解析 17MB 文件需要 966MB — JSC 对单文件做全量编译,bytecode + JIT 占用大量原生内存
47+
- 代码分割后(627 个小 chunk),Bun 按需加载,内存回到正常水平
48+
49+
## 建议
50+
51+
1. **开启 Vite 代码分割** — 在 `vite.config.ts` 中启用 `codeSplitting: true` 或使用 Rollup 的 `manualChunks` 配置。这是最直接的修复
52+
2. **或切换到 Bun.build**`bun run build` 已默认启用代码分割(`splitting: true`),Bun RSS 仅 30-318MB
53+
3. **如果必须单文件** — 考虑用 Node.js 运行 Vite 产物(`node dist/cli-node.js`),代价是失去 Bun 特有 API
54+
4. **验证 `codeSplitting: false` 的存在理由** — 注释说"all dynamic imports inlined",可能是为了简化部署。评估是否真的需要单文件

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "claude-code-best",
3-
"version": "2.4.3",
3+
"version": "2.6.6",
44
"description": "Reverse-engineered Anthropic Claude Code CLI — interactive AI coding assistant in the terminal",
55
"type": "module",
66
"author": "claude-code-best <claude-code-best@proton.me>",

packages/@ant/claude-for-chrome-mcp/src/bridgeClient.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { SocketConnectionError } from './mcpSocketClient.js'
99
import {
1010
localPlatformLabel,
1111
type BridgePermissionRequest,
12+
toLoggerDetail,
1213
type ChromeExtensionInfo,
1314
type ClaudeForChromeContext,
1415
type PermissionMode,
@@ -578,7 +579,7 @@ export class BridgeClient implements SocketClient {
578579
const durationMs = Date.now() - this.connectionStartTime
579580
logger.error(
580581
`[${serverName}] Failed to create WebSocket after ${durationMs}ms:`,
581-
error,
582+
toLoggerDetail(error),
582583
)
583584
trackEvent?.('chrome_bridge_connection_failed', {
584585
duration_ms: durationMs,
@@ -618,7 +619,10 @@ export class BridgeClient implements SocketClient {
618619
)
619620
this.handleMessage(message)
620621
} catch (error) {
621-
logger.error(`[${serverName}] Failed to parse bridge message:`, error)
622+
logger.error(
623+
`[${serverName}] Failed to parse bridge message:`,
624+
toLoggerDetail(error),
625+
)
622626
}
623627
})
624628

@@ -862,7 +866,10 @@ export class BridgeClient implements SocketClient {
862866
const allowed = await pending.onPermissionRequest(request)
863867
this.sendPermissionResponse(requestId, allowed)
864868
} catch (error) {
865-
logger.error(`[${serverName}] Error handling permission request:`, error)
869+
logger.error(
870+
`[${serverName}] Error handling permission request:`,
871+
toLoggerDetail(error),
872+
)
866873
this.sendPermissionResponse(requestId, false)
867874
}
868875
}

packages/@ant/claude-for-chrome-mcp/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@ export { localPlatformLabel } from './types.js'
88
export type {
99
BridgeConfig,
1010
ChromeExtensionInfo,
11+
ChromeBridgeTrackEventMetadata,
1112
ClaudeForChromeContext,
1213
Logger,
14+
LoggerDetail,
1315
PermissionMode,
1416
SocketClient,
1517
} from './types.js'
18+
export { toLoggerDetail } from './types.js'

packages/@ant/claude-for-chrome-mcp/src/mcpSocketClient.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type {
99
PermissionMode,
1010
PermissionOverrides,
1111
} from './types.js'
12+
import { toLoggerDetail } from './types.js'
1213

1314
export class SocketConnectionError extends Error {
1415
constructor(message: string) {
@@ -87,7 +88,10 @@ class McpSocketClient {
8788
await this.validateSocketSecurity(socketPath)
8889
} catch (error) {
8990
this.connecting = false
90-
logger.info(`[${serverName}] Security validation failed:`, error)
91+
logger.info(
92+
`[${serverName}] Security validation failed:`,
93+
toLoggerDetail(error),
94+
)
9195
// Don't retry on security failures (wrong perms/owner) - those won't
9296
// self-resolve. Only the error handler retries on transient errors.
9397
return
@@ -145,14 +149,20 @@ class McpSocketClient {
145149
logger.info(`[${serverName}] Received unknown message: ${message}`)
146150
}
147151
} catch (error) {
148-
logger.info(`[${serverName}] Failed to parse message:`, error)
152+
logger.info(
153+
`[${serverName}] Failed to parse message:`,
154+
toLoggerDetail(error),
155+
)
149156
}
150157
}
151158
})
152159

153160
this.socket.on('error', (error: Error & { code?: string }) => {
154161
clearTimeout(connectTimeout)
155-
logger.info(`[${serverName}] Socket error (code: ${error.code}):`, error)
162+
logger.info(
163+
`[${serverName}] Socket error (code: ${error.code}):`,
164+
toLoggerDetail(error),
165+
)
156166
this.connected = false
157167
this.connecting = false
158168

packages/@ant/claude-for-chrome-mcp/src/toolCalls.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type {
77
PermissionOverrides,
88
SocketClient,
99
} from './types.js'
10+
import { toLoggerDetail } from './types.js'
1011

1112
export const handleToolCall = async (
1213
context: ClaudeForChromeContext,
@@ -44,7 +45,10 @@ export const handleToolCall = async (
4445

4546
return handleToolCallDisconnected(context)
4647
} catch (error) {
47-
context.logger.info(`[${context.serverName}] Error calling tool:`, error)
48+
context.logger.info(
49+
`[${context.serverName}] Error calling tool:`,
50+
toLoggerDetail(error),
51+
)
4852

4953
if (error instanceof SocketConnectionError) {
5054
return handleToolCallDisconnected(context)
@@ -165,8 +169,7 @@ async function handleToolCallConnected(
165169

166170
// Fallback for unexpected result format
167171
context.logger.warn(
168-
`[${context.serverName}] Unexpected result format from socket bridge`,
169-
response,
172+
`[${context.serverName}] Unexpected result format from socket bridge: ${JSON.stringify(response)}`,
170173
)
171174

172175
return {

0 commit comments

Comments
 (0)