事件描述 @

昨天claude源码泄漏事件被暴漏出来,然后整个开源社区就疯狂了,其代码被fork了上千次,很多大佬已经开始分析claude的源码并且使用python重写其核心逻辑。

  • 源码仓库 claude-code-sourcemap,截止目前已经fork了7K+次。

  • 已经有人使用claude分析它自己的源码,跑出了一份报告 claude-code-deep-dive

  • claw-code使用python重写claude的核心逻辑,并且star数快速飙升到目前的43.6K,截止目前fork了43.6K+次

整体架构图 @

我也简单使用opencode跑了下项目,可以看出claude主要使用typescript+bun构建,使用react+Ink作为UI框架。此前我也看过opencode的代码,使用的他们自己实现的OpenTUI,而像类似crush的go版本AI终端工具则使用的bubbletea和他们团队自己写的TUI组件。

┌─────────────────────────────────────────────────────────────────────────┐
│                              main.tsx                                    │
│                         (CLI 入口, 4684 行)                              │
└─────────────────────────────────────────────────────────────────────────┘
        ┌───────────────────────────┼───────────────────────────┐
        ▼                           ▼                           ▼
┌───────────────┐          ┌─────────────────┐         ┌────────────────┐
│   bootstrap/  │          │    QueryEngine  │         │    tools.ts    │
│   启动初始化   │◄────────►│    (核心引擎)    │◄──────►│   (工具注册)   │
└───────────────┘          └─────────────────┘         └────────────────┘
                                    │                           │
                                    ▼                           ▼
                            ┌─────────────────┐         ┌────────────────┐
                            │    query.ts     │         │  tools/        │
                            │  (查询逻辑)     │         │  (30+ 工具)    │
                            └─────────────────┘         └────────────────┘
        ┌───────────────────────────┼───────────────────────────┐
        ▼                           ▼                           ▼
┌───────────────┐          ┌─────────────────┐         ┌────────────────┐
│    services/  │          │    state/       │         │   ink/         │
│   (API/MCP)   │          │   (状态管理)    │         │  (终端UI)      │
└───────────────┘          └─────────────────┘         └────────────────┘
        │                           │                           │
        ▼                           ▼                           ▼
┌───────────────┐          ┌─────────────────┐         ┌────────────────┐
│   bridge/     │          │  AppState.tsx   │         │ components/    │
│  (远程会话)   │          │  (React状态)    │         │  (消息/权限)   │
└───────────────┘          └─────────────────┘         └────────────────┘

提示词设计 @

claude的提示词设计很有意思,分为很多个层次

  1. 身份介绍
  2. 系统指令
  3. 任务执行指南
  4. 行动准则(危险操作确认)
  5. 工具使用指南
  6. 语气风格
  7. 输出效率

其中在Verification Agent 中就有对抗思维,也就是目前所说的harness工程

You are a verification specialist. Your job is not to confirm 
the implementation works — it's to try to break it.

Two documented failure patterns:
1. Verification avoidance: finding reasons not to run checks
2. Being seduced by the first 80%: passing polished UI without testing functionality

=== VERIFICATION STRATEGY ===
Adapt based on change type:
- Frontend: Start dev server → browser automation → curl resources
- Backend: Start server → curl endpoints → verify response shapes
- CLI: Run with inputs → verify stdout/stderr/exit codes
- etc.

=== RECOGNIZE YOUR OWN RATIONALIZATIONS ===
- "The code looks correct" — reading is not verification
- "The implementer's tests already pass" — verify independently
- "Probably is fine" — probably is not verified

其中几条感觉挺有意思,不断给AI增加约束,让其自我反思,而不是自嗨。

  • “代码看起来正确”——阅读并不等于验证
  • “实现者的测试已经通过”——独立验证
  • “可能没问题”——可能没有验证

Claude Code Buddy @

claude的伙伴系统挺有意思,主要由 6 个文件组成:

src/buddy/
├── types.ts          # 类型定义:物种、稀有度、属性
├── companion.ts      # 核心逻辑:生成算法、缓存
├── sprites.ts        # ASCII 艺术素材(500+ 行)
├── prompt.ts         # 系统提示词集成
├── CompanionSprite.tsx  # React 组件:渲染与动画
└── useBuddyNotification.tsx  # 通知系统

每个用户的 Buddy 基于 userId + salt 生成,确保同一用户始终获得相同的结果:

const SALT = 'friend-2026-401'

export function roll(userId: string): Roll {
  const key = userId + SALT
  // 使用 Mulberry32 PRNG 保证确定性
  return rollFrom(mulberry32(hashString(key)))
}

稀有度系统遵循游戏化的概率设计:

const RARITY_WEIGHTS = {
  common: 60,      // 60%
  uncommon: 25,   // 25%
  rare: 10,       // 10%
  epic: 4,        // 4%
  legendary: 1,   // 1%
}

每个 Buddy 有 5 种属性,稀有度越高,数值上限越高:

const RARITY_FLOOR: Record<Rarity, number> = {
  common: 5,
  uncommon: 15,
  rare: 25,
  epic: 35,
  legendary: 50,
}

属性类型:DEBUGGINGPATIENCECHAOSWISDOMSNARK——每个名字都透露着 Claude Code 的极客气质。每种物种有 3 帧动画(idle fidget),每个 sprite 5 行 × 12 列:

// duck 示例
[duck]: [
  [
    '            ',
    '    __      ',
    '  <({E} )___  ',  // {E} 会替换为眼睛字符
    '   (  ._>   ',
    '    `--´    ',
  ],
  // ... 更多帧

  // 6 种眼睛样式
const EYES = ['·', '✦', '×', '◉', '@', '°']

// 8 种帽子
const HATS = ['none', 'crown', 'tophat', 'propeller', 'halo', 'wizard', 'beanie', 'tinyduck']
]

上下文压缩 @

claude的上下文压缩其实也很简单,不是把历史对话都塞进上下文,而是使用合理的分层策略:

  • 热数据:最近 5-10 轮完整保留
  • 温数据:中期历史压缩为摘要
  • 冷数据:早期历史按需从磁盘恢复

可以举个简单的例子,比如想象你在和一个项目经理聊天,他已经陪你工作了 8 小时。这时候他说:“稍等,我整理一下之前的记录。”

然后他花了 30 秒,快速写了一份备忘录:

  • 客户要求做什么
  • 做了哪些改动
  • 遇到什么问题
  • 接下来要做什么

写完之后,他把 8 小时的会议记录扔了,只留下这份 300 字的备忘录。下次你们继续聊的时候,他只需要看一下这份备忘录,就能无缝衔接工作。Claude Code 做的事情差不多就是这样。

但不是每次对话都会压缩,要等到“装得差不多了”才动手:

压缩阈值 = 上下文窗口大小 - 13,000 tokens

对于 200K 窗口的模型,大概在 187K 左右触发自动压缩。用户也可以手动执行 /compact 触发。

  1. 第一步:叫 AI 来“总结”,把之前所有的对话发给模型,然后让其把这些对话整理成一份摘要,要包含下面部分

    • 用户让你做什么
    • 你看了哪些文件、改了什么
    • 遇到了什么错误、怎么修的
    • 接下来要干什么
  2. 第二步:严格的输出格式,模型必须这样输出:

    <analysis>
    [先在这里分析对话过程]
    </analysis>
    
    <summary>
    1. 用户请求:...
    2. 涉及的文件:...
    3. 错误修复:...
    4. 待办事项:...
    5. 当前进度:...
    </summary>
    

    为什么要分 <analysis><summary> 两部分?因为 <analysis> 是模型思考的过程,对后续没用,直接扔掉。只保留 <summary> 部分。

  3. 第三步:替换旧消息,压缩后的对话变成这样:

    [这是一条分割线]
    [压缩后的摘要]
    [最近的几条对话保留不变]
    

    用户完全感知不到这个过程,下一句话就能继续聊。

预算控制 @

                        ┌─────────────────┐
                        │  任务开始       │
                        └────────┬────────┘
                    ┌────────────────────────┐
                    │ 检查是否达到 90% 阈值? │
                    └────────┬───────────────┘
              ┌──────────────┴──────────────┐
              │                             │
             否                            是
              ▼                             ▼
    ┌─────────────────┐           ┌──────────────────┐
    │ 检测边际递减    │           │ 检查是否有连续   │
    │ (连续3次增长<500│           │ 继续的历史?      │
    │  tokens?)       │           └────────┬─────────┘
    └────────┬────────┘                    │
             │                      ┌──────┴──────┐
      ┌──────┴──────┐                 │             │
      │             │                是            否
      ▼             ▼                ▼             ▼
  ┌───────┐   ┌───────────┐   ┌───────────┐  ┌──────────┐
  │ 递减   │   │ 继续执行   │   │  停止任务  │  │ 等待下一轮 │
  │ 停止   │   │ + 提示信息 │   │           │  │          │
  └───────┘   └───────────┘   └───────────┘  └──────────┘

Token Budget 机制是 Claude Code 处理长任务的核心能力之一:

阶段 关键函数 职责
声明解析 parseTokenBudget() 从自然语言提取数字
状态快照 snapshotOutputTokensForTurn() 记录每轮基准
决策判断 checkTokenBudget() 90% 阈值 + 边际递减
循环控制 query.ts 中的 continue 驱动多轮工作
API 传递 configureTaskBudgetParams() 通知模型预算

这套机制让 AI 从"一次性的问答"变成"有预算意识的长跑运动员"——既不会过早放弃,也不会无限徘徊。

查询引擎 @

这部分相当于是claude的核心逻辑,也基本是是目前大多数主流AI的循环模式。

┌──────────────────────────────────────────────────────────────┐
│                      Query 循环                               │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│    ┌─────────┐    API 调用    ┌─────────────┐               │
│    │  用户   │ ──────────────▶│  模型响应   │               │
│    │  消息   │                │  (ToolUse)  │               │
│    └─────────┘                └──────┬──────┘               │
│                                      │                       │
│                              ┌───────┴───────┐               │
│                              ▼               ▼               │
│                       ┌──────────┐    ┌──────────┐           │
│                       │ 执行工具  │    │  结束    │           │
│                       └─────┬────┘    └──────────┘           │
│                             │                                 │
│                             ▼                                 │
│                       ┌──────────┐                            │
│                       │ 结果处理  │                            │
│                       │ + 压缩   │                            │
│                       │ + Token  │                            │
│                       │   Budget │                            │
│                       └─────┬────┘                            │
│                             │                                 │
│                             ▼                                 │
│                       ┌──────────┐                            │
│                       │ 下一轮? │                            │
│                       └──────────┘                            │
│                                                              │
└──────────────────────────────────────────────────────────────┘

QueryEngine 是 Claude Code 的大脑,负责管理整个查询生命周期:

  • 消息状态管理:维护会话历史,支持压缩恢复
  • 输入处理:解析用户输入、提取预算声明、处理附件
  • 查询循环:调用 API → 执行工具 → 处理结果 → 检查预算 → 继续或结束
// src/QueryEngine.ts
export class QueryEngine {
  private mutableMessages: Message[]
  private abortController: AbortController
  private readFileState: FileStateCache
  private discoveredSkillNames = new Set<string>()
  
  async submitMessage(input: string): Promise<void> {
    // 1. 处理用户输入
    const { messages } = await processUserInput(...)
    
    // 2. 执行查询循环
    const result = await query({
      messages,
      tools: this.config.tools,
      // ...其他配置
    })
    
    // 3. 更新状态
    this.mutableMessages = result.messages
  }
}

总结 @

Claude Code 展示了一个成熟 AI CLI 工具的工程化设计精髓:

设计维度 核心思路 工程价值
预算控制 Token Budget + 边际检测 长任务可靠性
资源管理 分层缓存 + 自动压缩 无限会话能力
工具系统 buildTool + 延迟加载 可扩展架构
技能系统 Command + Hooks 组合式提示工程
状态管理 QueryEngine + Feature Flag 生产级稳定性
任务处理 类型化任务 + 安全 ID 并发安全

这些设计模式不仅适用于 CLI 工具,也为构建企业级 AI 应用提供了可复制的架构参考,源码还有非常多有意思的设计,大家可以自行参考。