Skip to content

第十七章 Claude Code 独特设计与服务架构

← 返回目录 | 上一章:Claude Code 状态管理与 UI | 下一章:上下文工程(三系统对比)→

前置阅读第十四章 Claude Code Agent 与编排系统第十六章 状态管理与 UI

源码位置services/compact/services/PromptSuggestion/memdir/buddy/skills/hooks/native-ts/upstreamproxy/

本章聚焦 Claude Code 中那些独特的、不易归入常规分类的设计——它们体现了团队在实际运营大规模 AI 编码产品中积累的工程洞察。

17.1 Compaction 层级体系

上下文窗口是 LLM 应用的核心约束。Claude Code 为此建立了一套五级压缩层级,从轻到重逐级介入:

轻量 ──────────────────────────────────── 重量
 Snip → Microcompact → Context Collapse → Autocompact → Reactive

第一级:Snip(裁剪)

对过长的单条工具输出进行截断,保留头尾、省略中间。不调用 LLM,纯规则裁剪。

第二级:Microcompact(微压缩)

services/compact/microCompact.ts(530 行)——对特定工具类型的旧结果进行选择性清除:

typescript
const COMPACTABLE_TOOLS = new Set([
  'Read', 'Bash', 'Grep', 'Glob', 'WebSearch', 'WebFetch', 'Edit', 'Write'
])

只清除这些"重输出"工具的历史结果,保留其调用记录和摘要。还支持基于时间的衰减策略timeBasedMCConfig.ts),越旧的结果越激进地清除。

第三级:Context Collapse(上下文折叠)

手动触发的部分压缩——用户选择一个消息边界,将边界之前/之后的内容用 LLM 生成的摘要替换。保留用户选择的"锚点",同时大幅缩减上下文。

第四级:Autocompact(自动压缩)

services/compact/autoCompact.ts(351 行)——当 token 使用量接近上下文窗口阈值时自动触发:

typescript
const AUTOCOMPACT_BUFFER_TOKENS = 13_000
const WARNING_THRESHOLD_BUFFER_TOKENS = 20_000

function getAutoCompactThreshold(model: string): number {
  return getEffectiveContextWindowSize(model) - AUTOCOMPACT_BUFFER_TOKENS
}

关键细节:

  • 预留 20,000 tokens 给压缩摘要本身(基于 p99.99 统计)
  • 连续失败 3 次后断路(circuit breaker),停止重试——防止在不可压缩的上下文上浪费 API 调用
  • 支持 CLAUDE_CODE_AUTO_COMPACT_WINDOW 环境变量手动收窄窗口

第五级:Session Memory Compact(会话记忆压缩)

sessionMemoryCompact.ts(630 行)——实验性功能,将压缩后的会话摘要持久化到会话记忆中,跨压缩轮次保留关键发现。

对比:Opencode 的上下文管理相对简洁——主要依赖 session.summary() 单级压缩 + token 计数触发。OmO 通过 Skill 系统添加了上下文裁剪提示,但本质上仍是单层策略。Claude Code 的五级层级反映了在海量用户场景下,单一策略无法覆盖所有对话模式的现实。

17.2 投机执行(Speculation)

services/PromptSuggestion/speculation.ts(991 行)实现了一个大胆的优化:在用户还没输入下一条消息时,Claude Code 就预测用户可能的下一步操作,并提前执行

工作原理

  1. 生成预测:LLM 完成响应后,立即用 promptSuggestion.ts 预测用户的下一条输入
  2. 安全检查:只允许执行只读工具(Read, Glob, Grep, LSP, ToolSearch 等)或已被标记为安全的写工具
  3. 沙盒执行:投机执行在 overlay 目录中运行,不修改真实文件系统
  4. 接受/拒绝:用户输入与预测匹配时,直接使用缓存结果(零延迟);不匹配则丢弃
typescript
const MAX_SPECULATION_TURNS = 20    // 最多投机 20 轮
const MAX_SPECULATION_MESSAGES = 100 // 最多 100 条消息

const SAFE_READ_ONLY_TOOLS = new Set([
  'Read', 'Glob', 'Grep', 'ToolSearch', 'LSP', 'TaskGet', 'TaskList'
])

状态追踪

UI 状态中的 speculationspeculationSessionTimeSavedMs 字段追踪投机执行状态和累计节省时间。用户可以在界面中看到"Speculation saved Xs"的提示。

这是整个 AI 编码工具领域中最激进的延迟优化之一——本质上是 CPU 分支预测思路在人机交互中的应用。

17.3 Hooks 系统

utils/hooks.ts(5022 行)定义了 Claude Code 的生命周期钩子系统——允许用户通过 shell 命令在关键时刻注入自定义逻辑。

钩子事件类型

支持 20+ 种事件,覆盖完整的交互生命周期:

类别事件触发时机
会话SessionStart, SessionEnd会话开始/结束
工具PreToolUse, PostToolUse, PostToolUseFailure工具执行前/后/失败后
权限PermissionDenied, PermissionRequest权限被拒/权限请求时
压缩PreCompact, PostCompact上下文压缩前/后
AgentSubagentStart, SubagentStop子 Agent 生命周期
任务TaskCreated, TaskCompleted任务创建/完成
配置ConfigChange, CwdChanged, InstructionsLoaded配置/路径/指令变更
交互UserPromptSubmit, Elicitation, ElicitationResult用户提交/问答交互
系统Setup, Stop, StopFailure, FileChanged初始化/停止/文件变更
特殊Notification, StatusLine, FileSuggestion, TeammateIdle通知/状态栏/建议/空闲

钩子能力

钩子不仅能观察,还能影响行为

  • PreToolUse 钩子可以返回 { decision: "deny" } 阻止工具执行
  • PermissionRequest 钩子可以返回批准/拒绝,替代用户手动确认
  • StatusLine 钩子可以在状态栏显示自定义信息
  • FileSuggestion 钩子可以提供文件路径建议

钩子来源

钩子可以从多个源加载:用户配置、项目配置、插件、managed 设置。优先级与权限规则类似,支持 shouldAllowManagedHooksOnly 策略限制钩子来源。

对比:Opencode 不提供显式的钩子系统——其扩展点通过 OmO 的 Skill 系统(system prompt 注入 + 行为约束)间接实现。Claude Code 的 hooks 是外部进程级别的集成——执行的是 shell 命令,不是内嵌代码。这使得任何语言编写的外部工具都能参与 Claude Code 的生命周期,但也引入了进程启动开销和安全边界问题。

17.4 Skills 系统

skills/loadSkillsDir.ts(1086 行)实现了 Claude Code 的 Skill 加载机制——不同于 OmO 的 SKILL.md 注入模式,Claude Code 的 Skills 更接近可执行的项目级配置

Skill 加载路径

Skills 可以从多个位置加载:

typescript
type LoadedFrom =
  | 'commands_DEPRECATED'  // 旧版 commands/ 目录(已弃用)
  | 'skills'               // .claude/skills/ 目录
  | 'plugin'               // 插件提供的 skill
  | 'managed'              // 企业管理的 skill
  | 'bundled'              // 内置 skill
  | 'mcp'                  // MCP 服务器提供的 skill

Skill 结构

每个 Skill 是一个 Markdown 文件(*.md),支持 frontmatter 元数据:

  • description:简短描述,显示在 / 命令列表中
  • allowed-tools:执行时允许使用的工具白名单
  • model:指定执行 skill 时使用的模型
  • effort:控制推理努力程度
  • hooks:skill 可以注册自己的生命周期钩子
  • shell:指定 hook 的执行环境

Skill 的 Markdown 正文作为 system prompt 注入——这一点与 OmO 的 SKILL.md 模式异曲同工。

与 MCP 的桥接

mcpSkillBuilders.ts 实现了 MCP 服务器到 Skill 的桥接——MCP 提供的 Prompt 资源可以自动转换为 Claude Code 的 Skill。这统一了本地 Skill 和远程 MCP Prompt 的调用接口。

17.5 Memory 系统(memdir)

memdir/ 目录(8 个文件)实现了 Claude Code 的持久记忆:

MEMORY.md

核心是一个 MEMORY.md 入口文件(限制 200 行或 25KB),作为记忆的索引。Claude 在工作中发现的项目惯例、用户偏好、关键路径等信息都可以自动或手动保存到这里。

typescript
export const ENTRYPOINT_NAME = 'MEMORY.md'
export const MAX_ENTRYPOINT_LINES = 200
export const MAX_ENTRYPOINT_BYTES = 25_000

Auto Memory

自动记忆模式下,Claude 会在认为有价值时主动将信息写入 memory 目录。findRelevantMemories.ts 负责在新会话开始时检索与当前上下文相关的记忆条目。

Team Memory

teamMemPaths.tsteamMemPrompts.ts 处理 Swarm 模式下的团队级记忆——团队成员共享的项目知识,与个人记忆分开管理。

对比:Opencode 的 AGENTS.md 和 OmO 的 SKILL.md 系统侧重于指令注入——告诉 AI 怎么做。Claude Code 的 Memory 系统侧重于知识积累——记录 AI 发现了什么。两者是互补的:指令是静态的"应该",记忆是动态的"知道"。

17.6 Companion(陪伴精灵)

buddy/ 目录(6 个文件)实现了一个令人意外的功能——终端中的虚拟宠物。

程序化生成

companion.ts 使用 Mulberry32 伪随机数生成器,基于用户标识的哈希值确定性地生成一只"同伴":

typescript
// Species, hat, eyes, rarity, stats — all deterministic from user seed
function rollCompanion(seed: string): Companion {
  const rng = mulberry32(hashString(seed))
  const species = pick(rng, SPECIES)
  const rarity = rollRarity(rng)        // common/uncommon/rare/epic/legendary
  const hat = pick(rng, HATS)
  const eyes = pick(rng, EYES)
  const stats = rollStats(rng, rarity)  // peak stat + dump stat + scatter
  ...
}

每个用户看到的是独一无二但固定的同伴——有物种、帽子、眼睛、稀有度和属性值。CompanionSprite.tsx 渲染 ASCII 艺术,useBuddyNotification.tsx 在适当时机显示通知。

这是产品情感化设计的典型实践:一个纯功能性的 CLI 工具,通过一个毫无"生产力"价值的小功能,建立用户情感连接。

17.7 Native TypeScript 模块

native-ts/ 目录包含三个性能敏感的纯 TypeScript 实现:

  • color-diff/:颜色差异计算(用于 diff 高亮)
  • file-index/:文件索引(快速文件查找)
  • yoga-layout/:Yoga 布局引擎的 TypeScript 绑定

这些模块避免了 native addon(.node 文件)的跨平台编译问题,同时通过纯 TS 实现保持了合理的性能。

17.8 Upstream Proxy

upstreamproxy/ 目录(2 个文件)解决了企业环境中常见的 HTTP 代理问题:

  • upstreamproxy.ts:检测和配置上游代理
  • relay.ts:实现代理请求中继

在企业网络中,AI 工具的 API 请求经常需要通过公司代理服务器。这个模块确保 Claude Code 在代理环境下正常工作——一个看似简单但在实际部署中至关重要的功能。

17.9 构建时特性门控

贯穿整个代码库的 feature() 函数(来自 bun:bundle)是 Claude Code 的编译时特性门控系统

typescript
// 构建时被替换为 true/false 常量
const useVoiceIntegration = feature('VOICE_MODE')
  ? require('../hooks/useVoiceIntegration.js').useVoiceIntegration
  : () => noop

// 内部版 vs 外部版
const useFrustrationDetection = "external" === 'ant'
  ? require('./useFrustrationDetection.js').useFrustrationDetection
  : () => ({ state: 'closed' })

已确认的特性标志包括:

标志说明
VOICE_MODE语音输入模式
COORDINATOR_MODECoordinator 多 Agent 编排
BUDDYCompanion 陪伴精灵
WEB_BROWSER_TOOL内置浏览器工具
PROACTIVE / KAIROS主动式行为 / 调度系统
AGENT_TRIGGERS定时任务触发器
MESSAGE_ACTIONS消息操作栏
CACHED_MICROCOMPACT缓存微压缩
TEAMMEM团队记忆

process.env.USER_TYPE === 'ant' 则区分内部(Anthropic 员工)和外部构建——内部版包含 frustration 检测、组织安全警告、开发者工具栏等功能。

这种方式让同一份源码产出多个不同能力的构建产物,且未启用的功能在最终产物中零字节——比运行时 if/else 更彻底。

17.10 小结

本章覆盖的这些子系统,揭示了 Claude Code 作为一个成熟商业产品(而非开源项目)的工程深度:

  • Compaction 五级层级:不是一个算法能解决的问题,而是根据对话模式统计数据逐层叠加的策略
  • 投机执行:将 CPU 分支预测的思路应用于人机交互,用空闲时间换响应延迟
  • Hooks 系统:5000+ 行代码、20+ 事件类型——一个完整的外部集成框架
  • Skills 与 Memory:指令(怎么做)+ 记忆(知道什么)的双维度上下文增强
  • Companion:在纯工具型产品中注入情感化设计
  • 构建时 DCE:同一源码,多个产物,零运行时开销

这些设计中,有些是 Claude Code 独创的(投机执行、Companion),有些是对已有模式的工业级实现(Hooks、Compaction),有些则反映了 Anthropic 作为 AI 公司的独特视角(Memory 系统将 AI 的"发现"持久化)。

下一章(第九章更新版)我们将进入三系统跨领域对比,从上下文工程的角度重新审视 Opencode、OmO 和 Claude Code 的设计选择。


← 返回目录 | 上一章:Claude Code 状态管理与 UI | 下一章:上下文工程(三系统对比)→