mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-02 13:39:41 +02:00
Merge pull request #404 from timkjr/pr-ctrlz-suspend-trap
fix(terminal): trap Ctrl+Z in non-shell sessions to prevent accidental suspend
This commit is contained in:
@@ -2314,6 +2314,27 @@ Object.assign(CodemanApp.prototype, {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ctrl+Z (SIGTSTP/job-control suspend): a teammate/subagent pane is always
|
||||
// running an agent CLI (Task-tool dispatched, never a plain shell), so
|
||||
// unlike the main terminal's mode-gated trap this one is unconditional.
|
||||
// Mirrors the main terminal's guard in terminal-ui.js's
|
||||
// attachCustomKeyEventHandler — case-insensitive so Caps Lock (which
|
||||
// flips ev.key to 'Z' without setting shiftKey) can't slip a suspend past it.
|
||||
terminal.attachCustomKeyEventHandler((ev) => {
|
||||
if (
|
||||
ev.type === 'keydown' &&
|
||||
ev.key.toLowerCase() === 'z' &&
|
||||
ev.ctrlKey &&
|
||||
!ev.altKey &&
|
||||
!ev.metaKey &&
|
||||
!ev.shiftKey
|
||||
) {
|
||||
ev.preventDefault();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// Wait for terminal renderer to fully initialize before any writes.
|
||||
// xterm.js needs a few frames after open() before write() is safe.
|
||||
setTimeout(() => {
|
||||
|
||||
@@ -383,6 +383,29 @@ Object.assign(CodemanApp.prototype, {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ctrl+Z (SIGTSTP/job-control suspend): in a plain shell session this is the
|
||||
// user's own job-control tool (suspend a foreground command, `fg` it back) —
|
||||
// leave it alone. In every other mode (claude/omp/pi/codex/... — Ink/TUI apps
|
||||
// that normally run in raw mode with ISIG off, so ^Z is usually inert there
|
||||
// already) suspending the CLI stops an unattended agent loop dead with no
|
||||
// visible output — the same failure shape as an XOFF freeze. Swallow it
|
||||
// before xterm can send \x1a into the PTY rather than relying on every CLI's
|
||||
// raw-mode state holding at every instant (startup, raw-mode toggles, etc).
|
||||
if (
|
||||
ev.type === 'keydown' &&
|
||||
ev.key.toLowerCase() === 'z' &&
|
||||
ev.ctrlKey &&
|
||||
!ev.altKey &&
|
||||
!ev.metaKey &&
|
||||
!ev.shiftKey
|
||||
) {
|
||||
const activeCtrlZSession = this.activeSessionId ? this.sessions.get(this.activeSessionId) : null;
|
||||
if (activeCtrlZSession && activeCtrlZSession.mode !== 'shell') {
|
||||
ev.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Shift+Enter / Ctrl+Enter: insert newline for multi-line input.
|
||||
// xterm.js sends plain \r for all Enter variants, so Claude Code (Ink) can't
|
||||
// distinguish them. We use tmux send-keys -H to send a line feed byte (0x0a)
|
||||
|
||||
Reference in New Issue
Block a user