#!/usr/bin/env bash set -euo pipefail # Walnut CLI installer # Usage: curl -fsSL https://walnut.sh | bash RELEASES_URL="${WALNUT_RELEASES_URL:-https://releases.walnut.sh}" VERSION="${WALNUT_VERSION:-latest}" INSTALL_DIR="${WALNUT_INSTALL_DIR:-$HOME/.walnut}" BIN_DIR="$INSTALL_DIR/bin" tildify() { if [[ $1 == "$HOME"/* ]]; then echo "~${1#"$HOME"}" else echo "$1" fi } info() { printf '%s\n' "$@" } warn() { printf '%s\n' "$@" >&2 } main() { local platform arch platform="$(uname -s | tr '[:upper:]' '[:lower:]')" arch="$(uname -m)" case "$arch" in x86_64) arch="x64" ;; aarch64|arm64) arch="arm64" ;; *) warn "error: unsupported architecture: $arch" && exit 1 ;; esac case "$platform" in darwin|linux) ;; *) warn "error: unsupported platform: $platform" && exit 1 ;; esac local binary="walnut-${platform}-${arch}" local url="${RELEASES_URL}/${VERSION}/${binary}" info "Installing walnut ${VERSION} for ${platform}-${arch}..." info " from: ${url}" mkdir -p "$BIN_DIR" if ! curl -fsSL "$url" -o "$BIN_DIR/walnut"; then echo "" warn "error: download failed. Check that version '${VERSION}' exists at:" warn " ${RELEASES_URL}/${VERSION}/" exit 1 fi chmod +x "$BIN_DIR/walnut" # Verify the binary runs. if ! "$BIN_DIR/walnut" version >/dev/null 2>&1; then warn "error: downloaded binary failed to execute. This may be a platform mismatch." rm -f "$BIN_DIR/walnut" exit 1 fi local installed_version installed_version=$("$BIN_DIR/walnut" version 2>/dev/null || echo "unknown") info "" info " ${installed_version}" info " installed to ${BIN_DIR}/walnut" # ------------------------------------------------------------------------- # Add to PATH: detect shell, append to rc file if not already present. # ------------------------------------------------------------------------- if [[ ":$PATH:" == *":$BIN_DIR:"* ]]; then # Already on PATH — nothing to do. return fi local shell_name shell_name="$(basename "${SHELL:-bash}")" local refresh_command="" local rc_updated=false case "$shell_name" in fish) local fish_config="${XDG_CONFIG_HOME:-$HOME/.config}/fish/config.fish" if append_to_rc "$fish_config" \ "# walnut" \ "set --export WALNUT_INSTALL $(quote_for_shell "$INSTALL_DIR")" \ "set --export PATH \$WALNUT_INSTALL/bin \$PATH"; then rc_updated=true refresh_command="source $(tildify "$fish_config")" fi ;; zsh) local zsh_config="$HOME/.zshrc" if append_to_rc "$zsh_config" \ "# walnut" \ "export WALNUT_INSTALL=$(quote_for_shell "$INSTALL_DIR")" \ "export PATH=\"\$WALNUT_INSTALL/bin:\$PATH\""; then rc_updated=true refresh_command="exec $SHELL" fi ;; bash|*) # Try each bash config in order, use the first writable one. local bash_configs=() # Prefer .bash_profile on macOS (login shells), .bashrc on Linux. if [[ "$platform" == "darwin" ]]; then bash_configs+=("$HOME/.bash_profile" "$HOME/.bashrc") else bash_configs+=("$HOME/.bashrc" "$HOME/.bash_profile") fi if [[ -n "${XDG_CONFIG_HOME:-}" ]]; then bash_configs+=("$XDG_CONFIG_HOME/.bashrc" "$XDG_CONFIG_HOME/.bash_profile") fi local bash_config for bash_config in "${bash_configs[@]}"; do if append_to_rc "$bash_config" \ "# walnut" \ "export WALNUT_INSTALL=$(quote_for_shell "$INSTALL_DIR")" \ "export PATH=\"\$WALNUT_INSTALL/bin:\$PATH\""; then rc_updated=true refresh_command="source $(tildify "$bash_config")" break fi done ;; esac if $rc_updated; then info "" info "Added $(tildify "$BIN_DIR") to \$PATH" info "" info "To start using walnut, run:" info "" info " $refresh_command" else info "" info "Manually add walnut to your PATH:" info "" info " export PATH=\"$(tildify "$BIN_DIR"):\$PATH\"" info "" info "Add that line to your shell config to make it permanent." fi } # Append lines to an rc file if: (a) the file exists or can be created, # (b) it's writable, and (c) it doesn't already contain a walnut PATH entry. # Returns 0 (success) if lines were appended, 1 otherwise. append_to_rc() { local rc_file="$1" shift local lines=("$@") # Create the file if it doesn't exist (e.g. fresh machine). if [[ ! -f "$rc_file" ]]; then local rc_dir rc_dir="$(dirname "$rc_file")" if [[ ! -d "$rc_dir" ]]; then mkdir -p "$rc_dir" 2>/dev/null || return 1 fi touch "$rc_file" 2>/dev/null || return 1 fi if [[ ! -w "$rc_file" ]]; then return 1 fi # Don't duplicate if already present. if grep -q 'WALNUT_INSTALL' "$rc_file" 2>/dev/null; then return 0 fi printf '\n' >> "$rc_file" for line in "${lines[@]}"; do printf '%s\n' "$line" >> "$rc_file" done return 0 } # Quote a path for embedding in a shell config file. quote_for_shell() { if [[ "$1" == "$HOME"/* ]]; then # Use $HOME reference so the config stays portable across machines. echo "\"\$HOME${1#"$HOME"}\"" elif [[ "$1" == *" "* || "$1" == *"'"* ]]; then echo "\"$1\"" else echo "$1" fi } main