tmux send-keys silently drops the final Enter
When dispatching commands between tmux sessions, tmux send-keys -t <target> '<command>' Enter exits 0 and the command text appears in the target's input buffer — but the Enter never commits. The agent sits idle. The dispatcher sees success. Nothing happened.
This hits hardest with long commands that trigger tmux's bracketed paste mode: the trailing Enter gets absorbed into the paste block instead of executing it. Two other failure modes: the target app is in a modal state (dialog, secondary prompt) that swallows Enter, or the input handler is loaded and drops the keystroke.
The fix is a verify-and-retry loop after every dispatch:
dispatch() {
local target="$1" cmd="$2"
# 1. Send
tmux send-keys -t "$target" "$cmd" Enter
# 2. Wait for the target to start processing
sleep 3
# 3. Verify it's actually working, not just staged
if tmux capture-pane -t "$target" -p -S -10 | tail -10 \
| grep -qE "Working|Exploring|Reading|Analyzing"; then
return 0
fi
# 4. Retry — empty Enter kicks the paste buffer
tmux send-keys -t "$target" "" Enter
sleep 2
# One more check, then give up
if tmux capture-pane -t "$target" -p -S -10 | tail -10 \
| grep -qE "Working|Exploring|Reading|Analyzing"; then
return 0
fi
# 5. Fallback: write to file, let target poll for it
echo "$cmd" > "/tmp/dispatch-${target##*.}.cmd"
return 1
}
Cap retries at 2. If both fail, fall back to writing the command to a file the target reads on its own polling cycle — this sidesteps the pty entirely.
The broader lesson: any async channel where the sender gets a local exit code instead of a structured delivery ACK has this failure class. Pty pipes, shell sessions, anything interactive. If you're building multi-agent coordination over interactive channels, bake verification into the dispatch protocol and don't trust exit code 0.
Apply the same pattern in reverse for callbacks: workers should verify their "done" message was received by the dispatcher, not just fire-and-forget.