主题
第十七章 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 就预测用户可能的下一步操作,并提前执行。
工作原理
- 生成预测:LLM 完成响应后,立即用
promptSuggestion.ts预测用户的下一条输入 - 安全检查:只允许执行只读工具(
Read,Glob,Grep,LSP,ToolSearch等)或已被标记为安全的写工具 - 沙盒执行:投机执行在 overlay 目录中运行,不修改真实文件系统
- 接受/拒绝:用户输入与预测匹配时,直接使用缓存结果(零延迟);不匹配则丢弃
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 状态中的 speculation 和 speculationSessionTimeSavedMs 字段追踪投机执行状态和累计节省时间。用户可以在界面中看到"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 | 上下文压缩前/后 |
| Agent | SubagentStart, 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 服务器提供的 skillSkill 结构
每个 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_000Auto Memory
自动记忆模式下,Claude 会在认为有价值时主动将信息写入 memory 目录。findRelevantMemories.ts 负责在新会话开始时检索与当前上下文相关的记忆条目。
Team Memory
teamMemPaths.ts 和 teamMemPrompts.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_MODE | Coordinator 多 Agent 编排 |
BUDDY | Companion 陪伴精灵 |
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 的设计选择。