fix(paliadin): 200ms settle delay between paste and Enter so submit registers
m's dogfood 2026-05-08 20:35: "the paliadin hook does not always work — it does not confirm the claude / terminal command... like lacking an enter key. Or too fast." Race between two consecutive tmux send-keys calls: the first writes the prompt literally with `-l`; the second sends an Enter key event. Claude Code's TUI debounces keyboard input. When the Enter lands while the paste is still being absorbed, the carriage-return collapses into the input buffer as a literal newline character instead of registering as a "submit" gesture — the prompt sits typed but unsubmitted, and the backend's pollForResponse then times out on the missing response file. Fix: sleep 200ms between the literal paste and the Enter. Below the human-perceptible threshold but well above tmux's pty flush window and the TUI's input-debounce window. Applied to both code paths: - scripts/paliadin-shim:send_to_pane (the SSH/RPC production path) - internal/services/paliadin.go:LocalPaliadinService.sendToPane (the laptop-only direct-tmux path) The Go-side variant uses a context-aware sleep so request cancellation still propagates correctly. Production shim copy at /home/m/.local/bin/paliadin-shim refreshed locally on mRiver so the next turn picks up the fix without waiting for redeploy. (The Dokploy container does not run paliadin — gate on PaliadinOwnerEmail is owner-only and prod has no claude+tmux anyway — so no deploy step required for the shim path.)
This commit is contained in:
@@ -668,6 +668,19 @@ func (s *LocalPaliadinService) sendToPane(ctx context.Context, target, msg strin
|
||||
if err := runTmux(ctx, "send-keys", "-t", target, "-l", msg); err != nil {
|
||||
return err
|
||||
}
|
||||
// Settle delay between the literal paste and the Enter. Claude Code's
|
||||
// TUI debounces keyboard input; if Enter lands while the paste is
|
||||
// still being absorbed, the carriage-return collapses into the input
|
||||
// buffer as a literal newline character instead of registering as a
|
||||
// "submit" gesture, leaving the prompt typed but unsubmitted (m's
|
||||
// dogfood 2026-05-08 20:35: "lacking an enter key... or too fast").
|
||||
// 200ms is below the human-perceptible threshold but well above
|
||||
// tmux's pty flush window. Mirrors scripts/paliadin-shim:send_to_pane.
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-time.After(200 * time.Millisecond):
|
||||
}
|
||||
// Trailing Enter. tmux send-keys treats "Enter" as a special key name.
|
||||
if err := runTmux(ctx, "send-keys", "-t", target, "Enter"); err != nil {
|
||||
return err
|
||||
|
||||
@@ -126,9 +126,19 @@ ensure_pane() {
|
||||
}
|
||||
|
||||
# send_to_pane writes a literal string then Enter.
|
||||
#
|
||||
# Settle delay between the literal paste and the Enter: Claude Code's
|
||||
# TUI debounces keyboard input; if Enter lands while the paste is still
|
||||
# being absorbed, the carriage-return collapses into the input buffer
|
||||
# as a literal newline character instead of registering as a "submit"
|
||||
# gesture, leaving the prompt typed but unsubmitted (m's dogfood
|
||||
# 2026-05-08 20:35: "lacking an enter key... or too fast"). 200ms is
|
||||
# below the human-perceptible threshold but well above tmux's pty flush
|
||||
# window.
|
||||
send_to_pane() {
|
||||
local target="$1" msg="$2"
|
||||
tmux send-keys -t "$target" -l -- "$msg"
|
||||
sleep 0.2
|
||||
tmux send-keys -t "$target" Enter
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user