fix(handoff): preserve tmux session by setting remain-on-exit before kill

When gt handoff killed pane processes before respawning, the pane would
be destroyed (since remain-on-exit defaults to off), causing respawn-pane
to fail with "can't find pane" error.

Fix: Set remain-on-exit=on before killing processes, so the pane survives
process death and can be respawned. This restores tmux session reuse on
handoffs.

Changes:
- Add SetRemainOnExit method to tmux package
- Call SetRemainOnExit(true) before KillPaneProcesses in:
  - Local handoff (runHandoff)
  - Remote handoff (handoffRemoteSession)
  - Mayor attach respawn (runMayorAttach)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
mayor
2026-01-24 22:17:25 -08:00
committed by Steve Yegge
parent baf9311bfe
commit 36c7222d5b
3 changed files with 36 additions and 0 deletions

View File

@@ -200,6 +200,12 @@ func runMayorAttach(cmd *cobra.Command, args []string) error {
return fmt.Errorf("building startup command: %w", err)
}
// Set remain-on-exit so the pane survives process death during respawn.
// Without this, killing processes causes tmux to destroy the pane.
if err := t.SetRemainOnExit(paneID, true); err != nil {
style.PrintWarning("could not set remain-on-exit: %v", err)
}
// Kill all processes in the pane before respawning to prevent orphan leaks
// RespawnPane's -k flag only sends SIGHUP which Claude/Node may ignore
if err := t.KillPaneProcesses(paneID); err != nil {
@@ -207,6 +213,7 @@ func runMayorAttach(cmd *cobra.Command, args []string) error {
style.PrintWarning("could not kill pane processes: %v", err)
}
// Note: respawn-pane automatically resets remain-on-exit to off
if err := t.RespawnPane(paneID, startupCmd); err != nil {
return fmt.Errorf("restarting runtime: %w", err)
}