Claude Code 的上下文窗口是怎么被填满的:构成拆解

2026-08-18

现象:还没开始干活,上下文就已经不空了

很多人第一次注意到上下文这件事,是从一个反直觉的观察开始的:新开一个会话,一个字还没输入,上下文里已经有内容了;等真正开始改代码,涨得也比”我就让它读了两个文件”要快。

Claude Code 官方文档有一页专门讲这个,路径是 code.claude.com/docs/en/context-window,标题是 Explore the context window。正文第一句写明:上下文窗口装的是这个会话里 Claude 知道的一切——你的指令、它读过的文件、它自己的回复,以及从头到尾都不会出现在你终端里的那部分内容。后半句才是要命的地方:占用大头里有相当一部分,你在终端里根本看不见,于是只能靠猜。

这篇只做一件事:把”谁占的”拆开,逐类对号。窗口满了以后报 Prompt is too long 怎么办,我们另有一篇专门讲;本文也不涉及任何上下文长度、token 上限、阈值的具体数值——那些随模型和版本变动。

第一步:先做判定动作,别靠感觉

判断”上下文被谁占了”,官方文档给了三个可执行的入口,从粗到细:

/context。文档写明它给出按类别(by category)的实时占用明细并附优化建议,其中包括哪些 CLAUDE.md 与 auto memory 文件实际加载进了本次会话。文档在 Check your own session 一节里特意声明:那个交互式可视化里的 token 数是”representative numbers”(示意值),要看真实占用就跑 /context

/memory。文档写明它列出 CLAUDE.md、CLAUDE.local.md 以及其它 memory 文件的位置,覆盖 user 与 project 两个 scope,连还不存在的条目也会列出来;同时提供 auto memory 的开关。

InstructionsLoaded hook。memory 页给的一条提示:用这个 hook 记录到底哪些指令文件被加载、何时加载、为什么加载。文档说它对排查 path-specific rules 和子目录里的懒加载文件特别有用——这两类正好最容易判断反。

顺序:先 /context 看哪一类偏大,再用 /memoryInstructionsLoaded 精确到文件。

第二步:按构成逐类对号

一、你输入第一句之前就装好的

文档把这一段归为 auto-loaded,包含这几类:

  • system prompt。文档在 What the timeline shows 里补了一句:你自己的设置可能往这里再加东西,比如 output style,或者 --append-system-prompt 传进去的文本,两者都以同样方式进 system prompt。
  • auto memory(MEMORY.md。只加载索引开头的一段——文档给的是行数与体积两个阈值、先到者为准(具体数值以官方文档为准,本文不写)。超出的部分在会话开始时不加载debugging.md 这类 topic 文件同样不在启动加载范围内,Claude 需要时用普通文件工具按需读。
  • environment info。工作目录、平台、shell、OS 版本、是否 git 仓库。文档特别说明:git 分支、状态与最近提交是单独一块,挂在 system prompt 的最末尾。
  • MCP 工具(deferred)。默认只列工具名让 Claude 知道有什么可用,完整 schema 保持 deferred,用到时再通过 tool search 按需加载。两个环境变量取值:ENABLE_TOOL_SEARCH=auto 表示在 schema 能塞进上下文窗口的一小部分时提前加载(占比数值见官方文档),ENABLE_TOOL_SEARCH=false 表示全部加载。
  • skill descriptions。每个 skill 一行描述,正文只有真正用到时才加载。带 disable-model-invocation: true 的 skill 不在这个清单里,在你用 /name 显式调用之前,它完全不占上下文。
  • ~/.claude/CLAUDE.md 与项目 CLAUDE.md

CLAUDE.md 的加载路径值得单说,因为它最容易装进来一堆你没打算装的东西。memory 页写明:Claude Code 从当前工作目录往上走目录树,逐级检查 CLAUDE.mdCLAUDE.local.md,全部拼接进上下文而不是互相覆盖;顺序是从文件系统根一路到工作目录,越靠近你启动位置的越后读,同一目录内 CLAUDE.local.md 排在 CLAUDE.md 之后。工作目录以下子目录里的同名文件不在启动时加载,而是等 Claude 读到那些目录里的文件时才带进来。

文档列出的 CLAUDE.md 位置一共四种 scope:managed policy、user、project、local。managed policy 三个平台路径各不相同——macOS 是 /Library/Application Support/ClaudeCode/CLAUDE.md,Linux 与 WSL 是 /etc/claude-code/CLAUDE.mdWindows 是 C:\Program Files\ClaudeCode\CLAUDE.md。排查时有用:Windows 上若发现上下文里多了一段来源不明的组织级指令,先去这个路径看;文档明说 managed policy 的 CLAUDE.md 不能被 claudeMdExcludes 排除。

两个反直觉的占用规则:

  • @path/to/import 导入的文件在启动时就展开进上下文,最多四跳。文档在”我的 CLAUDE.md 太大”那节写得很直白:拆成 import 只帮组织,不减少上下文
  • 反过来,块级 HTML 注释在内容注入前被剥掉,不花 token(代码块内的注释保留),给人类维护者留的话可以放心写在里面。

还有一个默认值容易踩:--add-dir 带进来的目录,其中的 CLAUDE.md 默认不加载。要加载得显式开:

CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 claude --add-dir ../shared-config

文档说明这会加载额外目录下的 CLAUDE.md.claude/CLAUDE.md.claude/rules/*.mdCLAUDE.local.md。这是官方文档给出的 shell 前缀赋值写法,Linux/macOS 的 bash 可直接照抄;Windows 的 PowerShell 与 cmd 设环境变量语法不同,官方文档没有给出 Windows 侧的对应写法,请按你所用 shell 的规则改写。

二、干活过程中的增量

  • 文件读取。文档在时间线的提示里直说 file reads dominate context usage,给的建议是提示词写具体(点名到文件),研究型任务交给 subagent。
  • path-scoped rules.claude/rules/ 下带 paths: frontmatter 的规则,在 Claude 读到匹配文件时自动进上下文;终端里只有一行 Loaded 通知,规则正文你看不到。文档强调触发时机是”读到匹配的文件”,不是每次工具调用。
  • hook 的回传。这一条口径细得容易记反:PostToolUse hook 通过 hookSpecificOutput.additionalContext 字段把内容送进 Claude 的上下文;exit 0 时的普通 stdout 不进上下文,只写进 debug log;PostToolUse 的 exit code 2 会把 stderr 作为错误暴露出来,但拦不住任何事——工具已经跑完了。文档还提醒这段输出进上下文时不做截断,所以要短。每一个匹配的工具事件都会触发一次,一次编辑一次开销。
  • 你自己敲的东西! 前缀的 bash 模式,命令和它的输出作为你这条消息的一部分进上下文;用 / 调用一个此前不在清单里的 skill,正文此刻才加载进来。
  • 工具输出。搜索结果、测试输出这类,终端里是一行摘要,上下文里是全文。

三、subagent 用的是另一个窗口

文档写明 subagent 有自己独立的上下文窗口,启动时装的是:自己的 system prompt(比主会话短,通用 agent 是一段简短提示加环境信息)、自己那一份项目 CLAUDE.md(同一个文件、同样内容,但算它的账不算你的;内置的 Explore 与 Plan agent 跳过这一步以换更小的上下文)、同样的 MCP servers 与 skills,但拿不到几类在嵌套场景下不适用的工具——文档点名了 plan-mode 控制、后台任务工具,以及默认情况下 Agent 工具本身(防止递归)。

主会话的 auto memory 不进 subagent;文档给的例外是 fork,它继承父会话与 system prompt。若自定义 agent 的 frontmatter 里写了 memory:,它加载的是自己那份独立的 MEMORY.md。回到你窗口的只有它最后那段文本回复,外加一小段 metadata trailer(token 计数与耗时)。

第三步:压缩之后哪些回得来

code.claude.com/docs/en/context-window 的 What survives compaction 一节给了一张七行表。按行为分成三类读更省事:

  • 不属于消息历史的:system prompt 与 output style,不变。
  • 从磁盘重新注入的:项目根 CLAUDE.md、没有 paths 的 rules、auto memory。
  • 丢掉直到再次触发的:带 paths: frontmatter 的 rules、子目录里的 nested CLAUDE.md。它们本来就是”读到匹配文件时才进消息历史”,所以会被连同对话一起总结掉,下次 Claude 读到匹配文件时再回来。
  • 表格里 hooks 那一行写的是 not applicable:hooks 以代码方式运行,本来就不占上下文。

两处补充。其一,被调用过的 skill 正文会重新注入,但文档写明有每个 skill 与总量两道上限,超了先丢最老的;截断保留文件开头,所以最重要的指令要放在 SKILL.md 靠前的位置。其二,skill 描述清单是启动内容里唯一不在 /compact 之后重新注入的,只有你真正调用过的 skill 会被保留下来。

如果某条规则必须跨压缩存活,文档给的办法只有两个:去掉 paths: frontmatter,或者挪进项目根 CLAUDE.md。

第四步:处置之后怎么验证

改完之后别凭感觉,回到判定动作重跑一遍:再跑 /context,比对分类占比有没有按预期的那一类降下来,以及 Memory files 列表里是不是还留着你以为已经排除掉的文件;跑 /memory 确认文件本身(比如 claudeMdExcludes 配上之后,别的团队那份 CLAUDE.md 是否还在);装上 InstructionsLoaded hook 看日志,确认 path-scoped rules 是否真的只在读到匹配文件时才进来。

如果目标只是腾地方,文档在 When your context fills up 一节给了四个动作:带焦点压缩(/compact focus on the auth bug fix 是文档原样给出的示例)、用 /autocompact 接一个 token 数把自动压缩的触发点提前(可接受的取值与覆盖方式见官方文档,本文不写数值)、切换到无关任务时 /clear、把大批量读文件委派给 subagent。文档同时说明:接近上限时 Claude Code 会自动压缩,满了的窗口不会终止你的会话,自动那一遍与手动 /compact 是同一套逻辑。

第五步:什么情况说明不是”构成”这个原因

最后一步别省,否则容易在错的方向上折腾半天。以下几种情形,根子不在上下文构成:

/context 的 Memory files 里明明列着你的 CLAUDE.md,但指令没被遵守。 这不是加载问题。memory 页写明:CLAUDE.md 的内容是作为 system prompt 之后的一条 user message 送进去的,Claude 会读、会尽量遵守,但没有严格合规的保证,对含糊或互相冲突的指令尤其如此。文档给的分流很明确——要在固定时机无条件拦住一个动作,写 PreToolUse hook;要放到 system prompt 层,用 --append-system-prompt(每次调用都得传,更适合脚本与自动化)。

/compact 之后某条指令消失了。 如果它本来就只在对话里说过一次,或者住在子目录的 nested CLAUDE.md、住在 path-scoped rule 里,那是按设计不重新注入,不是被别的东西挤掉了。处置是把它写进 CLAUDE.md,而不是去砍 MCP 或 skills。

报了 Prompt is too long 那是另一条独立的线,触发条件与处置都不同,站内另有一篇专门讲,本文不展开。

你怀疑 Claude Code 对窗口大小判断得不对。 文档写明当模型 ID 来自 LLM gateway 别名或自定义 ID 时,可能会按错误的窗口来估算,并给出了单独一节讲怎么纠正。那是模型配置问题,不是构成问题。

auto memory 索引报错。 MEMORY.md 超过读取上限时,文档写明写入仍然成功,但会返回一个错误让 Claude 重写索引,因为超出部分下次加载时会被丢弃。这条与你装了多少 MCP、读了多少文件没有关系。

最后提醒一件确实会咬人的事:文档里多处带着”某个版本之前行为不同”的注记(例如 path-scoped rules 与 --setting-sources 的关系在 v2.1.211 前后不一样)。如果你观察到的行为和上面写的对不上,先看你手上的版本,再看官方文档那一页有没有对应的版本注记。这个产品迭代频繁,文中涉及的命令、配置项与默认值都以官方文档最新内容为准。


本文依据 Claude Code 官方文档(code.claude.com/docs)于 2026-08-17 的公开内容整理。 该产品闭源,本文只复述官方文档写明的机制,不推断其内部实现我们没有对文中涉及的功能做过实测,因此不涉及界面外观、操作手感与运行速度的任何描述。 该产品迭代频繁,文中涉及的命令、配置项与默认值随版本变动,请以官方文档最新内容为准。 本文不涉及价格、额度与限流的具体数值,相关信息请以官方定价与用量说明页为准。

安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。