diff --git a/bin/rclaude b/bin/rclaude index 2b5f117..2825c3a 100755 --- a/bin/rclaude +++ b/bin/rclaude @@ -646,36 +646,6 @@ scan_hosts() { done } -# POSIX single-quote escape: wraps in single quotes and escapes any -# embedded single quotes via the '\'' idiom. Used to build safe remote shell -# commands for ssh — the remote shell re-parses argv, so anything containing -# spaces, $, `, etc. must be quoted before transmission. -sh_quote() { - printf "'%s'" "$(printf %s "$1" | sed "s/'/'\\\\''/g")" -} - -# Filter target rows on stdin to those matching :. -# Input rows are TSV: host\tkind\tsession\tdetail[\tcwd] -# Only KIND=tmux rows are eligible (we can only send-keys to live sessions). -# -# Selectors: -# all → every tmux row -# host → exact host match (col 1) -# match → substring in session name (col 3) OR cwd (col 5, if present). -# The tmux session name already embeds a slugified cwd via -# claude_slug(), so name-substring covers most cwd intents -# (e.g. `--match lilith` hits any session whose cwd contained -# "lilith"). Col 5 is reserved for future enrichment. -filter_targets() { - _sel=$1; _pat=$2 - awk -F '\t' -v sel="$_sel" -v pat="$_pat" ' - $2 != "tmux" { next } - sel == "all" { print; next } - sel == "host" && $1 == pat { print; next } - sel == "match" && (index($3, pat) > 0 || (NF >= 5 && index($5, pat) > 0)) { print; next } - ' -} - # --------------------------------------------------------------------------- # Subcommands # --------------------------------------------------------------------------- @@ -1323,74 +1293,6 @@ cmd_version() { fi } -cmd_send() { - # Broadcast a prompt to live rclaude tmux sessions matching a selector. - # Useful for batch-prompting agents you have running across hosts. - # - # rclaude send "fix the build" → all live rclaude tmuxes - # rclaude send --on apricot "context update" → only apricot - # rclaude send --match lilith "rebase main" → tmux name or cwd matches - # rclaude send --no-enter "draft only..." → don't press Enter after - # rclaude send --dry-run "..." → show targets, don't send - _selector=all - _pattern="" - _enter=1 - _dry=0 - _text="" - while [ $# -gt 0 ]; do - case $1 in - --on) shift; _selector=host; _pattern=${1:-}; shift ;; - --on=*) _selector=host; _pattern=${1#--on=}; shift ;; - --match) shift; _selector=match; _pattern=${1:-}; shift ;; - --match=*) _selector=match; _pattern=${1#--match=}; shift ;; - --no-enter) _enter=0; shift ;; - --dry-run|-n) _dry=1; shift ;; - --) shift; _text=$*; break ;; - -h|--help) - cat <|--match ] [--no-enter] [--dry-run] - -Broadcasts to every live rclaude tmux session matching the selector -via 'tmux send-keys'. Disk-only sessions are skipped (can't send-keys to -something not running). -EOF - return 2 ;; - *) - if [ -z "$_text" ]; then _text=$1 - else _text="$_text $1" - fi - shift ;; - esac - done - if [ -z "$_text" ]; then - echo "rclaude send: missing text. See 'rclaude send --help'" >&2 - exit 2 - fi - _rows=$(scan_hosts | while IFS= read -r _h; do list_tmux_on "$_h"; done) - _targets=$(printf '%s\n' "$_rows" | filter_targets "$_selector" "$_pattern") - if [ -z "$_targets" ]; then - echo "rclaude send: no matching live tmux sessions" >&2 - exit 1 - fi - _count=$(printf '%s\n' "$_targets" | wc -l | tr -d ' ') - printf 'rclaude send: %s target(s)\n' "$_count" >&2 - printf '%s\n' "$_targets" | while IFS=$(printf '\t') read -r _h _kind _name _rest; do - printf ' → %s : %s\n' "$_h" "$_name" >&2 - [ "$_dry" = "1" ] && continue - _qtext=$(sh_quote "$_text") - _qname=$(sh_quote "$_name") - if is_local "$_h"; then - tmux send-keys -t "$_name" -l "$_text" - [ "$_enter" = "1" ] && tmux send-keys -t "$_name" Enter - else - ssh -o BatchMode=yes -o ConnectTimeout=5 "$_h" \ - "tmux send-keys -t $_qname -l $_qtext" - [ "$_enter" = "1" ] && \ - ssh -o BatchMode=yes "$_h" "tmux send-keys -t $_qname Enter" - fi - done -} - cmd_voice() { # `rclaude voice` — toggle / inspect the rvoice push-to-talk binding. # rvoice itself is a separate script (bin/rvoice) driven by Hammerspoon. @@ -1465,7 +1367,6 @@ case ${1:-} in send) shift; cmd_send "$@"; exit ;; setup|install) shift; cmd_setup "$@"; exit ;; voice) shift; cmd_voice "$@"; exit ;; - send) shift; cmd_send "$@"; exit ;; -v|--version) cmd_version; exit ;; -h|--help|help) cmd_help; exit ;; esac