diff --git a/bin/rclaude b/bin/rclaude index 2825c3a..6e0cae0 100755 --- a/bin/rclaude +++ b/bin/rclaude @@ -140,10 +140,14 @@ list_disk_on() { } # List on-disk Claude sessions per UUID on a host (via _claude-projects --sessions). -# Output one row per session jsonl: -# \tsession\t\t\t · +# Default output (column-aligned consumers): one row per session jsonl: +# \tsession\t\t\t · \t +# When the second arg is "tsv", emit a machine-readable shape with cwd and +# mtime_epoch as separate columns (no relative-time string): +# \tsession\t\t\t\t list_sessions_on() { _host=$1 + _fmt=${2:-pretty} _helper_dir=$(dirname "$(resolve_self)") if is_local "$_host"; then _raw=$("$_helper_dir/_claude-projects" --sessions 2>/dev/null || true) @@ -151,7 +155,7 @@ list_sessions_on() { _raw=$(ssh -o BatchMode=yes -o ConnectTimeout=3 "$_host" 'python3 - --sessions' < "$_helper_dir/_claude-projects" 2>/dev/null || true) fi _now=$(date +%s) - printf %s "$_raw" | awk -F'\t' -v host="$_host" -v now="$_now" ' + printf %s "$_raw" | awk -F'\t' -v host="$_host" -v now="$_now" -v fmt="$_fmt" ' function rel(secs, abs, s) { abs = (secs < 0) ? -secs : secs if (abs < 60) s = abs " seconds" @@ -162,8 +166,12 @@ list_sessions_on() { } NF >= 3 { snippet = ($4 == "" ? "(no user text)" : $4) - # col 6 = raw mtime, hidden — used for cross-host dedup/sort. - printf "%s\tsession\t%s\t%s\t%s · %s\t%s\n", host, $2, snippet, $3, rel(now - $1), $1 + if (fmt == "tsv") { + printf "%s\tsession\t%s\t%s\t%s\t%s\n", host, $2, snippet, $3, $1 + } else { + # col 6 = raw mtime, hidden — used for cross-host dedup/sort. + printf "%s\tsession\t%s\t%s\t%s · %s\t%s\n", host, $2, snippet, $3, rel(now - $1), $1 + } } ' } @@ -652,43 +660,80 @@ scan_hosts() { cmd_triage() { # Pass-through args: --limit, --refresh, --uuids ... - _opts="$*" - printf "%-8s %-8s %-3s %-15s %-50s %s\n" \ - "HOST" "UUID" "PRI" "STATUS" "SUMMARY" "NEXT ACTION" + # --tsv: emit raw TSV (host\ttriage\tuuid\tpri\tstatus\tsummary\tnext_action\tcwd\tmtime) + # and skip the column-aligned awk formatting + header. + _tsv=0 + _opts="" + for _a in "$@"; do + if [ "$_a" = "--tsv" ]; then + _tsv=1 + else + _opts="$_opts $_a" + fi + done + if [ "$_tsv" -eq 0 ]; then + printf "%-8s %-8s %-3s %-15s %-50s %s\n" \ + "HOST" "UUID" "PRI" "STATUS" "SUMMARY" "NEXT ACTION" + fi scan_hosts | while IFS= read -r h; do # Row format from list_triage_on: # host \t triage \t uuid \t priority \t status \t summary \t next_action \t cwd \t mtime - # shellcheck disable=SC2086 - list_triage_on "$h" $_opts | awk -F'\t' ' - { uuid8 = substr($3, 1, 8) - printf "%-8s %-8s %-3s %-15s %-50.50s %s\n", - $1, uuid8, $4, $5, $6, $7 } - ' + if [ "$_tsv" -eq 1 ]; then + # shellcheck disable=SC2086 + list_triage_on "$h" $_opts + else + # shellcheck disable=SC2086 + list_triage_on "$h" $_opts | awk -F'\t' ' + { uuid8 = substr($3, 1, 8) + printf "%-8s %-8s %-3s %-15s %-50.50s %s\n", + $1, uuid8, $4, $5, $6, $7 } + ' + fi done } cmd_list() { - _mode=${1:-all} # all | tmux | disk | sessions - printf "%-10s %-7s %-60s %s\n" "HOST" "KIND" "SESSION/CWD/UUID" "DETAIL" + # Positional mode + optional --tsv flag (order-agnostic). + # --tsv: skip the header + column-aligned awk; print raw TSV rows from + # list_*_on (with full uuids, separate cwd / mtime columns for sessions). + _mode="" + _tsv=0 + for _a in "$@"; do + case $_a in + --tsv) _tsv=1 ;; + *) [ -z "$_mode" ] && _mode=$_a ;; + esac + done + _mode=${_mode:-all} + _sess_fmt=pretty + [ "$_tsv" -eq 1 ] && _sess_fmt=tsv + if [ "$_tsv" -eq 0 ]; then + printf "%-10s %-7s %-60s %s\n" "HOST" "KIND" "SESSION/CWD/UUID" "DETAIL" + fi scan_hosts | while IFS= read -r h; do case $_mode in tmux) list_tmux_on "$h" ;; disk) list_disk_on "$h" ;; sessions|--sessions) list_tmux_on "$h" - list_sessions_on "$h" ;; - *) list_all_on "$h" ;; - esac | awk -F'\t' '{ - # Tmux/disk rows: $3 is the display target. Session rows: $3=uuid, - # $4=snippet (show snippet, abbreviate uuid into DETAIL via $5). - if ($2 == "session") { - uuid_short = substr($3, 1, 8) - detail = (NF >= 5 ? $5 : "") " [" uuid_short "]" - printf "%-10s %-7s %-60.60s %s\n", $1, $2, $4, detail - } else { - printf "%-10s %-7s %-60.60s %s\n", $1, $2, $3, $4 - } - }' + list_sessions_on "$h" "$_sess_fmt" ;; + *) list_tmux_on "$h" + list_disk_on "$h" ;; + esac | if [ "$_tsv" -eq 1 ]; then + cat + else + awk -F'\t' '{ + # Tmux/disk rows: $3 is the display target. Session rows: $3=uuid, + # $4=snippet (show snippet, abbreviate uuid into DETAIL via $5). + if ($2 == "session") { + uuid_short = substr($3, 1, 8) + detail = (NF >= 5 ? $5 : "") " [" uuid_short "]" + printf "%-10s %-7s %-60.60s %s\n", $1, $2, $4, detail + } else { + printf "%-10s %-7s %-60.60s %s\n", $1, $2, $3, $4 + } + }' + fi done }