#!/bin/sh # Everest website bootstrapper for macOS and Linux. set -eu : "${HOME:?HOME is not set}" EVEREST_VERSION="${EVEREST_VERSION:-0.2.17}" UV_VERSION="${UV_VERSION:-0.9.27}" EVEREST_PACKAGE="${EVEREST_PACKAGE:-everest-cli}" EVEREST_RELEASE_BASE_URL="${EVEREST_RELEASE_BASE_URL:-https://install.everestagi.com/releases/v${EVEREST_VERSION}}" EVEREST_WHEEL_URL="${EVEREST_WHEEL_URL:-${EVEREST_RELEASE_BASE_URL}/everest_cli-${EVEREST_VERSION}-py3-none-any.whl}" EVEREST_WHEEL_SHA256_URL="${EVEREST_WHEEL_SHA256_URL:-${EVEREST_WHEEL_URL}.sha256}" # An override makes it possible to verify release candidates without publishing # their checksum file. Normal installs download the checksum beside the wheel. EVEREST_WHEEL_SHA256="${EVEREST_WHEEL_SHA256:-}" UV_INSTALL_URL="${UV_INSTALL_URL:-https://astral.sh/uv/${UV_VERSION}/install.sh}" EVEREST_BIN_DIR="${EVEREST_BIN_DIR:-${HOME}/.local/bin}" EVEREST_ENDPOINT="${EVEREST_ENDPOINT:-}" EVEREST_SKIP_LOGIN="${EVEREST_SKIP_LOGIN:-0}" EVEREST_ONBOARDING_ID="${EVEREST_ONBOARDING_ID:-b9c29447-f228-4718-80d1-9ed5cd5d51de}" EVEREST_ONBOARDING_EVENT_URL="${EVEREST_ONBOARDING_EVENT_URL:-https://install.everestagi.com/_events}" case "$EVEREST_ONBOARDING_ID" in *[!0-9a-fA-F-]*|'') EVEREST_ONBOARDING_ID="" ;; esac if [ "${#EVEREST_ONBOARDING_ID}" -ne 36 ]; then EVEREST_ONBOARDING_ID="" fi export EVEREST_ONBOARDING_ID usage() { cat <<'EOF' Usage: install.sh [--uninstall] Install Everest for the current user, or remove it with --uninstall. No sudo access is required. EOF } die() { printf 'everest installer: %s\n' "$*" >&2 exit 1 } find_uv() { if command -v uv >/dev/null 2>&1; then command -v uv elif [ -x "${EVEREST_BIN_DIR}/uv" ]; then printf '%s\n' "${EVEREST_BIN_DIR}/uv" else return 1 fi } find_everest() { if command -v everest >/dev/null 2>&1; then command -v everest elif [ -x "${EVEREST_BIN_DIR}/everest" ]; then printf '%s\n' "${EVEREST_BIN_DIR}/everest" else return 1 fi } # Match the shell files and conflicts checked by the CLI before downloading or # installing anything. A pre-existing Everest-managed block is safe to update. preflight_shell() { shell_name="${SHELL##*/}" case "$shell_name" in zsh|bash) ;; *) if [ "$(uname -s)" = Darwin ]; then shell_name=zsh else shell_name=bash fi ;; esac if [ "$shell_name" = zsh ]; then rc_path="${HOME}/.zshrc" else rc_path="${HOME}/.bashrc" fi [ -f "$rc_path" ] || return 0 if grep -Eq '^[[:space:]]*(function[[:space:]]+)?codex[[:space:]]*\([[:space:]]*\)[[:space:]]*\{' "$rc_path" \ || grep -Eq '^[[:space:]]*alias[[:space:]]+codex=' "$rc_path" \ || grep -Eq '^[[:space:]]*(source|\.)[[:space:]]+.*codex-cmprs\.sh([[:space:]]|$)' "$rc_path"; then die "$rc_path already defines or sources a codex wrapper. Remove that line or wrapper, then rerun this installer. No Everest package was installed." fi } remove_tool() { everest_bin="$(find_everest || true)" uv_bin="$(find_uv || true)" if [ -n "$everest_bin" ]; then "$everest_bin" uninstall --keep-cli || die "Everest could not remove its shell integration." else printf '%s\n' "Everest is not on PATH; continuing with package removal." fi if [ -n "$uv_bin" ] && "$uv_bin" tool list | awk '{print $1}' | grep -Fx "$EVEREST_PACKAGE" >/dev/null 2>&1; then if "$uv_bin" tool uninstall "$EVEREST_PACKAGE"; then printf '%s\n' "Everest was uninstalled. Saved credentials and usage history were preserved." else die "The Everest package could not be removed with uv." fi elif [ -n "$everest_bin" ] && [ -z "$uv_bin" ]; then printf '%s\n' "Everest shell integration was removed, but uv was not found; remove the package manually." else printf '%s\n' "Everest package removal is complete. Saved credentials and usage history were preserved." fi } install_uv() { command -v curl >/dev/null 2>&1 || die "curl is required to install uv." uv_script="${tmp_dir}/uv-install.sh" printf 'Installing uv %s for the current user...\n' "$UV_VERSION" curl --fail --silent --show-error --location "$UV_INSTALL_URL" --output "$uv_script" UV_INSTALL_DIR="$EVEREST_BIN_DIR" sh "$uv_script" --no-modify-path [ -x "${EVEREST_BIN_DIR}/uv" ] || die "uv installed, but ${EVEREST_BIN_DIR}/uv was not found." printf '%s\n' "${EVEREST_BIN_DIR}/uv" } verify_wheel() { wheel_path=$1 expected_sha256="$EVEREST_WHEEL_SHA256" if [ -z "$expected_sha256" ]; then checksum_path="${tmp_dir}/everest-wheel.sha256" curl --fail --silent --show-error --location \ "$EVEREST_WHEEL_SHA256_URL" --output "$checksum_path" expected_sha256="$(awk 'NR == 1 {print $1}' "$checksum_path")" fi expected_sha256="$(printf '%s' "$expected_sha256" | tr 'A-F' 'a-f')" case "$expected_sha256" in *[!0-9a-fA-F]*|'') die "the Everest release checksum is invalid." ;; esac [ "${#expected_sha256}" -eq 64 ] || die "the Everest release checksum is invalid." if command -v sha256sum >/dev/null 2>&1; then actual_sha256="$(sha256sum "$wheel_path" | awk '{print $1}')" elif command -v shasum >/dev/null 2>&1; then actual_sha256="$(shasum -a 256 "$wheel_path" | awk '{print $1}')" else die "sha256sum or shasum is required to verify the Everest release." fi [ "$actual_sha256" = "$expected_sha256" ] || die "Everest wheel checksum verification failed." } track_install_completed() { [ -n "$EVEREST_ONBOARDING_ID" ] || return 0 curl --fail --silent --show-error --location \ --data-urlencode "onboarding_id=$EVEREST_ONBOARDING_ID" \ --data-urlencode "event_name=install_completed" \ --data-urlencode "release_version=$EVEREST_VERSION" \ "$EVEREST_ONBOARDING_EVENT_URL" >/dev/null 2>&1 || true } case "${1:-}" in "") ;; --uninstall) [ "$#" -eq 1 ] || die "--uninstall does not accept additional arguments." remove_tool exit 0 ;; -h|--help) usage exit 0 ;; *) usage >&2 exit 2 ;; esac [ "$#" -le 1 ] || die "unexpected arguments" case "$(uname -s)" in Darwin|Linux) ;; *) die "only macOS and Linux are supported." ;; esac case "$(uname -m)" in arm64|aarch64|x86_64|amd64) ;; *) die "unsupported CPU architecture: $(uname -m)" ;; esac command -v curl >/dev/null 2>&1 || die "curl is required." if command -v codex >/dev/null 2>&1; then integration=codex preflight_shell elif command -v freebuff >/dev/null 2>&1; then integration=freebuff else die "install Codex or FreeBuff before enabling Everest integration." fi tmp_dir="$(mktemp -d "${TMPDIR:-/tmp}/everest-install.XXXXXX")" trap 'rm -rf "$tmp_dir"' EXIT HUP INT TERM mkdir -p "$EVEREST_BIN_DIR" uv_bin="$(find_uv || true)" if [ -z "$uv_bin" ]; then install_uv uv_bin="$(find_uv || true)" fi [ -n "$uv_bin" ] || die "uv was installed, but its command could not be found." wheel_path="${tmp_dir}/everest_cli-${EVEREST_VERSION}-py3-none-any.whl" printf 'Downloading Everest %s...\n' "$EVEREST_VERSION" wheel_download_url="$EVEREST_WHEEL_URL" if [ -n "$EVEREST_ONBOARDING_ID" ]; then case "$wheel_download_url" in *\?*) wheel_download_url="${wheel_download_url}&onboarding_id=${EVEREST_ONBOARDING_ID}" ;; *) wheel_download_url="${wheel_download_url}?onboarding_id=${EVEREST_ONBOARDING_ID}" ;; esac fi curl --fail --silent --show-error --location "$wheel_download_url" --output "$wheel_path" verify_wheel "$wheel_path" printf '%s\n' "Installing Everest for the current user..." UV_TOOL_BIN_DIR="$EVEREST_BIN_DIR" "$uv_bin" tool install --force "$wheel_path" everest_bin="${EVEREST_BIN_DIR}/everest" [ -x "$everest_bin" ] || die "Everest installed, but its command was not found in ${EVEREST_BIN_DIR}." if [ -n "$EVEREST_ENDPOINT" ]; then "$everest_bin" install --integration "$integration" --endpoint "$EVEREST_ENDPOINT" else "$everest_bin" install --integration "$integration" fi track_install_completed printf '\n%s\n' "Everest ${EVEREST_VERSION} is installed." if [ "$EVEREST_SKIP_LOGIN" = "1" ]; then printf '%s\n' "Next, run: everest login" else printf '%s\n' "Starting browser login. If it does not open, follow the URL shown below." "$everest_bin" login || die "Everest was installed, but login did not complete. Run 'everest login' to retry." fi if [ "$integration" = codex ]; then printf '%s\n' "Open a new terminal, then run: codex" else printf '%s\n' "Open a new terminal, then run: freebuff" fi printf '%s\n' "To remove Everest later: everest uninstall"