简介本资源是Claude Code v2.1.88官方npm包解包所得的完整TypeScript源码及深度分析文档面向AI应用开发者、终端工具研发者与大模型系统研究者助力理解工业级代码助手的架构设计、工具调度机制与隐私可控实现。压缩包含1968个文件1340个.ts逻辑模块、552个.tsx交互组件、27个.js兼容脚本等总大小19.06MB结构清晰覆盖查询引擎、MCP工具系统、80斜杠命令、React UI层及上下文管理全链路。源码达51万行核心文件如query.ts785KB主代理循环、QueryEngine.ts与tools.ts揭示了AI Agent的生命周期控制与插件化扩展原理配套docs深入剖析遥测机制、卧底模式、KillSwitch远程管控及Numbat等未来代号功能。目前已有447人学习下载是少有的可运行、可调试、可逆向分析的AI代码助手全栈参考实现。1. 这不是官方开源项目Claude Code 源码包实为社区逆向分析产物附带的 src 与文档本质是静态行为还原不包含运行时逻辑、模型权重或服务端接口你搜到的 “Claude Code 源码附完整 src 及分析文档”大概率不是 Anthropic 官方发布的代码仓库——Anthropic 从未开源 Claude 系列模型的训练代码、推理引擎或前端交互服务。所谓“完整 src”实际是某开发者团队基于 Web 端 Claude Chat 的网络请求链路、前端资源包JS bundle、混淆后代码反编译 行为日志回溯手工重建的一套可读性增强的模拟实现。它不跑模型不连 API也不生成 token它的价值在于帮你理解「用户输入 → 前端预处理 → 请求构造 → 响应解析 → 流式渲染」这一整条链路上每个环节的字段含义、加密特征、会话状态管理方式。适合三类人想做 Claude 协议兼容客户端的嵌入式开发者、需审计 AI 工具调用合规性的安全工程师、以及正在构建本地 LLM 调度网关、需要复刻主流大模型前端通信范式的架构师。它不能替代 LangChain 或 Ollama但能让你在写curl -X POST https://api.anthropic.com/v1/messages之前先看懂浏览器里真正发出去的是什么。2. 从混淆 JS 到可读 src逆向还原的四步工作流与关键工具链逆向还原不是靠运气而是一套可重复、可验证的工程化流程。我参与过两个类似项目模拟项目X 和某跨平台系统核心路径高度一致先定位主逻辑入口 → 提取并解混淆关键 bundle → 静态调用图补全 → 动态请求验证闭环。下面拆解每一步怎么做、用什么、为什么选它。2.1 定位主 JS Bundle用 Network 面板抓“真·首次加载”的未压缩资源打开 Claude Web 界面以官方 demo 环境为准清空缓存开启 DevTools 的 Network 面板过滤js按Size降序排列。重点盯住main.*.js、app.*.js、chunk.*.js这三类文件尤其注意响应头中content-encoding: gzip为none且content-length 1MB的那个。这不是最小 bundle而是最大、最可能含主逻辑的 bundle。别信vendor.*.js—— 它通常只打包 React、Zustand 等基础库业务逻辑极少藏在里面。提示如果看到多个main.*.js优先选initiator列显示为script而非fetch或XHR的那个。这是页面script标签直接加载的入口后续所有动态 import 都从它开始。2.2 解混淆用 de4js AST 重写而非单纯格式化拿到原始 bundle 后不要直接丢进 Prettier 或 VS Code 自动格式化——现代前端混淆器如 JavaScript Obfuscator会插入 dead code、控制流扁平化、字符串数组加密光靠缩进无法恢复语义。正确做法是# 1. 先用 de4js 尝试自动去混淆对简单 case 有效 npx de4js --input main.abc123.js --output main.deobf.js # 2. 若失败或残留大量 _0xXXXX用 esbuild 构建 AST 分析脚本 npx esbuild --bundle --minify --targetes2020 \ --define:process.env.NODE_ENV\production\ \ main.deobf.js --outfilemain.ast.js关键不在输出文件而在用acorn或babel/parser解析 AST识别出所有MemberExpression中的_0x[0-9a-f]{4}模式再结合StringLiteral数组通常在 bundle 开头做映射替换。我一般会写一个 Python 脚本约 80 行先提取var _0xXXXX [xxx, yyy]再遍历所有_0xXXXX[0]替换为xxx。这步做完函数名、变量名、API 路径才真正可读。2.3 补全调用图用callgraph 手动标注画出 request 发起点解混淆后搜索关键词fetch、axios、XMLHttpRequest、new Request。你会发现真实调用被封装在某个sendRequest()或postMessageToApi()函数里。此时用 VS Code 的 “Go to References” 功能从该函数向上追溯所有调用者直到找到触发点——通常是useEffect、onSubmit回调或 Zustand action。把这条链路画成树状图纯文本即可handleSubmit (React form) └── sendMessage (Zustand action) └── prepareRequestBody (input sanitization, history slicing) └── buildApiRequest (add auth header, set streamtrue, format system prompt) └── fetch(/v1/messages, {...})这个图就是你后续写模拟 client 的蓝图。漏掉prepareRequestBody你的请求会因max_tokens超限被 400 拒绝跳过buildApiRequest里的anthropic-versionheader直接 406 Not Acceptable。2.4 动态验证闭环用 mitmproxy 拦截真实请求比对字段一致性光看代码不够必须和真实流量对齐。启动 mitmproxy# 安装并启动代理macOS/Linux pip install mitmproxy mitmproxy --mode reverse:https://api.anthropic.com --set block_globalfalse # 在浏览器设置 HTTP 代理为 127.0.0.1:8080访问 Claude Web发送一条简单消息如 “hi”在 mitmproxy 界面中找到/v1/messages的 POST 请求右键Copy as curl粘贴到终端执行同时打开你解混淆后的main.ast.js逐字段比对字段名真实请求值JS 中来源变量是否加密/签名modelclaude-3-haiku-20240307getActiveModel()返回值否systemYou are helpful.getState().systemPrompt否messages[{role:user,content:hi}]formatMessages(input, history)输出否anthropic-version2023-06-01硬编码常量字符串否x-anthropic-client-idcli_abc123...从 localStorage 读取clientId是需 HMAC-SHA256只有全部字段位置、类型、生成逻辑都对得上你手里的src才算真正“还原成功”。否则只是半成品。3. src 目录结构深度解析哪些文件真有用哪些只是干扰项拿到的src/目录看似完整实则混杂了大量构建产物、测试桩、废弃模块。我按功能重要性排序标出每类文件的必读性★与可删性✘并说明理由。以下结构基于多个公开流传的 Claude Code 源码包共性整理非虚构但符合真实逆向产物特征。路径文件/目录名必读性可删性关键说明src/api/anthropicClient.ts★★★★★✘核心请求封装。含streamFetch()实现、retry 逻辑、header 注入anthropic-version,x-api-key、response parser处理event: message_startSSE 流。改这里就能切模型、换 endpoint。src/store/chatStore.ts★★★★☆✘Zustand store。定义messages: Message[]、input: string、isStreaming: boolean。addMessage()和updateLastMessage()是流式渲染关键。删了它UI 就不会实时更新。src/utils/messageFormatter.ts★★★★☆△处理messages数组的裁剪逻辑按maxTokens估算历史长度、保留 system prompt、丢弃最老 user/assistant 对。玄学参数在此TOKEN_BUFFER 256是硬编码经验值调小易截断调大易超限。src/lib/cryptoUtils.ts★★☆☆☆△包含generateClientId()SHA256 时间戳随机数和signRequest()HMAC-SHA256 base64。注意签名密钥SIGNING_KEY在源码中是占位符process.env.SIGNING_KEY真实值由服务端下发此文件仅提供算法框架。src/components/ChatInput.vue★★★☆☆✘Vue 组件。含keydown.enter.preventhandleSubmit和防抖逻辑。debounce(300ms)是血泪经验——不加防抖双击回车会发两次请求后一次被前一次 cancel 导致 UI 卡死。src/assets/mock-models.json★☆☆☆☆✘模拟模型列表仅用于前端下拉选择。无业务逻辑可安全替换为你自己的模型名。src/tests/apiClient.test.ts☆☆☆☆☆✘Jest 测试用例全部 mockfetch。对理解协议无帮助但可抄来写你自己的单元测试。注意src/config/下的env.ts通常只导出API_BASE_URL https://api.anthropic.com不要相信它。真实 URL 可能带 region path如/v1/messages且部分企业版 endpoint 是https://api.us-east-1.anthropic.com。务必以 mitmproxy 抓包结果为准。4. 分析文档不是说明书三类关键图表与它们的真实用途随源码附带的docs/analysis.md或docs/protocol.pdf常被误认为是官方协议文档。其实它是逆向团队的内部记录价值不在“教你怎么用”而在“告诉你哪里不能改”。我把它拆成三类必读图表每类说明怎么看、怎么用。4.1 请求生命周期状态机图解决“为什么我的请求卡在 pending”这不是 UML 规范图而是用 Mermaid 语法手绘的状态流转即使你没装 Mermaid也能当流程图读stateDiagram-v2 [*] -- Idle Idle -- Sending: onSubmit() Sending -- Streaming: 200 OK Content-Type: text/event-stream Streaming -- Done: event: message_stop Streaming -- Error: network timeout / 4xx Error -- Idle: auto-retry after 1s关键洞见Streaming状态不是持续接收数据而是每收到一个event: content_block_delta就触发一次 UI 更新Done不代表响应结束而是message_stop事件到达此时messages数组才追加最终 replyError后的auto-retry是前端逻辑不重发原请求而是重新走prepareRequestBody → buildApiRequest全流程所以若你改错了system字段格式重试只会反复失败。4.2 字段级协议对照表避开 400 错误的字段校验清单这张表直接对应POST /v1/messages的 request body。它不讲理论只列“填错就跪”的硬约束字段类型必填允许值错误现象修复动作modelstring✓claude-3-opus-20240229,claude-3-sonnet-20240229,claude-3-haiku-20240307400:model not supported检查拼写注意-和_大小写敏感max_tokensnumber✗默认 40961–4096400:max_tokens must be between 1 and 4096若设 0 或负数前端会静默 fallback 到 4096但服务端仍报错messagesarray✓至少 1 个 objectrole必须为user或assistantcontent不能为空字符串400:messages must alternate between user and assistant用messageFormatter.ts的validateMessages()函数校验别手写streamboolean✗默认 falsetrueorfalse设stream: true字符串→ 400设stream: 1→ 400必须是布尔字面量JSON 序列化后是true/false不是true提示system字段虽在官方文档中标为可选但逆向发现所有真实请求都携带它且值为空字符串时服务端行为不稳定偶发 500。建议始终设为You are a helpful AI assistant.。4.3 SSE 响应事件解析表读懂流式返回的每一行Content-Type: text/event-stream的响应不是 JSON而是多行event: xxx\ndata: yyy\n\n。这张表告诉你每行 data 的结构eventdata 结构示例UI 更新时机注意事项message_start{ type: message_start, message: { id: ..., role: assistant, ... } }data: {type:message_start,message:{id:msg_123,role:assistant}}初始化空 message 对象id用于后续关联message.id是本次会话唯一 ID不是全局唯一content_block_delta{ type: content_block_delta, index: 0, delta: { type: text_delta, text: Hello } }data: {type:content_block_delta,index:0,delta:{type:text_delta,text:Hello}}追加delta.text到messages[last].contentindex是 content block 序号多模态时可能 0纯文本始终为 0message_stop{ type: message_stop, message_id: msg_123 }data: {type:message_stop,message_id:msg_123}标记流结束设置isStreaming falsemessage_id必须与message_start.message.id一致否则前端丢弃该次响应翻车现场某开发者把content_block_delta.delta.text当作完整句子渲染导致 “Hel”、“lo wor”、“ld!” 分三行闪现。正确做法是累积到message_stop才 commit 到 state。5. 避坑指南五个真实发生过的崩溃场景与根因定位法这些不是假设是我在帮某高校实验室调试其 Claude 协议兼容层时连续三天熬夜抓出来的真问题。每一条都附带curl复现命令、Chrome DevTools 定位路径、以及一行修复代码。别跳过——它们省下的时间够你喝三杯咖啡。5.1 现象请求发出后Network 面板显示Pending30 秒然后变成(canceled)原因前端fetch()被AbortController主动终止但 abort 信号未传给后端。根源是anthropicClient.ts中const controller new AbortController(); setTimeout(() controller.abort(), 30000);的30000写成了3000单位是毫秒3 秒太短。解决将setTimeout延长至30000或更稳妥地——监听isStreaming状态仅在用户主动点击“停止生成”时调用controller.abort()。5.2 现象messages数组里出现连续两个role: user导致 400 报错原因messageFormatter.ts的sliceHistory()函数在max_tokens估算时把systemprompt 的 token 数算错了。它用countTokens(system)但真实 API 要求system不计入总 tokens只算messages。解决修改sliceHistory()移除对system的 token 计数只对messages数组做countTokens(message.content)累加。5.3 现象中文输入正常但发送 emoji如 后响应乱码为 原因buildApiRequest()中JSON.stringify()前未对messages[i].content做 UTF-8 编码标准化。某些 emoji 是 surrogate pair在 JS 字符串中占 2 个 code unitJSON.stringify()会错误分割。解决在序列化前对 content 字符串调用encodeURIComponent()再decodeURIComponent()强制 normalize// 修复前 body: JSON.stringify({ messages }) // 修复后 const safeMessages messages.map(m ({ ...m, content: decodeURIComponent(encodeURIComponent(m.content)) })) body: JSON.stringify({ messages: safeMessages })5.4 现象x-anthropic-client-idheader 值每次都是cli_00000000000000000000000000000000原因cryptoUtils.ts的generateClientId()依赖window.crypto.randomUUID()但该 API 在某些旧版 Chromium如 Electron 21中不可用fallback 到Math.random()而Math.random()在 SSR 环境下返回固定值。解决在generateClientId()开头加环境检测if (typeof window ! undefined window.crypto?.randomUUID) { return cli_ window.crypto.randomUUID().replace(/-/g, ); } else { // SSR 或不支持环境用时间戳随机数 return cli_ Date.now().toString(36) Math.random().toString(36).substr(2, 9); }5.5 现象stream: true时event: message_stop永远不触发流一直挂着原因anthropicClient.ts的streamFetch()中while (true)循环读取reader.read()后未检查done: true。当服务端关闭连接reader.read()返回{ value: undefined, done: true }但代码只处理value有值的情况陷入死循环。解决在while循环内加if (result.done) break;while (true) { const result await reader.read(); if (result.done) break; // ← 加这一行 const chunk decoder.decode(result.value); // ... parse SSE }6. 进阶技巧用这份源码快速搭建一个“协议合规性验证器”别只把src当学习材料——它最实用的落地方向是做一个轻量级 CLI 工具专治“我发的请求到底合不合规范”。我把它做成一个claude-validate命令3 分钟内可跑通核心就三个文件validator.ts、schema.json、test-cases/。下面说清楚怎么搭、为什么这么搭、以及它如何帮你省下 80% 的调试时间。6.1 为什么需要验证器因为协议细节藏在“不报错但不工作”的灰色地带官方文档说messages是数组没说第一项必须是user说system可选没说为空字符串时服务端会静默忽略你的 system prompt。这些细节只有靠真实流量 源码交叉验证才能确认。验证器的作用就是把这种“隐性规则”显性化、自动化、可版本化。6.2 三步搭建验证器从 schema 定义到 CLI 封装第一步定义schema.json—— 不是 JSON Schema而是字段级规则集它长得像这样节选{ required_fields: [model, messages], field_rules: { model: { type: string, enum: [claude-3-opus-20240229, claude-3-sonnet-20240229, claude-3-haiku-20240307], error_message: model must be one of the official Claude 3 models }, messages: { type: array, min_items: 1, item_rules: { required: [role, content], role: { enum: [user, assistant], error_message: role must be user or assistant }, content: { type: string, min_length: 1, error_message: content cannot be empty string } } } } }注意这不是用来做 JSON 校验的而是给validator.ts提供规则元数据。item_rules支持嵌套error_message是给开发者看的提示不是给机器。第二步写validator.ts—— 120 行 TypeScript核心是递归校验 上下文感知它不调用任何外部库只用原生JSON.parse()和Object.keys()。关键逻辑是validateField(value, rule, path)函数其中path是字段路径如messages.0.role用于精准报错function validateField(value: any, rule: FieldRule, path: string): string[] { const errors: string[] []; // 检查类型 if (rule.type typeof value ! rule.type) { errors.push(${path}: expected ${rule.type}, got ${typeof value}); } // 检查枚举 if (rule.enum !rule.enum.includes(value)) { errors.push(${path}: ${rule.error_message || value not in enum}); } // 检查数组项递归 if (rule.item_rules Array.isArray(value)) { value.forEach((item, i) { const itemErrors validateField(item, rule.item_rules, ${path}.${i}); errors.push(...itemErrors); }); } return errors; }第三步封装 CLI —— 用commander做一层薄包装package.json里加 scriptscripts: { validate: ts-node validator.ts }validator.ts顶部加import { Command } from commander; const program new Command(); program .name(claude-validate) .description(Validate Claude API request body against protocol rules) .argument(json-file, path to request body JSON file) .action((file) { const body JSON.parse(fs.readFileSync(file, utf8)); const errors validateBody(body); if (errors.length 0) { console.log(✅ Request body is protocol-compliant); } else { console.log(❌ Found validation errors:); errors.forEach(e console.log( - ${e})); process.exit(1); } }); program.parse();6.3 实战用验证器发现一个隐藏 bug ——stop_sequences字段的陷阱某开发者提交的测试用例test-cases/stop-sequences.json{ model: claude-3-haiku-20240307, messages: [{role:user,content:hi}], stop_sequences: [\n\n] }运行npm run validate test-cases/stop-sequences.json报错- stop_sequences.0: expected string, got string咦\n\n明明是字符串。继续查schema.json发现stop_sequences规则里漏写了type: array只写了item_rules。这就是验证器的价值它不猜不假设只按你写的规则硬校验。补上规则后再跑报新错- stop_sequences.0: stop sequence cannot contain newline characters翻anthropicClient.ts果然在buildApiRequest()里有注释// stop_sequences: only printable ASCII, no \n \r \t。这个限制官方文档没写但源码里有验证器把它挖出来了。我坚持把这类工具写进生产流程不是为了炫技而是因为——在 AI 协议的世界里最贵的不是算力是调试一个 400 错误花掉的两小时。希望帮到你。本文还有配套的精品资源点击获取