造壳 MkShell
/ #agent #Codex #工作流

Codex session 太长怎么办?用交接文件把任务迁移到新 chat

从 resume、fork、compact 与新 chat 的差异出发,介绍怎样把目标、决策、进度和验证结果落到仓库文件,让 Codex 在不继承旧聊天历史的情况下继续长期任务。

我最近遇到一个问题:Codex 里的 session 越来越长,执行时也显得越来越重。但是任务本身还没有结束,旧 session 里又积累了不少决策和进度,直接新开一个似乎会“失忆”。

我的任务主要靠两样东西维持:一个是 /goal,另一个是本地的 项目目标与进度基线.md。问题就变成了:怎样换到一个更干净的 session,同时又不丢掉真正有用的信息?

先说结论:

不要迁移完整聊天历史,而要迁移已经确认的事实、决策、进度、验证结果和下一步。

具体做法是:让旧 session 生成一份可复查的交接文件,更新项目进度基线,然后新建一个完全独立的 chat,由它从仓库文件恢复现场。这样迁移的是项目状态,而不是旧模型的全部思考过程。

#先分清 session、chat 和几种“继续”

为了方便,本文仍把一段长期对话称为 session。当前官方文档在桌面应用里主要使用 chat,CLI 的命令说明里仍能看到 session。它们在本文讨论的工作流里都指向同一个问题:Codex 下一轮工作要从哪里恢复上下文。

resumefork/compact 和新 chat 看起来都能解决“对话太长”,但它们保留的东西并不一样。

操作对原聊天历史的处理适合什么不适合什么
resume重新加载原 session,保留原有历史中断后继续同一条工作链想摆脱旧 transcript 的负担
fork把当前或已有 chat 复制到一个新 chat保留现场,尝试另一种方案只想迁移结论,不想复制历史
/compact用摘要替换较早的上下文,释放窗口长任务中途临时整理上下文彻底摆脱旧 session
新 chat不执行恢复或复制,从新的聊天上下文开始通过仓库文件重新接手任务依赖旧聊天里尚未落盘的信息
/goal把持久目标附着在当前 chat 上有明确终点和验证循环的长任务代替跨 chat 的项目状态文件

官方的 Developer commands 对这些边界写得很清楚:resume 会恢复保存的聊天并保留原历史,fork 会克隆当前聊天,/compact 则把早期内容替换成摘要。桌面应用里的 /fork/compact/goal 可以在 Slash commands 中确认。

所以,如果目标只是“刚才断了,接着干”,用 resume 没问题;如果想保留现有上下文,探索另一条实现路径,用 fork;如果上下文只是暂时吃紧,可以先 /compact。但如果旧聊天已经长到想真正重新开始,新 chat 才是最干净的入口。

在桌面应用中,可以点击 New chat,也可以使用 Cmd/Ctrl + NCmd/Ctrl + Shift + O。当前快捷键以官方的 桌面端命令文档 为准。

#新 chat 为什么还能接上旧任务

因为一个长期项目真正需要继承的,并不是聊天的每一句话。

旧 session 里通常混着四类内容:

  1. 已经确认的目标、约束和设计决策;
  2. 当前代码、工作区和测试结果;
  3. 搜索过程、失败尝试和临时推理;
  4. 已经被后续结论取代的旧计划。

新 session 真正需要的是前两类,以及第三类中仍然会影响下一步的部分。至于几十次搜索命中、重复解释和已经放弃的方案,继续携带反而会让接手者分不清什么才是当前事实。

这和工程里的交接班很像。下一班不需要重看整晚的监控录像,但必须知道事故是否结束、排除了哪些原因、哪些操作已经验证,以及下一步应该观察什么。

因此,仓库需要承担一部分“外部记忆”。

#把长期状态分成四层

我会把长期任务的状态拆成下面四层:

文件保存什么更新频率
AGENTS.md仓库级稳定规则、命令、安全边界和验收要求规则真正变化时
项目目标与进度基线.md当前目标、checkpoint、已完成事项、待办和风险每个重要 checkpoint
docs/agent-handoffs/LATEST.md上一个 session 留给下一个 session 的压缩交接每次迁移 session 前
PLANS.md阶段计划、里程碑和较长的实施拆解计划变化时

这里最容易犯的错误,是把所有内容都塞进 AGENTS.md。它适合保存稳定规则,不适合记录“今天改到哪了”。官方的 AGENTS.md 文档 也把它定位为持久的项目指令,并支持从仓库根目录到子目录逐层覆盖。

换句话说:

  • AGENTS.md 回答“在这个仓库里应该怎样工作”;
  • 进度基线回答“这个项目现在走到哪里”;
  • handoff 回答“上一个 session 刚做完什么、接下来先看什么”;
  • PLANS.md 回答“这一阶段准备怎样完成”。

职责分开之后,新 session 不需要猜哪段信息是否过期。

#第一步:让旧 session 只做交接

准备迁移时,不要再让旧 session 顺手多修一个问题。它最后的任务应该是核对现场和生成交接。

下面这段提示词可以直接使用:

请只做 session 交接,不要继续实现业务功能。

目标:把当前 session 中仍然有效的上下文压缩并落到仓库文件,
让一个不读取旧聊天历史的新 Codex chat 可以继续工作。

请先读取并核对:

- AGENTS.md,以及当前目录下可能生效的嵌套 AGENTS.md
- 项目目标与进度基线.md
- PLANS.md(如果存在)
- 本轮实际修改过的相关文件
- git status --short
- git branch --show-current

然后:

1. 创建或更新 docs/agent-handoffs/LATEST.md;
2. 更新 项目目标与进度基线.md 中的当前目标和 checkpoint;
3. 不要修改业务代码。

交接文件必须包含:

- 本轮 session 的目标;
- 已确认的关键设计决策及理由;
- 已修改文件和当前工作区状态;
- 已完成事项与未完成事项;
- 已运行的验证命令及结果;
- 尚未运行的验证;
- 阻塞、风险和证据缺口;
- 已经否定、不要重复尝试的方案;
- 下一位 agent 启动后的第一步;
- 需要优先阅读的文件。

完成后只汇报更新了哪些状态文件,不要继续开发。

这份提示词有两个关键点。

第一,交接前先读 Git 状态和实际文件,而不是只凭聊天记忆写总结。聊天里可能还说着“准备修改”,但工作区中可能已经改完,也可能根本没有落盘。

第二,要求记录“不要重复做的事”。一个失败方案如果只存在于旧聊天里,新 session 很可能会再走一遍。

#第二步:检查交接是否能独立成立

交接文件不是“旧 session 的总结作文”,而是新 session 的启动输入。至少要能回答下面几个问题:

  • 当前唯一目标是什么?
  • 到什么状态才算完成?
  • 哪些结论已经被代码、命令或文档验证?
  • 工作区有没有未提交修改?
  • 下一步应该读哪个文件、执行哪个命令?
  • 哪些操作有风险,必须先停下来确认?

如果 handoff 里写的是“继续完成之前讨论的方案”,这份交接就失败了。新 session 没有“之前”。

更好的写法是:

## 当前 checkpoint

认证中间件已经切换到新的 token 校验入口,但刷新流程尚未迁移。

## 已验证

- `pnpm test auth` 通过;
- 登录和过期 token 用例通过;
- 尚未运行完整构建。

## 下一步

先阅读 `src/auth/refresh.ts` 和对应测试,确认刷新 token 是否仍调用旧入口。
完成修改后运行 `pnpm test auth``pnpm build`

即使完全看不到旧对话,这段信息也能让下一位 agent 开始工作。

#第三步:用新 chat 恢复现场

确认交接已经落盘后,再创建新 chat。不要 resume,也不要从旧聊天 fork,因为这两种操作的目的本来就是保留原现场。

新 chat 的第一条消息可以这样写:

请接手当前仓库任务,但不要依赖任何旧聊天历史。

开始工作前必须读取:

1. AGENTS.md,以及当前任务目录下可能生效的嵌套 AGENTS.md;
2. 项目目标与进度基线.md;
3. docs/agent-handoffs/LATEST.md;
4. PLANS.md(如果存在)。

然后执行只读检查:

- git status --short
- git branch --show-current
- 阅读 handoff 指向的相关文件

先总结你恢复出的:

- 当前目标和完成条件;
- 已完成事项;
- 当前 checkpoint;
- 未完成事项与下一步;
- 工作区状态;
- 风险、阻塞和未运行的验证。

如果文件之间冲突,不要自行拼凑结论。指出冲突、文件日期和 Git 证据,
再给出你建议采用的基线。

多步任务先进入 plan mode。确认计划前不要修改业务文件。

这里故意要求先做只读检查。新 session 的第一反应不应该是“根据摘要继续写代码”,而是确认摘要和仓库当前状态仍然一致。

#第四步:在新 chat 重新建立 goal

/goal 很适合有明确终点、验证循环和停止条件的长期任务。官方的 Goal mode 指南 建议在目标里说明要先读取的文件、怎样验证进度,以及什么时候停止。

/goal 是当前 chat 的持久目标,不是整个仓库的项目数据库。换了新 chat,先恢复文件状态,再重新设置目标:

/goal 基于 `项目目标与进度基线.md`
`docs/agent-handoffs/LATEST.md` 继续推进当前任务。

每个 checkpoint 后:

1. 更新进度基线;
2. 运行文件中约定的验证命令;
3. 记录通过、失败和未运行的检查;
4. 遇到目标冲突、破坏性操作或缺少关键输入时暂停。

当进度基线中的完成条件全部满足,并且要求的验证通过后停止。

如果目标本身还没有收敛,可以先用 /plan 把范围和验收条件谈清楚,再设置 /goal。当前桌面应用的 Slash commands 文档也把这条路径作为推荐用法。

#把迁移变成固定循环

一次迁移不难,难的是半年后仍然知道哪个文件可信。可以把日常工作固定成下面的循环:

读取规则与进度基线

执行当前 checkpoint

运行验证并记录结果

更新进度基线

需要换 chat 时生成 handoff

新 chat 重新读取并核对仓库

每个 checkpoint 不必写成长篇日报。有效的进度记录只需要说明:做了什么、证据是什么、还剩什么、下一步是什么。

LATEST.md 也不必无限增长。它表示最近一次交接,历史交接可以按日期归档,例如:

docs/
  agent-handoffs/
    LATEST.md
    2026-07-28-codex-session-handoff.md

如果项目没有长期追溯需求,只保留 LATEST.md 也可以。关键不是文件数量,而是新 session 能找到唯一、明确且足够新的入口。

#什么时候不需要这样做

这套方法不是每次对话都要执行。

如果只是关掉终端后继续昨天的同一个任务,resume 更直接;如果要保留当前上下文,验证一个替代设计,fork 更合适;如果聊天仍然可靠,只是上下文窗口暂时紧张,先 /compact 就够了。

只有当你明确想摆脱旧 transcript,同时项目又不能从头开始时,才值得做“交接落盘 → 新 chat 恢复”。

还要注意:本文没有证明新 chat 一定能带来多少 CPU、内存或响应时间改善。它能确定减少的是继承的聊天历史,并把长期状态变成可检查的仓库文件。至于实际性能,还会受到模型、工具调用、仓库规模和当前应用版本影响。

#总结

长 session 的问题,不只是上下文太多,更重要的是项目状态和聊天历史混在了一起。

resume 负责继续原 session,fork 负责复制现场探索分支,/compact 负责在原聊天里压缩上下文。它们都有用,但都不是“只带结论重新开始”。

真正可持续的做法,是把稳定规则放进 AGENTS.md,把当前目标和 checkpoint 放进进度基线,把最近一次交接放进 LATEST.md。然后开一个新 chat,让它先读文件、核对 Git,再重新建立 /goal

聊天可以结束,项目状态不能只活在聊天里。

Share this post