Skip to content

fix(terminal): trap Ctrl+Z in non-shell sessions to prevent accidental suspend - #404

Open
timkjr wants to merge 1 commit into
Ark0N:masterfrom
timkjr:pr-ctrlz-suspend-trap
Open

fix(terminal): trap Ctrl+Z in non-shell sessions to prevent accidental suspend#404
timkjr wants to merge 1 commit into
Ark0N:masterfrom
timkjr:pr-ctrlz-suspend-trap

Conversation

@timkjr

@timkjr timkjr commented Sep 10, 2026

Copy link
Copy Markdown

Summary

  • Ctrl+Z (SIGTSTP) suspends the foreground job on the pane's tty. In a plain shell session that's normal job control, but in claude/omp/pi/codex/etc. sessions it silently stops an unattended agent loop dead — same failure shape as an XOFF freeze, just via job control instead of tty flow control.
  • Swallowed client-side in attachCustomKeyEventHandler, mode-gated so shell sessions keep normal Ctrl+Z job control (suspend/fg) untouched. Mirrors the existing Ctrl+V/Ctrl+Backspace interception pattern in the same handler.
  • Case-insensitive key match — Caps Lock flips ev.key to 'Z' without setting shiftKey, so a plain === 'z' check let the exact suspend keystroke this exists to catch slip through.
  • Also covers subagent/teammate terminal windows (panels-ui.js's initTeammateTerminal), which render a separate xterm instance with no custom key handler at all and always run an agent CLI (never a shell), so the trap there is unconditional.

Test plan

  • npm run check:frontend-syntax — both changed files parse cleanly
  • Existing terminal key-handling tests pass (terminal-copy-selection.test.ts, shortcut-registry-overlay.test.ts)
  • Live-tested: Ctrl+S/Ctrl+Q flow control unaffected, Ctrl+Z verified inert in a claude session and still suspends normally in a shell session
  • Reviewed twice via /code-review --level high (including the Caps Lock finding that shaped this diff)

🤖 Generated with Claude Code

…l suspend

Ctrl+Z (SIGTSTP) suspends the foreground job on the pane's tty. In a plain
shell session that's the user's own job-control tool (suspend, fg back),
but in claude/omp/pi/codex/etc. sessions it stops an unattended agent loop
dead with no visible output — the same failure shape as an XOFF freeze,
just via job control instead of tty flow control. Ink-based TUIs usually
run in raw mode (ISIG off) where ^Z is inert, but that only holds once the
CLI is actually running and stays in raw mode; it's live at the shell
prompt before launch and during any raw-mode toggle.

Swallow it client-side in attachCustomKeyEventHandler, mode-gated so shell
sessions keep normal job control, mirroring the existing Ctrl+V/Ctrl+Backspace
interception pattern in the same handler. Case-insensitive key match (Caps
Lock flips ev.key to 'Z' without setting shiftKey, so a plain === 'z' check
let the exact suspend keystroke this exists to catch slip through).

Also cover subagent/teammate terminal windows (panels-ui.js's
initTeammateTerminal), which render a separate xterm instance with no
custom key handler at all and are always running an agent CLI — never a
shell — so the trap there is unconditional.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant