Claude Code 会话恢复后丢失先前工作记忆 —— 排查与修复

恢复 Claude Code 会话却像全新开始 —— 计划没了、决定没了、未完成的重构也没了。从压缩、对话链断裂、临时工具结果三方面定位并修复。

合上电脑。第二天 claude --continue(或 claude --resume)把会话重新打开。看上去还是同一段对话 —— 工具调用历史看得见,计划也在。但你刚说”继续”,Claude 就问这是什么项目、把昨天读过的文件重新读一遍、把你下午 5 点明确否决的设计又重新提一次。恢复给的是”看上去连续”,不是”实际连续”。

最快的修复(90 秒): 在你打”继续”之前,先粘贴一条简短的”当前状态”消息,写清楚项目、已经做出的决定、相关文件、下一步具体动作。重新给当前上下文打底,永远比跟恢复机制硬碰硬更省事。本文剩下的部分解释记忆为什么会消失,以及怎样让状态可靠地扛过一次关开。

底层上:每次恢复一定能保住的是磁盘上那份可见的对话记录。不一定能保住的,是模型的工作上下文 —— 隐式摘要、完整的工具结果字节、推导出来的决策。这些在重新打开时都从对话记录里重建,而重建是有损的。

你属于哪一类?

恢复时的症状最可能的原因跳到
历史里出现 Compacted / 被摘要的轮次,具体决策不见了自动压缩把细节丢了原因 1
Claude 立刻重读昨天读过的文件工具结果没重新注入原因 2
只载入最后几条消息,更早的历史够不到.jsonlparentUuid 链断了原因 3
恢复卡住、一直加载不完会话文件里有超大工具结果行原因 3
行为变了(测试命令、包管理器不一样)两次会话之间改了 CLAUDE.md / settings原因 4
昨天能用的路径报 “File not found”从不同的工作目录恢复原因 5
一段深度子代理结论现在只剩一句话子代理 / Task 结果是临时的,又被压缩原因 6
--resume <id> 报 “No conversation found”cwd 不对,或文件过 30 天被清掉原因 7

常见原因

按影响排序。

1. 自动压缩把工作上下文丢了

长会话会被压缩。截至 2026 年 6 月,自动压缩在 token 用量到达约 98% 的有效上下文窗口时触发:Claude Code 先清掉较早的工具输出,再把较早的对话摘要成一份精简历史,并以这份摘要为起点开一段新上下文。细节就这么丢了 —— “我们决定不用 Redis”可能塌缩成一句话备注,也可能整条掉出去。

怎么判断:会话中途跑 /context 看是什么在占空间;发生过自动压缩的会话,对话记录顶部会出现一段摘要块,而不是原始轮次。你记得做过的决策在可见历史里找不到。

2. 恢复重新注入的是消息文本,不是完整工具结果字节

工具结果块(文件内容、命令输出)是对话记录里最占体积的部分。重新打开时,Claude 从文本里知道自己”读过 foo.ts”,但当前上下文不一定再次持有 foo.ts 的字节 —— 大体量输出可能被存到行外、不再载回工作记忆。

怎么判断:Claude 立刻重读昨天读过的同一批文件;尽管可见历史还显示着旧的读取,token / 缓存计数却从头算起。

3. .jsonl 对话链断裂或过大

会话以 JSONL 存储,每一行通过 parentUuid 指向它的父节点。恢复时从最后一条消息沿这条链往回走。链一旦断裂(有一类已知 bug:file-history-snapshotmessageId 跟真实消息的 uuid 撞了),恢复就只能载入最近几条消息,其余历史虽然还在文件里却够不到。另外,如果某个工具结果被以完整体积(几 MB)写进了 .jsonl,恢复可能在加载它时无限卡住。

怎么判断:恢复后只有最后几轮,或者恢复永远走不完。用 wc -c 看文件大小(见下);一份对话记录里有一两行几 MB 的,就是卡死的特征。

4. 两次会话之间 CLAUDE.md 或 settings 改了

如果你在两次会话之间改了 CLAUDE.md.claude/settings.json,恢复出的对话记录仍反映旧规则,而系统提示载入的是新规则。行为就不一致。

怎么判断:与关机前行为不同 —— 包管理器换了、测试命令换了等等。

5. 恢复时工作目录变了

会话按项目目录存储与查找(用绝对路径的哈希作键)。cwd 决定哪份 CLAUDE.md、哪个 .claude/、哪些相对路径有效。从不同的 shell 位置恢复,记录里的相对路径就不再指向同一批文件;在别处创建的会话 ID,在这里甚至根本找不到。

怎么判断:昨天能用的路径今天 Claude 说 “file not found”,或者 claude --resume <id>No conversation found with session ID

6. 子代理 / Task 结果本就是临时的

Task 工具子代理在运行时把结果返回进父对话。父对话一被压缩,子代理的发现就塌缩成一句话。原始细节不可恢复。

怎么判断:你记得某次子代理跑出来的深度调研结论;恢复后只剩一句简短提及。

7. 会话文件过期或你升级了 Claude Code

本地对话记录默认 30 天后删除(cleanupPeriodDays)。Claude Code 升级后,旧会话文件也可能部分不兼容 —— 技术上 resume 成功,但部分字段加载失败。

怎么判断:上周还能 --resume <id> 的会话现在报找不到,文件已从 ~/.claude/projects/ 消失,或者你中间升级了 Claude Code。

开始前

  • 看两次会话之间隔了多久;越久压缩风险越大(文件也可能已经过了 30 天被清掉)。
  • 找一个具体的”丢失记忆”样例 —— 某条本应延续的决定或任务。
  • 看你在上一次会话之后是否升级了 Claude Code,或改了 CLAUDE.md / settings。
  • 想清楚你真正要什么:完整的状态延续,还是够用就行?

需要收集的信息

  • 会话文件。对话记录在 ~/.claude/projects/<project>/<session-id>.jsonl,其中 <project> 由你的工作目录路径推导而来。(若设了 CLAUDE_CONFIG_DIR,去那里找。)
  • 会话文件大小:wc -c ~/.claude/projects/<project>/<session-id>.jsonl。单行几 MB 指向原因 3。
  • 是否发生过压缩:在对话记录里搜 compact 或摘要块,或在活跃会话里跑 /context
  • 现在的 Claude Code 版本 vs 原会话开始时的版本(claude --version)。
  • 任何应当配套的外部状态文件(PLAN.md、会话笔记、agent.log)。

一步步修复

按 ROI 排序 —— 最便宜的先做。

第 1 步:用一条”当前状态”消息重新打底

任何 resume 都适用的最佳 90 秒解法。在你说”继续”之前粘贴:

Quick context dump before we continue:

Project: <name>
Goal of this session: <goal>
Where we left off: <specific step or file>
Decisions already made (do not re-propose):
- <decision 1>
- <decision 2>
Files in scope: <list>
Next concrete step: <action>

花 60 秒,省下一小时的重新推导。

第 2 步:动手前先让 Claude 读对的文件

主动重读关键文件,把它们的完整字节塞进当前上下文(修复原因 2):

Read these files to refresh context:
- src/auth/login.ts (the one we are refactoring)
- src/auth/login.test.ts (the test we are keeping green)
- docs/architecture.md (the constraints)
Then summarize back to me what you understand. Do not act until I confirm.

这样把完整内容塞进上下文窗口,而不只是”我昨天读过”的摘要。

第 3 步:从正确的 cwd 恢复

会话按项目目录解析,所以目录必须跟原会话一致(修复原因 5):

cd ~/projects/myrepo
claude --resume <session-id>

选对入口:

命令作用
claude --continue(-c)恢复当前目录里最近的那个会话
claude --resume(-r)打开交互式会话选择器
claude --resume <name>直接恢复指定名字 / ID 的会话
claude --from-pr <number>恢复关联到某个 PR 的会话
/resume(会话内)不退出当前会话就切到另一段对话

确认 Claude 在你以为的位置:

What is your current working directory? Print it.

如果 --resume <id>No conversation found with session ID,说明你在错误的目录(或文件已过 30 天)。在选择器里,Ctrl+W 扩到仓库的所有 worktree,Ctrl+A 扩到本机所有项目。

第 4 步:重新同步当前 CLAUDE.md

恢复后,强制重新读一遍,让两次会话之间的改动生效(修复原因 4):

Please re-read CLAUDE.md from disk and acknowledge any changes since the last loaded version. Treat the current file as authoritative.

第 5 步:在仓库里维护一份会话状态文件

留一份 .claude/session-notes.md(或类似),记录决策、待解决问题、当前步骤。每天关之前更新它。下次恢复:

Read .claude/session-notes.md and recap to me before doing anything else.

这份文件存在于对话之外,因此能跨过压缩存活 —— 是这里最耐久的修复。

第 6 步:文件损坏或卡死,就分叉或重开

如果只载入最后几轮,或恢复卡住(原因 3),别再跟那份 .jsonl 死磕:

  • 趁会话还部分加载着,跑 /export 把能抢救的内容存成文本文件,然后开新会话、喂给它你的笔记。
  • 如果原会话只是体积大但没损坏,用 /branch(或 claude --continue --fork-session)分叉出一份干净副本。
  • 如果文件有几 MB、带着巨大的工具结果行,直接放弃它;在新的 claude 会话里用 PLAN.md 和笔记重建上下文。

第 7 步:接受 resume 有边界;大动作开新会话

跨多天的工作,别指望 resume 扛过 1-2 次关开循环。改用这套流程:

  1. 每天结束写一份”当前状态”笔记进仓库(并提交在制品)。
  2. 第二天用 claude(不用 --resume)开新会话。
  3. 开场一句”Read .claude/session-notes.md and continue”。

新会话有干净的上下文窗口、没有压缩历史负债。

第 8 步:超长项目,把计划外化

仓库里搞一份 PLAN.md:

# Refactor auth to async/await

## Completed
- [x] login.ts converted
- [x] signup.ts converted
- [x] login.test.ts updated

## In progress
- [ ] reset-password.ts (started, partial)

## Not started
- [ ] sso.ts
- [ ] mfa.ts

## Decisions
- Using axios for HTTP, not fetch (team preference)
- No new dependencies allowed

计划不存在对话里,存在 git 里,每次会话都读它。

怎么确认已修复

  • 新一次恢复 + 重新打底之后,让 Claude 复述当前步骤和决策,跟你写下的核对。
  • 跑下一步具体动作,确认它没重做已完成的工作、没在没被要求时重读文件。
  • /context,确认关键文件和笔记真的在窗口里,而不是只被提到。
  • 打开会话文件,确认大小合理(没有单行几 MB)。
  • 用 1-2 天对比”一直续 resume”和”新会话+笔记”,大多数场景后者赢。

长期预防

  • 状态外化。任何需要存活超过 24 小时的东西都该在仓库的文件里,而不是对话里。
  • 把 resume 当作一日工具。跨天工作直接靠笔记重启。
  • 给会话命名(claude -n auth-refactor,或会话内 /rename),这样能按名字找回、按名字恢复,不用翻 ID。
  • CLAUDE.mdPLAN.md 随用随改,不要等到一天结束才更新。
  • 关键决定在对话里加显式标记(DECISION: using axios, not fetch),压缩中更容易保留。
  • 一天结束前提交在制品;diff 本身也是一种记忆辅助。
  • 相关上下文丢失模式见 Claude Code 上下文损坏Claude Code 输出被上下文截断
  • 定期审计 ~/.claude/projects/,从旧文件恢复比新开更麻烦,而且它们 30 天后本来也会自动删除(cleanupPeriodDays)。

常见坑

  • 相信恢复会”完整记忆地”接着上次 —— 不会。
  • 把整套计划放对话里(“这是 30 个步骤”),而不是放文件里。
  • 恢复后立刻甩一句模糊指令(“继续”) —— 压缩之后 Claude 压根不知道这是什么意思。
  • 两次会话之间改了 CLAUDE.md,但没让恢复出来的 Claude 重读。
  • 把子代理结论当作持久信息;它们不是。
  • --resume 前忘了 cd 到正确目录;cwd 解析规则见 Claude Code 项目 CLAUDE.md 未加载
  • 以为 /rewind 能撤销一切 —— 它会把对话和 Claude 的文件修改回滚到某个检查点,但撤销不了 bash 的副作用(删掉的文件、装上的包、推出去的提交)。
  • 工作日中间升级了 Claude Code,然后周一发现周五的会话恢复不干净。

FAQ

Q: Claude Code 的会话到底存在哪?

存成 JSONL 文件,路径是 ~/.claude/projects/<project>/<session-id>.jsonl,其中 <project> 由工作目录路径推导。设 CLAUDE_CONFIG_DIR 可整体迁移 ~/.claude 目录树。文件默认 30 天后删除,用 settings 里的 cleanupPeriodDays 改。

Q: --continue--resume 有什么区别?

claude --continue(-c)无提示地重开当前目录里最近的会话。claude --resume(-r)打开选择器,或在你传名字 / ID 时恢复指定会话。在运行中的会话里,/resume 不退出就切换对话。

Q: 有没有设置可以关掉压缩?

没有。长会话能存在,就是因为有压缩(它在约 98% 上下文窗口处启动)。修复思路是把需要存活的部分外化,而不是跟压缩对抗。用 /compact <instructions> 引导它保留什么,或在一段话题结束后用 /clear 重新开始。

Q: 为什么恢复只载入最后几条消息,或者一直卡住?

几乎总是 .jsonl 损坏:断裂的 parentUuid 链让加载器走几条就停,而一行巨大的工具结果(几 MB)会让加载卡死。用 wc -c 看看文件。用 /export 抢救,然后在新会话里用笔记重建上下文。

Q: 一个会话现实里能跑多久 resume 才不可靠?

我们的经验:活跃使用 8-12 小时,或约 3 次关开循环。超出之后,新会话+笔记更可靠。

Q: 为什么 Claude 会问我昨天就答过的问题?

答案被压缩掉了。要么在新轮次再答一次,要么先从笔记里把答案捞出来再让 Claude 继续。

标签: #Claude Code #session #memory #排查 #context