#!/bin/sh # Haiphen CLI installer # Usage: curl -fsSL https://get.haiphen.io | sh # # Detects OS/arch, downloads the latest release from GitHub, verifies the # SHA-256 checksum, and installs to /usr/local/bin (or ~/.local/bin). set -e REPO="haiphenAI/haiphen-cli" BINARY_NAME="haiphen" # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- info() { printf "\033[1;34m==>\033[0m %s\n" "$1"; } warn() { printf "\033[1;33mwarning:\033[0m %s\n" "$1" >&2; } error() { printf "\033[1;31merror:\033[0m %s\n" "$1" >&2; exit 1; } need() { command -v "$1" >/dev/null 2>&1 || error "Required command '$1' not found. Please install it and retry." } # --------------------------------------------------------------------------- # Detect platform # --------------------------------------------------------------------------- detect_os() { case "$(uname -s)" in Darwin*) echo "darwin" ;; Linux*) echo "linux" ;; MINGW*|MSYS*|CYGWIN*) error "Windows detected. Use install.ps1 instead: irm https://get.haiphen.io/install.ps1 | iex" ;; *) error "Unsupported OS: $(uname -s)" ;; esac } detect_arch() { case "$(uname -m)" in x86_64|amd64) echo "amd64" ;; arm64|aarch64) echo "arm64" ;; *) error "Unsupported architecture: $(uname -m)" ;; esac } # --------------------------------------------------------------------------- # Fetch latest release tag # --------------------------------------------------------------------------- latest_version() { need curl local url="https://api.github.com/repos/${REPO}/releases/latest" local tag tag=$(curl -fsSL "$url" 2>/dev/null | grep '"tag_name"' | head -1 | sed 's/.*"tag_name": *"//;s/".*//') if [ -z "$tag" ]; then # Fall back to releases listing (in case latest is a draft) tag=$(curl -fsSL "https://api.github.com/repos/${REPO}/releases" 2>/dev/null \ | grep '"tag_name"' | head -1 | sed 's/.*"tag_name": *"//;s/".*//') fi [ -z "$tag" ] && error "Could not determine latest release version." echo "$tag" } # --------------------------------------------------------------------------- # Download, verify, install # --------------------------------------------------------------------------- main() { need curl need tar if ! command -v sha256sum >/dev/null 2>&1 && ! command -v shasum >/dev/null 2>&1; then error "Required command 'sha256sum' or 'shasum' not found. Please install one and retry." fi local os arch version os=$(detect_os) arch=$(detect_arch) version=$(latest_version) local version_no_v="${version#v}" info "Installing ${BINARY_NAME} ${version} (${os}/${arch})" local archive="${BINARY_NAME}_${version_no_v}_${os}_${arch}.tar.gz" local base_url="https://github.com/${REPO}/releases/download/${version}" local tmpdir tmpdir=$(mktemp -d) # Download archive and checksums info "Downloading ${archive}..." curl -fsSL -o "${tmpdir}/${archive}" "${base_url}/${archive}" \ || error "Failed to download ${base_url}/${archive}" info "Downloading checksums..." curl -fsSL -o "${tmpdir}/checksums.txt" "${base_url}/checksums.txt" \ || error "Failed to download checksums" # Verify checksum info "Verifying checksum..." local expected expected=$(grep "${archive}" "${tmpdir}/checksums.txt" | awk '{print $1}') [ -z "$expected" ] && error "Archive not found in checksums.txt" local actual if command -v sha256sum >/dev/null 2>&1; then actual=$(sha256sum "${tmpdir}/${archive}" | awk '{print $1}') else actual=$(shasum -a 256 "${tmpdir}/${archive}" | awk '{print $1}') fi if [ "$expected" != "$actual" ]; then error "Checksum mismatch!\n expected: ${expected}\n actual: ${actual}" fi # Extract info "Extracting..." tar -xzf "${tmpdir}/${archive}" -C "${tmpdir}" # Install local install_dir="/usr/local/bin" if [ ! -w "$install_dir" ] && [ "$(id -u)" -ne 0 ]; then install_dir="${HOME}/.local/bin" mkdir -p "$install_dir" warn "No write access to /usr/local/bin. Installing to ${install_dir}" warn "Make sure ${install_dir} is in your PATH." fi install -m 755 "${tmpdir}/${BINARY_NAME}" "${install_dir}/${BINARY_NAME}" # Cleanup rm -rf "$tmpdir" info "Installed ${BINARY_NAME} ${version} to ${install_dir}/${BINARY_NAME}" printf "\n Run '\033[1m%s --help\033[0m' to get started.\n\n" "${BINARY_NAME}" } main "$@"