Skip to content

fix: WezTerm completion hook response requires manual Enter#149

Merged
bfly123 merged 1 commit intobfly123:mainfrom
M-Marbouh:fix/wezterm-completion-hook-enter
Mar 30, 2026
Merged

fix: WezTerm completion hook response requires manual Enter#149
bfly123 merged 1 commit intobfly123:mainfrom
M-Marbouh:fix/wezterm-completion-hook-enter

Conversation

@M-Marbouh
Copy link
Copy Markdown
Contributor

@M-Marbouh M-Marbouh commented Mar 21, 2026

Problem

When the completion hook delivers a response back to a Claude Code pane in
WezTerm, the user must press Enter manually to submit it. The response text
appears in the input buffer but is never auto-submitted.

Root cause: send_via_wezterm() in the completion hook sent the multi-line
response with --no-paste, causing each \n character to arrive as a raw LF
keystroke (0x0A). Claude Code runs as a raw-mode TUI that does not submit on
LF — it requires a real Enter key event. The subsequent \r byte fallback was
also insufficient for raw-mode TUIs.

The send path (terminal.py WeztermBackend.send_text) already handles this
correctly: bracketed paste for the body + wezterm cli send-key --key Enter.
The completion hook was inconsistent with this pattern.

Fix

  • Send the response body using bracketed paste mode (omit --no-paste) so
    intermediate \n characters are treated as literal newlines in a paste block
  • After a 0.1s pause for the TUI to process the paste, send a proper Enter key
    event via wezterm cli send-key, trying --key Enter then positional Enter
    across WezTerm CLI versions, with a \r byte final fallback

Tmux is not affected: send_via_tmux() already uses paste-buffer +
send-keys Enter correctly.

May also reduce some cases in #142 where fragmented \n keystrokes caused
incomplete delivery of responses to Claude Code.

267/268 tests pass (1 pre-existing flaky threading test).

The 1 failing test (test_per_session_worker_pool_reuses_same_key) is a pre-existing flaky threading test that fails consistently across all recent runs on main and other PRs — not related to this change. 267/268 tests pass.

… response

When the completion hook delivers a Codex/Gemini response back to a Claude
Code pane, the multi-line message was sent with --no-paste, causing each \n
character to arrive as a raw LF keystroke. Claude Code runs as a raw-mode TUI
that does not submit on LF (0x0A) — it requires a real Enter key event. As a
result, the response was pasted into the input buffer but never auto-submitted,
requiring the user to press Enter manually.

The send path (terminal.py WeztermBackend.send_text) already handles this
correctly: it uses bracketed paste mode for multi-line content, then calls
_send_enter() which uses `wezterm cli send-key --key Enter`. The completion
hook's send_via_wezterm() was inconsistent with this pattern.

Fix:
- Send the response body using bracketed paste mode (omit --no-paste) so
  intermediate \n chars are treated as literal newlines in a paste block
- After a brief pause (0.1s) to let the TUI process the paste, send a proper
  Enter key event via `wezterm cli send-key`, trying both --key Enter and
  positional Enter across WezTerm CLI versions, with a \r byte fallback

Tmux is not affected: send_via_tmux() already uses paste-buffer + send-keys Enter.

May also reduce cases reported in bfly123#142 where fragmented \n keystrokes caused
incomplete delivery of the response to Claude Code's input.
patrickrho-patty added a commit to patrickrho-patty/claude_code_bridge that referenced this pull request Mar 23, 2026
…tion

When multiple Claude Code instances run in the same project directory,
completion hook responses were routed to the wrong instance because all
instances share a single session file (.claude-session). The session file
contains one pane_id, which gets overwritten by whichever instance wrote
last — so responses always went to that instance, not the one that
originated the request.

Fix: capture the caller's terminal pane ID (WEZTERM_PANE or TMUX_PANE)
at ask-time and thread it through the entire request chain:

  ask (capture) → daemon RPC → ProviderRequest → adapter →
  notify_completion → completion hook env → direct terminal send

When CCB_CALLER_PANE_ID is set, the completion hook sends directly to
that pane, bypassing the session file lookup entirely. When unset (older
ask clients), the existing session-file-based routing is preserved as
fallback.

Also fixes auto-submit on older WezTerm versions (pre-send-key):
replaces the send-key Enter approach with a trailing \n in the bracketed
paste payload, which triggers submission in raw-mode TUIs like Claude
Code across all WezTerm versions.

Changes (13 files):
- bin/ask: _caller_pane_info() helper, threads pane ID through daemon
  request and background script env vars
- bin/ccb-completion-hook: direct pane routing fast path; session file
  search moved to else branch (skipped when direct pane available);
  simplified send_via_wezterm using trailing \n instead of send-key
- lib/askd/adapters/base.py: caller_pane_id/caller_terminal fields on
  ProviderRequest
- lib/askd/daemon.py: reads caller_pane_id/caller_terminal from RPC msg
- lib/completion_hook.py: passes CCB_CALLER_PANE_ID/CCB_CALLER_TERMINAL
  env vars to hook subprocess
- All 7 adapter files: forward caller_pane_id/caller_terminal to
  notify_completion

Related: bfly123#142, bfly123#149
268/268 tests pass.
@bfly123 bfly123 merged commit 6f2bcaf into bfly123:main Mar 30, 2026
3 of 13 checks passed
@M-Marbouh M-Marbouh deleted the fix/wezterm-completion-hook-enter branch March 30, 2026 06:55
M-Marbouh added a commit to M-Marbouh/claude_code_bridge that referenced this pull request Mar 30, 2026
WezTerm builds pre-dating send-key (e.g. 20240203) fall through to the
CR byte fallback immediately after send-text completes. Without a short
delay, the \r arrives before the TUI has finished processing the
bracketed paste sequence, causing Claude Code to ignore it and require
a manual Enter.

Add time.sleep(0.1) before any Enter-sending attempt so the bracketed
paste is fully consumed first. Reproduces the timing that was present
in bfly123#149 and was inadvertently dropped in bfly123#151.

Fixes: bfly123#149 regression introduced by bfly123#151 on older WezTerm versions.
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.

2 participants