Skip to content

fix: prevent DCS passthrough race in tdl causing nvim E349 on startup#5256

Open
peregrinus879 wants to merge 1 commit intobasecamp:devfrom
peregrinus879:fix/tdl-passthrough-race
Open

fix: prevent DCS passthrough race in tdl causing nvim E349 on startup#5256
peregrinus879 wants to merge 1 commit intobasecamp:devfrom
peregrinus879:fix/tdl-passthrough-race

Conversation

@peregrinus879
Copy link
Copy Markdown

Summary

When tdl launches OpenCode (alias c) alongside nvim, OpenCode's TUI framework sends DCS passthrough terminal capability queries during initialization (wrapped as \ePtmux;\e...\eST). Because tdl creates the AI pane last, that pane has focus when send-keys fires. The queries are forwarded to the terminal emulator via allow-passthrough=on in tmux.conf.

The subsequent select-pane shifts focus to the editor pane before the terminal's responses arrive. Tmux delivers the incoming responses to the now-focused editor pane, where nvim misinterprets the leaked bytes as normal-mode commands, triggering E349 ("No identifier under cursor") as a one-time flash on startup.

Why this only affects OpenCode, not Claude Code

  • OpenCode (alias c / opencode): Its TUI framework sends DCS passthrough terminal capability queries (DECRQM, XTVERSION, Kitty graphics queries, pixel resolution queries, etc.) immediately during startup. These are the sequences that get misrouted.
  • Claude Code (alias cx / claude): Does not send DCS passthrough queries during TUI initialization. The cx alias also includes a printf screen-clear before launching, which produces only CSI sequences handled internally by tmux and generates no passthrough traffic.

Fix

Temporarily disable allow-passthrough on AI panes at creation time using per-pane tmux set-option -p, blocking the DCS queries during the race window. After the focus transition completes, a background subshell restores passthrough after 1 second, once the AI tool's TUI init is finished. This preserves full passthrough capability for AI panes during normal use.

Reproduction

  1. tmux with allow-passthrough=on and focus-events=on (Omarchy defaults)
  2. tdl c (OpenCode in AI pane, nvim in editor pane)
  3. E349 flashes in nvim on startup

Confirmed not affected

  • tdl cx (Claude Code)
  • nvim alone
  • Any tdl invocation without OpenCode

Test plan

  • Run tdl c repeatedly; E349 should never appear
  • Run tdl cx; confirm no regression
  • Run tdl c cx (dual AI); confirm no regression
  • Confirm passthrough still works on AI panes after the 1-second restore (e.g., any tool needing DCS passthrough)
  • Test over SSH to confirm fix holds with network latency

🤖 Generated with Claude Code

When tdl launches OpenCode (alias c) alongside nvim, OpenCode's TUI
framework sends DCS passthrough terminal capability queries during
initialization (wrapped as \ePtmux;\e...\eST). Because tdl creates the
AI pane last, that pane has focus when send-keys fires. The queries are
forwarded to the terminal emulator via allow-passthrough=on (tmux.conf).
The subsequent select-pane shifts focus to the editor pane before the
terminal's responses arrive. Tmux delivers incoming responses to the
now-focused editor pane, where nvim misinterprets the leaked bytes as
normal-mode commands, triggering E349 ("No identifier under cursor")
as a one-time flash on startup.

This does not occur with Claude Code (alias cx) because Claude Code
does not send DCS passthrough queries during TUI initialization. The
cx alias also includes a printf screen-clear before launching, which
produces only CSI sequences handled internally by tmux and generates
no passthrough traffic.

The fix temporarily disables allow-passthrough on AI panes at creation
time, blocking the DCS queries during the race window. After the focus
transition completes, a background subshell restores passthrough after
1 second, once the AI tool's TUI init is finished. This preserves full
passthrough capability for AI panes during normal use.

Reproduction:
  1. tmux with allow-passthrough=on and focus-events=on (default)
  2. tdl c (OpenCode in AI pane, nvim in editor pane)
  3. E349 flashes in nvim on startup

Confirmed not affected: tdl cx, nvim alone, any tdl without OpenCode.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 8, 2026 14:21
peregrinus879 added a commit to peregrinus879/dotfiles-arch that referenced this pull request Apr 8, 2026
OpenCode's TUI sends DCS passthrough capability queries during init.
When tdl switches focus to the editor pane before responses arrive,
tmux misroutes them to nvim, triggering E349. Guard AI panes with
per-pane allow-passthrough=off during init, restore after 1 second.

Claude Code is not affected. Proposed upstream in basecamp/omarchy#5256.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a race condition where OpenCode's DCS passthrough terminal capability queries during TUI initialization are misrouted to the editor pane, causing nvim to display E349 ("No identifier under cursor") on startup.

Changes:

  • Disable allow-passthrough on AI panes immediately after creation to block DCS queries during the race window
  • Disable allow-passthrough on secondary AI pane if present
  • Re-enable allow-passthrough on AI panes after 1 second via background subshell, once OpenCode's TUI initialization completes

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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