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