Claude Code 会话和上下文:怎么接着上次干,什么时候该清空,什么时候该压缩
Claude Code 的对话存在本机,关掉终端也能接着干。本站实测了 --continue、--resume、给会话起名、/branch 开分支,以及 /clear 和 /compact 前后上下文占用的变化:读了四个文件后消息占 41k,压缩后降到 13.8k,并验证了压缩之后哪些细节还在、哪些没了。
本站已实测,测试日期:2026-10-12。
本页目录(13 节)
这篇教程解决两个连在一起的问题:一件事一次做不完,明天怎么接着干;聊得久了它开始变慢、跑偏、忘事,该怎么办。
前一个靠会话,后一个靠管好上下文。两样东西经常被混在一起,先分清:
- 会话是存在你电脑上的一段对话记录,跟着项目目录走。关掉终端它还在,可以恢复、改名、开分支。
- 上下文是每次请求实际发给模型的内容:系统提示词、工具说明、CLAUDE.md,再加上这段对话到现在为止的消息。它有上限,而且每多一点,之后的每次请求都要多带一点。
恢复会话,就是把存下来的对话重新装回上下文。清空和压缩,改的是上下文,存下来的记录不受影响。
下面的界面和数字都来自本站的实测。
| 实测环境 | |
|---|---|
| 日期 | 2026-10-12 |
| 版本 | Claude Code 2.1.296 |
| 系统 | Ubuntu 24.04 |
| 模型 | Opus 5.5,auto 模式 |
| 连接方式 | 通过酷站AI 中转站,不是直连官方 |
| 示例仓库 | Express 的源码,v5.3.0,带一份 CLAUDE.md,和前几篇是同一个 |
接着上次干
对话是边聊边存的,不需要你做什么。回来的入口有这几个,表来自官方文档:
| 命令 | 作用 |
|---|---|
claude --continue |
打开当前目录下最近的那个会话 |
claude --resume |
打开会话选择器,自己挑 |
claude --resume <名字> |
直接恢复叫这个名字的会话 |
claude --resume <会话 ID> |
按 ID 恢复,在哪个目录下运行都行 |
/resume |
已经在一个会话里,切到另一个 |
我们先起了一个带名字的会话,问了一个只读的问题:
claude -n send-content-type
❯ res.send() 是怎么决定响应的 Content-Type 的?分字符串、Buffer、对象三种情况说,
每种给出 lib/response.js 里的行号。只读代码,不要改任何文件。
它读了几段代码,给了带行号的回答。输入 /exit 退出,终端上留下一句提示:
Resume this session with:
claude --resume "send-content-type"
再运行 claude --continue,整段对话原样回到屏幕上,输入框上方还挂着会话的名字。为了确认它不只是把字显示出来,我们追问了一句,并且不许它再读文件:
❯ 不要再读文件。凭我们前面聊的,用一句话回答:res.send(null) 的 Content-Type 是什么?
● res.send(null) 不会设置 Content-Type:第 149–150 行只是把 null 换成空字符串,
不会调用 this.type() 或 res.json,所以响应里只有你之前自己设置过的 Content-Type,
没设置过就没有这个头。
答案里的行号是上一次读代码时得到的,说明上下文确实接上了。
恢复的时候,哪些会回来
按官方文档,恢复的会话带回来的有:完整的对话历史(包括工具调用和结果)、当时用的模型、还没到期的定时任务、还在进行的 /goal。在终端里用 --continue 或按名字、按 ID 恢复时,权限模式也会恢复成当时的;有一个例外,上次结束在 bypassPermissions 的不会自动回到这个模式。
不会回来的是启动时用参数临时加的东西:--mcp-config、--settings、--plugin-dir、--add-dir 加的目录。会话依赖它们的话,恢复时要再传一遍。写在 settings.json 里的配置每次启动都会重新读,不用管。
用 claude -p 跑的会话不在列表里
claude -p(不带界面运行)产生的会话,会话选择器和 claude --continue 都不列。这一点我们验证了:跑了一条 claude -p,记录目录里多了一个文件,选择器里没有它。
但按 ID 仍然能恢复,而且不限目录。我们换到另一个目录,用上面那个会话的 ID 问了一句:
cd ~/demo/a4-p
claude -p --resume 0aeaf9b4-ffa0-40c6-9618-9ee5cf8f117d "不要读文件,只凭记得的回答:lib/application.js 一共多少行?只回数字。"
631
ID 写错的话,它会直接报错并以状态码 1 退出:
No conversation found with session ID: 00000000-0000-4000-8000-000000000000
给会话起名字
同时做几件事的时候,名字比“最近的那个”可靠。起名的办法,按官方文档:
| 什么时候 | 怎么起 |
|---|---|
| 启动时 | claude -n auth-refactor |
| 会话进行中 | /rename auth-refactor |
| 在会话选择器里 | 选中一条,按 Ctrl+R |
不起名字的会话,Claude Code 会用一个后台请求给它生成一个标题,这个标题也能拿来 --resume。官方文档说这个请求用的是“小而快的模型”,通常是 Haiku 那一档。
会话选择器
运行 claude --resume 不带参数,或者在会话里输入 /resume:
Resume session
╭──────────────────────────────────────────────────────────────╮
│ ⌕ Search… │
╰──────────────────────────────────────────────────────────────╯
a5-express
❯ send-content-type
25 seconds ago · demo · 724.3KB
send-content-type
3 minutes ago · demo · 8.2KB
try-buffer-default
4 minutes ago · demo · 219.3KB
Ctrl+A to show all projects · Ctrl+B to only show current branch · Space to preview · Ctrl+R to rename · Type to search · Esc to cancel
每一条下面是:多久之前活动过、当时所在的 git 分支(这里是 demo)、记录文件的大小。常用的几个键:
| 按键 | 作用 |
|---|---|
↑ ↓ |
上下选 |
Enter |
恢复选中的会话 |
Space |
预览内容,不恢复 |
| 直接打字 | 搜索 |
Ctrl+R |
改名 |
Ctrl+B |
只看当前 git 分支上的会话 |
Ctrl+A |
看这台机器上所有项目的会话 |
按 Space 预览我们试了,能看到那个会话最后的几轮对话,每条回复旁边还标着时间和模型。
一个容易踩的地方:重名
上面的列表里有两条都叫 send-content-type。原因是我们中途用了一次 /clear:它开了一个新会话,而新会话沿用了原来的名字。
重名之后,按名字恢复就不再直接进去了。运行 claude --resume send-content-type,出来的是选择器,搜索框里预先填好了这个名字,要你自己挑:
│ ⌕ send-content-type │
send-content-type
1 minute ago · demo · 724.3KB
send-content-type
4 minutes ago · demo · 8.2KB
这和官方文档的说法一致:名字只对上一个会话时直接恢复,对上多个时打开选择器。文档还给了一个避免重名的写法:/clear 后面带一个名字,比如 /clear release-prep,这个名字会留给你离开的那个会话,新会话不带名字。这个写法我们没有试。
想试另一条路:/branch
事情做到一半,想换个思路试试,又不想把现在这条线弄乱,就开一个分支。它把到目前为止的对话复制一份,你进到副本里,原来的会话原样留着。
❯ /branch try-buffer-default
⎿ Branched conversation "try-buffer-default". You are now in the new branch
(session b053db6a-6057-4433-bd7e-3c42a5c6ec6c). Use /resume
0aeaf9b4-ffa0-40c6-9618-9ee5cf8f117d ("send-content-type") to return to the
original, or run claude -r 0aeaf9b4-ffa0-40c6-9618-9ee5cf8f117d in a new terminal.
输入框上方的名字跟着变成了 try-buffer-default。我们在分支里问了一句,然后用 /resume send-content-type 回到原来的会话:屏幕上的对话停在开分支之前,分支里问的那句不在里面。
要注意两点:
- 分支只复制对话,不复制代码。 两个会话面对的是同一份工作目录。分支里让它改了文件,回到原会话,文件还是改过的样子。想让代码也各走各的,用 worktree。
- 不要不开分支就在两个终端里恢复同一个会话。 官方文档说明,那样两边的消息会混着写进同一份记录。
命令行里对应的写法是 claude --continue --fork-session,这个我们没有试。
上下文里现在有什么:/context
问完第一个问题之后,输入 /context:
Opus 5.5
claude-opus-5-5
37k/1m tokens (4%)
Estimated usage by category
⛁ System prompt: 2.6k tokens (0.3%)
⛁ System tools: 20.8k tokens (2.1%)
⛁ Memory files: 2.4k tokens (0.2%)
⛁ Skills: 2k tokens (0.2%)
⛁ Messages: 9.2k tokens (0.9%)
⛶ Free space: 930k (93.0%)
⛝ Autocompact buffer: 33k tokens (3.3%)
Auto-compact window: 1m tokens
Memory files · /memory
└ CLAUDE.md: 2.4k tokens
读法:
- 前四项是一开口就有的固定开销,合计约 28k:系统提示词、工具说明、CLAUDE.md、skill 的简介。你还没说话,它们已经在了。
- Messages 是这段对话本身:你的话、它的回答、它读过的文件、跑过的命令的输出。会涨的就是这一项。
- Auto-compact window 是自动压缩的参照窗口。这里是 1M,所以 37k 只占 4%。
输出的下半部分还会逐个列出加载了哪些记忆文件和 skill,各占多少。想知道 CLAUDE.md 是不是太长了,看这里最直接。
换一件事就清空:/clear
输入 /clear,屏幕清空,再看 /context:
| 清空前 | 清空后 | |
|---|---|---|
| 合计 | 37k | 27.9k |
| Messages | 9.2k | 106 |
固定开销还在,对话没了。
清掉的对话并没有丢,它作为一个会话存着。除了用 /resume 找回来,还有一个更快的入口:输入框为空时连按两次 Esc 打开回退菜单,最上面多出一条“上一个会话”。
Rewind
Restore the code and/or conversation to the point before…
❯ /resume 0aeaf9b4-ffa0-40c6-9618-9ee5cf8f117d (previous session)
(current)
选它回车,清空之前的对话就回来了。官方文档说明,这一条只在同一次运行里有效,退出 Claude Code 或者恢复了别的会话之后就没有了。
什么时候该清,官方的最佳实践说得很直接:
- 换一件不相干的事,先清。 上一件事留下的内容会挤占位置,还会让它分心。
- 同一个问题纠正了两次还不对,清掉重来。 这时上下文里堆的都是失败的尝试。带着你新了解到的情况,重新写一条更具体的提示词,通常比接着纠正快。
事没做完但上下文太满:/compact
/compact 把对话历史换成一份摘要,会话不变,可以接着干。
为了看出效果,我们先让它把四个文件完整读一遍,把上下文撑大,然后不带任何要求直接压缩:
❯ /compact
⎿ Compacted (ctrl+o to see full summary)
⎿ Referenced file lib/request.js
⎿ Referenced file lib/application.js
⎿ Referenced file lib/response.js
⎿ Read lib/utils.js (272 lines)
| 读完四个文件 | 压缩后 | |
|---|---|---|
| 合计 | 68.8k | 41.6k |
| Messages | 41k | 13.8k |
压缩之后,它还记得什么
最后四行输出是关键。官方文档的说法是:压缩完,Claude Code 会把这个会话里读过或改过的文件重新读回来,最多五个,最近修改的优先;超过 5,000 token 的文件只留一个路径,不带内容,显示成 Referenced file。
四个文件里只有 lib/utils.js 够小,被整个放了回来,另外三个只剩路径。我们马上问了一个需要细节的问题来验证,并且不许它读文件:
❯ 不要读文件、不要跑命令,只凭你现在记得的:lib/utils.js 里 setCharset 函数的完整代码是什么?
lib/application.js 一共多少行?记不清就直说记不清。
● setCharset:这个我能完整给出。压缩后系统把 lib/utils.js 的全文重新放回了上下文,
代码在第 225–238 行:
(完整代码略)
lib/application.js:631 行。这个数字来自压缩摘要,application.js 的内容已经不在
上下文里了。如果要确认,需要重新读一遍文件。
结论进了摘要,所以行数还在;文件内容没进摘要,所以没了。压缩之后如果它开始重新读之前读过的文件,原因就在这里。
其他东西压缩后的去向,按官方文档整理:
| 内容 | 压缩之后 |
|---|---|
| 系统提示词 | 照常生效 |
项目根目录的 CLAUDE.md、不带 paths 的规则、自动记忆 |
从磁盘重新读入 |
| plan 模式下写的计划 | 从磁盘重新读入 |
带 paths 的规则、子目录里的 CLAUDE.md |
被摘要带走,等下次碰到对应的文件再加载 |
| 用过的 skill 的正文 | 重新放回,每个最多 5,000 token,总共最多 25,000 |
| 后台的命令和子代理 | 继续跑 |
| 你在对话里口头交代的要求 | 进摘要,细节可能丢 |
最后一行最要紧。一定要一直生效的规矩,写进 CLAUDE.md,不要指望它在对话里记一路。
带一句要求再压缩
可以告诉它摘要里留什么:
/compact 只保留 res.send 判定 Content-Type 的结论和对应的行号,读文件的过程不用留
这一条我们是在会话还很小的时候试的,Messages 从 12.8k 降到 9.3k,省得不多。对话本来就短的时候,压缩没什么可压的。
官方文档还给了两个办法,我们没有试:
- 在 CLAUDE.md 里写一段压缩时的要求,比如“压缩时始终保留改过的文件清单和测试命令”。自动压缩也会照着做。
- 只压缩一部分:在回退菜单里选中某一条消息,选 Summarize from here(把这之后的压成摘要)或 Summarize up to here(把这之前的压成摘要)。
自动压缩
上下文快满的时候,Claude Code 会自己压缩,不会因为满了就中断。自动的这一次和手动的 /compact 是同一套做法,区别只是留什么由它猜。
在我们的环境里,窗口是 1M,一个下午的实测远远碰不到。但没满不等于没代价:对话里的每一个 token,之后的每次请求都要再带一遍。长会话越聊越贵,原因在这里,细节见怎么省用量。
通过中转站用的读者要多留意一件事:有的网关设的上限比模型原生的窗口小。这种情况下 Claude Code 以为还没满,网关已经拒绝了。怎么处理见通过中转站用 Claude Code里“常见报错”那一节。
顺手问一句,不占上下文:/btw
有些问题只要一句话的答案,不值得留在对话里。/btw 的问答不进对话历史,回答显示在一个浮层里,按 Esc 关掉。
它有一个限制,我们一试就碰到了:
/btw mime-types 这个包在 package.json 里要求的版本是多少?
这个我答不了。这次对话里没读过 package.json,我只知道 lib/utils.js 第 18 行
require('mime-types') 用到了这个包,不知道它要求哪个版本。这里是旁支提问,
没法读文件,请在主对话里让我看一下 package.json 的 dependencies。
/btw 不能用工具,只能凭上下文里已有的内容回答。适合问“刚才那个配置文件叫什么”“它前面为什么选了这个方案”,不适合问要去查的事。
记录存在哪,怎么导出
会话记录是 JSONL 文件,按项目目录分开放:
~/.claude/projects/-home-ccdemo-demo-a5-express/
├── 0aeaf9b4-ffa0-40c6-9618-9ee5cf8f117d.jsonl 原来的会话
├── b053db6a-6057-4433-bd7e-3c42a5c6ec6c.jsonl /branch 出来的分支
├── 02d3560e-6dc7-4aba-8e6c-89c3ead549ec.jsonl /clear 之后的新会话
├── bb0c3aed-a375-4e1f-8483-00e9711744af.jsonl claude -p 跑的那一条
└── memory/
目录名是工作目录的路径,把字母数字以外的字符换成了 -。几点说明,来自官方文档:
- 默认保留 30 天,到期自动清理。要改,在
settings.json里设cleanupPeriodDays。 - 不要直接解析这些文件。 格式是 Claude Code 内部用的,版本之间会变。脚本要用会话的内容,走
claude -p --resume <ID> --output-format json。 - 记录里有你和它说过的所有内容,包括它读过的文件。 这个目录不要随手分享。
要一份给人看的文本,用 /export:
❯ /export a5-session.txt
⎿ Conversation exported to: /home/ccdemo/demo/a5-express/a5-session.txt
有一点要留意:我们是在压缩之后导出的,文件里没有压缩之前的那段问答,开头就是一行 Conversation compacted。压缩前的原始消息还在 JSONL 记录里。想导出完整的对话,在压缩之前导。
什么时候用哪个
| 你的情况 | 做法 |
|---|---|
| 明天接着干 | 起个名字,回来用 claude --resume <名字> |
| 刚关掉,马上接着干 | claude --continue |
| 换一件不相干的事 | /clear |
| 同一个问题纠正两次还不对 | /clear,重写一条更具体的提示词 |
| 事没做完,但读过的东西太多 | /compact,带上一句要留什么 |
| 想试另一种做法,又不想丢掉现在的 | /branch |
| 一个只要一句话答案的小问题 | /btw |
| 要读一大堆文件的调查 | 交给子代理,文件内容留在它那边 |
| 改坏了想退回去 | 回退菜单,见权限模式那一篇 |
这一趟花了多少
主会话恢复之后看 /cost,显示的是累计数:1.24 美元,模型工作 1 分 56 秒。它包括读四个文件和两次压缩。这是 Claude Code 按官方价格估算的数字,不是中转站实际扣的金额。
恢复会话之后 /cost 接着之前的数往上加,这一点是这次顺带看到的。
这次实测没有覆盖到的
- 自动压缩没有触发。 窗口是 1M,实测用量最高到 68.8k。自动压缩的表现按官方文档写的。
--fork-session、/clear <名字>、回退菜单里的两个 Summarize 选项、CLAUDE.md 里的压缩要求没有试。- 自动生成的会话标题没有观察。 我们的会话都是自己起的名字。这把 key 调不了 Haiku 5.5,生成标题的后台请求在这种情况下会怎样,没有查。
- “从摘要恢复”的对话框没有出现。 官方文档说它只在 Pro 或 Max 订阅上、会话搁置一小时以上且超过 100,000 token 时才弹。
--from-pr、后台会话、跨 worktree 的会话列表没有试。- VS Code 扩展和桌面应用各有自己的会话列表,这篇只讲命令行。
- 只跑了一次。 压缩后哪些文件被放回来,取决于文件大小和修改时间,换一个项目结果会不同。
下一步
- 系列的下一篇:怎么省用量。
- 上下文里的固定开销由什么决定:CLAUDE.md、skill、hook、子代理、MCP、插件各管什么。
- 几件事同时做:用 worktree 同时开两个会话。