1. 先把场景说清楚为什么要折腾 Claude Code 可运行版源码Claude Code 是 Anthropic 官方推出的终端 AI 编程工具能在命令行里直接读写文件、跑命令、调工具很多人把它当成“住在终端里的结对程序员”。但官方 CLI 是打包后的产物想研究它内部怎么组织 REPL、怎么做工具调用循环、怎么做权限校验光看黑盒行为是不够的。于是社区里出现了把 Claude Code 工程化能力复现出来的可运行版源码项目目标是把大部分功能还原成能读、能改、能自己构建的 TypeScript 工程。这个场景真正卡人的地方不在“有没有源码”而在“源码拿到手之后怎么在本地跑起来”。这类项目通常用 Bun 做包管理和构建产物又要能同时被 Bun 和 Node 启动中间还牵扯 feature flag polyfill、monorepo workspace、code splitting 多文件打包。你如果只按普通 Node 项目的习惯去npm install node index.js大概率会撞上一堆莫名其妙的报错。这篇就聚焦一件事把可运行版源码在 Bun 与 Node 双环境下跑通 CLI并且接上统一的 API 通道做连通性验证。适合已经在本地做开发调试、想读源码或二次改造的人。下面给的settings.json、config.toml骨架和启动命令都可以直接复制我会把每一步的预期结果和常见坑一起写清楚。2. 前置准备TaoToken 统一 Key 与 API 通道源码跑起来只是第一步CLI 要真正能对话、能调工具得有一个稳定的模型 API 入口。我这边习惯用 TaoToken 做统一通道原因是它把 Key 管理和 API 地址收敛成一套Bun 和 Node 两种运行时读同一份配置就行不用为每个环境单独改 base URL。你需要先拿到一个 API Key。进入控制台创建即可控制台入口https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewriteAPI Key 管理https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite创建完 Key 之后API 的基础地址是https://taotoken.net/api注意这个地址后面不要带 UTM 参数直接作为 base URL 写进配置。模型名按你实际要用的填比如做代码任务常用的 Claude 系列模型标识。提示Key 只存在本地配置文件或环境变量里不要提交到 git。源码项目里如果有.env.example照着复制成.env再填。如果你后面要长期跑编码任务或者接 Agent 流程可以顺带了解下 Coding Plan额度模型更适合持续调用Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite3. 可复制配置settings.json 与 config.toml 骨架Claude Code 系工具一般会读两类配置一类是 JSON 格式的 settings管权限、hook、模型一类是 TOML 格式的 config管 provider 和认证。下面给的是最小可跑骨架你按自己路径改。先看settings.json放在项目根目录或用户配置目录下{ model: claude-sonnet-4-5, apiProvider: anthropic, permissions: { mode: manual, allow: [ Read, Glob, Grep ], deny: [ Bash(rm -rf:*) ] }, hooks: { preToolUse: [], postToolUse: [] }, env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-your-key-here } }这里几个字段值得说明。permissions.mode用manual最稳工具调用前会问你想省事可以改auto但本地调试阶段不建议一上来就放开。deny里挡掉危险命令是基本操作Bash(rm -rf:*)这种模式匹配能拦住大部分误删。再看config.toml管 provider 通道[provider] name taotoken base_url https://taotoken.net/api api_key_env ANTHROPIC_API_KEY timeout_seconds 120 [provider.models] default claude-sonnet-4-5 fast claude-haiku-4-5 [runtime] prefer bun node_fallback trueapi_key_env指向环境变量名这样 Key 不落盘在 TOML 里更干净。runtime.prefer设成bun但保留node_fallback正好对应我们要验证的双环境。环境变量在 shell 里导出export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_API_KEYsk-your-key-hereWindows PowerShell 用$env:ANTHROPIC_API_KEYsk-...。这一步做完Bun 和 Node 启动时都能读到同一份通道配置。4. 双环境启动Bun 与 Node 分别怎么跑源码项目一般用 Bun workspaces 管理 monorepo构建脚本是build.ts产物输出到dist/入口是dist/cli.js加一堆 chunk 文件。先确认 Bun 版本这个项目对 Bun 版本很敏感版本低了会出一堆奇怪 BUGbun --version # 期望 1.3.11 bun upgrade升级完装依赖bun install开发模式启动看到版本号打印出来就说明入口通了bun run dev构建产物bun run build构建采用 code splitting 多文件打包产物在dist/下入口dist/cli.js加约 450 个 chunk。构建完成后Bun 和 Node 都能启动这个产物这是这个项目比较关键的一点。用 Bun 跑构建产物bun dist/cli.js --version用 Node 跑同一个产物node dist/cli.js --version两个命令都应该打印出版本号。如果 Bun 能跑、Node 报模块解析错误多半是构建后处理没把 Node 兼容层打进去检查build.ts里 Node.js 兼容后处理那段是否执行。注意开发模式bun run dev和构建产物dist/cli.js是两条路径。调试源码逻辑用前者验证发布形态用后者别混着排查问题。5. 连通性验证发一次真实请求确认通道打通版本号能打印只说明 CLI 起来了不代表 API 通道通。做一次最小请求验证。先确认环境变量在当前 shell 生效echo $ANTHROPIC_BASE_URL echo $ANTHROPIC_API_KEY | head -c 8第一个应输出https://taotoken.net/api第二个输出 Key 前 8 位。然后跑一个 print 模式的单次请求bun dist/cli.js -p 用一句话说明当前目录下有哪些文件类型预期结果是模型返回一段描述并且 CLI 内部会触发 Glob 或 Read 工具去读目录。如果你在settings.json里设了manual权限会先弹出工具确认输入允许后继续。Node 环境同样验证一遍node dist/cli.js -p 输出当前工作目录路径两次都返回正常内容说明 Bun/Node 双环境加统一 API 通道全部打通。想更直观地看模型对话效果也可以直接在网页端模型对话里试同一个 Key模型对话https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite如果请求返回 401是 Key 或环境变量问题返回 404多半是 base URL 写成了带路径的形式确认是https://taotoken.net/api而不是别的拼接。6. 本篇常见错排查Bun 版本过低导致构建失败。现象是bun run build中途报feature()未定义或 chunk 生成异常。这个项目入口cli.tsx顶部注入了feature()polyfill让所有 feature flag 返回 false跳过未实现分支。Bun 版本低时 polyfill 注入时机可能不对。先bun upgrade到 1.3.11 以上再试。Node 启动产物报Cannot find module。构建产物是 code splitting 多文件chunk 之间用相对路径引用。如果你把dist/cli.js单独拷出来跑chunk 找不到就报这个。要么整个dist/目录一起移动要么在dist/目录内执行。API 请求超时。先看config.toml里timeout_seconds默认 120 秒对长上下文可能不够调到 300 试试。再确认网络能访问https://taotoken.net/api用 curl 快速探一下curl -s -o /dev/null -w %{http_code} https://taotoken.net/api返回非 5xx 说明通道可达问题在认证或请求体。工具调用被权限拦住不执行。manual模式下每次工具调用都要确认调试时容易以为是卡死。要么在交互里按提示允许要么临时把permissions.mode改成auto但记得改回来。feature flag 相关功能全部不可用。这是预期行为。原版通过构建时注入 flag 控制灰度这个项目里feature()恒返回 false所以 KAIROS、BRIDGE_MODE、VOICE_MODE 这类功能都是关闭的。你看到某些斜杠命令或工具不生效先查它是不是挂在某个 flag 下别当成 bug 提。接入和排障过程中如果遇到认证配置问题可以对照接入文档再核一遍参数接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite7. 继续往下走从跑通到改造跑通之后比较自然的下一步是读src/entrypoints/cli.tsx和src/main.tsx看 Commander 怎么定义子命令、REPL 怎么用 Ink 渲染。工具调用循环在query.ts会话状态在QueryEngine.ts权限系统单独一块代码量不小但结构清晰。想改行为优先从settings.json的 hook 和权限规则入手比直接改源码风险低。如果你打算把这个 CLI 接进长期编码流程或者 Agent 编排单次 Key 调用会很快碰到额度管理问题Coding Plan 那套更适合持续跑Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite最后提醒一句这类复现项目更新很快构建脚本和目录结构可能隔几天就变。遇到和本文不一致的地方以仓库当前build.ts和package.json为准先跑bun install再bun run build大部分问题都能定位到具体那一步。