feat(desktop): confirm before closing a terminal pane with a running process
What & why
Closing a terminal pane by mistake (Cmd+W) silently kills whatever is running in it. This adds a confirmation dialog that appears only when a foreground command is actually running, with a persisted "Don't ask again" checkbox. Closing at an idle shell prompt still closes instantly — no nag.
Covers every close route through the pane's onBeforeClose guard: Cmd+W (CLOSE_PANE), the close button, middle-click, context menu, and browser-pane Cmd+W.
How "a process is running" is detected
No such signal existed. It's computed on demand from the shell's controlling-terminal foreground process group via ps -o tpgid -o pgid:
- idle prompt → terminal's foreground group
==the shell's own group → not running - running command → the shell handed the terminal to the command's group → they differ → running
This is precise: unlike a "shell has child processes" check it does not false-positive on suspended/background jobs. Fails closed (returns false) on any ps error, missing tty, or if we can't reach the query — never blocks a close.
Changes
packages/pty-daemon/src/process-tree.ts— newhasRunningForegroundProcess(shellPid)packages/host-service/…/terminal/terminal.ts—sessionHasRunningProcess(terminalId)(session pid → detection)packages/host-service/…/trpc/router/terminal/terminal.ts— newterminal.hasRunningProcessquerypackages/ui/…/Alert/Alert.tsx—alert()gains an optionalcheckbox+onDismiss(Escape/outside-click resolves as cancel instead of hanging)apps/desktop/…/stores/terminal-close-confirm/store.ts— persisted suppression flag (localStorage)apps/desktop/…/usePaneRegistry.tsx— terminalonBeforeCloseguard
Verification
Driven end-to-end in the running desktop app (v2 workspace, over CDP):
| Scenario | Result |
|---|---|
Running sleep 300 + Cmd+W | Dialog appears with checkbox + Cancel / Close terminal |
| Cancel | Pane stays open |
| Idle prompt (after Ctrl+C) + Cmd+W | Closes instantly, no dialog |
| Don't-ask-again checked → Close | Closes, persists suppressed:true |
| Suppressed + running terminal + Cmd+W | Closes instantly, no dialog |
| Browser (non-terminal) pane close | Instant, no dialog |
Plus a real-pty integration test (test/foreground-process.test.ts) exercising idle→running→idle, mutation-verified to fail when the core comparison breaks. typecheck / lint / pty-daemon suite all pass.
Scope
Pane-level close only. Closing a whole tab (CLOSE_TAB, a different shortcut) that contains a running terminal does not warn yet — left as a follow-up.
Summary by cubic
Adds a confirm dialog when closing a terminal pane or tab that has a running foreground command, with a “Don’t ask again” option. Also disposes host-service terminals on workspace close/delete and closed worktree delete, broadcasting cleanup to all local hosts and pruning disposed rows to prevent leaks.
-
New Features
- Detects running foreground commands via
ps(tpgidvspgid) in@superset/pty-daemon(hasRunningForegroundProcess), returning false on errors. - Exposes status via
sessionHasRunningProcessand tRPCterminal.hasRunningProcess(workspace-gated; probes live withstaleTime: 0). - Shared confirm covers pane close and tab close (tab X, Close Others/All,
CLOSE_TABhotkey); skips backgrounded terminals; suppression persisted viauseTerminalCloseConfirmStore.@superset/uialert()adds optional checkbox,onDismiss, returns a boolean; probe or Alerter failures never block close.
- Detects running foreground commands via
-
Bug Fixes
- Prevents leaked host-service sessions by disposing on workspace close/delete and closed worktree delete; disposal is best-effort and broadcast to every running local host-service across orgs.
- After disposal, prunes non-active terminal rows in the host DB for both workspace and worktree paths. Security:
terminal.hasRunningProcessenforces workspace ownership.
Summary by CodeRabbit
- New Features
- Added terminal-pane close confirmation when a foreground command is running.
- Added a “Don’t ask again” checkbox to persist the preference.
- Added workspace/tab close guarding that prompts only when needed, including via the close-tab hotkey.
- Bug Fixes
- Improved detection of whether foreground work is still running, reducing unnecessary blocking.
- After deleting a workspace or worktree, added best-effort cleanup to prevent leftover terminal sessions.
- Tests
- Added an integration test covering foreground-process detection behavior.