Claude Code 与 Codex 交接:哪些状态搬得过去,哪些搬不过去
会话是本地文件,能增量搬;系统提示、权限批准、没落盘的推理搬不过去。搬不动的部分,只能靠交接件重述。
一句话结论:会话不是黑盒——Claude Code 的每一次会话就是 ~/.claude/projects/ 下的一个 JSONL 文件,Codex 可以走它自己的 app-server 读,所以"把任务搬到另一侧"是可以做成增量的,不需要你重讲背景。但能搬的只是"消息 + 压缩后的工具痕迹";系统提示、权限批准、MCP 连接状态、以及模型没落盘的那段推理,永远搬不过去。所以正确姿势是两段式:能搬的用游标搬,搬不动的用交接件重述。
披露:本文编译五篇 2026-10 的一手文章与一份备考资料,作者立场各有不同(见文末)。ccx 的实现细节来自其作者自述,我们没有在 macOS 上跑过它;其余方案(half-clone、Stop hook、子 agent 边界)同样未独立复现。
一、先认清:会话是一堆状态,不是一段对话
原文作者的切换理由很朴素:一侧额度用完了(Claude Code 有 5 小时窗口和周上限,Codex 也有),或者换模型查 bug(一个模型在原地打转,另一个一遍过)。
两种情况下,新的一侧都是"冷的":不知道项目是什么、做到哪、哪些方案已经排除、现在坏在哪。把 transcript 粘过去也不行——工具调用加输出动辄几万词,粘过去直接撑爆上下文。
于是问题变成:到底有哪些状态,各自存在哪,能不能搬。

图:把"会话"拆成四类状态,决定了你能自动化到哪一步。(编者据源文绘制)
| 状态 | 存在哪 | 能不能搬 | 怎么搬 |
|---|---|---|---|
| 用户消息、助手回复 | Claude:JSONL 一行一个事件 | ✅ | 逐字 |
| 工具调用与结果 | 同上 | ⚠️ 能搬但不能原样 | 压缩:调了什么、作用于什么、大约返回什么 |
| todo / plan | 会话内(Claude todo、Codex plan) | ✅ | 取最新一份带上 |
| 是否停在半步 | 会话内 | ✅ | 标注"上一侧是中断的" |
| 粘贴的图片 | 应用自己的缓存副本 | ⚠️ | 只搬缓存副本的路径 |
| git status | 仓库 | ✅ | 现取现带(代码本来就在盘上) |
| 系统提示 / 项目指令 | 各工具自己拼 | ❌ | 只能是"重述",不是"迁移" |
| 权限批准、MCP 连接状态 | 运行时 | ❌ | 到另一侧要重新批准/重新连 |
| 未落盘的推理、被压缩掉的原文 | 上下文里 | ❌(半救) | 压缩掉的部分用 read_session 分页找回 |
这张表的用处:看到 ❌ 的那几行,就知道"全自动交接"不可能做满。它们不是工程没做好,是设计上就不该跨进程搬(权限尤其:搬过去等于绕过批准)。
二、Claude 侧:整段历史就是一个 JSONL
这是整套方案的地基,也是很多人不知道的一点:
~/.claude/projects/<escaped-project-path>/<session-id>.jsonl
一个会话一个文件,一行一个事件:用户消息、助手回复、工具调用、工具结果、todo 更新。所以不需要任何 API 就能读完整段会话。
(顺便:另一个源文给了同一件事的路径规则——项目路径里的 / 变成 -,例如 /Users/yk/Desktop/projects/claude-code-tips 对应 ~/.claude/projects/-Users-yk-Desktop-projects-claude-code-tips/。这也解释了"老对话去哪了":一直在你自己的机器上。)
作者说,难的不是读,是决定读多少:
- 工具结果可能巨大(整份文件读取、完整跑一遍测试);
- 所以压缩:消息逐字保留,每个工具调用降维成"调了什么 / 作用于什么 / 大约返回什么",再附上当前 todo 和
git status。
这三行 bash 就够你自己翻历史(需要 jq):
# 哪些会话提过某个词
grep -l -i "reddit" ~/.claude/projects/-Users-you-project/*.jsonl
# 今天的会话里搜关键词
find ~/.claude/projects/-Users-you-project/*.jsonl -mtime 0 -exec grep -l -i "keyword" {} \;
# 只抽用户消息
cat ~/.claude/projects/.../<session>.jsonl | jq -r 'select(.type=="user") | .message.content'
三、Codex 侧:走它自己的 app-server,别解析内部文件
Codex 也在本地存会话记录,但原文作者刻意不去解析:
只使用 Codex 自带的 app-server:建 thread、往里发消息、读回来。这样 Codex 某次更新换了文件格式也不会把我的东西搞坏,而且写入走的是官方路径。
具体用到的三个能力:thread/list、thread/read、session import。
这个选择值得单独记一笔:"读别人的私有存储"是最容易在某次升级后静默坏掉的东西。一边是你的解析器,一边是别人的内部格式——没有契约。能用官方接口就别省这一步。
额度检查同理:Codex 有 account/rateLimits/read,直接读。
四、增量同步:配对 + 游标 + 只投递一次
作者的第一版是一次性导出:Claude 写一份 HANDOFF.md,Codex 读。这版能用,但有个明显缺陷——切回来的时候,Claude 不知道 Codex 改了什么,于是你又得导一次。手动,就回到原点了。
现在这版是双向的:

图:配对 + 双向游标 + 一次性投递。(编者据源文绘制)
四个环节:
- 配对:Claude 会话 A 与 Codex 线程 T 在
~/.ccx/pairs.json里构成一对,每侧记一个游标——"对方已经收到哪了"。 - 只发增量:切换时只发游标之后、压缩过的进展。
- 投递:你在 A 里发消息时,
UserPromptSubmithook 把 T 的新进展前置到这条消息里,然后移动游标。同一份内容不会送两次,hook 也绝不阻塞你的输入。 - 兜底:如果某段内容被压缩掉了,模型可以用
read_session工具分页翻回来。
原文的形容很准:"这些内容作为上下文到达模型,而不是变成新的聊天气泡。" 每次更新通常几千 token;没有新内容时再点一次,什么也不会发生。
结果就是:两侧在同一个任务上工作,而不是两个互不相关的对话。
五、什么时候该切:盯额度,但别绕过额度
大多数切换是因为额度。所以 ccx 在任一侧 5 小时窗口超过 90%、以及用完时,菜单栏各提醒一次,并给你"用对方继续"的入口。
这里有个不对称,很能说明"哪些状态搬不过去":
- Codex:额度从 app-server 的
account/rateLimits/read读,内置。 - Claude:本地没有任何达标前的信号。所以它只能去读你已经在装的那些工具的文档化输出(CodexBar、Claude Code Usage Monitor、
ccusage、abtop、claude-hud、ccstatusline等),装了哪个用哪个,不需要额外配置。
作者也明确了两条边界:不绕过任何额度(各用各的套餐),不上传任何东西(同步全在本地,只有安装和检查更新时才连 GitHub)。
六、同一个问题,四条路:清、压、写、切
第二篇源文把"上下文快满了怎么办"整理成四级阶梯,从"交出控制权"到"自己动手",这个排序比工具本身更有用。
| 手段 | 留下什么 | 什么时候用 | 代价 |
|---|---|---|---|
/clear + 新会话 |
什么都不留 | 换到不相关的任务 | 上下文全丢 |
/compact |
模型自己写的摘要 | 急需腾空间、细节不太重要 | 摘要不知道什么对你重要 |
HANDOFF.md |
你审过的交接文件 | 长任务、有死胡同值得记 | 要人多看一眼 |
/branch、--fork-session |
分叉点之前完整对话 | 想在某个点试另一条路 | 会话数变多 |
| half-clone / quarter-clone | 后半段(或后四分之一)逐字 | 长对话、最近状态最重要 | 丢掉开头 |
三条值得抄的实践:
1)把自动压缩关掉。 理由不是"压缩不好",而是自动摘要不知道什么对你重要——它可能留下一个已经定论的争论,却丢掉你只提过一次的小约束。关了不等于不压缩,而是你挑时机(通常在某个里程碑之后)并挑留下什么。
2)交接文件比摘要强,因为你能读它。 原文给了一个具体例子:让 Claude 把剩下的计划写进 HANDOFF.md,说明"试过什么、什么成了、什么没成",让"一个有干净上下文的 agent 只读这一个文件就能接着干"——产出是 129 行,开头是目标("把 Claude Code 的系统提示压掉约 45%(现在 11%,还差约 34%)"),后面是进展和已经写好的脚本。
然后关键的一步是:别文件一落地就开新会话。先扫一眼,缺什么就问(比如"你有没有写清楚要迭代测试,而不是想一次做完?")——这个问题常常能省掉下一个会话的整个下午。确认之后再开新会话,只贴路径:
> experiments/system-prompt-extraction/HANDOFF.md
之后每次都让 agent 更新同一个文件,留给下一个接手的人。(源文附了一个 /handoff skill 把这套流程自动化。)
3)half-clone 不做摘要。 它把超长对话复制成"只保留后半段"的副本,你和 Claude 的消息逐字保留,只是丢掉较早的部分;副本第一条消息带 [HALF-CLONE Jan 7 14:30] 标记,让你知道自己在哪个版本里。嫌多还有 --quarter。和压缩的区别很清楚:压缩会重新解释,half-clone 只做截断。
再往前一步是自动化:一个 Stop hook(check-context.sh)在每次回复后检查上下文占用,超过 85% 就不让 Claude 停,让它去跑 /half-clone 生成一个只带后半段的新会话,让新 agent 在那里继续。前提条件写死:必须关掉 Auto-compact,否则 Claude Code 可能在 hook 生效前先自己压了。
原作者的一句话总结很到位:如果只养成一个习惯,就养成交接文件。 它迫使你和 agent 把"现在到底到哪了"讲清楚——而这正好是干净上下文最需要的东西。
七、更窄的边界:子 agent 只拿到 prompt
如果你把"交接"缩小到同一个 agent 内部派活,能过的状态更少。一份备考资料把边界列得很干脆:
| 方向 | 能过去的东西 |
|---|---|
| 父 → 子 | 只有 Agent 工具(原 Task 工具)的 prompt 字符串 |
| 不继承 | 父对话历史、工具结果、系统提示;skills 里没列出的技能内容也不会自动带过去 |
| 子 → 父 | 只有最终消息;中间的工具调用留在子 agent 内部 |
| 例外 | fork(/subtask 或 subagent_type: "fork")会复制整段对话 |
| 配置 | AgentDefinition 必填 description + prompt;同名时程序化定义覆盖文件定义 |
所以"发现、约束、质量标准"必须写进那句 prompt——你不能指望它从父上下文里"感受到"。作者给的实践是:上下文用结构化记录传(内容与元数据分开),并要求结构化最终报告。否则协调者拿不回来源。
还有一个容易误读的字段:allowed_tools 是"免批准",不是"权限边界"——它让 Agent 不问你直接跑,不代表它跑不了别的。
八、团队级:共享会话与"可执行的流程"
第三篇介绍的 Agent Relay 把这件事推到团队层(Apache-2.0,v14.0.0,2026-10-13 发布,约 900 star),四件套:
- Messaging:agent 之间用频道、线程、DM、文件、搜索、实时事件通信,可以跨机器共享工作区(像给 agent 用的 Slack 原语)。
- Integrations 当虚拟文件系统:GitHub、Linear、Notion、Slack 以
ls/cat/grep/写文件的方式暴露,用来替代"每个工具接一个 MCP server"。 - Shared Sessions:捕获会话,供队友和他们的 agent 搜索"之前做过什么、为什么这么定";通过 plugin 或
agent-relay mcp --sessions-only访问(文档提到要云登录)。 - Flows:用 TypeScript 定义多步流程,带确定性检查、必需步骤和人工闸——把"你希望 agent 遵守的规则"变成"不遵守就过不去的流程"。
写这篇的介绍者明确说自己没有跑过它,并给了一个谨慎的试法:先拿一个废弃仓库,让 Claude Code 干一件小事,再让 Codex 读它的会话接着做;交接能成,再接真仓库。这条建议本身就值钱——它是"先验证通道,再接生产"。
九、三段式:搬状态、搬契约、留在原地
把上面拼起来,判据只有三句话:
| 层 | 适用于 | 手段 | 判据 |
|---|---|---|---|
| 搬状态 | 消息、压缩后的工具痕迹、todo、git status | 游标增量同步(JSONL / app-server) | 切换后对方不需要你再讲背景 |
| 搬契约 | revision、命令、预期输出、验收人、未完成项、Do Not Change |
HANDOFF.md(可读、可提交、可审) |
换到任何工具都能开工,包括你下周新装的那个 |
| 不搬 | 权限、系统提示、连接状态、未落盘推理"是否该这么干"的判断 | 留在原 agent 做完,或人来做 | 搬过去等于绕过批准 / 等于猜 |
第三层最容易被忽略。"能不能全自动"的真正答案在第三行:凡是需要重新获得授权的东西(权限、部署、外发消息),都不该被"搬"过去——那正是第 68 篇讲的 staged tools 想在同一个进程里解决的问题。
第四篇源文(团队工作流那篇)把"搬契约"这一层写成了文件名清单,可以直接抄:PROJECT.md(目标与约束)、ARCHITECTURE.md、docs/PLAN.md、docs/TASKS.md、docs/DECISIONS.md、docs/WORKLOG.md、docs/HANDOFF.md;CLAUDE.md 与 AGENTS.md 只当薄适配层,指向上面的规范文件,避免两边规则漂移。
它的交接模板里有三个字段值得直接偷:
- Revision:branch / base commit / 待评审的 head commit / 未提交改动(有就列出);
- Verification:命令 × 通过/失败/未跑 × 在哪个提交上跑的;
- Do Not Change:受保护行为与范围排除项。
最后一条还附了一句提醒:Do Not Change 只是记录约束,不提供强制。 同一篇文章里还有两句同类的:分支不是访问控制边界,worktree 只是组织改动、不是沙箱。这三句放在一起,基本把"用文件解决权限问题"的幻想堵住了。
十、坑(都是踩过的)
- 平台:
ccx只有 macOS 13+,要 Claude 和/或 Codex 桌面应用;Windows / Linux / 独立 CLI 都还不行。想在 Linux 上用,就得自己照它的思路写。 - JSONL 会越来越大:一个会话一个文件,工具结果全在里面。要定期清理或按项目归档,别指望它永远轻。
- 压缩会丢细节:被压掉的内容只能靠
read_session分页找;如果那一段已经从磁盘上删了(比如你自己清了历史),就真没了。 - hook 的纪律:不能阻塞输入、不能往 stdout 打印(打印会进上下文)、必须幂等(同一份只投一次)。这几条和第 68 篇里 Claude 生命周期 hook 的规则是同一套。
- 图片只是路径:搬过去的是一个缓存副本的路径,换机器就断。
- 自动压缩会让 Stop hook 失效:想让
85% → /half-clone生效,必须先关 Auto-compact。 - 别拿旧对话当交接:源文把它列进"常见错误"第一条区——旧会话既没有 revision,也没有验证记录。
- 子 agent 的
allowed_tools不是防火墙,prompt 也不是访问控制;审批状态不能搬(搬了就是绕过批准)。
十一、三步落地(每步有判据)
第 1 步(半天):先只做"能搬的那半"。 写个 50 行脚本:读某个会话的 JSONL → 压缩工具结果 → 生成一段"现状摘要"附到新会话开头。判据:新会话接到任务后,第一轮不再问你"项目是干什么的 / 之前试过什么"。
第 2 步(一天):加游标,做成双向。 配对表(一个会话 ↔ 一个对方线程)+ 两个游标 + 一次性投递。判据:来回切三次,没有一次重复投递、没有一次漏掉对方的改动。
第 3 步(一天):把"搬不动"的部分固化成 HANDOFF.md。 字段:revision(含待评审 head)、验证(命令 × 结果 × 提交)、Do Not Change、未完成项、验收人。放在源文件旁边写进仓库;新会话只贴路径。判据:换任意一个工具接手都能开工——包括你下周新装的那个。
团队级共享会话(第 8 节那套)放到这三步之后:先在一个废弃仓库验证"两个 agent 互读会话",再考虑接真仓库。
编者补充:和第 68 篇的关系
- 第 68 篇讲交接件写什么(revision / 命令 / 预期输出 / 验收人)与台账怎么推导状态;这篇讲这些状态里哪些根本搬不过去,所以你才需要那个交接件(见 多 Agent 交接:把"写条"换成四字段契约与台账)。
- 两篇叠起来的结论:同步解决"重复叙述",契约解决"无法开工",闸门解决"越权"——三者不能互相替代。
- 与站内 多 Agent 同机:Git 作者与凭据归属 的关系:那篇讲"谁签的字",这篇讲"谁记得住"。
边界
- 本文为编译整理,未在 macOS 上运行
ccx,也未实测 half-clone / Stop hook / Agent Relay;所有机制细节来自源文自述。 - 立场披露:
ccx与 Agent Relay 都是各自作者的项目(前者个人开源,后者是 Agent Workforce 的产品,介绍者声明"未运行过");HANDOFF.md/half-clone 一套来自一份 50 条 tips 的二手整理(原始观点见 YK Sugi 的claude-code-tips仓库);子 agent 边界那张表来自一份备考资料(非 Anthropic 官方文档,作者声明与 Anthropic 无关);团队工作流那篇是工具站内容。 Agent工具名、--fork-session、/autocompact、hook 事件名等随版本变化,以你本地claude --version的文档为准。- 文中"通常几千 token"这类量级是作者在其设置下的观察,不是基准测试。
相关阅读:AI 编程 / Vibe Coding 完全指南 | Agent / MCP / 自动化完全指南 | 多 Agent 交接:四字段契约与台账 | 多 Agent 写代码:协议才是系统 | 子代理交接的三种做法:compaction vs subagent vs fold | 多机并行 coding agent 实战栈
Sources
- How I hand a Claude Code session to Codex (and back) without re-explaining anything,dev.to,2026-10-21:https://dev.to/aaron_w_ef987250d3531be6d/how-i-hand-a-claude-code-session-to-codex-and-back-without-re-explaining-anything-2poe
- How Claude Code and Codex store sessions, and how to hand a task from one to the other,dev.to,2026-10-23:https://dev.to/aaron_w_ef987250d3531be6d/how-claude-code-and-codex-store-sessions-and-how-to-hand-a-task-from-one-to-the-other-m2m
- Claude Code Context Management: Compact, Handoff, and Half-Clone,camnangai.com,2026-10-24:https://camnangai.com/en/for/developers/claude-code-tips-context-management
- Spawning subagents and passing context(Claude Certified Architect 备考资料),2026-10-22:https://www.certifyforce.com/study-guide/claude-certified-architect-foundations/agentic-architecture-and-orchestration/spawning-subagents-and-passing-context
- Claude Code and Codex shared workflow: A practical setup guide,agentkit.best,2026-10-13:https://agentkit.best/blog/claude-code-guides/claude-code-and-codex-shared-workflow-a-practical-setup-guide
- Agent Relay: Open-Source Messaging, Shared Sessions and Flows,explainx.ai,2026-10-23:https://explainx.ai/blog/agent-relay-open-source-shared-sessions-flows-coding-agents-handoff-apache-2026
本文由 hubwiz 编译整理,转载请注明出处。
这是「AI 编程 / Vibe Coding」专题的一部分。完整地图见:AI 编程 / Vibe Coding 完全指南