How to fork Codex and OpenCode sessions (from UI/TUI, or from your phone)

A practical how-to for branching a session at the right point (fork-from-message vs fork-latest), plus what happens to context after the fork.

Based on
CLI
0.1.0
Preview ref
f36aa45

Forking is just branching.

You keep the original session intact, and you create a child session that starts from an earlier point.

This guide is a straightforward how-to for forking Codex and OpenCode sessions:

  • from their own UI/TUI (when supported)
  • and from a phone/browser UI (Happier is one option)

The only thing to get right is where you fork from.

TL;DR

  1. Decide what you want to branch from:
    • Fork latest (branch from “right now”)
    • Fork from message (branch earlier)
  2. In Codex:
    • forking is most reliable from the latest session state
  3. In OpenCode:
    • server-native fork-from-message is possible when you’re using an OpenCode server backend
  4. If you want a consistent fork UI across devices, Happier is one option: it exposes “Fork from this message” inside the transcript and creates a child session automatically.

What “fork” means (in practice)

A fork is not a copy/paste.

A fork is:

  • a new session id
  • with ancestor context linked
  • and a new message stream from the fork point onward

The original session stays unchanged.

Fork latest vs fork from message (how to choose)

Fork latest

Use this when:

  • you like the current direction
  • you just want to try an alternative approach in parallel

Fork from message

Use this when:

  • you can point to the exact moment where you want to diverge
  • you want to redo an instruction cleanly

Option A: fork inside Codex

Codex support varies by surface, but the workflow is usually some version of:

  • fork the current session (fork-latest)
  • continue the forked session as a new branch

When Codex fork-latest is the right move

Fork-latest is great when:

  • you want an alternative implementation path
  • you want to compare two approaches
  • you’re about to do a risky change and want a safe branch

When you actually want fork-from-message

Fork-from-message is the "I want to rewind" move:

  • you want to redo an instruction cleanly
  • you want to diverge before the session started going off-track

If your Codex surface doesn’t support fork-from-message, the common fallback is replay:

  • create a new session
  • seed it with enough context to behave like the original

(That’s why a good “fork UX” always includes a replay path.)

Option B: fork inside OpenCode

OpenCode has a strong client/server story.

If you’re using an OpenCode server backend, server-native fork-from-message can be available.

A simple OpenCode decision rule

  • If you know the exact message you want to branch from → fork-from-message
  • Otherwise → fork-latest

If fork-from-message isn’t available in your current OpenCode surface, the replay fallback applies here too.

Option C: fork from your phone (Happier)

If you want a consistent fork UI from phone/browser/desktop, Happier is one option.

Here’s what it looks like (implementation-backed):

Fork from a specific message

This is the most useful fork, and it’s the one most tools make surprisingly hard.

In Happier:

  1. Open the session transcript.
  2. Find the message you want to branch from.
  3. Choose Fork from this message.

Two details that matter:

  • The fork button only appears when that message can be used as a fork point.
  • Happier forks by sequence number (forkPoint: { type: 'seq', upToSeqInclusive }) so the fork point is stable.

A small UX detail I really like

If you fork on a committed user message, Happier treats it like “redo this instruction cleanly”:

  • it forks before the user message
  • it restores the user message text into the child composer as an editable draft

So you can:

  • tweak the wording
  • add one missing constraint
  • resend it cleanly

Without rewriting the whole setup.

(Implementation-backed: this is resolveForkFromMessageSemantics producing restoredDraftText, which is then written into the child session draft.)

Fork latest (branch from now)

If you don’t care about an exact fork point, fork-latest is still useful.

In practice it’s the “parallel thread starting now” move.

What happens to context in the child session

After the fork:

  • ancestor messages are visible as read-only context
  • a divider row is inserted (“Forked from …”)
  • you can open the parent at the cutoff point

(Implementation-backed: ancestor messages are annotated via injectForkContextRows, and the divider row is rendered by ForkDividerRow.)

What you’ll see after you fork

In the child transcript, Happier injects a divider row:

  • “Forked from …”
  • with a button to open the parent at the cutoff point

Under the hood, injectForkContextRows annotates ancestor messages as read-only context, and ForkDividerRow provides the “open parent” deep link.

Troubleshooting

I don’t see a “Fork from this message” button

Common causes:

  • the session/provider doesn’t support fork-from-message in this surface
  • you’re on a message type that isn’t eligible as a fork point

If you can’t fork-from-message, use fork-latest (or a replay/new session approach).

My forked session feels like it lost context

This usually means the fork mechanism fell back to replay with a smaller seed than you expected.

Two fixes:

  • fork earlier (include more ancestor context)
  • ask for a summary checkpoint in the parent before forking

I want to redo one instruction, not create a whole new branch

Fork-from-message + restored draft text is exactly for this. Fork before the user message, edit the restored draft, and resend.

FAQ

Does forking delete the original session?

No. Forking creates a child session and keeps the original intact.

When should I fork instead of just sending a correction?

If the correction changes the whole direction (or you’re about to do something risky), fork.

If it’s a small clarification, just send a follow-up.

Common mistakes

  • forking too late (you really wanted an earlier fork point)
  • using fork-latest when you needed fork-from-message
  • broadcasting a fork decision without telling teammates what changed
codexopencodeforkingworkflowsmobile
Last updated: 2026-04-03