#!/bin/bash # 01-macos-notification.sh — show a native macOS banner when HearthGate # fires a connect / disconnect event. # # Why you might want this: # The simplest possible "someone connected" alert. The banner appears in # the top-right of the screen via Notification Center, no third-party # service required, no internet, no setup. If you only ever install one # HearthGate hook, this is it. # # Setup: # Make the script executable, then add it from HearthGate's Hooks tab. # Full guide: https://codnamacs.com/hearthgate/help/features/hooks # # Environment HearthGate provides (you do not need to set these): # HEARTHGATE_EVENT — on-connect | after-connect | on-disconnect | after-disconnect # HEARTHGATE_SESSION_DURATION_SEC — only on disconnect events; how long the session ran # # Test it without a real SSH connection: # HEARTHGATE_EVENT=on-connect ./01-macos-notification.sh # HEARTHGATE_EVENT=on-disconnect HEARTHGATE_SESSION_DURATION_SEC=125 ./01-macos-notification.sh set -euo pipefail EVENT="${HEARTHGATE_EVENT:-${1:-unknown}}" DURATION_SEC="${HEARTHGATE_SESSION_DURATION_SEC:-}" # Format the duration in a human-friendly way: "2m 5s" beats "125". format_duration() { local secs="$1" if [ "$secs" -lt 60 ]; then echo "${secs}s" elif [ "$secs" -lt 3600 ]; then echo "$((secs / 60))m $((secs % 60))s" else echo "$((secs / 3600))h $(((secs % 3600) / 60))m" fi } notify() { local message="$1" # `display notification` lives in osascript so we never have to install # anything. The title shows up bold; subtitle is one line below. osascript -e "display notification \"${message}\" with title \"HearthGate\" sound name \"Tink\"" } case "$EVENT" in on-connect|after-connect) notify "Remote session started" ;; on-disconnect|after-disconnect) if [ -n "$DURATION_SEC" ]; then notify "Session ended after $(format_duration "$DURATION_SEC")" else notify "Session ended" fi ;; *) # Unknown event — log so the user can debug, but do not fail. A non- # zero exit code would mark the hook as "errored" in HearthGate's UI. echo "macos-notification: unrecognised event '$EVENT'" >&2 ;; esac