Files
gh-dashed-claude-marketplac…/tools/list-sessions.sh
2025-11-29 18:17:58 +08:00

256 lines
6.5 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# list-sessions.sh - List all registered tmux sessions
#
# Lists all sessions in the registry with health status information.
# Supports both human-readable table format and JSON output.
#
# Usage:
# ./list-sessions.sh [--json]
#
# Options:
# --json Output as JSON instead of table
# -h, --help Show this help message
#
# Exit codes:
# 0 - Success
# 1 - Error
set -euo pipefail
# Get script directory to source libraries
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib/registry.sh
source "$SCRIPT_DIR/lib/registry.sh"
# shellcheck source=lib/time_utils.sh
source "$SCRIPT_DIR/lib/time_utils.sh"
# Path to pane-health tool
PANE_HEALTH="$SCRIPT_DIR/pane-health.sh"
#------------------------------------------------------------------------------
# Configuration
#------------------------------------------------------------------------------
output_format="table"
#------------------------------------------------------------------------------
# Functions
#------------------------------------------------------------------------------
usage() {
cat << EOF
Usage: $(basename "$0") [--json]
List all registered tmux sessions with health status.
Options:
--json Output as JSON instead of table format
-h, --help Show this help message
Output Formats:
Table (default):
NAME SOCKET TARGET STATUS PID CREATED
my-python claude.sock my-python:0.0 alive 1234 2h ago
my-gdb claude.sock my-gdb:0.0 dead - 1h ago
JSON (--json):
{
"sessions": [
{"name": "my-python", "socket": "...", "status": "alive", ...}
],
"total": 2,
"alive": 1,
"dead": 1
}
Health Status:
alive - Session is running and healthy
dead - Pane is marked as dead
missing - Session/pane not found
zombie - Process not running
server - Tmux server not running
Examples:
# List sessions in table format
$(basename "$0")
# List sessions as JSON
$(basename "$0") --json
Exit codes:
0 - Success
1 - Error
EOF
}
# Get health status for a session
# Returns: status string (alive, dead, missing, zombie, server)
get_health_status() {
local socket="$1"
local target="$2"
if [[ ! -x "$PANE_HEALTH" ]]; then
echo "unknown"
return
fi
# Call pane-health.sh and interpret exit code
if "$PANE_HEALTH" -S "$socket" -t "$target" --format text >/dev/null 2>&1; then
echo "alive"
else
local exit_code=$?
case $exit_code in
1) echo "dead" ;;
2) echo "missing" ;;
3) echo "zombie" ;;
4) echo "server" ;;
*) echo "unknown" ;;
esac
fi
}
#------------------------------------------------------------------------------
# Argument parsing
#------------------------------------------------------------------------------
while [[ $# -gt 0 ]]; do
case "$1" in
--json)
output_format="json"
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Error: Unknown option: $1" >&2
usage
exit 1
;;
esac
done
#------------------------------------------------------------------------------
# Get sessions from registry
#------------------------------------------------------------------------------
registry_data=$(registry_list_sessions)
session_names=$(echo "$registry_data" | jq -r '.sessions | keys[]' 2>/dev/null || echo "")
# Count sessions
total_count=0
alive_count=0
dead_count=0
# Build session list with health info
sessions_with_health=()
if [[ -n "$session_names" ]]; then
while IFS= read -r name; do
[[ -z "$name" ]] && continue
# Get session data
socket=$(echo "$registry_data" | jq -r ".sessions[\"$name\"].socket")
target=$(echo "$registry_data" | jq -r ".sessions[\"$name\"].target")
type=$(echo "$registry_data" | jq -r ".sessions[\"$name\"].type")
pid=$(echo "$registry_data" | jq -r ".sessions[\"$name\"].pid // \"\"")
created=$(echo "$registry_data" | jq -r ".sessions[\"$name\"].created_at")
# Get health status
status=$(get_health_status "$socket" "$target")
# Update counters
total_count=$((total_count + 1))
if [[ "$status" == "alive" ]]; then
alive_count=$((alive_count + 1))
else
dead_count=$((dead_count + 1))
fi
# Store session info
sessions_with_health+=("$name|$socket|$target|$status|$pid|$created|$type")
done <<< "$session_names"
fi
#------------------------------------------------------------------------------
# Output results
#------------------------------------------------------------------------------
if [[ "$output_format" == "json" ]]; then
# JSON output
echo "{"
echo " \"sessions\": ["
first=true
for session_info in "${sessions_with_health[@]+"${sessions_with_health[@]}"}"; do
IFS='|' read -r name socket target status pid created type <<< "$session_info"
if [[ "$first" == false ]]; then
echo ","
fi
first=false
# Get basename of socket for cleaner output
socket_basename=$(basename "$socket")
cat << EOF
{
"name": "$name",
"socket": "$socket",
"socket_basename": "$socket_basename",
"target": "$target",
"type": "$type",
"status": "$status",
"pid": ${pid:-null},
"created_at": "$created"
}
EOF
done
echo ""
echo " ],"
echo " \"total\": $total_count,"
echo " \"alive\": $alive_count,"
echo " \"dead\": $dead_count"
echo "}"
else
# Table output
if [[ $total_count -eq 0 ]]; then
echo "No sessions registered."
exit 0
fi
# Print header
printf "%-20s %-20s %-20s %-10s %-8s %-15s\n" \
"NAME" "SOCKET" "TARGET" "STATUS" "PID" "CREATED"
printf "%-20s %-20s %-20s %-10s %-8s %-15s\n" \
"----" "------" "------" "------" "---" "-------"
# Print sessions
for session_info in "${sessions_with_health[@]+"${sessions_with_health[@]}"}"; do
IFS='|' read -r name socket target status pid created type <<< "$session_info"
# Get basename of socket for cleaner output
socket_basename=$(basename "$socket")
# Format time ago
time_str=$(time_ago "$created")
# Truncate long values
name_trunc="${name:0:20}"
socket_trunc="${socket_basename:0:20}"
target_trunc="${target:0:20}"
printf "%-20s %-20s %-20s %-10s %-8s %-15s\n" \
"$name_trunc" "$socket_trunc" "$target_trunc" "$status" "${pid:--}" "$time_str"
done
# Print summary
echo ""
echo "Total: $total_count | Alive: $alive_count | Dead: $dead_count"
fi
exit 0