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 ... --yes -- <text...> # actually send (default: preview)
|
||||
# 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() {
|
||||
_sel=""; _pat=""; _dry=0; _yes=0
|
||||
_sel=""; _pat=""; _dry=0; _yes=0; _slash=0
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
--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 ;;
|
||||
--dry-run) _dry=1; shift ;;
|
||||
--yes) _yes=1; shift ;;
|
||||
--slash) _slash=1; shift ;;
|
||||
--) shift; break ;;
|
||||
-*) echo "rclaude send: unknown flag: $1" >&2; exit 2 ;;
|
||||
*) break ;;
|
||||
|
|
@ -832,12 +856,16 @@ cmd_send() {
|
|||
|
||||
if [ -z "$_sel" ]; then
|
||||
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
|
||||
--host <h> target every claude-* session on a specific host
|
||||
--match <pat> substring match against tmux session name (which embeds slug)
|
||||
--dry-run preview targets and exit (default unless --yes is passed)
|
||||
--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
|
||||
exit 2
|
||||
fi
|
||||
|
|
@ -848,6 +876,17 @@ EOF
|
|||
exit 2
|
||||
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.
|
||||
_rows=$(scan_hosts | while IFS= read -r _h; do list_tmux_on "$_h"; done \
|
||||
| filter_targets "$_sel" "$_pat")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue