#!/bin/sh # # ThreadBear installer — https://threadbear.dev # # curl -fsSL https://threadbear.dev/install.sh | sh # # What this script does, and nothing more: # 1. Confirms you are on macOS and picks the right architecture. # 2. Resolves the latest published release of ericlitman/threadbear. # 3. Downloads the archive and its published SHA-256 checksum. # 4. Verifies the checksum BEFORE anything is extracted or executed. # 5. Installs the binary to ~/.local/bin (no sudo, ever). # 6. Hands off to `threadbear install`, which explains what it will change # and asks for one confirmation before it touches Codex or your LaunchAgent. # # It does not write outside ~/.local, does not need root, and does not configure # anything on its own. Read it, then run it. set -eu REPO="ericlitman/threadbear" BIN_DIR="${THREADBEAR_BIN_DIR:-$HOME/.local/bin}" API="https://api.github.com/repos/$REPO/releases/latest" # --- pretty output (degrades to plain text when not a tty) -------------------- if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then B=$(printf '\033[1m'); DIM=$(printf '\033[2m'); R=$(printf '\033[0m') YEL=$(printf '\033[33m'); RED=$(printf '\033[31m'); GRN=$(printf '\033[32m') else B=''; DIM=''; R=''; YEL=''; RED=''; GRN='' fi say() { printf '%s\n' "$*"; } step() { printf '%s==>%s %s\n' "$YEL" "$R" "$*"; } die() { printf '%s\n' "" >&2; printf '%serror:%s %s\n' "$RED" "$R" "$1" >&2; exit 1; } printf '\n %s🧵🐻 ThreadBear%s\n %swrangle your Codex threads%s\n\n' "$B" "$R" "$DIM" "$R" # --- platform ---------------------------------------------------------------- OS=$(uname -s) [ "$OS" = "Darwin" ] || die "ThreadBear is macOS-only (it manages Codex Desktop and a LaunchAgent). Detected: $OS" case $(uname -m) in arm64) ARCH="arm64" ;; x86_64) ARCH="amd64" ;; *) die "unsupported architecture: $(uname -m)" ;; esac for cmd in curl shasum tar mkdir; do command -v "$cmd" >/dev/null 2>&1 || die "required command not found: $cmd" done # --- resolve the latest release --------------------------------------------- step "Looking for the latest release…" HTTP_BODY=$(mktemp) || die "could not create a temp file" CLEANUP_FILES="$HTTP_BODY" # shellcheck disable=SC2064 trap 'rm -rf $CLEANUP_FILES' EXIT INT TERM HTTP_CODE=$(curl -sSL -w '%{http_code}' -o "$HTTP_BODY" \ -H 'Accept: application/vnd.github+json' "$API" 2>/dev/null || echo "000") if [ "$HTTP_CODE" = "404" ]; then cat <