Skip to content

Course · Codex · Sessions & context

Compare two approaches with /fork

You want to try two implementations and pick one, but a single thread makes them blur: keyword tables pick up fuzzy scoring ideas, and regex approaches inherit table-shaped assumptions. Comparing two designs in one conversation destroys the comparison.

A session here is the saved Codex conversation (restorable with codex resume). Forking copies that conversation into a second thread that evolves separately, so each approach gets its own context from the same starting point.

budgetcli is a small personal-finance API (166 lines of Python, about 230 lines all told, pytest, AGENTS.md at the root). app/services/categorise.py holds a keyword-to-category table and a categorise() helper; in the starter tree nothing calls it yet. You might grow the table (more merchants, substring match, first match wins) or replace it with regex and scoring. On paper either might work; in code you want both tried cleanly.

Running “now try the other way” in the same thread leaves both designs in one window. Fork pays for a second copy of shared history so the two futures stay separate.

/fork splits a copy of the current session that carries the full conversation so far and evolves on its own. The TUI marks the seam with a history line naming the parent (documented shape; stand-in id, not a captured run):

> /fork
Thread forked from budgetcli · date fix (4f9c2a1e)

When the parent has no name, the line shows the id. If you lose track of which thread you are in, /status can show a Forked from: line with the parent id.

Build the first approach in the fork:

> grow the keyword table in app/services/categorise.py: add merchants
under each existing category, keep the substring match and
first-match-wins, keep the "uncategorised" fallback. Add tests for
the new rows in tests/.

The original session stays at the shared starting point. When you want the second design, codex resume opens the picker; the original appears as its own titled session (illustrative rows):

$ codex resume
grow the keyword table in app/services/cate… today 11:20
❯ budgetcli · date fix yesterday 18:40
> replace the keyword table in app/services/categorise.py with regex
patterns per category and a scoring fallback ...

Each design then grew in focused context. You can run both against the same data and read real disagreements (which rows land in which category) instead of arguing from memory. The cost: shared history is stored twice, once per thread.

From the shell, codex fork is the top-level subcommand to branch a saved session (picker; --last skips it where supported).

Session history is good for the decision hour; it is not your long-term archive. When a comparison is worth keeping, promote it to git. In the TUI, a line starting with ! runs a local shell command under current approval and sandbox settings:

> !git checkout -b cat-table && git add -A && git commit -m "categorizer: grow the keyword table"
> !git checkout main && git checkout -b cat-scoring
> !git diff cat-table cat-scoring -- app/services/categorise.py

Fork for throwaway exploration; branches for what you might merge. As with any session tool here, files on disk survive either way; only what you commit is authoritative for the repo (the resume lesson covers the restored-conversation vs working-tree distinction in full).

Collapsing both designs back into one chat recreates the contamination fork was meant to prevent. Keep threads apart until you choose.

For a small, disposable question that should not join the main transcript and does not need a second persistent thread, /side is the lighter move.