#!/bin/sh # ───────────────────────────────────────────────────────────────────────────── # Birdify CLI installer · macOS & Linux # # curl -fsSL https://birdify.dev/install.sh | sh # # Detects your OS + architecture, downloads the matching prebuilt binary, # verifies its SHA-256 against the published checksums, and installs it onto # your PATH. Windows users: irm https://birdify.dev/install.ps1 | iex # # Environment overrides: # BIRDIFY_INSTALL_DIR install location (default: /usr/local/bin → ~/.local/bin) # BIRDIFY_VERSION version tag to install (default: latest) # BIRDIFY_INSTALL_BASE_URL override the download base URL (advanced / testing) # ───────────────────────────────────────────────────────────────────────────── set -eu REPO="krishpranav/birdify-cli" VERSION="${BIRDIFY_VERSION:-latest}" # ── pretty output (only when writing to a terminal) ────────────────────────── if [ -t 2 ]; then B=$(printf '\033[1m'); DIM=$(printf '\033[2m'); BLUE=$(printf '\033[38;5;33m') GREEN=$(printf '\033[32m'); RED=$(printf '\033[31m'); R=$(printf '\033[0m') else B=; DIM=; BLUE=; GREEN=; RED=; R= fi say() { printf '%s\n' "$*" >&2; } step() { printf ' %s➜%s %s\n' "$BLUE" "$R" "$*" >&2; } ok() { printf ' %s✓%s %s\n' "$GREEN" "$R" "$*" >&2; } die() { printf ' %s✗ %s%s\n' "$RED" "$*" "$R" >&2; exit 1; } # ── prerequisites ──────────────────────────────────────────────────────────── if command -v curl >/dev/null 2>&1; then fetch() { curl -fsSL "$1" -o "$2"; } elif command -v wget >/dev/null 2>&1; then fetch() { wget -qO "$2" "$1"; } else die "need curl or wget to download birdify" fi # ── detect platform ────────────────────────────────────────────────────────── os=$(uname -s | tr '[:upper:]' '[:lower:]') arch=$(uname -m) case "$arch" in x86_64 | amd64) arch=amd64 ;; arm64 | aarch64) arch=arm64 ;; *) die "unsupported architecture: $arch (need x86_64 or arm64)" ;; esac case "$os" in darwin | linux) ;; msys* | mingw* | cygwin* | windows*) die "Windows detected — run in PowerShell instead: irm https://birdify.dev/install.ps1 | iex" ;; *) die "unsupported OS: $os (macOS and Linux only)" ;; esac asset="birdify_${os}_${arch}" if [ -n "${BIRDIFY_INSTALL_BASE_URL:-}" ]; then base="$BIRDIFY_INSTALL_BASE_URL" elif [ "$VERSION" = "latest" ]; then base="https://github.com/${REPO}/releases/latest/download" else base="https://github.com/${REPO}/releases/download/${VERSION}" fi say "" say " ${B}${BLUE}🐦 Birdify${R} ${DIM}· over-the-air code push${R}" say "" # ── download ───────────────────────────────────────────────────────────────── tmp=$(mktemp -d) trap 'rm -rf "$tmp"' EXIT INT TERM step "Downloading ${B}${asset}${R} ${DIM}(${os}/${arch})${R}" fetch "$base/$asset" "$tmp/birdify" || die "download failed: $base/$asset" fetch "$base/checksums.txt" "$tmp/checksums.txt" || die "could not fetch checksums.txt" # ── verify sha256 ──────────────────────────────────────────────────────────── expected=$(awk -v a="$asset" '$2==a || $2=="*"a {print $1}' "$tmp/checksums.txt" | head -n1) [ -n "$expected" ] || die "no checksum entry for $asset" if command -v shasum >/dev/null 2>&1; then actual=$(shasum -a 256 "$tmp/birdify" | awk '{print $1}') elif command -v sha256sum >/dev/null 2>&1; then actual=$(sha256sum "$tmp/birdify" | awk '{print $1}') else die "need shasum or sha256sum to verify the download" fi [ "$expected" = "$actual" ] || die "checksum mismatch (expected $expected, got $actual)" ok "Checksum verified ${DIM}(sha256)${R}" chmod +x "$tmp/birdify" # ── choose an install dir ──────────────────────────────────────────────────── dir="${BIRDIFY_INSTALL_DIR:-}" if [ -z "$dir" ]; then if [ "$(id -u)" = "0" ] || [ -w /usr/local/bin ] 2>/dev/null; then dir="/usr/local/bin" else dir="$HOME/.local/bin" fi fi mkdir -p "$dir" 2>/dev/null || true if [ -w "$dir" ]; then mv "$tmp/birdify" "$dir/birdify" elif command -v sudo >/dev/null 2>&1; then step "Installing to ${B}$dir${R} ${DIM}(requires sudo)${R}" sudo mv "$tmp/birdify" "$dir/birdify" else die "cannot write to $dir and sudo is unavailable — set BIRDIFY_INSTALL_DIR to a writable directory" fi ok "Installed ${B}birdify${R} → $dir/birdify" # ── PATH hint ──────────────────────────────────────────────────────────────── case ":$PATH:" in *":$dir:"*) ;; *) say "" step "Add ${B}$dir${R} to your PATH, then restart your shell:" say " ${DIM}export PATH=\"$dir:\$PATH\"${R}" ;; esac say "" "$dir/birdify" version 2>/dev/null || true say "" ok "Get started: ${DIM}birdify flutter|rn|native create ${R}" say ""