#!/bin/sh # Umbra Provider uninstaller for macOS. # # This script stops the per-user host service and removes the Umbra app, CLI # wrapper, and local Umbra data. It deliberately DOES NOT remove the Apple # Device Management profile: macOS requires the owner to review and remove that # profile in System Settings. set -eu YES=0 KEEP_DATA=0 usage() { cat <<'EOF' Usage: sh umbra-uninstall.sh [--yes] [--keep-data] --yes Skip the interactive confirmation after printing the plan. --keep-data Preserve ~/.umbra, including downloaded models and local config. --help Show this help. The Umbra Device Management profile is never removed by this script. Remove it yourself in System Settings > General > Device Management after reviewing it. EOF } while [ "$#" -gt 0 ]; do case "$1" in --yes) YES=1 ;; --keep-data) KEEP_DATA=1 ;; -h|--help) usage; exit 0 ;; *) printf 'Unknown option: %s\n\n' "$1" >&2; usage >&2; exit 2 ;; esac shift done die() { printf 'Umbra uninstall: %s\n' "$*" >&2; exit 1; } say() { printf '%s\n' "$*"; } [ "$(uname -s 2>/dev/null || true)" = "Darwin" ] || die "this uninstaller runs on macOS only" [ -n "${HOME:-}" ] && [ "$HOME" != "/" ] || die "HOME is missing or unsafe" case "$HOME" in /*) ;; *) die "HOME must be an absolute path" ;; esac HOME_PATH="$(CDPATH= cd -- "$HOME" 2>/dev/null && pwd -P)" || die "HOME does not exist" [ -n "$HOME_PATH" ] && [ "$HOME_PATH" != "/" ] || die "HOME resolves to an unsafe path" APP_DIR="${UMBRA_INSTALL_DIR:-/Applications}" BIN_DIR="${UMBRA_BIN_DIR:-/usr/local/bin}" APP_PATH="$APP_DIR/Umbra Provider.app" CLI_PATH="$BIN_DIR/umbra" PLIST_PATH="$HOME_PATH/Library/LaunchAgents/dev.tryumbra.host.plist" DATA_PATH="$HOME_PATH/.umbra" DOMAIN="gui/$(id -u)" case "$APP_DIR" in /*) ;; *) die "UMBRA_INSTALL_DIR must be an absolute path" ;; esac case "$BIN_DIR" in /*) ;; *) die "UMBRA_BIN_DIR must be an absolute path" ;; esac [ "$APP_DIR" != "/" ] || die "refusing unsafe UMBRA_INSTALL_DIR=/" [ "$BIN_DIR" != "/" ] || die "refusing unsafe UMBRA_BIN_DIR=/" say "" say "Umbra Provider uninstall" say "" say "This will:" say " - stop the per-user dev.tryumbra.host LaunchAgent" say " - remove $PLIST_PATH" say " - remove $APP_PATH" say " - remove the Umbra wrapper at $CLI_PATH (when it matches this app)" if [ "$KEEP_DATA" -eq 1 ]; then say " - preserve $DATA_PATH (--keep-data)" else say " - remove $DATA_PATH, including downloaded models, local config, and status logs" fi say "" say "This will NOT remove the Umbra Device Management profile." say "You must review and remove that profile yourself in:" say " System Settings > General > Device Management > Umbra > Remove" say "" if [ "$YES" -ne 1 ]; then [ -t 0 ] || die "interactive confirmation required; download this script, inspect it, then run it from Terminal" printf 'Continue? [y/N] ' read -r answer || answer="" case "$answer" in y|Y|yes|YES) ;; *) say "Cancelled. Nothing was removed."; exit 0 ;; esac fi # Stop the managed launchd job directly. Do not execute the installed app while # uninstalling: an incomplete or tampered bundle must never gain execution just # because it occupies the conventional Umbra path. /bin/launchctl bootout "$DOMAIN/dev.tryumbra.host" >/dev/null 2>&1 || true /bin/launchctl bootout "$DOMAIN" "$PLIST_PATH" >/dev/null 2>&1 || true rm -f "$PLIST_PATH" say "Stopped and removed the Umbra host LaunchAgent." # Only remove the conventional app path when it is actually Umbra's bundle. if [ -e "$APP_PATH" ]; then BUNDLE_ID="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' "$APP_PATH/Contents/Info.plist" 2>/dev/null || true)" if [ "$BUNDLE_ID" = "com.umbra.provider" ]; then if rm -rf "$APP_PATH" 2>/dev/null; then :; else say "Administrator approval is required to remove $APP_PATH." sudo rm -rf "$APP_PATH" fi say "Removed $APP_PATH." else say "Left $APP_PATH in place because its bundle identifier was not com.umbra.provider." fi else say "Umbra Provider.app was not present." fi # The official installer writes a small text wrapper containing this exact app # path. Do not delete an unrelated executable that happens to be named `umbra`. if [ -e "$CLI_PATH" ] || [ -L "$CLI_PATH" ]; then if grep -Fq 'Umbra Provider.app/Contents/MacOS/umbra' "$CLI_PATH" 2>/dev/null; then if rm -f "$CLI_PATH" 2>/dev/null; then :; else say "Administrator approval is required to remove $CLI_PATH." sudo rm -f "$CLI_PATH" fi say "Removed $CLI_PATH." else say "Left $CLI_PATH in place because it was not the Umbra installer wrapper." fi else say "The Umbra CLI wrapper was not present." fi if [ "$KEEP_DATA" -ne 1 ]; then rm -rf "$DATA_PATH" say "Removed $DATA_PATH." fi say "" say "Umbra software removal is complete." say "The Device Management profile remains until you remove it in System Settings."