#!/bin/sh set -eu BASE_URL="https://downloads.poolside.ai/pool" INSTALL_DIR="${POOL_INSTALL_DIR:-${XDG_BIN_HOME:-$HOME/.local/bin}}" UPDATE_PATH="${POOL_INSTALL_UPDATE_PATH:-ask}" SHOW_SPLASH="${POOL_INSTALL_SPLASH:-1}" ACCEPT_EULA="${POOL_INSTALL_ACCEPT_EULA:-0}" POOL_PATH_WORKS=0 PATH_RC_FILE="" main() { os="$(detect_os)" arch="$(detect_arch)" version="$(resolve_version "${1:-latest}")" archive="pool-${os}-${arch}.tar.gz" url="${BASE_URL}/${version}/${archive}" checksum_url="${BASE_URL}/${version}/checksums.txt" tmpdir="$(mktemp -d)" trap 'rm -rf "$tmpdir"' EXIT maybe_show_splash "$version" confirm_install printf "Downloading pool %s (%s/%s)...\n" "$version" "$os" "$arch" download "$url" "$tmpdir/$archive" download "$checksum_url" "$tmpdir/checksums.txt" verify_checksum "$tmpdir" "$archive" tar -xzf "$tmpdir/$archive" -C "$tmpdir" binary="$tmpdir/pool-${os}-${arch}" chmod +x "$binary" mkdir -p "$INSTALL_DIR" mv "$binary" "$INSTALL_DIR/pool" printf "pool %s installed to %s/pool\n" "$version" "$INSTALL_DIR" maybe_update_path maybe_print_path_hint printf '\nRun pool to get started\n' } detect_os() { case "$(uname -s)" in Linux) echo "linux" ;; Darwin) echo "darwin" ;; *) fatal "unsupported OS: $(uname -s)" ;; esac } detect_arch() { case "$(uname -m)" in x86_64|amd64) echo "amd64" ;; aarch64|arm64) echo "arm64" ;; *) fatal "unsupported architecture: $(uname -m)" ;; esac } resolve_version() { if [ "$1" = "latest" ]; then v="$(download_stdout "${BASE_URL}/pool-latest-version.txt")" || fatal "failed to fetch latest version" v="$(printf '%s' "$v" | tr -d '[:space:]')" [ -n "$v" ] || fatal "empty version from pool-latest-version.txt" echo "$v" else echo "$1" fi } download() { if command -v curl >/dev/null 2>&1; then curl -fsSL --retry 3 -o "$2" "$1" elif command -v wget >/dev/null 2>&1; then wget -qO "$2" "$1" else fatal "curl or wget is required" fi } download_stdout() { if command -v curl >/dev/null 2>&1; then curl -fsSL --retry 3 "$1" elif command -v wget >/dev/null 2>&1; then wget -qO- "$1" else fatal "curl or wget is required" fi } maybe_show_splash() { version="$1" if [ "$SHOW_SPLASH" != "1" ] || [ ! -t 1 ]; then return 0 fi printf '\n' printf ' ░██ \n' printf ' ░██ \n' printf '░████████ ░███████ ░███████ ░██ \n' printf '░██ ░██ ░██ ░██ ░██ ░██ ░██ \n' printf '░██ ░██ ░██ ░██ ░██ ░██ ░██ \n' printf '░███ ░██ ░██ ░██ ░██ ░██ ░██ \n' printf '░██░█████ ░███████ ░███████ ░██ \n' printf '░██ \n' printf '░██ \n' printf ' %s loading... \n\n' "$version" sleep 0.2 } confirm_install() { if [ "$ACCEPT_EULA" = "1" ]; then return 0 fi if [ ! -r /dev/tty ] || [ ! -w /dev/tty ]; then fatal "interactive confirmation required. Rerun with POOL_INSTALL_ACCEPT_EULA=1 to accept the EULA in headless scenarios." fi printf 'By installing pool, you agree to the Poolside End User License Agreement: https://poolside.ai/eula\n\n' while :; do printf 'Continue? [Y/n] ' IFS= read -r reply > "$rc_file" POOL_PATH_WORKS=1 PATH_RC_FILE="$rc_file" printf "Added %s to PATH in %s\n" "$INSTALL_DIR" "$rc_file" return 0 fi POOL_PATH_WORKS=1 PATH_RC_FILE="$rc_file" } maybe_print_path_hint() { if path_has_dir "$INSTALL_DIR"; then return 0 fi printf '\n' if [ "$POOL_PATH_WORKS" = "1" ]; then printf 'pool will be on your PATH in new shells.\n' printf 'Use it now with:\n' printf ' export PATH="%s:$PATH"\n' "$INSTALL_DIR" printf 'Or reload your shell config:\n' printf ' . "%s"\n' "$PATH_RC_FILE" return 0 fi printf 'pool is not on your PATH yet.\n' printf 'Add it for this shell with:\n' printf ' export PATH="%s:$PATH"\n' "$INSTALL_DIR" printf 'Or rerun with POOL_INSTALL_UPDATE_PATH=1 to update your shell config automatically.\n' } choose_rc_file() { shell_name="$(basename "${SHELL:-}")" case "$shell_name" in zsh) printf '%s\n' "$HOME/.zshrc" ;; bash) printf '%s\n' "$HOME/.bashrc" ;; *) printf '%s\n' "$HOME/.profile" ;; esac } path_has_dir() { case ":${PATH:-}:" in *":$INSTALL_DIR:"*) return 0 ;; *) return 1 ;; esac } should_prompt_for_path_update() { [ -t 0 ] && [ -t 1 ] } confirm_path_update() { rc_file="$(choose_rc_file)" if [ -z "$rc_file" ]; then return 1 fi printf '\nAdd %s to PATH in %s? [Y/n] ' "$INSTALL_DIR" "$rc_file" >&2 if ! IFS= read -r answer; then printf '\n' >&2 return 1 fi case "$answer" in ""|y|Y|yes|YES|Yes) return 0 ;; *) return 1 ;; esac } verify_checksum() { dir="$1" file="$2" expected="$(grep "$file" "$dir/checksums.txt" | awk '{print $1}')" [ -n "$expected" ] || fatal "no checksum found for $file" if command -v sha256sum >/dev/null 2>&1; then actual="$(cd "$dir" && sha256sum "$file" | awk '{print $1}')" elif command -v shasum >/dev/null 2>&1; then actual="$(cd "$dir" && shasum -a 256 "$file" | awk '{print $1}')" else printf "Warning: no sha256sum or shasum found, skipping checksum verification\n" >&2 return 0 fi if [ "$actual" != "$expected" ]; then fatal "checksum mismatch for $file: expected $expected, got $actual" fi } fatal() { printf "Error: %s\n" "$1" >&2 exit 1 } main "$@"