feat(send): ✨ add slash-command mode for precise input control
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
f11e820d86
commit
a74af5e613
1 changed files with 41 additions and 2 deletions
43
bin/rclaude
43
bin/rclaude
|
|
@ -808,8 +808,31 @@ cmd_list() {
|
||||||
# rclaude send --match <pat> -- <text...>
|
# rclaude send --match <pat> -- <text...>
|
||||||
# rclaude send ... --yes -- <text...> # actually send (default: preview)
|
# rclaude send ... --yes -- <text...> # actually send (default: preview)
|
||||||
# rclaude send ... --dry-run -- <text...> # explicit preview (overrides --yes)
|
# rclaude send ... --dry-run -- <text...> # explicit preview (overrides --yes)
|
||||||
|
# rclaude send ... --slash -- /foo bar # slash-command mode (see below)
|
||||||
|
#
|
||||||
|
# Input-buffer contract (important — read before debugging missing sends):
|
||||||
|
#
|
||||||
|
# Delivery uses `tmux send-keys -l` followed by `Enter`. tmux types into
|
||||||
|
# whatever buffer is currently focused in the target pane — it has no notion
|
||||||
|
# of "Claude prompt-ready". Two consequences:
|
||||||
|
#
|
||||||
|
# 1. If Claude is mid-turn or already has buffered text in its input area
|
||||||
|
# (queued user input, a partial draft), the new text is APPENDED. The
|
||||||
|
# single Enter submits the merged blob as ONE user message. To stop
|
||||||
|
# that, every send first clears the input line (`C-a C-k`) before
|
||||||
|
# typing the payload.
|
||||||
|
#
|
||||||
|
# 2. Slash commands like `/remote-control claire-plum` only fire when they
|
||||||
|
# are the ENTIRE user message (leading `/`, no surrounding text). Use
|
||||||
|
# `--slash` to enforce this: the text must begin with `/`, must not
|
||||||
|
# contain newlines, and the line-clear is mandatory. Without --slash,
|
||||||
|
# a leading `/` is just text — easy to accidentally turn a slash
|
||||||
|
# command into prose.
|
||||||
|
#
|
||||||
|
# Concurrent sends to the same pane can still race the input buffer. Callers
|
||||||
|
# that need ordering should serialize externally (flock on a per-pane lock).
|
||||||
cmd_send() {
|
cmd_send() {
|
||||||
_sel=""; _pat=""; _dry=0; _yes=0
|
_sel=""; _pat=""; _dry=0; _yes=0; _slash=0
|
||||||
while [ $# -gt 0 ]; do
|
while [ $# -gt 0 ]; do
|
||||||
case $1 in
|
case $1 in
|
||||||
--all) [ -n "$_sel" ] && { echo "rclaude send: only one selector allowed" >&2; exit 2; }
|
--all) [ -n "$_sel" ] && { echo "rclaude send: only one selector allowed" >&2; exit 2; }
|
||||||
|
|
@ -824,6 +847,7 @@ cmd_send() {
|
||||||
_sel=match; _pat=${1#--match=}; shift ;;
|
_sel=match; _pat=${1#--match=}; shift ;;
|
||||||
--dry-run) _dry=1; shift ;;
|
--dry-run) _dry=1; shift ;;
|
||||||
--yes) _yes=1; shift ;;
|
--yes) _yes=1; shift ;;
|
||||||
|
--slash) _slash=1; shift ;;
|
||||||
--) shift; break ;;
|
--) shift; break ;;
|
||||||
-*) echo "rclaude send: unknown flag: $1" >&2; exit 2 ;;
|
-*) echo "rclaude send: unknown flag: $1" >&2; exit 2 ;;
|
||||||
*) break ;;
|
*) break ;;
|
||||||
|
|
@ -832,12 +856,16 @@ cmd_send() {
|
||||||
|
|
||||||
if [ -z "$_sel" ]; then
|
if [ -z "$_sel" ]; then
|
||||||
cat >&2 <<'EOF'
|
cat >&2 <<'EOF'
|
||||||
usage: rclaude send (--all | --host <h> | --match <pat>) [--dry-run] [--yes] -- <text...>
|
usage: rclaude send (--all | --host <h> | --match <pat>) [--dry-run] [--yes] [--slash] -- <text...>
|
||||||
--all target every live claude-* tmux session on scan_hosts
|
--all target every live claude-* tmux session on scan_hosts
|
||||||
--host <h> target every claude-* session on a specific host
|
--host <h> target every claude-* session on a specific host
|
||||||
--match <pat> substring match against tmux session name (which embeds slug)
|
--match <pat> substring match against tmux session name (which embeds slug)
|
||||||
--dry-run preview targets and exit (default unless --yes is passed)
|
--dry-run preview targets and exit (default unless --yes is passed)
|
||||||
--yes actually deliver (still prints preview first)
|
--yes actually deliver (still prints preview first)
|
||||||
|
--slash slash-command mode: text must start with '/', no newlines;
|
||||||
|
the input line is force-cleared before the payload so the
|
||||||
|
command lands solo (any buffered text is discarded). Use
|
||||||
|
this for /remote-control, /clear, etc.
|
||||||
EOF
|
EOF
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
@ -848,6 +876,17 @@ EOF
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$_slash" = 1 ]; then
|
||||||
|
case $_text in
|
||||||
|
/*) ;;
|
||||||
|
*) echo "rclaude send --slash: text must start with '/' (got: $_text)" >&2; exit 2 ;;
|
||||||
|
esac
|
||||||
|
case $_text in
|
||||||
|
*"$(printf '\n')"*)
|
||||||
|
echo "rclaude send --slash: text must not contain newlines" >&2; exit 2 ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
# Gather candidate rows across all hosts, then filter.
|
# Gather candidate rows across all hosts, then filter.
|
||||||
_rows=$(scan_hosts | while IFS= read -r _h; do list_tmux_on "$_h"; done \
|
_rows=$(scan_hosts | while IFS= read -r _h; do list_tmux_on "$_h"; done \
|
||||||
| filter_targets "$_sel" "$_pat")
|
| filter_targets "$_sel" "$_pat")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue