#!/usr/bin/env bash set -euo pipefail # hap CLI installer # Usage: # curl -fsSL https://happenings.social/install.sh | bash BIN_NAME="${BIN_NAME:-hap}" INSTALL_DIR="${HAP_INSTALL_DIR:-/usr/local/bin}" BASE_URL="${HAP_INSTALL_BASE_URL:-https://happenings.social}" VERSION="${HAP_CLI_VERSION:-}" if ! command -v curl >/dev/null 2>&1; then echo "error: curl is required" >&2 exit 1 fi OS="$(uname -s | tr '[:upper:]' '[:lower:]')" ARCH="$(uname -m)" case "${OS}" in linux|darwin) ;; *) echo "error: unsupported OS '${OS}' (supported: linux, darwin)" >&2 exit 1 ;; esac case "${ARCH}" in x86_64|amd64) ARCH="amd64" ;; arm64|aarch64) ARCH="arm64" ;; *) echo "error: unsupported architecture '${ARCH}' (supported: amd64, arm64)" >&2 exit 1 ;; esac ASSET="${BIN_NAME}-${OS}-${ARCH}" if [[ -z "${VERSION}" ]]; then VERSION="$(curl -fsSL "${BASE_URL}/downloads/latest.txt" 2>/dev/null | tr -d '[:space:]')" fi if [[ -z "${VERSION}" ]]; then echo "error: could not resolve latest hap version from ${BASE_URL}/downloads/latest.txt" >&2 exit 1 fi TMP_DIR="$(mktemp -d)" cleanup() { rm -rf "${TMP_DIR}" } trap cleanup EXIT TMP_BIN="${TMP_DIR}/${BIN_NAME}" URL="" CANDIDATES=( "${BASE_URL}/downloads/${VERSION}/${ASSET}" "${BASE_URL}/downloads/${ASSET}" ) for candidate in "${CANDIDATES[@]}"; do echo "Downloading ${ASSET} from ${candidate} ..." if curl -fsSL "${candidate}" -o "${TMP_BIN}"; then URL="${candidate}" break fi done if [[ -z "${URL}" ]]; then echo "error: download failed for ${ASSET}" >&2 echo "error: expected ${BASE_URL}/downloads/{latest.txt,/}${ASSET}" >&2 exit 1 fi chmod +x "${TMP_BIN}" TARGET_DIR="${INSTALL_DIR}" TARGET_BIN="${TARGET_DIR}/${BIN_NAME}" install_to() { local src="$1" local dst="$2" if command -v install >/dev/null 2>&1; then install -m 0755 "${src}" "${dst}" else cp "${src}" "${dst}" chmod 0755 "${dst}" fi } if mkdir -p "${TARGET_DIR}" >/dev/null 2>&1 && install_to "${TMP_BIN}" "${TARGET_BIN}" 2>/dev/null; then : elif command -v sudo >/dev/null 2>&1; then echo "Installing to ${TARGET_BIN} with sudo ..." sudo mkdir -p "${TARGET_DIR}" if command -v install >/dev/null 2>&1; then sudo install -m 0755 "${TMP_BIN}" "${TARGET_BIN}" else sudo cp "${TMP_BIN}" "${TARGET_BIN}" sudo chmod 0755 "${TARGET_BIN}" fi else TARGET_DIR="${HOME}/.local/bin" TARGET_BIN="${TARGET_DIR}/${BIN_NAME}" mkdir -p "${TARGET_DIR}" install_to "${TMP_BIN}" "${TARGET_BIN}" echo "Add ${TARGET_DIR} to PATH if needed:" echo ' export PATH="$HOME/.local/bin:$PATH"' fi echo "Installed ${BIN_NAME} to ${TARGET_BIN}" echo "" echo "Installing the Happenings agent skill for detected coding agents ..." "${TARGET_BIN}" skill install || echo "warning: agent skill install failed; run '${BIN_NAME} skill install' manually" >&2 echo "" echo "Get started:" echo " ${BIN_NAME} login" echo " ${BIN_NAME} whoami" echo " ${BIN_NAME} update" echo "" echo "Configure endpoints if needed:" echo " ${BIN_NAME} config set api_url http://localhost:8080" echo " ${BIN_NAME} config set web_url http://localhost:3000" echo "" echo "Run: ${BIN_NAME} --help"