#!/bin/sh # Fiberplane CLI installer # Usage: curl -fsSL https://setup.fp.dev/install.sh | sh # curl -fsSL https://setup.fp.dev/install.sh | sh -s -- --version 0.1.0 # # Options: # --version, -v VERSION Version to install (default: stable) # --target, -t TARGET Target triple (auto-detected if not set) # --install-dir, -d DIR Installation directory (default: ~/.fiberplane/bin) # # Environment variables (alternative to options): # FP_VERSION - Version to install (default: stable) # FP_TARGET - Target triple (auto-detected if not set) # FP_INSTALL_DIR - Installation directory (default: ~/.fiberplane/bin) set -e BASE_URL="${FP_BASE_URL:-https://setup.fp.dev}" VERSION="${FP_VERSION:-stable}" INSTALL_DIR="${FP_INSTALL_DIR:-$HOME/.fiberplane/bin}" # Parse command line arguments while [ $# -gt 0 ]; do case "$1" in --version|-v) VERSION="$2" shift 2 ;; --target|-t) FP_TARGET="$2" shift 2 ;; --install-dir|-d) INSTALL_DIR="$2" shift 2 ;; --help|-h) echo "Usage: install.sh [OPTIONS]" echo "" echo "Options:" echo " --version, -v VERSION Version to install (default: stable)" echo " --target, -t TARGET Target triple (auto-detected if not set)" echo " --install-dir, -d DIR Installation directory (default: ~/.fiberplane/bin)" echo " --help, -h Show this help message" exit 0 ;; *) echo "Unknown option: $1" >&2 exit 1 ;; esac done # Colors (disabled if not a terminal) if [ -t 1 ]; then RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' BLUE='\033[0;34m' NC='\033[0m' else RED='' GREEN='' YELLOW='' BLUE='' NC='' fi info() { printf "${BLUE}info${NC}: %s\n" "$1" } success() { printf "${GREEN}success${NC}: %s\n" "$1" } warn() { printf "${YELLOW}warn${NC}: %s\n" "$1" } error() { printf "${RED}error${NC}: %s\n" "$1" >&2 exit 1 } detect_os() { case "$(uname -s)" in Linux*) echo "linux" ;; Darwin*) echo "darwin" ;; *) error "Unsupported operating system: $(uname -s)" ;; esac } detect_arch() { case "$(uname -m)" in x86_64|amd64) echo "x86_64" ;; arm64|aarch64) echo "aarch64" ;; *) error "Unsupported architecture: $(uname -m)" ;; esac } detect_libc() { # ldd --version reliably identifies the libc if command -v ldd >/dev/null 2>&1; then if ldd --version 2>&1 | grep -qi musl; then echo "musl" return fi # Fallback: check for musl dynamic linker elif [ -f /lib/ld-musl-x86_64.so.1 ] || [ -f /lib/ld-musl-aarch64.so.1 ]; then echo "musl" return fi # Default to glibc (most common on Linux servers) echo "gnu" } detect_target() { os=$(detect_os) arch=$(detect_arch) case "$os" in linux) libc=$(detect_libc) if [ "$libc" = "musl" ]; then echo "${arch}-unknown-linux-musl" else echo "${arch}-unknown-linux-gnu" fi ;; darwin) echo "${arch}-apple-darwin" ;; esac } check_command() { command -v "$1" >/dev/null 2>&1 } # Detect target if not set TARGET="${FP_TARGET:-$(detect_target)}" info "Installing Fiberplane CLI" info "Version: $VERSION" info "Target: $TARGET" info "Install directory: $INSTALL_DIR" # Check for required tools if ! check_command curl; then error "curl is required but not installed" fi if ! check_command tar; then error "tar is required but not installed" fi # Create install directory mkdir -p "$INSTALL_DIR" # Create temp directory TMP_DIR=$(mktemp -d) trap 'rm -rf "$TMP_DIR"' EXIT ARTIFACT_URL="$BASE_URL/fp/$VERSION/$TARGET" CHECKSUM_URL="$ARTIFACT_URL/checksum" BUNDLE_PATH="$TMP_DIR/bundle.tar.gz" CHECKSUM_PATH="$TMP_DIR/checksum.sha256" # Download checksum info "Downloading checksum..." if ! curl -fsSL "$CHECKSUM_URL" -o "$CHECKSUM_PATH"; then error "Failed to download checksum from $CHECKSUM_URL" fi EXPECTED_CHECKSUM=$(cat "$CHECKSUM_PATH") # Download artifact info "Downloading artifact..." if ! curl -fsSL "$ARTIFACT_URL" -o "$BUNDLE_PATH"; then error "Failed to download artifact from $ARTIFACT_URL" fi # Verify checksum info "Verifying checksum..." if check_command sha256sum; then ACTUAL_CHECKSUM=$(sha256sum "$BUNDLE_PATH" | cut -d' ' -f1) elif check_command shasum; then ACTUAL_CHECKSUM=$(shasum -a 256 "$BUNDLE_PATH" | cut -d' ' -f1) else warn "Neither sha256sum nor shasum found, skipping checksum verification" ACTUAL_CHECKSUM="$EXPECTED_CHECKSUM" fi if [ "$ACTUAL_CHECKSUM" != "$EXPECTED_CHECKSUM" ]; then error "Checksum verification failed.\nExpected: $EXPECTED_CHECKSUM\nActual: $ACTUAL_CHECKSUM" fi success "Checksum verified" # Extract info "Extracting..." tar -xzf "$BUNDLE_PATH" -C "$TMP_DIR" # Install info "Installing to $INSTALL_DIR..." mv "$TMP_DIR/fp" "$INSTALL_DIR/fp" chmod +x "$INSTALL_DIR/fp" success "Fiberplane CLI installed successfully!" # Check if install dir is in PATH case ":$PATH:" in *":$INSTALL_DIR:"*) info "Run 'fp --help' to get started" ;; *) echo "" warn "$INSTALL_DIR is not in your PATH" echo "" echo "Add it to your shell profile:" echo "" echo " # For bash (~/.bashrc)" echo " export PATH=\"\$PATH:$INSTALL_DIR\"" echo "" echo " # For zsh (~/.zshrc)" echo " export PATH=\"\$PATH:$INSTALL_DIR\"" echo "" echo " # For fish (~/.config/fish/config.fish)" echo " fish_add_path $INSTALL_DIR" echo "" ;; esac