---
title: 'Codex session 太长怎么办？用交接文件把任务迁移到新 chat'
description: '从 resume、fork、compact 与新 chat 的差异出发，介绍怎样把目标、决策、进度和验证结果落到仓库文件，让 Codex 在不继承旧聊天历史的情况下继续长期任务。'
pubDate: 2026-07-28
tags: [agent, Codex, 工作流]
lang: zh-CN
draft: false
---

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

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

先说结论：

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

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

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

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

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

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

官方的 [Developer commands](https://learn.chatgpt.com/docs/developer-commands?surface=cli) 对这些边界写得很清楚：`resume` 会恢复保存的聊天并保留原历史，`fork` 会克隆当前聊天，`/compact` 则把早期内容替换成摘要。桌面应用里的 `/fork`、`/compact` 和 `/goal` 可以在 [Slash commands](https://learn.chatgpt.com/docs/reference/slash-commands) 中确认。

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

在桌面应用中，可以点击 **New chat**，也可以使用 `Cmd/Ctrl + N` 或 `Cmd/Ctrl + Shift + O`。当前快捷键以官方的 [桌面端命令文档](https://learn.chatgpt.com/docs/reference/commands) 为准。

## 新 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 文档](https://learn.chatgpt.com/docs/agent-configuration/agents-md) 也把它定位为持久的项目指令，并支持从仓库根目录到子目录逐层覆盖。

换句话说：

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

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

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

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

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

```markdown
请只做 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 没有“之前”。

更好的写法是：

```markdown
## 当前 checkpoint

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

## 已验证

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

## 下一步

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

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

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

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

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

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

开始工作前必须读取：

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 指南](https://learn.chatgpt.com/use-cases/follow-goals) 建议在目标里说明要先读取的文件、怎样验证进度，以及什么时候停止。

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

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

每个 checkpoint 后：

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

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

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

## 把迁移变成固定循环

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

**图 1：从读取规则和进度基线到新 chat 恢复的迁移循环**

```mermaid
flowchart TD
  A["读取规则与进度基线"] --> B["执行当前 checkpoint"]
  B --> C["运行验证并记录结果"]
  C --> D["更新进度基线"]
  D --> E{"需要换 chat？"}
  E -- "否" --> B
  E -- "是" --> F["生成 handoff"]
  F --> G["新 chat 重新读取并核对仓库"]
  G --> A
```

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

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

```text
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`。

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