Skip to content

Commit be86356

Browse files
committed
fix(scripts): improve tmux-send.sh reliability and add --paste flag
- Add retry logic for session detection (default 3 attempts with 0.3s delay) - Add --paste flag to paste clipboard content via bracketed paste mode - Add --retry N option to customize retry count - Update README with new options and examples Fixes issue where --key option would fail to find sessions that exist due to race conditions in session registration.
1 parent c566f4c commit be86356

File tree

2 files changed

+91
-4
lines changed

2 files changed

+91
-4
lines changed

scripts/tmux/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,13 @@ Send input to a running session.
121121
./scripts/tmux/tmux-send.sh SESSION --key Escape
122122
./scripts/tmux/tmux-send.sh SESSION --key C-c
123123
./scripts/tmux/tmux-send.sh SESSION --key Enter
124+
125+
# Paste clipboard content and submit immediately
126+
./scripts/tmux/tmux-send.sh SESSION --paste
127+
128+
# Paste clipboard but don't submit (useful for testing attachment UI)
129+
# This lets you capture a screenshot of the attachment card before sending
130+
./scripts/tmux/tmux-send.sh SESSION --paste --no-enter
124131
```
125132

126133
### `tmux-capture.sh`

scripts/tmux/tmux-send.sh

Lines changed: 84 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
# USAGE:
1717
# ./scripts/tmux/tmux-send.sh SESSION_NAME "your text here"
1818
# ./scripts/tmux/tmux-send.sh SESSION_NAME --key KEY
19+
# ./scripts/tmux/tmux-send.sh SESSION_NAME --paste
1920
#
2021
# ARGUMENTS:
2122
# SESSION_NAME Name of the tmux session
@@ -24,8 +25,15 @@
2425
# OPTIONS:
2526
# --key KEY Send a special key instead of text
2627
# Supported: Enter, Escape, Up, Down, Left, Right,
27-
# C-c, C-u, C-d, Tab
28+
# C-c, C-u, C-d, C-v, Tab
29+
# --paste Paste current clipboard content using bracketed paste
30+
# mode. This triggers the CLI's paste handler correctly,
31+
# unlike --key C-v which just sends the raw keystroke.
32+
# By default, Enter is pressed after pasting. Use with
33+
# --no-enter to paste without submitting (useful for
34+
# testing attachment UI before sending).
2835
# --no-enter Don't automatically press Enter after text
36+
# --retry N Retry session detection N times (default: 3)
2937
# --help Show this help message
3038
#
3139
# EXAMPLES:
@@ -41,6 +49,12 @@
4149
# # Send Ctrl+C to interrupt
4250
# ./scripts/tmux/tmux-send.sh cli-test-123 --key C-c
4351
#
52+
# # Paste clipboard content and submit immediately
53+
# ./scripts/tmux/tmux-send.sh cli-test-123 --paste
54+
#
55+
# # Paste clipboard content but don't submit (view attachment card first)
56+
# ./scripts/tmux/tmux-send.sh cli-test-123 --paste --no-enter
57+
#
4458
# WHY BRACKETED PASTE?
4559
# The Codebuff CLI uses OpenTUI for rendering, which processes keyboard
4660
# input character-by-character. When tmux sends characters rapidly,
@@ -62,6 +76,9 @@ PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
6276
# Defaults
6377
AUTO_ENTER=true
6478
SPECIAL_KEY=""
79+
PASTE_CLIPBOARD=false
80+
RETRY_COUNT=3
81+
RETRY_DELAY=0.3
6582

6683
# Check minimum arguments
6784
if [[ $# -lt 1 ]]; then
@@ -89,10 +106,18 @@ while [[ $# -gt 0 ]]; do
89106
SPECIAL_KEY="$2"
90107
shift 2
91108
;;
109+
--paste)
110+
PASTE_CLIPBOARD=true
111+
shift
112+
;;
92113
--no-enter)
93114
AUTO_ENTER=false
94115
shift
95116
;;
117+
--retry)
118+
RETRY_COUNT="$2"
119+
shift 2
120+
;;
96121
--help)
97122
head -n 55 "$0" | tail -n +2 | sed 's/^# //' | sed 's/^#//'
98123
exit 0
@@ -104,9 +129,21 @@ while [[ $# -gt 0 ]]; do
104129
esac
105130
done
106131

107-
# Verify session exists
108-
if ! tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
109-
echo "❌ Session '$SESSION_NAME' not found" >&2
132+
# Verify session exists with retry logic
133+
# Sometimes sessions take a moment to be fully registered
134+
SESSION_FOUND=false
135+
for ((i=1; i<=RETRY_COUNT; i++)); do
136+
if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
137+
SESSION_FOUND=true
138+
break
139+
fi
140+
if [[ $i -lt $RETRY_COUNT ]]; then
141+
sleep "$RETRY_DELAY"
142+
fi
143+
done
144+
145+
if [[ "$SESSION_FOUND" != true ]]; then
146+
echo "❌ Session '$SESSION_NAME' not found after $RETRY_COUNT attempts" >&2
110147
echo " Run: tmux list-sessions" >&2
111148
exit 1
112149
fi
@@ -130,6 +167,49 @@ EOF
130167
exit 0
131168
fi
132169

170+
# Paste clipboard content if --paste flag is set
171+
if [[ "$PASTE_CLIPBOARD" == true ]]; then
172+
# Get clipboard content using pbpaste (macOS) or xclip (Linux)
173+
if command -v pbpaste &>/dev/null; then
174+
CLIPBOARD_CONTENT=$(pbpaste)
175+
elif command -v xclip &>/dev/null; then
176+
CLIPBOARD_CONTENT=$(xclip -selection clipboard -o)
177+
elif command -v xsel &>/dev/null; then
178+
CLIPBOARD_CONTENT=$(xsel --clipboard --output)
179+
else
180+
echo "❌ No clipboard utility found (pbpaste, xclip, or xsel)" >&2
181+
exit 1
182+
fi
183+
184+
if [[ -z "$CLIPBOARD_CONTENT" ]]; then
185+
echo "❌ Clipboard is empty" >&2
186+
exit 1
187+
fi
188+
189+
# Send clipboard content using bracketed paste mode
190+
tmux send-keys -t "$SESSION_NAME" $'\e[200~'"$CLIPBOARD_CONTENT"$'\e[201~'
191+
192+
# Optionally press Enter
193+
if [[ "$AUTO_ENTER" == true ]]; then
194+
tmux send-keys -t "$SESSION_NAME" Enter
195+
fi
196+
197+
# Log the paste as YAML
198+
SESSION_DIR="$PROJECT_ROOT/debug/tmux-sessions/$SESSION_NAME"
199+
if [[ -d "$SESSION_DIR" ]]; then
200+
TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
201+
CONTENT_LENGTH=${#CLIPBOARD_CONTENT}
202+
cat >> "$SESSION_DIR/commands.yaml" << EOF
203+
- timestamp: $TIMESTAMP
204+
type: paste
205+
content_length: $CONTENT_LENGTH
206+
auto_enter: $AUTO_ENTER
207+
EOF
208+
fi
209+
210+
exit 0
211+
fi
212+
133213
# Check if text was provided
134214
if [[ -z "$TEXT" ]]; then
135215
echo "❌ No text or --key specified" >&2

0 commit comments

Comments
 (0)