#!/bin/sh # Glamdring — Foe-hammer · installer — https://thot.ai/glamdring/install.sh # # curl -fsSL https://thot.ai/glamdring/install.sh | sh # # Downloads the notarization-pending Glamdring.app from its GitHub release, verifies it against a # sha256 pinned INTO THIS SCRIPT (which is served from thot.ai — a different origin than the binary # on GitHub, so a tampered download can't ship its own matching checksum), and installs it to # /Applications. Nothing here needs root; the script never asks for your password. # # Inspect before you run: open the URL above in a browser, or `curl -fsSL … -o install.sh` and read # it. That is the honest way to run a piped installer — we link it prominently on the page for that # reason. Source: https://github.com/cloud-dance/Glamdring set -eu # --- release coordinates ----------------------------------------------------------------------- OWNER_REPO="cloud-dance/Glamdring" VERSION="v0.1.0" ASSET="Glamdring-macos-arm64.tar.gz" URL="https://github.com/${OWNER_REPO}/releases/download/${VERSION}/${ASSET}" # sha256 of the exact ${ASSET} published under ${VERSION}. If a future release changes the binary, # this line MUST be bumped in lockstep (the /glamdring page shows the same value). A mismatch fails # the install closed rather than installing something unverified — that is the intended behavior. EXPECTED_SHA256="567cba81e6d03d8e355a2b0a5ce7d43894b11b3ce69636adf617a4ef4899fba2" APP="Glamdring.app" DEST="/Applications" # --- tiny ui ----------------------------------------------------------------------------------- say() { printf '\033[36m⚔ %s\033[0m\n' "$1"; } note() { printf ' %s\n' "$1"; } warn() { printf '\033[33m %s\033[0m\n' "$1"; } die() { printf '\033[31merror:\033[0m %s\n' "$1" >&2; exit 1; } have() { command -v "$1" >/dev/null 2>&1; } # --- pre-flight -------------------------------------------------------------------------------- [ "$(uname -s)" = "Darwin" ] || die "Glamdring is a macOS app. This looks like $(uname -s)." if [ "$(uname -m)" != "arm64" ]; then die "This build is Apple Silicon (arm64) only; you're on $(uname -m). An Intel build isn't published yet." fi have curl || die "curl is required (it ships with macOS — check your PATH)." have tar || die "tar is required (it ships with macOS)." if have shasum; then SHA_CMD="shasum -a 256" elif have openssl; then SHA_CMD="openssl dgst -sha256" else die "need 'shasum' or 'openssl' to verify the download."; fi # --- download ---------------------------------------------------------------------------------- TMP="$(mktemp -d "${TMPDIR:-/tmp}/glamdring.XXXXXX")" || die "could not create a temp dir." trap 'rm -rf "$TMP"' EXIT INT TERM TARBALL="$TMP/$ASSET" say "Downloading Glamdring ${VERSION} …" note "$URL" curl -fsSL "$URL" -o "$TARBALL" || die "download failed. Is ${VERSION} published at ${OWNER_REPO}? See https://github.com/${OWNER_REPO}/releases" # --- verify integrity (fail closed) ------------------------------------------------------------ GOT="$($SHA_CMD "$TARBALL" | awk '{print $1}')" if [ "$GOT" != "$EXPECTED_SHA256" ]; then printf '\033[31mchecksum mismatch — refusing to install.\033[0m\n' >&2 printf ' expected: %s\n' "$EXPECTED_SHA256" >&2 printf ' got: %s\n' "$GOT" >&2 die "the download did not match the pinned sha256. Do not run it. Report this at https://github.com/${OWNER_REPO}/issues" fi say "Verified sha256 ✓" # --- install ----------------------------------------------------------------------------------- tar -xzf "$TARBALL" -C "$TMP" || die "could not unpack the archive." [ -d "$TMP/$APP" ] || die "the archive did not contain $APP." if [ -d "$DEST/$APP" ]; then note "Replacing the existing $DEST/$APP …" rm -rf "$DEST/$APP" 2>/dev/null || die "couldn't remove the old app. Quit Glamdring, then re-run — or move it aside manually." fi if ! mv "$TMP/$APP" "$DEST/$APP" 2>/dev/null; then warn "No write access to $DEST. Finishing the install by hand:" note " mv \"$TMP/$APP\" \"$DEST/\" # (this temp copy is deleted when the script exits)" die "move Glamdring.app into /Applications yourself, then re-run to verify." fi # A curl+tar install carries no com.apple.quarantine flag, so Gatekeeper won't wall it off the way a # browser download would. Strip it (and provenance) anyway, best-effort, so first launch is clean. xattr -dr com.apple.quarantine "$DEST/$APP" 2>/dev/null || true xattr -dr com.apple.provenance "$DEST/$APP" 2>/dev/null || true # --- done -------------------------------------------------------------------------------------- say "Installed → $DEST/$APP" printf '\n' note "Launch it: open -a Glamdring (or find the blue blade in Applications / Spotlight)" note "Runtime: needs Python 3.11+ on this Mac (the engine is stdlib-only — no pip install)." note "Logs: ~/.glamdring/app.log" printf '\n' warn "Heads up: this build is ad-hoc signed and not yet notarized by Apple. Installed this way it" warn "launches normally; if macOS ever says it \"cannot verify\" the app, open System Settings →" warn "Privacy & Security and click \"Open Anyway\" once." printf '\n' note "Glamdring defends only your own machine and link — it never hacks back, and nothing leaves" note "your laptop. Read the whole story: https://thot.ai/glamdring"