Skip to content

spawn focus-steal: human keystrokes corrupt launcher line, spawn wedges until manual Enter #434

Description

@EtanHey

What happened (Etan, live, 2026-08-17 ~22:10)

brainlayerClaude spawned a cursor worker while Etan was typing. The new pane stole focus mid-keystroke; his characters ("ng") landed in the fresh shell before the launcher command. Terminal record:

Last login: Mon Aug 17 22:10:32 on ttys000
ng %
etanheyman ~  $
etanheyman ~  $ brainlayerCursor -s
[4] 55084

The launcher line sat unsubmitted until Etan manually pressed Enter. Until then the pane never registered as initiated for the fleet. He reports this is recurring and recent ("wasn't the case that much in the past").

Mechanism (from source)

  1. agent-engine.ts:6834-6847 — spawn MUST focusSurface the new pane before any I/O ("a tab created in an unfocused pane does not initialize its terminal"). This is the focus-steal window: any human keystrokes in flight land in the new shell.
  2. server.ts sendLauncherCommandToSurface waits for shell-ready, then types the command and Return as terminal input into the focused pane.
  3. The recovery path submitPendingLauncherCommand only presses Return when screenShowsPendingShellInput(screen, sanitizedCommand) matches. A human-corrupted line (ng + command fragments) fails the match — the engine correctly refuses the mutation, but then nothing clears and retypes, so the spawn wedges until a human presses Enter. clearAndVerifyFreshShellPrompt (ctrl-c + re-verify) exists but evidently did not run/recover in this scenario.

Asks

  1. Shrink or eliminate the focus window. If cmux offers any PTY-direct write that initializes an unfocused tab, use it. If not: focus → immediately restore the user's previous focus after terminal init, before the shell-ready wait (the typing window is currently seconds long).
  2. Detect foreign characters and recover. When the pending-line check fails because the line contains MORE than the sent command (human prefix/suffix), clear the line (ctrl-u), retype, re-verify, then submit — instead of stalling.
  3. Surface the wedge. A spawn whose launcher line never submitted should go to an error/blocked state with a receipt saying so — not sit in booting until a human notices. (Same family as fix: make prompt freezes observable #418 blocked_on_prompt.)

Related: #432 (busy-send false-fail), boot-prompt-late issue filed alongside this one.

— cmuxlayerClaude (lead) · claude-code/claude-fable-5

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions