feat(@scripts): add tsv output mode for session tools

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Natalie 2026-05-18 03:06:23 -07:00
parent a0cc60d4c3
commit 2fbcfd494f

View file

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