#!/usr/bin/env bash # Still Here — macOS installer # Usage: curl -fsSL https://stillhere.work/install.sh | bash set -euo pipefail APP_NAME="StillHere" INSTALL_DIR="/Applications" API_URL="https://stillhere.work/api/install/latest?platform=macos" echo "" echo " ╔══════════════════════════════════╗" echo " ║ Still Here — macOS Installer ║" echo " ╚══════════════════════════════════╝" echo "" # Get latest release DMG URL from our API echo "→ Finding latest release..." RESPONSE=$(curl -fsSL "$API_URL") DMG_URL=$(echo "$RESPONSE" | grep -o '"downloadUrl":"[^"]*"' | sed 's/"downloadUrl":"//;s/"//') VERSION=$(echo "$RESPONSE" | grep -o '"version":"[^"]*"' | sed 's/"version":"//;s/"//') if [ -z "$DMG_URL" ]; then echo "✗ No macOS release found. Visit https://stillhere.work/download" exit 1 fi echo "→ Latest version: ${VERSION:-unknown}" # Download TMPDIR=$(mktemp -d) DMG_PATH="${TMPDIR}/${APP_NAME}.dmg" echo "→ Downloading..." curl -fSL --progress-bar "$DMG_URL" -o "$DMG_PATH" # Mount DMG echo "→ Installing..." MOUNT_POINT=$(hdiutil attach "$DMG_PATH" -nobrowse | grep -o '/Volumes/.*' | head -1 | sed 's/[[:space:]]*$//') if [ -z "$MOUNT_POINT" ] || [ ! -d "$MOUNT_POINT" ]; then echo "✗ Failed to mount DMG" exit 1 fi echo "→ Mounted at: $MOUNT_POINT" # Find the .app inside the mounted DMG if [ ! -d "${MOUNT_POINT}/${APP_NAME}.app" ]; then echo "→ Contents: $(ls "${MOUNT_POINT}")" echo "✗ ${APP_NAME}.app not found in DMG" hdiutil detach "${MOUNT_POINT}" -quiet 2>/dev/null exit 1 fi # Copy app to /Applications (remove old version first) if [ -d "${INSTALL_DIR}/${APP_NAME}.app" ]; then rm -rf "${INSTALL_DIR}/${APP_NAME}.app" fi cp -R "${MOUNT_POINT}/${APP_NAME}.app" "${INSTALL_DIR}/" # Unmount hdiutil detach "${MOUNT_POINT}" -quiet 2>/dev/null || true # Clear quarantine flag xattr -cr "${INSTALL_DIR}/${APP_NAME}.app" 2>/dev/null || true # Cleanup rm -rf "$TMPDIR" echo "" echo " ✓ Still Here installed to /Applications" echo " ✓ Quarantine flag cleared — no Gatekeeper warnings" echo "" echo " Launch: open /Applications/${APP_NAME}.app" echo "" # Ask to launch — read from /dev/tty so it works when piped via curl | bash if [ -t 0 ]; then read -p " Launch now? [Y/n] " -n 1 -r echo "" else REPLY="" if [ -c /dev/tty ]; then read -p " Launch now? [Y/n] " -n 1 -r REPLY < /dev/tty || true echo "" fi fi if [[ ! $REPLY =~ ^[Nn]$ ]]; then open "${INSTALL_DIR}/${APP_NAME}.app" echo " ✓ Launched!" fi echo ""