Repository navigation
feat(session-history): Resume in New CLI forks a native chat's conversation into the terminal - #26336
Conversation
…LI session Agent Session History offered "Resume in New Chat" to move a terminal session into native chat, but nothing went the other way: once a native chat owned a conversation, its row only reopened the chat, and Orca refused any terminal resume of it so two programs never write one conversation. Rows a native chat owns (Claude, Codex) now offer "Resume in New CLI". It forks: the terminal runs `claude --resume <id> --fork-session` or `codex fork <id>`, so the CLI gets the full history under a new id and the chat is unchanged. The host's resume guard lets a Claude fork through, and the fork tab records no provider session, so a restart never re-enters the chat's conversation. "Resume in New Chat" is renamed "Resume in New Native Chat".
The tooltip balanced one wrapped string inside a box sized before balancing, leaving a gap beside its lines. It is now two block lines with no fixed width.
… and tighten the fork guard - Resume in New CLI now asks the host for the same Codex account home plain Resume uses, so a fork no longer starts under whichever account's copy of the rollout sorted first. The preparation call carries an optional `fork` flag that skips only the owned-conversation refusal; plain resume still refuses. - An older paired host that refuses the fork now shows "Update Orca on the host that runs this chat to resume it in a new CLI." instead of a raw error code. - The host guard admits `--fork-session` only before a `--` terminator and never alongside `--session-id`, since either shape lets Claude write the owned conversation. - Tests for the click path, the menu item's eligibility, the fork home preparation, and the tightened guard.
…session record A fork of an older (non-paginated) Codex thread writes its own session record first and then copies the parent's history, the parent's session record included. The history scanner kept the last one it saw, so the fork's row took the parent's id, title, folder and branch: on a native chat's fork it looked like the chat itself, and Resume on it opened the chat instead of the fork. Codex itself treats the first session record as the thread's own and ignores later ones; the scanner now does the same, as Orca's duplicate-rollout check already did.
…k keeps When Resume in New CLI can't move a Codex fork to the selected account (that account has no copy of the conversation yet, or the system default is selected), the fork runs in the account home the history row came from. A new Codex tab only gets Orca's status hooks in the selected account's home, and the fork carries no provider session, so nothing set up the hooks in that row home. In a home only native chat had used, the fork tab could show no working or idle status. The fork's home preparation now readies that home the same way a resumed session's home is readied (hook install or refresh, plus the daemon-socket guard). That code is moved into prepareCodexPinnedLaunchHome and shared by both paths. The fork tab still carries no provider session, so it never reopens the chat's conversation on restart.
… fork The fork's hook setup ran in whatever Codex home the request named, so a paired client could have Orca write hook and config files into any directory. Plain Resume only readies a home it has verified: one this host lists for Codex sessions that actually holds the rollout. The fork now uses that same check, through a shared trustedCodexResumeHomes list, and readies the home only when the verified home is the one the fork will run in. With no Codex runtime home service it does nothing, as plain Resume does. A failed check or setup is logged and never stops the fork from launching. Tests cover the untrusted home, a missing runtime home service, a rollout on another host, a WSL home, a fork moved into the real home, and a failed setup.
…raps the fork refusal When the local preparation step for Resume in New CLI is refused, Electron hands the renderer the error as "Error invoking remote method '…': Error: agent_session_conflict". The fork's failure text matched only the bare code, so the toast showed that raw line instead of asking the user to update Orca on the host. It now unwraps the message with the shared IPC error helper before matching.
Review summary (head a856685)The problem. In the old terminal-backed native chat you could switch a conversation between the chat and the terminal. The updated structured native chat has no terminal underneath, so once a conversation belonged to a native chat there was no way back to the CLI. Agent Session History only offered "Resume", which reopens the chat. Orca deliberately refuses to resume a chat-owned conversation in a terminal, because two writers on one conversation split it silently. What changes for you. Rows in Agent Session History whose conversation a native chat owns (Claude or Codex) get Resume in New CLI in the ⋯ menu, the right-click menu and the expanded details. Its tooltip says it makes a copy: "Forks this conversation into a new CLI session." / "The native chat stays as it is." Clicking it opens a terminal tab that forks the conversation ( Fixed during review
Checked and ruled out
Deferred (P2/P3, not blocking)
Verified
Not verified
The stacked follow-up #26375 has these fixes merged in. This PR stays a draft. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (43)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 4 remain after this review. 📝 WalkthroughWalkthroughThe change adds a “Resume in New CLI” action for eligible Claude and Codex sessions. It builds fork startup commands, sends fork mode through session preparation, and adds conditional Codex launch-home preparation. The session list exposes the action in its menus and details, with updated labels, tooltips, and translations. The Codex session parser now ignores metadata records after the first. Priority: ⬇️ Low Merge Risk: ⚪ Minimal · up to This adds a Resume in New CLI fork action for Claude and Codex sessions. No concrete merge-blocking risk was found in the reviewed changes. Live Codex fork behavior and paired-host behavior were not exercised, which is normal validation uncertainty rather than an identified defect. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 30.43% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 46 functions across 37 files. (6 skipped: 6 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Post-merge audit (main at e0a98a4)What this PR was for. A native chat has no terminal behind it, so before this PR you couldn't continue a native chat's conversation in the Claude or Codex CLI. Session History now offers Resume in New CLI on a chat's row. It opens a new terminal with a copy (fork) of the conversation: the chat stays as it was, and the two can diverge from there. "Resume in New Chat" was renamed Resume in New Native Chat. What the audit checked. After the merge, four fresh reviewers each read the landed code on current main (the squash has the same changes as the head reviewed before merge, a856685). One sketched a design from the issue alone before reading the code, then compared the two. The other three covered:
Result: no follow-up fix needed. No problem found at P0-P2.
Minor issues found and deferred (none blocks anything):
Verified:
Not verified:
|
ELI5
Once a conversation was moved into native chat, there was no way to pick it back up in a terminal (the CLI). Agent Session History now has a Resume in New CLI button for those conversations. It opens the CLI with a copy of the whole conversation, and the native chat stays exactly as it was.
What Changed
The problem. The old terminal-based native chat had a live chat/terminal switcher, because a terminal was always running underneath it. The updated structured native chat talks to the agent directly, with no terminal underneath, so there is nothing to switch to. Agent Session History already let you move a terminal session into native chat ("Resume in New Chat"), but nothing went the other way. A row owned by a native chat only offered "Resume", which reopens the chat. Orca also refuses to resume a chat-owned conversation in a terminal on purpose: if the chat and a terminal both wrote the same conversation, it would split silently (Codex takes no lock of its own).
What's different for you (Agent Session History: the row's ⋯ menu, its right-click menu, and its expanded details):
claude --resume <id> --fork-sessionorcodex fork <id>.How it works.
claude … --fork-sessionthrough, because a fork only reads the original. It only counts--fork-sessionbefore a--and never when--session-idis also given (Claude would then write under that id).codex forkalready passed.forkflag that skips only that refusal, because a fork never writes the original. When the fork stays in the row's own home, Orca sets up its status hooks there the same way plain Resume does (one shared function), and only for a home the host itself lists. An older host ignores the flag and refuses, which shows the update message above.ai-vault-resume-platform.ts. The duplicated platform/shell lookup became oneresolveAiVaultResumeHost. "Resume" and the fork now share one terminal-launch path, so targeting, toasts and errors are identical.Why
Fork, not move. The alternative was to move the conversation: stop and retire the chat, and hand ownership to the terminal. That needs a new saved "handed off" state on every chat record, a guard so a handed-off chat never restarts, and a new host call that paired remote hosts must support. A rollback to an older Orca would also treat the chat as owning the conversation again. Forking needs none of that, works while the chat is open or mid-reply, and can't create two writers. The trade-off is that the chat and the CLI copy go separate ways after the fork. The tooltip says so.
Differences from the common pattern:
Linked Issue
N/A (maintainer request)
Visual Proof
Captured with a hidden, isolated Orca dev build (its own home folder and agent config folders; stand-in
claude/codexscripts that only print their arguments, so no real agent ran). The session is a seeded Claude transcript, adopted into a native chat with "Resume in New (Native) Chat".Chat-owned row, ⋯ menu. Before: no way back to the CLI. After: "Resume in New CLI", with the fork tooltip ("Forks this conversation into a new CLI session." / "The native chat stays as it is.").
Terminal-session row, ⋯ menu. "Resume in New Chat" is renamed "Resume in New Native Chat"; nothing else changes.
After: the same action in the row's expanded details, and what clicking it runs. The new terminal tab ran the stand-in with
--resume <id> --fork-session.Re-checked at the final commit (a856685) on a second Mac, in a hidden, isolated dev build with stand-in agents:
After clicking it: the new terminal ran
--resume <id> --fork-session, and the original row is still the native chat ("Claude Chat", its own transcript, "Resume in New CLI" still offered). No extra row appeared.Testing
tc:web,tc:node,orca-ci-checks(lint, code quality, localization) pass locally at each pushed commit.Targeted vitest across the changed areas passes. New tests cover the fork commands (Claude and Codex, including a stored
--continueselector being replaced), that a fork tab never records the chat's session id, that agents without fork support return nothing rather than a resume, which rows show the item (both menus), the click path (fork plan, never the resume plan; one toast on failure; the update message, including the desktop's wrapped error text), the host check (admits real forks; refuses--fork-sessionafter--or with--session-id), the Codex account-home step withfork, the hook setup for a kept home (only host-listed homes; skipped for remote, WSL, missing service; failure never blocks), and a fork-shaped Codex history file keeping the fork's own id.Manual: the flow above in isolated macOS dev builds of this branch and of
main, and again at the final commit on a second Mac. Claude only: the Codex fork command is covered by unit tests, but a Codex fork was not run live (a stand-in can't make a chat-owned Codex row, and no real agent was run).Platforms: macOS locally. Windows/PowerShell quoting and Codex homes go through the same shared resume builder as an ordinary resume.
I manually tested these changes locally
Automated tests added/updated, or explained why not below
Review
Agent skill upstream boundary
docs/reference/agent-skill-sharing-upstream-boundary.mdand copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.Notes
Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)Author: @BrennanKB5