上下文窗口管理:动态装配、剪裁与压缩重组
在 Claude Code 的设计中,上下文窗口(Context Window)不是一个静态增长的缓冲区,而是一个高度动态的、经过精细剪裁的“工作视图”。它是 Claude 能够理解超大规模项目并保持高效推理的核心。
它解决了什么问题
上下文管理本质上是 Prompt 的动态物化(Materialization)协议。
它旨在解决长会话中的三大核心矛盾:项目文件太多放不下(Token 溢出)、无关信息干扰推理(注意力漂移)、以及 Token 消耗带来的成本与延迟。Claude Code 不会将所有文件一股脑塞给模型,而是根据当前任务状态、用户需求和历史交互,实时构建一份最相关的“上下文快照”。
运行时的真相
上下文窗口的生命周期由四层装配与重组逻辑驱动:
启动装配层(Environment Mirroring): 在
claude-code-opensource/src/context.ts中,系统会首先构建基础环境镜像。- Git 状态:包含当前分支、主分支对比、近期提交摘要和
git status。这些信息是快照式的,在会话中不会实时通过 fs watcher 自动更新,而是依赖重新装配。 - 规则注入:核心是
CLAUDE.md和各级.claude/rules的递归读取,以及本地记忆文件(Memory Files)的注入。
- Git 状态:包含当前分支、主分支对比、近期提交摘要和
按需补载层(Lazy Loading): Claude Code 的上下文是高度懒加载的。
- Skill 工具集:只有当模型在推理中显式需要某种能力时,相关的 Skill 定义才会被载入。
- 动态路径扫描:当用户在 Prompt 中提到特定路径或文件时,系统会实时检索并注入相关的子目录规则。
- MCP 资源:通过
@符号引用的外部资源,是在发送 Prompt 的前一刻才被物化为附件的。
精细剪裁层(Auto Pruning): 在正式发送前,系统会对物料进行预处理以防止溢出。
- Git Status 截断:如果
git status输出超过 2000 字符,会被强行截断,并提示用户通过BashTool自行查看。 - 附件化优化:大量的工具输出(如大规模的 grep 结果)会被转为附件(Attachments)而非直接放在正文中,以利用 Claude 3 家族对长上下文附件的处理优势。
- Git Status 截断:如果
压缩重组层(Context Compaction): 当 Token 接近临界值或用户手动执行
/compact时,系统会启动claude-code-opensource/src/services/compact/compact.ts中的算法。- 分叉总结:系统会启动一个“影子 Agent”(通过
runForkedAgent),在隔离会话中总结历史。它会提炼出:事实性发现(如 Bug 原因)、当前任务进度(Plan/Todos)和已修改文件列表。 - 物料保留:压缩不是简单的截断。算法会强制保留
CLAUDE.md、关键规则和最近读写过的文件附件(File Attachments),防止压缩后出现即时“失忆”。 - 增量策略:系统支持“层级总结”,保留上一次压缩后的简报,仅对新产生的对话进行递归归纳,从而最大化节省总结本身的 Token 成本。
- 分叉总结:系统会启动一个“影子 Agent”(通过
实战注意事项
- 非实时性陷阱:Git 状态和项目层级规则在
getUserContext中是经过 memoize 缓存的。如果你在会话中通过 Bash 切换了分支,Claude 的 System Prompt 可能仍保留着旧分支信息,除非触发了/compact或重新启动。 - 压缩代价:执行
/compact虽然腾出了 Token 空间,但会导致模型丢失极细微的历史痕迹(如之前被否决的拼写细节)。如果你的任务强依赖于“刚才那个拼写错误”,压缩后将无法回溯。 - Bare 模式的盲区:在
--bare模式下,自动化的CLAUDE.md发现、CWD 遍历和背景总结都会被彻底关闭,上下文退化为仅包含当前对话和显式追加的目录。 - 附件优先:模型看到的 Transcript 与你看到的终端输出并不一致。模型视图中充斥着大量的结构化 XML 元数据和隐藏的附件引用。
推荐阅读路径
- 如果你想了解如何通过快照回滚到压缩前的状态,请看 会话重绕与检查点:Rewind 机制。
- 如果你想了解
CLAUDE.md是如何被层级发现的,请看 项目指令加载协议:CLAUDE.md 与路径规则。 - 如果你关心 Token 计费与估算,请看 成本管理:Prompt Caching 与 Token 优化。
源码锚点
claude-code-opensource/src/context.ts— 上下文装配与缓存的主入口(memoize逻辑所在)。
📄 src/context.ts — 上下文装配与缓存的主入口(`memoize` 逻辑所在)。
typescript
export const getGitStatus = memoize(async (): Promise<string | null> => {
if (process.env.NODE_ENV === 'test') {
// Avoid cycles in tests
return null
}
const startTime = Date.now()
logForDiagnosticsNoPII('info', 'git_status_started')
const isGitStart = Date.now()
const isGit = await getIsGit()
logForDiagnosticsNoPII('info', 'git_is_git_check_completed', {
duration_ms: Date.now() - isGitStart,
is_git: isGit,
})
if (!isGit) {
logForDiagnosticsNoPII('info', 'git_status_skipped_not_git', {
duration_ms: Date.now() - startTime,
})
return null
}
try {
const gitCmdsStart = Date.now()
const [branch, mainBranch, status, log, userName] = await Promise.all([
getBranch(),
getDefaultBranch(),
execFileNoThrow(gitExe(), ['--no-optional-locks', 'status', '--short'], {
preserveOutputOnError: false,claude-code-opensource/src/services/compact/compact.ts— 核心压缩重组算法与影子总结 Agent 的实现。
📄 src/services/compact/compact.ts — 核心压缩重组算法与影子总结 Agent 的实现。
typescript
getAgentListingDeltaAttachment,
getDeferredToolsDeltaAttachment,
getMcpInstructionsDeltaAttachment,
} from '../../utils/attachments.js'
import { getMemoryPath } from '../../utils/config.js'claude-code-opensource/src/utils/claudemd.ts— 指令文件与路径规则的发现读取逻辑。
📄 src/utils/claudemd.ts — 指令文件与路径规则的发现读取逻辑。
typescript
type InstructionsLoadReason,
type InstructionsMemoryType,
} from './hooks.js'
import type { MemoryType } from './memory/types.js'