Skip to content

fix(projects): verify command echo before Enter; retry when shell startup swallows keystrokes#48

Open
milehimikey wants to merge 1 commit into
cloudmanic:mainfrom
milehimikey:pr-swallowed-keystroke
Open

fix(projects): verify command echo before Enter; retry when shell startup swallows keystrokes#48
milehimikey wants to merge 1 commit into
cloudmanic:mainfrom
milehimikey:pr-swallowed-keystroke

Conversation

@milehimikey

Copy link
Copy Markdown

Problem

When a project's startup command is typed into a freshly created pane, the shell's startup can swallow keystrokes — most often just the first character, so claude runs as laude ("command not found"). Two weaknesses in runCommand combine to cause this:

  • waitForPaneReady returns on the first non-blank read. Shells with slower startup (compinit, plugin managers, prompt frameworks) paint output in bursts before the line editor accepts input, so typing starts too early and characters land in the gap.
  • After typing, the echo check (waitForPaneText) has no teeth: when it times out, Enter is pressed anyway, submitting the mangled line.

Fix

  • waitForPaneReady now waits for quiescence — two consecutive identical non-blank reads 200ms apart — instead of first paint (call-site timeout 5s → 10s).
  • waitForPaneText reports whether the probe appeared.
  • runCommand only presses Enter once the command visibly echoes back intact. On a failed echo check it clears the line (ctrl+u — backward-kill-line in both zsh emacs and vi-insert keymaps) and retypes, up to 3 attempts, before degrading to the previous blind-Enter behavior so a shell that never echoes (or a full-screen program) still works.

Happy path cost is one extra 200ms quiescence read; the retry path only engages when the echo check fails.

Testing

  • go test -race ./... passes.
  • Reproduced the original failure with a slow-starting zsh (oh-my-zsh + compinit + mise + vi-mode) where project launches reliably typed laude; with this change the command lands intact across repeated launches, including with an artificial sleep 2 at the top of .zshrc.

🤖 Generated with Claude Code

A freshly spawned pane's shell startup (compinit, plugins, prompt frameworks)
paints output before the line editor accepts input. waitForPaneReady fired on
first paint, so the first typed character could be swallowed (claude -> laude),
and runCommand pressed Enter even when the echo check timed out, submitting the
mangled line.

- waitForPaneReady now waits for quiescence: two consecutive identical
  non-blank reads 200ms apart (call-site timeout 5s -> 10s).
- waitForPaneText returns whether the probe appeared.
- runCommand only submits after the command visibly echoes; on timeout it
  clears the line (ctrl+u) and retypes, up to 3 attempts, before degrading
  to the old blind-Enter behavior.

Co-Authored-By: Claude Fable 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