#!/usr/bin/env bash set -euo pipefail # Universal Kasy CLI installer for macOS and Linux. # Hosted at https://kasy.dev/install — run with: # curl -fsSL https://kasy.dev/install | bash CLI_NAME="kasy" PACKAGE_NAME="${KASY_CLI_PACKAGE:-kasy-cli}" INSTALL_ROOT="${KASY_CLI_HOME:-$HOME/.kasy}" BIN_DIR="$INSTALL_ROOT/bin" CLI_PATH="$BIN_DIR/$CLI_NAME" detect_platform() { case "$(uname -s)" in Darwin) printf 'macOS' ;; Linux) printf 'Linux' ;; *) printf '%s' "$(uname -s)" ;; esac } select_profile() { if [ -n "${KASY_CLI_PROFILE:-}" ]; then printf '%s' "$KASY_CLI_PROFILE" return fi for profile in "$HOME/.zshrc" "$HOME/.bashrc" "$HOME/.bash_profile" "$HOME/.profile"; do if [ -f "$profile" ]; then printf '%s' "$profile" return fi done if [ "${SHELL:-}" = "/bin/bash" ]; then printf '%s' "$HOME/.bashrc" else printf '%s' "$HOME/.zshrc" fi } printf '\nšŸš€ Kasy CLI Installer\n\n' printf 'šŸ“¦ Platform: %s\n\n' "$(detect_platform)" if ! command -v node >/dev/null 2>&1; then # On a fresh machine we prepare it for the user instead of asking them to go # install Node and start over. macOS: bootstrap Homebrew (also what the Flutter # auto-install in `kasy new` relies on), then install Node through it. if [ "$(uname -s)" = "Darwin" ]; then printf '\nšŸ”§ Node.js is needed and is not installed yet. Setting it up for you...\n\n' if ! command -v brew >/dev/null 2>&1; then printf 'ā¬‡ļø Installing Homebrew first (you may be asked for your Mac password)...\n' NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" || true # Put brew on PATH for THIS shell (Apple Silicon vs Intel locations) and, # on Apple Silicon, persist it so future terminals find brew (and node). for brew_bin in /opt/homebrew/bin/brew /usr/local/bin/brew; do if [ -x "$brew_bin" ]; then eval "$("$brew_bin" shellenv)" if [ "$brew_bin" = "/opt/homebrew/bin/brew" ]; then zprofile="$HOME/.zprofile" touch "$zprofile" line="eval \"\$(/opt/homebrew/bin/brew shellenv)\"" grep -Fq "$line" "$zprofile" || printf '\n%s\n' "$line" >> "$zprofile" fi fi done fi if command -v brew >/dev/null 2>&1; then printf 'ā¬‡ļø Installing Node.js...\n' brew install node || true fi fi # Re-check. If it is still missing, fall back to clear manual guidance. if ! command -v node >/dev/null 2>&1; then printf '\nāŒ Node.js 18+ is required (the Kasy CLI runs on Node).\n\n' >&2 if [ "$(uname -s)" = "Darwin" ]; then printf ' Could not set it up automatically. Install it by hand, then run this again:\n brew install node\n\n' >&2 else printf ' Install it with nvm, then run this again:\n curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash\n nvm install --lts\n\n' >&2 fi printf ' Or download it from https://nodejs.org\n' >&2 exit 1 fi printf 'āœ“ Node.js ready\n\n' fi if ! command -v npm >/dev/null 2>&1; then printf 'āŒ Error: npm command not found. Reinstall Node.js and run again.\n' >&2 exit 1 fi install_target="${PACKAGE_NAME}@latest" case "$PACKAGE_NAME" in /*|./*|../*|~/*|file:*|git+*|http://*|https://*) install_target="$PACKAGE_NAME" ;; esac printf 'ā¬‡ļø Installing...\n' npm install -g "$install_target" --prefix "$INSTALL_ROOT" >/dev/null printf 'āœ“ Installed\n' if [ ! -x "$CLI_PATH" ]; then printf '\nāŒ Error: install finished, but %s was not found.\n' "$CLI_PATH" >&2 exit 1 fi profile_file="$(select_profile)" mkdir -p "$(dirname "$profile_file")" touch "$profile_file" path_export="export PATH=\"$BIN_DIR:\$PATH\"" if ! grep -Fq "$path_export" "$profile_file"; then printf '\n%s\n' "$path_export" >> "$profile_file" fi printf '\nšŸŽ‰ Installation complete!\n\n' printf 'Close this terminal and open a NEW one, then run:\n' printf ' %s new\n' "$CLI_NAME"