flake-update-20260505
 1#!/usr/bin/env bash
 2# List SSH hosts and shpool sessions for raffi script filter.
 3# Outputs Alfred Script Filter JSON format.
 4#
 5# Usage: shpool-raffi [query]
 6#
 7# Without query or partial host match: lists SSH hosts from ~/.ssh/config
 8# With "host" or "host query": lists shpool sessions on that host
 9#
10# The action should be: ssh {value}
11# Values are formatted as host/session for direct ssh attach.
12set -euo pipefail
13
14query="${1:-}"
15host="${query%% *}"
16session_query=""
17if [[ "$query" == *" "* ]]; then
18    session_query="${query#* }"
19fi
20
21# Get SSH hosts (skip wildcards, patterns, git forges)
22get_hosts() {
23    grep "^Host " ~/.ssh/config 2>/dev/null \
24        | awk '{print $2}' \
25        | grep -v '\*' \
26        | grep -v '/' \
27        | grep -v -E '^(github\.com|gitlab\.com|codeberg\.org|git\.sr\.ht)$' \
28        | sort -u
29}
30
31# Check if the query matches exactly one host
32match_host() {
33    local q="$1"
34    local exact
35    exact=$(get_hosts | grep -x "$q" 2>/dev/null || true)
36    echo "$exact"
37}
38
39# List sessions on a remote host
40list_sessions() {
41    local h="$1"
42    local sq="$2"
43    local items="[]"
44
45    # Try to get sessions from remote host (timeout 3s)
46    local output
47    if output=$(ssh -o ConnectTimeout=3 "$h" shpool list 2>/dev/null); then
48        while IFS=$'\t' read -r name started_at status; do
49            [[ "$name" == "NAME" ]] && continue
50            [[ -z "$name" ]] && continue
51            if [[ -z "$sq" ]] || echo "$name" | grep -qi "$sq"; then
52                items=$(jq --arg n "$name" --arg h "$h" --arg s "$status" --arg t "$started_at" \
53                    '. + [{"title": $n, "subtitle": "\($h) — \($s) since \($t)", "arg": "\($h)/\($n)"}]' <<< "$items")
54            fi
55        done <<< "$output"
56    fi
57
58    # Add "new session" entry
59    local new_name="${sq:-main}"
60    items=$(jq --arg n "$new_name" --arg h "$h" \
61        '. + [{"title": "➕ New: \($n)", "subtitle": "Create or attach to \($n) on \($h)", "arg": "\($h)/\($n)"}]' <<< "$items")
62
63    jq -n --argjson items "$items" '{"items": $items}'
64}
65
66# List hosts
67list_hosts() {
68    local q="$1"
69    local items="[]"
70
71    while IFS= read -r h; do
72        if [[ -z "$q" ]] || echo "$h" | grep -qi "$q"; then
73            items=$(jq --arg h "$h" \
74                '. + [{"title": $h, "subtitle": "Connect to shpool on \($h)", "arg": $h}]' <<< "$items")
75        fi
76    done < <(get_hosts)
77
78    jq -n --argjson items "$items" '{"items": $items}'
79}
80
81# If host matches exactly, list sessions on that host
82if [[ -n "$host" ]] && [[ -n "$(match_host "$host")" ]]; then
83    list_sessions "$host" "$session_query"
84else
85    list_hosts "$query"
86fi