Skip to content

fix(web): send Ctrl+C input to the PTY - #77

Open
dhaern wants to merge 1 commit into
shekohex:mainfrom
dhaern:fix/web-ctrl-c
Open

dhaern wants to merge 1 commit into
shekohex:mainfrom
dhaern:fix/web-ctrl-c

Conversation

@dhaern

@dhaern dhaern commented Oct 6, 2026

Copy link
Copy Markdown

Summary

Pressing Ctrl+C in the web terminal never reaches the program running in the PTY. The page intercepts the keystroke and opens the "Are you sure you want to kill session" confirmation instead. This PR sends every keystroke to the PTY, Ctrl+C included. The Kill Session button still kills the session.

In plain terms: in a normal terminal, Ctrl+C stops the command that is running. In the web page it popped up a "kill this session?" box instead, so a runaway command could not be interrupted from the keyboard, and answering the box with "OK" killed the whole session. Now Ctrl+C behaves as it does in any terminal.

Cause

RawTerminal.setupInputHandling special-cased the \u0003 that xterm emits for Ctrl+C and called onInterrupt, which App wired to handleKillSession. That handler shows a confirm() and then deletes the session. The byte never went to onSendInput, so the PTY never saw it.

I typed Ctrl+C in a real headless Chromium against a session running sh -c 'trap "echo GOT_INT" INT; ...', answering the dialog with Cancel:

confirm dialogs PTY received SIGINT session
main 1 (Are you sure you want to kill session "ctrlc probe"?) no running
this PR 0 yes (GOT_INT printed) running

Changes

  • terminal-renderer.tsx: onData forwards everything to onSendInput. The onInterrupt prop and the Ctrl+C branch go away.
  • app.tsx: stop passing onInterrupt. handleKillSession stays and is still used by the Kill Session button.

Behavior changes

Ctrl+C in the web terminal now interrupts the foreground program, as in any terminal, instead of opening the kill confirmation. To end a session you use the Kill Session button.

Validation

There is no test in this PR. The client has no React test harness and no existing e2e test types Ctrl+C. The table above comes from a throwaway Playwright probe (Chromium) that I ran on main and on this branch and did not include. I can turn it into an e2e test if you want one.

bun test over test/*.test.ts, without the npm-pack and live suites, gives 184 passing. bun run typecheck, the build typecheck, bun run lint, bunx biome format . and vite build are clean. The CI workflow passes on this commit in my fork, including the Playwright e2e in Chromium and Firefox.

Diff

Production: -12 lines (+2/-14) in src/web/client/components/terminal-renderer.tsx and src/web/client/components/app.tsx.
Tests: none.

Ctrl+C in the web terminal opened the Kill Session confirmation instead of
reaching the PTY. Forward all xterm data through onSendInput and remove
onInterrupt. Ctrl+C now interrupts the foreground program; Kill Session
still kills.
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