#!/bin/sh set -e INSTALL_DIR="${SSH0_DIR:-$HOME/.ssh0}" BIN_DIR="${SSH0_BIN:-$HOME/.local/bin}" TARBALL="https://ssh0.sh/latest.tar.gz" main() { printf '\033[1mssh0\033[0m installer\n' printf 'install dir: %s\n' "$INSTALL_DIR" printf 'bin dir: %s\n\n' "$BIN_DIR" need_cmd curl need_cmd tar check_node if [ -d "$INSTALL_DIR" ]; then printf 'updating existing installation...\n' rm -rf "$INSTALL_DIR.bak" mv "$INSTALL_DIR" "$INSTALL_DIR.bak" fi printf 'downloading ssh0...\n' mkdir -p "$INSTALL_DIR" curl -fsSL "$TARBALL" | tar xz -C "$INSTALL_DIR" --strip-components=1 cd "$INSTALL_DIR" if [ -f package.json ] && command -v npm >/dev/null 2>&1; then npm install --production --no-fund --no-audit 2>/dev/null || true fi mkdir -p "$BIN_DIR" ln -sf "$INSTALL_DIR/bin/wh" "$BIN_DIR/wh" ln -sf "$INSTALL_DIR/bin/ssh0" "$BIN_DIR/ssh0" chmod +x "$INSTALL_DIR/bin/wh" "$INSTALL_DIR/bin/ssh0" ensure_path rm -rf "$INSTALL_DIR.bak" printf '\n\033[32mdone.\033[0m\n' printf ' wh — wormhole CLI (exec, shell, put, get, ping)\n' printf ' ssh0 — full protocol server + client\n' printf '\ntry: wh help\n' } check_node() { if command -v node >/dev/null 2>&1; then ver=$(node -v 2>/dev/null | sed 's/v//') major=$(echo "$ver" | cut -d. -f1) if [ "$major" -ge 18 ] 2>/dev/null; then printf 'node %s ✓\n' "$ver" return fi printf 'node %s found but >=18 required\n' "$ver" fi printf 'node not found or too old. install options:\n' printf ' curl -fsSL https://fnm.vercel.app/install | bash && fnm install 22\n' printf ' brew install node (macOS)\n' printf ' apt install nodejs (Debian/Ubuntu)\n' printf ' pacman -S nodejs (Arch)\n' exit 1 } need_cmd() { if ! command -v "$1" >/dev/null 2>&1; then printf 'error: %s is required but not found\n' "$1" exit 1 fi } ensure_path() { case ":$PATH:" in *":$BIN_DIR:"*) return ;; esac shell_name=$(basename "${SHELL:-/bin/sh}") rc="" case "$shell_name" in zsh) rc="$HOME/.zshrc" ;; bash) if [ -f "$HOME/.bash_profile" ]; then rc="$HOME/.bash_profile" else rc="$HOME/.bashrc"; fi ;; fish) rc="$HOME/.config/fish/config.fish" ;; *) rc="$HOME/.profile" ;; esac if [ -n "$rc" ] && [ -f "$rc" ]; then if ! grep -q "$BIN_DIR" "$rc" 2>/dev/null; then printf '\nexport PATH="%s:$PATH"\n' "$BIN_DIR" >> "$rc" printf 'added %s to PATH in %s\n' "$BIN_DIR" "$rc" fi fi export PATH="$BIN_DIR:$PATH" } main "$@"