Repository navigation
feat(desktop): continue a session in another harness - #1148
Draft
eric-liu-nvidia wants to merge 35 commits into
Draft
eric-liu-nvidia wants to merge 35 commits into
eric-liu-nvidia wants to merge 35 commits into
Conversation
elyasmnvidian
force-pushed
the
eric-liu/desktop-handoff-b
branch
from
October 26, 2026 19:20
48eb9ce to
c572cc6
Compare
elyasmnvidian
force-pushed
the
eric-liu/desktop-handoff-b
branch
2 times, most recently
from
October 26, 2026 21:11
288ff99 to
44b7b29
Compare
Base automatically changed from
emehtabuddin/s39-desktop-cargo-install
to
emehtabuddin/s34-desktop-gui-tray
October 27, 2026 21:34
…ite_tokens Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
…rminal app Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
… app (#1095) Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
… app Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
…reporting Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
…figs Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
…rminal app Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
…ute flows Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
…1109) * feat(desktop): add the Sessions page and recorded session inventory Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com> * feat(desktop): launch isolated worktree sessions from the terminal app (#1110) Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com> --------- Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
…olation (#1112) Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
…ytics (#1138) Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com> Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com> Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
* test(desktop): verify the desktop app frontend and route drafts Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com> * docs(desktop): add the desktop and terminal app quickstart Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com> --------- Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
* test(desktop): verify the desktop app frontend and route drafts Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com> * docs(desktop): add the desktop and terminal app quickstart Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com> * chore(desktop): simplify installation Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com> --------- Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
… worktrees Signed-off-by: Zengyuan Liu <zengyuanl@nvidia.com> Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Zengyuan Liu <zengyuanl@nvidia.com> Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
eric-liu-nvidia
force-pushed
the
eric-liu/desktop-handoff-b
branch
from
October 28, 2026 12:28
07dedf2 to
7d980da
Compare
Signed-off-by: Zengyuan Liu <zengyuanl@nvidia.com> Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
…his terminal Signed-off-by: Zengyuan Liu <zengyuanl@nvidia.com>
…e and the menu bar Signed-off-by: Zengyuan Liu <zengyuanl@nvidia.com>
…ssions page Signed-off-by: Zengyuan Liu <zengyuanl@nvidia.com>
… list Signed-off-by: Zengyuan Liu <zengyuanl@nvidia.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Lets a session continue in the other harness: a Codex CLI session in Claude Code, or a Claude Code session in Codex CLI. The app renders a bounded Markdown hand-off from the source session's own transcript (goal, compaction summary, last turns, files, commands, last error; ≤ 32 KiB), shows the whole text for review, then writes it to
~/.switchyard/handoffs/<id>/HANDOFF.md(0700/0600) and starts the destination harness in the same directory with an instruction to read the file, summarize the state in five lines, and continue. The destination model does the summarizing under its own login; the app makes no model call and shares no credential.Three ways to start one, all through the same controller actions:
switchyard-desktop handoff --to claude|codexfinds the newest transcript recorded in the current directory, prints the review, asks for confirmation, writes the hand-off, and replaces itself with the destination harness in that terminal (--transcript,--session,--route,--account,--source-account,--show,--yes).ccontinues the selected recorded session,xcontinues a transcript file,hlists the selected harness's sessions; the review ends with the full hand-off text and asks forHANDOFF.Code:
controller.rs:PreviewHandoff/Handoff(preview token bound to server config, app settings, and the transcript's size + mtime; compatibility, login-mode and binary checks; warnings for a possibly running source, a branch mismatch, a cut excerpt; one review opens one session;attachreturns the harness command instead of opening a terminal),RecentSessions+recent_sessions()(on-demand listing across both harnesses and saved accounts, each session with its default destination and, for managed worktrees, the session ID it keeps; sessions whose directory is not on this computer are counted aselsewhereand left out),Snapshot.handoffsplus a once-per-run purge of records older than seven days.handoff_cli.rs(new): thehandoffsubcommand; Unixexec, Windows spawn-and-wait.handoffs.rs(new): private store, symlink refusal, listing, age-based purge.sessions.rs:open_harnessis built from anInvocationso the review shows the exact command; newOpenRequestfields fordeveloper_instructions(Codex),--append-system-prompt+--add-dir(Claude) and a first prompt;append_launchrecords the hand-off in the session receipt;script_accountfactored out oflaunch.transcripts.rs:detecttells a rollout from a Claude transcript.gui.rs:tray_continuecommand and session rows in the tray view (re-read at most every 30 s).ui/app.js,ui/tray.*: the card (two dropdowns and two buttons), the popup rows, and a new-session route that follows the chosen harness.Stacked on #1115 (Elyas's stack, rebased onto its current tip) and includes the commits of #1079 (A1) and #1146 (A2); the diff shrinks to this feature once those land. The terminal app's hand-off reply arms follow the stack's current conventions (
set_popupand thepopup_matchesguard). Draft until the macOS checks below are done.Why
Switching harnesses today costs the whole conversation. This lets a user park a session in one CLI and pick it up in another through the app, without replaying transcripts across providers or crossing logins, which is the "context hand-off" step of the agentic-memory design.
Notes for reviewers
Start with
controller.rsAction::PreviewHandoff/Action::Handoffand the privacy decisions: the preview reply carries the fullHANDOFF.mdtext (the user sees exactly what is written), the excerpt never goes on the command line (only a < 1 KB pointer does), transcript sources never get aworktrees/<id>-settings/session.jsonso cleanup can never reach a real checkout, and a hand-off that fails to open removes its directory. Thensessions::invocation(theopen_harnessrefactor keeps the generated script semantically identical; the existing fixture test still passes),recent_sessions(),handoff_cli.rs, andhandoffs.rs.An earlier revision took the GUI destination from the new-session form, which left a Codex route selected after switching the harness to Claude Code; the controller rejected it and the only feedback was a toast. Every entry point now computes a compatible default and checks it before the review.
Confirmed on macOS: Claude Code's
--add-dirtakes every following word as a directory, so the Claude command lists--add-dirfirst and keeps the prompt as the last word (sessions::tests::the_first_prompt_is_the_last_word_and_no_list_option_precedes_it). A hand-off into Claude Code launched the harness in the right directory through theclauderoute with the login forwarded, and a Codex → Claude Code switch from the Sessions card ran end to end: Claude Code read the hand-off on its own and answered with the summary.Known gaps for follow-ups: Codex
-c developer_instructionsand the Seatbelt read of~/.switchyard/handoffs/…are unverified on a real binary (a positional first prompt naming the file is always passed as the fallback); Pi and Codex app are not destinations; Windows passes the same arguments throughTerminalJobbut was not exercised; Claude'ssettings.jsonfor a hand-off lives in the hand-off directory and is purged with it after seven days.Evidence
cargo fmt --all -- --check,cargo clippy -p switchyard-desktop --all-targets -- -D warnings: clean.cargo test -p switchyard-desktop: 15 lib + 31 bin + 6 integration tests pass. New:controller::tests::session_handoff_requires_an_unchanged_review_and_opens_the_other_harness(child-process fixture with stubcodex/claude/terminal: both directions, wrong/missing token, stale transcript after preview, 0700/0600 modes, receiptlaunches[1].handoff, destination argv contains--add-dir/--settings/--append-system-prompt/developer_instructionsand never the excerpt, no receipt for transcript sources, mergedRecentSessionswith per-session destinations andmanaged_id, a transcript recorded on another computer counted and left out),handoff_cli::tests::handoff_command_writes_the_file_and_runs_the_destination_here(the subcommand picks the rollout recorded in the current directory and execs a stubclaude; argv, environment, cwd, 0600 file and record are checked),tui::tests::continue_keys_hand_off_the_selected_session_and_a_transcript_file,handoffs::tests::handoffs_are_private_listed_newest_first_and_purged_by_age; frontend testshand-off previews and session listings read without taking the busy lockanda hand-off destination defaults to the first route its harness can use(need Node ≥ 18; not run on the Linux box).index.htmlandtray.html: each dropdown preselects the newest session of its harness, Switch to Claude Code opens the review and sendshandoffwith the managed session ID, Switch to Codex previews a transcript source, an incompatible route override and a missing harness grey the button out with the reason under it, a harness without sessions disables its dropdown, the list reloads on window focus, the new-session route follows the harness, and the popup forwards{source, destination}totray_continue; zero page or console errors in every state.cargo desktop installfrom this branch: Codex → Claude Code from the card works end to end. Still pending: Claude Code → Codex, the popup and the subcommand end to end,/varvs/private/var, quoting,originsplit in the routing log.🤖 Generated with Claude Code