Skip to content

fix(watch): copy backend cascade + tmux load-buffer + env pre-flight#35

Merged
jiunbae merged 1 commit into
mainfrom
fix/copy-tmux-osc52-fallback
May 6, 2026
Merged

fix(watch): copy backend cascade + tmux load-buffer + env pre-flight#35
jiunbae merged 1 commit into
mainfrom
fix/copy-tmux-osc52-fallback

Conversation

@jiunbae
Copy link
Copy Markdown
Member

@jiunbae jiunbae commented May 6, 2026

Summary

User on a headless SSH dev box hit `copy failed: xclip exited with 1` when pressing `c` in `muxa watch`. `xclip` was on PATH so the priority list tried it; without `$DISPLAY` set the binary exits 1, and the dispatch surfaced that failure to the user instead of cascading.

Three improvements

  1. Lead with `tmux load-buffer` when `$TMUX` is set. Loads the prompt into tmux's paste buffer (`prefix + ]`); on tmux 3.2+ with `set -g set-clipboard on` it also forwards to the host terminal's clipboard via OSC 52. Single backend covers most of the "remote dev over SSH" case.
  2. Pre-flight env check before each X11/Wayland backend: skip `wl-copy` if `$WAYLAND_DISPLAY` is unset, skip `xclip` / `xsel` if `$DISPLAY` is unset. Prevents the misleading "xclip exit 1" surface entirely on headless hosts.
  3. Cascade past `Failed`, not just `NotFound`. Combined with (2), the chain now only contains plausibly-working backends, so any failure cleanly falls through to the next.

`xsel` added as another X11 candidate.

Test plan

  • `cargo test --workspace` — 477 / 477 (existing recorder-based tests don't shell out)
  • `cargo clippy --workspace --all-targets -- -D warnings` — clean
  • `cargo fmt --all -- --check` — clean
  • Manual: this dev box (SSH, no $DISPLAY, in tmux) reproduces the original bug pre-fix; with this fix `c` should land in tmux's paste buffer.

🤖 Generated with Claude Code

User on a headless SSH dev box hit `copy failed: xclip exited with 1`
when pressing `c` in `muxa watch`. Root cause: `xclip` was on PATH
so the previous backend list tried it; with `$DISPLAY` unset the
binary exits 1, and the dispatch surfaced that failure to the user
instead of cascading to the /tmp fallback.

Three improvements:

1. Lead with `tmux load-buffer` when `$TMUX` is set. Loads the
   prompt into tmux's paste buffer (`prefix + ]`); on tmux 3.2+
   with `set -g set-clipboard on` it also forwards to the host
   terminal's clipboard via OSC 52. A single backend covers most
   of the "remote dev over SSH" case where xclip/wl-copy can't
   reach a display server.

2. Pre-flight env check before each X11/Wayland backend:
   `wl-copy` requires `$WAYLAND_DISPLAY`; `xclip` / `xsel` require
   `$DISPLAY`. If the env var is unset we skip the backend
   entirely instead of running it and waiting for it to fail.

3. Cascade past `Failed`, not just `NotFound`. The original code
   bubbled `Failed` to the user — the comment said "so the user
   sees `xclip: ...` rather than a silent /tmp surprise" — but
   that's only the right call if there's no further backend to
   try. With the env pre-flight in place the chain only contains
   plausibly-working backends, so a Failed from any of them means
   "this one really didn't work, try the next."

Also added `xsel` as another X11 candidate for users who don't
install xclip.

Tests pass without modification — the existing recorder-based
tests don't actually invoke clipboard helpers; they just exercise
the action-dispatch state machine. Workspace 477 → 477 (same), but
clippy required two minor adjustments alongside the rewrite:

- `PipeErr::Failed(String)` is now `#[allow(dead_code)]` — the
  cascade past Failed means callers don't read the message; it
  stays for debug traces and future use.
- Used `is_ok()` instead of a `match` over a single happy-path
  variant in the new dispatch loop (clippy `single_match`).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jiunbae jiunbae merged commit 7f6367c into main May 6, 2026
6 checks passed
@jiunbae jiunbae deleted the fix/copy-tmux-osc52-fallback branch May 6, 2026 01:07
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