#!/bin/sh set -eu KNOWN_CRED_FILE="$HOME/.ssh/known_creds" KNOWN_HOSTS_FILE="$HOME/.ssh/known_hosts" # === 1. Load credentials from file === TMP_CREDS=$(mktemp) trap 'rm -f "$TMP_CREDS"' EXIT if [ -f "$KNOWN_CRED_FILE" ]; then cp "$KNOWN_CRED_FILE" "$TMP_CREDS" fi # === 2. Parse known_hosts (deduped) === TMP_HOSTS=$(mktemp) trap 'rm -f "$TMP_CREDS" "$TMP_HOSTS"' EXIT if [ -f "$KNOWN_HOSTS_FILE" ]; then grep -v '^[[:space:]]*#' "$KNOWN_HOSTS_FILE" | \ awk ' { split($1, parts, ",") for (i in parts) { h = parts[i] gsub(/[][]/, "", h) port = 22 if (match(h, /:[0-9]+$/)) { port = substr(h, RSTART+1) h = substr(h, 1, RSTART-1) } key = h ":" port if (!(key in seen)) { seen[key] = 1; print h "|" port } } }' > "$TMP_HOSTS" fi # Check if hosts found if [ ! -s "$TMP_HOSTS" ]; then echo "⚠️ No hosts in ~/.ssh/known_hosts. Run 'ssh user@host' first." >&2 exit 1 fi # === 3. Build menu + store full credentials === hosts_data=() echo "📋 Available hosts:" i=1 while IFS='|' read -r host port; do user="" pass="" # Safely extract credentials (avoid grep failure) match=$(grep "^$host|" "$TMP_CREDS" 2>/dev/null | head -n1) || true if [ -n "$match" ]; then IFS='|' read -r _ user _ pass <<< "$match" fi # Determine mode: 1 = auto-pass, 0 = manual mode=0 if [ -n "$user" ] && [ -n "$pass" ]; then mode=1 fi hosts_data+=("$host|$port|$user|$pass|$mode") if [ "$mode" -eq 1 ]; then echo "$i) $host ($port) — $user (auto-pass)" else echo "$i) $host ($port)" fi i=$((i + 1)) done < "$TMP_HOSTS" echo "$i) Cancel" # === 4. Prompt for host === PS3="Select: " while true; do read -r choice || exit 0 if [ "$choice" = "$i" ]; then echo "Cancelled." exit 0 elif [ "$choice" -ge 1 ] && [ "$choice" -lt "$i" ]; then break fi echo "Invalid. Try again:" done # Extract selected host/credentials item="${hosts_data[$((choice-1))]}" IFS='|' read -r host port user pass mode <<< "$item" # === 5. Get credentials if not auto-pass === if [ "$mode" -eq 0 ]; then read -rp "Username [$USER]: " user user="${user:-$USER}" stty -echo 2>/dev/null || true read -rp "Password: " pass stty echo 2>/dev/null || true echo # Save if requested read -rp "Save credentials? [y/N]: " save if [ "$save" = "y" ] || [ "$save" = "Y" ]; then if [ -f "$KNOWN_CRED_FILE" ]; then grep -v "^$host|" "$KNOWN_CRED_FILE" > "${KNOWN_CRED_FILE}.tmp" || true mv "${KNOWN_CRED_FILE}.tmp" "$KNOWN_CRED_FILE" fi echo "$host|$user|$port|$pass" >> "$KNOWN_CRED_FILE" chmod 600 "$KNOWN_CRED_FILE" fi fi # === 6. Launch SSH — reuse existing window/pane === # Ensure sshpass is available if ! command -v sshpass >/dev/null 2>&1; then echo "⚠️ Install sshpass: brew install hudochenkov/sshpass/sshpass" exit 1 fi # Get WezTerm pane ID if available pane_id="" if osascript -e 'application "WezTerm" is running' >/dev/null 2>&1; then pane_id=$(wezterm cli list-panes -q 2>/dev/null | head -n1 | cut -d' ' -f1) || true fi # Create safe command with quoted password safe_cmd=$(printf 'sshpass -p %q ssh -p %s %s@%s' "$pass" "$port" "$user" "$host") # Reuse pane or spawn new tab if [ -n "$pane_id" ]; then wezterm cli send-text --pane "$pane_id" "$safe_cmd\n" else # Fallback: spawn new tab in existing window wezterm cli spawn --cwd "$HOME" -- sh -c "$safe_cmd" fi