Skip to content

Commit 707856c

Browse files
authored
add cmux terminal support for overlay launcher (umputun#35)
* add cmux terminal support for overlay launcher cmux (https://cmux.com) is a native macOS terminal for AI coding agents built on libghostty. It sets TERM_PROGRAM=ghostty, which causes the existing Ghostty AppleScript path to fail. Detect cmux first via $CMUX_SURFACE_ID and use its CLI API (new-split + send --surface) instead of AppleScript. * replace sleep with wait-for synchronization for shell readiness Instead of a fixed sleep 0.5 before sending commands to the new split, use cmux wait-for as a sync primitive: retry a compound signal-and-exec command until the shell processes it. Adapts to any shell startup time. * simplify: single send instead of retry loop The pty input buffer holds text until the shell reads it, so a single cmux send immediately after new-split is sufficient. No retry loop, no wait-for synchronization, no visual noise in the split pane.
1 parent 29dfea5 commit 707856c

10 files changed

Lines changed: 94 additions & 13 deletions

File tree

.claude-plugin/skills/revdiff/SKILL.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: revdiff
3-
description: Review diffs, files, and documents with inline annotations in a TUI overlay, or answer questions about revdiff usage, configuration, themes, and keybindings. Opens revdiff in tmux/kitty/wezterm/ghostty/iterm2/emacs-vterm, captures annotations, and addresses them. Activates on "revdiff", "review diff", "annotate diff", "git review with revdiff", "interactive diff review", "revdiff all files", "review all files", "browse all files", "revdiff config", "revdiff themes", "revdiff keybindings", "how to configure revdiff", "what themes does revdiff have".
3+
description: Review diffs, files, and documents with inline annotations in a TUI overlay, or answer questions about revdiff usage, configuration, themes, and keybindings. Opens revdiff in tmux/kitty/wezterm/cmux/ghostty/iterm2/emacs-vterm, captures annotations, and addresses them. Activates on "revdiff", "review diff", "annotate diff", "git review with revdiff", "interactive diff review", "revdiff all files", "review all files", "browse all files", "revdiff config", "revdiff themes", "revdiff keybindings", "how to configure revdiff", "what themes does revdiff have".
44
argument-hint: 'optional: git ref(s), "all files", or file path'
55
allowed-tools: [Bash, Read, Edit, Write, Grep, Glob]
66
---
@@ -26,7 +26,7 @@ If the user asks a question about revdiff (configuration, themes, keybindings, i
2626

2727
## How It Works
2828

29-
1. Launch revdiff in a terminal overlay (tmux popup, kitty overlay, wezterm split-pane, ghostty split+zoom, iTerm2 split pane, or Emacs vterm frame)
29+
1. Launch revdiff in a terminal overlay (tmux popup, kitty overlay, wezterm split-pane, cmux split, ghostty split+zoom, iTerm2 split pane, or Emacs vterm frame)
3030
2. User navigates the diff, adds annotations on specific lines
3131
3. On quit, annotations are captured from stdout
3232
4. Claude reads annotations and addresses each one
@@ -88,7 +88,7 @@ ${CLAUDE_PLUGIN_ROOT}/.claude-plugin/skills/revdiff/scripts/launch-revdiff.sh [b
8888
```
8989

9090
The script:
91-
- Detects available terminal (tmux → kitty → wezterm → ghostty → iTerm2 → Emacs vterm)
91+
- Detects available terminal (tmux → kitty → wezterm → cmux → ghostty → iTerm2 → Emacs vterm)
9292
- Launches revdiff in an overlay
9393
- Captures annotation output to a temp file
9494
- Prints captured annotations to stdout

.claude-plugin/skills/revdiff/references/install.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ go install github.com/umputun/revdiff/cmd/revdiff@latest
1919
/plugin install revdiff@umputun-revdiff
2020
```
2121

22-
Use: `/revdiff [base] [against]` — opens review session in a terminal overlay (tmux, kitty, wezterm, ghostty, iTerm2, or Emacs vterm).
22+
Use: `/revdiff [base] [against]` — opens review session in a terminal overlay (tmux, kitty, wezterm, cmux, ghostty, iTerm2, or Emacs vterm).
2323

2424
### Plan Review Plugin
2525

.claude-plugin/skills/revdiff/scripts/launch-revdiff.sh

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/env bash
2-
# launch revdiff in a terminal overlay (tmux/kitty/wezterm/ghostty/iterm2) and capture annotations.
2+
# launch revdiff in a terminal overlay (tmux/kitty/wezterm/cmux/ghostty/iterm2) and capture annotations.
33
# usage: launch-revdiff.sh [ref] [--staged] [--only=file1 ...]
44
# output: annotation text from revdiff stdout (empty if no annotations)
55

@@ -90,6 +90,43 @@ if [ -n "${WEZTERM_PANE:-}" ] && command -v wezterm >/dev/null 2>&1; then
9090
exit 0
9191
fi
9292

93+
# cmux: split pane via cmux CLI (must precede ghostty — cmux also sets TERM_PROGRAM=ghostty)
94+
if [ -n "${CMUX_SURFACE_ID:-}" ] && command -v cmux >/dev/null 2>&1; then
95+
SENTINEL=$(mktemp /tmp/revdiff-done-XXXXXX)
96+
rm -f "$SENTINEL"
97+
98+
LAUNCH_SCRIPT=$(mktemp /tmp/revdiff-launch-XXXXXX.sh)
99+
trap 'rm -f "$OUTPUT_FILE" "$SENTINEL" "$LAUNCH_SCRIPT"' EXIT
100+
cat > "$LAUNCH_SCRIPT" <<LAUNCHER
101+
#!/bin/sh
102+
$REVDIFF_CMD; touch '$SENTINEL'
103+
LAUNCHER
104+
chmod +x "$LAUNCH_SCRIPT"
105+
106+
# capture new surface ref from "OK surface:N ..." output
107+
CMUX_NEW=$(cmux new-split down 2>&1) || true
108+
CMUX_SURF=$(echo "$CMUX_NEW" | grep -o 'surface:[0-9]*' | head -1)
109+
110+
# send exec command immediately — the pty input buffer holds the text
111+
# until the new pane's shell finishes initializing and reads it
112+
if [ -n "$CMUX_SURF" ]; then
113+
cmux send --surface "$CMUX_SURF" "exec $LAUNCH_SCRIPT\n"
114+
else
115+
cmux send "exec $LAUNCH_SCRIPT\n"
116+
fi
117+
118+
while [ ! -f "$SENTINEL" ]; do
119+
sleep 0.3
120+
done
121+
# close the split pane
122+
if [ -n "$CMUX_SURF" ]; then
123+
cmux close-surface --surface "$CMUX_SURF" 2>/dev/null || true
124+
fi
125+
rm -f "$SENTINEL" "$LAUNCH_SCRIPT"
126+
cat "$OUTPUT_FILE"
127+
exit 0
128+
fi
129+
93130
# ghostty: split pane via AppleScript (macOS only, requires Ghostty 1.3.0+)
94131
if [ "${TERM_PROGRAM:-}" = "ghostty" ] && command -v osascript >/dev/null 2>&1; then
95132

@@ -280,5 +317,5 @@ LAUNCHER
280317
exit 0
281318
fi
282319

283-
echo "error: no overlay terminal available (requires tmux, kitty, wezterm, ghostty, iTerm2, or emacs vterm)" >&2
320+
echo "error: no overlay terminal available (requires tmux, kitty, wezterm, cmux, ghostty, iTerm2, or emacs vterm)" >&2
284321
exit 1

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,14 @@ The plugin requires one of the following terminals since Claude Code itself cann
5959
| **tmux** | `display-popup` (blocks until quit) | `$TMUX` env var |
6060
| **kitty** | `kitty @ launch --type=overlay` | `$KITTY_LISTEN_ON` env var |
6161
| **wezterm** | `wezterm cli split-pane` | `$WEZTERM_PANE` env var |
62+
| **cmux** | `cmux new-split` + `cmux send` | `$CMUX_SURFACE_ID` env var |
6263
| **ghostty** | AppleScript split + zoom (macOS only) | `$TERM_PROGRAM` + AppleScript probe |
6364
| **iTerm2** | `osascript` split pane (macOS only) | `$ITERM_SESSION_ID` env var |
6465
| **Emacs vterm** | New frame via `emacsclient` | `$INSIDE_EMACS` env var |
6566

66-
Priority: tmux → kitty → wezterm → ghostty → iTerm2 → Emacs vterm (first detected wins). If none are available, the plugin exits with an error.
67+
Priority: tmux → kitty → wezterm → cmux → ghostty → iTerm2 → Emacs vterm (first detected wins). If none are available, the plugin exits with an error.
68+
69+
> **Note:** cmux is detected before ghostty because cmux also sets `$TERM_PROGRAM=ghostty`. The cmux block uses the cmux CLI (`new-split` + `send --surface`) instead of Ghostty's AppleScript API.
6770
6871
> **Note:** iTerm2 uses a split pane (vertical or horizontal, auto-detected from terminal dimensions) rather than a full-screen overlay. The iTerm2 AppleScript API does not expose a zoom command, so the split view shares screen space with the invoking session.
6972

llms.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ revdiff is a terminal-based UI tool for code review and document annotation. It
3030

3131
Install: `/plugin marketplace add umputun/revdiff && /plugin install revdiff@umputun-revdiff`
3232

33-
Supports tmux, kitty, wezterm, ghostty, and iTerm2 terminal overlays.
33+
Supports tmux, kitty, wezterm, cmux, ghostty, and iTerm2 terminal overlays.
3434

3535
Usage: `/revdiff HEAD~1` or natural language like "review diff against main"
3636

plugins/revdiff-planning/scripts/launch-plan-review.sh

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,41 @@ if [ -n "${WEZTERM_PANE:-}" ] && command -v wezterm >/dev/null 2>&1; then
7878
exit 0
7979
fi
8080

81+
# cmux: split pane via cmux CLI (must precede ghostty — cmux also sets TERM_PROGRAM=ghostty)
82+
if [ -n "${CMUX_SURFACE_ID:-}" ] && command -v cmux >/dev/null 2>&1; then
83+
SENTINEL=$(mktemp /tmp/plan-review-done-XXXXXX)
84+
rm -f "$SENTINEL"
85+
86+
LAUNCH_SCRIPT=$(mktemp /tmp/plan-review-launch-XXXXXX.sh)
87+
trap 'rm -f "$OUTPUT_FILE" "$SENTINEL" "$LAUNCH_SCRIPT"' EXIT
88+
cat > "$LAUNCH_SCRIPT" <<LAUNCHER
89+
#!/bin/sh
90+
$REVDIFF_CMD; touch '$SENTINEL'
91+
LAUNCHER
92+
chmod +x "$LAUNCH_SCRIPT"
93+
94+
CMUX_NEW=$(cmux new-split down 2>&1) || true
95+
CMUX_SURF=$(echo "$CMUX_NEW" | grep -o 'surface:[0-9]*' | head -1)
96+
97+
# send exec command immediately — the pty input buffer holds the text
98+
# until the new pane's shell finishes initializing and reads it
99+
if [ -n "$CMUX_SURF" ]; then
100+
cmux send --surface "$CMUX_SURF" "exec $LAUNCH_SCRIPT\n"
101+
else
102+
cmux send "exec $LAUNCH_SCRIPT\n"
103+
fi
104+
105+
while [ ! -f "$SENTINEL" ]; do
106+
sleep 0.3
107+
done
108+
if [ -n "$CMUX_SURF" ]; then
109+
cmux close-surface --surface "$CMUX_SURF" 2>/dev/null || true
110+
fi
111+
rm -f "$SENTINEL" "$LAUNCH_SCRIPT"
112+
cat "$OUTPUT_FILE"
113+
exit 0
114+
fi
115+
81116
# ghostty: split pane via AppleScript (macOS only, requires Ghostty 1.3.0+)
82117
if [ "${TERM_PROGRAM:-}" = "ghostty" ] && command -v osascript >/dev/null 2>&1; then
83118

@@ -257,5 +292,5 @@ LAUNCHER
257292
exit 0
258293
fi
259294

260-
echo "error: no overlay terminal available (requires tmux, kitty, wezterm, ghostty, iTerm2, or emacs vterm)" >&2
295+
echo "error: no overlay terminal available (requires tmux, kitty, wezterm, cmux, ghostty, iTerm2, or emacs vterm)" >&2
261296
exit 1

plugins/revdiff-planning/scripts/plan-review-hook.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
1212
requirements:
1313
- revdiff binary in PATH
14-
- tmux, kitty, wezterm, or ghostty (macOS) terminal
14+
- tmux, kitty, wezterm, cmux, or ghostty (macOS) terminal
1515
"""
1616

1717
import json

site/docs.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,12 +352,13 @@ <h2 id="plugin-terminals">Terminal support</h2>
352352
<tr><td><strong>tmux</strong></td><td><code>display-popup</code> (blocks until quit)</td><td><code>$TMUX</code></td></tr>
353353
<tr><td><strong>kitty</strong></td><td><code>kitty @ launch --type=overlay</code></td><td><code>$KITTY_LISTEN_ON</code></td></tr>
354354
<tr><td><strong>wezterm</strong></td><td><code>wezterm cli split-pane</code></td><td><code>$WEZTERM_PANE</code></td></tr>
355+
<tr><td><strong>cmux</strong></td><td><code>cmux new-split</code> + <code>cmux send</code></td><td><code>$CMUX_SURFACE_ID</code></td></tr>
355356
<tr><td><strong>ghostty</strong></td><td>AppleScript split + zoom (macOS only)</td><td><code>$TERM_PROGRAM</code></td></tr>
356357
<tr><td><strong>iTerm2</strong></td><td>AppleScript split pane (macOS only)</td><td><code>$ITERM_SESSION_ID</code></td></tr>
357358
<tr><td><strong>Emacs vterm</strong></td><td>New frame via <code>emacsclient</code></td><td><code>$INSIDE_EMACS</code></td></tr>
358359
</tbody>
359360
</table>
360-
<p>Priority: tmux &rarr; kitty &rarr; wezterm &rarr; ghostty &rarr; iTerm2 &rarr; Emacs vterm (first detected wins). iTerm2 uses a split pane rather than a full-screen overlay.</p>
361+
<p>Priority: tmux &rarr; kitty &rarr; wezterm &rarr; cmux &rarr; ghostty &rarr; iTerm2 &rarr; Emacs vterm (first detected wins). cmux is checked before ghostty because it also sets <code>$TERM_PROGRAM=ghostty</code>. iTerm2 uses a split pane rather than a full-screen overlay.</p>
361362

362363
<h2 id="plugin-usage">Plugin usage</h2>
363364
<h3>Slash commands</h3>

site/index.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ <h2>Works with your terminal</h2>
196196
<div class="terminal-method"><code>wezterm cli split-pane</code></div>
197197
<div class="terminal-detect"><code>$WEZTERM_PANE</code></div>
198198
</div>
199+
<div class="terminal-card">
200+
<div class="terminal-name">cmux</div>
201+
<div class="terminal-method"><code>cmux new-split</code> + <code>cmux send</code></div>
202+
<div class="terminal-detect"><code>$CMUX_SURFACE_ID</code></div>
203+
</div>
199204
<div class="terminal-card">
200205
<div class="terminal-name">ghostty</div>
201206
<div class="terminal-method">AppleScript split + zoom</div>
@@ -212,7 +217,7 @@ <h2>Works with your terminal</h2>
212217
<div class="terminal-detect"><code>$INSIDE_EMACS</code></div>
213218
</div>
214219
</div>
215-
<p class="terminal-priority">Priority: tmux &rarr; kitty &rarr; wezterm &rarr; ghostty &rarr; iTerm2 &rarr; Emacs vterm</p>
220+
<p class="terminal-priority">Priority: tmux &rarr; kitty &rarr; wezterm &rarr; cmux &rarr; ghostty &rarr; iTerm2 &rarr; Emacs vterm</p>
216221
</div>
217222
</section>
218223

site/llms.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ revdiff is a terminal-based UI tool for code review and document annotation. It
3030

3131
Install: `/plugin marketplace add umputun/revdiff && /plugin install revdiff@umputun-revdiff`
3232

33-
Supports tmux, kitty, wezterm, ghostty, and iTerm2 terminal overlays.
33+
Supports tmux, kitty, wezterm, cmux, ghostty, and iTerm2 terminal overlays.
3434

3535
Usage: `/revdiff HEAD~1` or natural language like "review diff against main"
3636

0 commit comments

Comments
 (0)