如何分叉 Codex 和 OpenCode 会话(从 UI/TUI 或手机)

一份在正确位置分叉会话的实用指南(从消息分叉与从最新分叉),以及分叉后上下文会怎样。

基于版本
CLI
0.2.17
预览 ref
a2c45c8

分叉就是建分支。

你保留原始会话不变,并创建一个从更早位置开始的子会话。

这份指南直接说明如何分叉 Codex 和 OpenCode 会话:

  • 从它们自己的 UI/TUI(在支持时)
  • 以及从手机或浏览器界面(Happier 是一种选择)

唯一需要做对的,是从哪里分叉。

简要总结

  1. 决定你想从哪里建分支:
    • 从最新分叉(从“现在”建分支)
    • 从消息分叉(从更早的位置建分支)
  2. 在 Codex 中:
    • 从最新的会话状态分叉较为可靠
  3. 在 OpenCode 中:
    • 使用 OpenCode 服务器后端时,可以进行服务器原生的从消息分叉
  4. 如果你想在各设备上获得一致的分叉界面,Happier 是一种选择:它在对话记录中提供 从此消息分叉(Fork from this message),并自动创建子会话。

“分叉”的实际含义

分叉不是复制粘贴。

分叉是:

  • 一个新的会话 ID
  • 链接着祖先上下文
  • 从分叉点开始的新消息流

原始会话保持不变。

从最新分叉与从消息分叉(如何选择)

从最新分叉

在以下情况使用:

  • 你喜欢当前的方向
  • 你只是想并行尝试另一种方法

从消息分叉

在以下情况使用:

  • 你能指出想要分道扬镳的确切时刻
  • 你想干净地重做一条指令

方式 A:在 Codex 中分叉

Codex 的支持情况因界面而异,但工作流通常大致是:

  • 分叉当前会话(从最新分叉)
  • 把分叉出的会话作为新分支继续

什么时候适合在 Codex 中从最新分叉

从最新分叉适合:

  • 你想尝试另一条实现路径
  • 你想比较两种方法
  • 你即将做一个有风险的改动,想要一个安全的分支

什么时候你真正想要的是从消息分叉

从消息分叉是“我想倒回去”的操作:

  • 你想干净地重做一条指令
  • 你想在会话开始跑偏之前分开

如果你用的 Codex 界面不支持从消息分叉,常见的替代做法是重放:

  • 创建一个新会话
  • 给它足够的上下文,让它像原会话一样工作

(这就是为什么好的“分叉体验”总会包含一条重放路径。)

方式 B:在 OpenCode 中分叉

OpenCode 的客户端/服务器架构很完善。

如果你使用 OpenCode 服务器后端,可能可以使用服务器原生的从消息分叉。

一条简单的 OpenCode 决策规则

  • 如果你知道想从哪条消息建分支 → 从消息分叉
  • 否则 → 从最新分叉

如果当前的 OpenCode 界面不支持从消息分叉,这里同样适用重放的替代做法。

方式 C:从手机分叉(Happier)

如果你想在手机、浏览器和桌面上获得一致的分叉界面,Happier 是一种选择。

以下是它的样子(有实现依据):

从特定消息分叉

这是非常有用的分叉方式,但很多工具却把它做得出乎意料地难。

在 Happier 中:

  1. 打开会话的对话记录。
  2. 找到你想建分支的那条消息。
  3. 选择 从此消息分叉(Fork from this message)。

有两个重要细节:

  • 只有当这条消息可以作为分叉点时,分叉按钮才会出现。
  • Happier 按序号分叉(forkPoint: { type: 'seq', upToSeqInclusive }),所以分叉点是稳定的。

一个值得了解的小体验细节

如果你在一条已提交的用户消息上分叉,Happier 会把它当作“干净地重做这条指令”:

  • 它在用户消息之前分叉
  • 它把用户消息文本恢复到子会话的输入框中,作为可编辑的草稿

所以你可以:

  • 调整措辞
  • 补上一条遗漏的约束
  • 干净地重新发送

而不用重写整套设置。

(实现依据:resolveForkFromMessageSemantics 生成 restoredDraftText,然后写入子会话的草稿。)

从最新分叉(从现在建分支)

如果你不在乎确切的分叉点,从最新分叉依然有用。

实际上它就是“从现在开始一条并行线程”的操作。

子会话中的上下文会怎样

分叉之后:

  • 祖先消息以只读上下文的形式显示
  • 插入一条分隔行(“分叉自……”)
  • 你可以在截断点打开父会话

(实现依据:祖先消息通过 injectForkContextRows 进行标注,分隔行由 ForkDividerRow 渲染。)

分叉后你会看到什么

在子会话的对话记录中,Happier 会插入一条分隔行:

  • “分叉自……”
  • 带有一个在截断点打开父会话的按钮

在底层,injectForkContextRows 把祖先消息标注为只读上下文,ForkDividerRow 提供“打开父会话”的深度链接。

故障排查

我看不到“从此消息分叉”按钮

常见原因:

  • 在这个界面中,会话或提供商不支持从消息分叉
  • 你选中的消息类型不能作为分叉点

如果无法从消息分叉,就使用从最新分叉(或重放/新会话的方式)。

分叉出的会话好像丢失了上下文

这通常意味着分叉机制回退到了重放,而且初始上下文比你预期的少。

两种解决方法:

  • 更早分叉(包含更多祖先上下文)
  • 在分叉之前,先在父会话中要一份检查点总结

我只想重做一条指令,而不是创建一个全新分支

从消息分叉加上恢复的草稿正是为此设计的。在用户消息之前分叉,编辑恢复的草稿,然后重新发送。

常见问题

分叉会删除原始会话吗?

不会。分叉会创建一个子会话,并保持原会话不变。

什么时候应该分叉,而不是直接发送纠正?

如果纠正会改变整体方向(或者你即将做有风险的事),就分叉。

如果只是小小的澄清,发一条后续消息就行。

常见错误

  • 分叉太晚(你其实想要更早的分叉点)
  • 需要从消息分叉时却用了从最新分叉
  • 宣布分叉决定,却不告诉队友改了什么

相关指南

codexopencodeforkingworkflowsmobile
最后更新: 2026-10-26