From ab3041c96a73ce83f35088cf86eeebecca14c1d1 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 15 Jan 2026 16:41:04 +0000 Subject: [PATCH] feat: add one-command installation for Mac/Linux and Windows - Add install.sh for Unix systems (curl-able installer) - Auto-detects macOS/Linux - Installs Node.js via Homebrew, apt, dnf, yum, pacman, or nvm - Installs Git via system package manager - Clones and sets up ralph-cli globally - Add install.ps1 for Windows (PowerShell installer) - Installs dependencies via winget or Chocolatey - Handles non-admin scenarios gracefully - Includes Windows-specific bash guidance - Update README.md and CLAUDE.md with new install commands: - curl -fsSL .../install.sh | bash (Mac/Linux) - iwr -useb .../install.ps1 | iex (Windows) --- CLAUDE.md | 4 +- README.md | 40 +++++- install.ps1 | 353 +++++++++++++++++++++++++++++++++++++++++++++++ install.sh | 389 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 782 insertions(+), 4 deletions(-) create mode 100644 install.ps1 create mode 100755 install.sh diff --git a/CLAUDE.md b/CLAUDE.md index dad072c..9d8c02a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,7 +6,9 @@ Autonomous coding loop for Claude Code. PRD-based workflow with bash implementat | Use Case | Command | | ------------------------ | ---------------------------------------------------------------------------------------------- | -| **Install ralph-cli** | `git clone https://github.com/AskTinNguyen/ralph-cli.git && cd ralph-cli && npm i && npm link` | +| **Install (Mac/Linux)** | `curl -fsSL https://raw.githubusercontent.com/AskTinNguyen/ralph-cli/main/install.sh \| bash` | +| **Install (Windows)** | `iwr -useb https://raw.githubusercontent.com/AskTinNguyen/ralph-cli/main/install.ps1 \| iex` | +| **Install (manual)** | `git clone https://github.com/AskTinNguyen/ralph-cli.git && cd ralph-cli && npm i && npm link` | | **Install to project** | `ralph install` | | **Generate PRD** | `ralph prd` | | **Create plan from PRD** | `ralph plan` (creates PRD-N folder) | diff --git a/README.md b/README.md index 9405342..07bcf84 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,30 @@ Ralph is a minimal, file-based agent loop for autonomous coding. Each iteration ## Quick Start (5 minutes) -### Prerequisites +### One-Command Install + +**macOS / Linux:** +```bash +curl -fsSL https://raw.githubusercontent.com/AskTinNguyen/ralph-cli/main/install.sh | bash +``` + +**Windows (PowerShell):** +```powershell +iwr -useb https://raw.githubusercontent.com/AskTinNguyen/ralph-cli/main/install.ps1 | iex +``` + +The installer automatically: +- Checks for Node.js (v18+), npm, and Git +- Installs missing dependencies (via Homebrew, apt, winget, or Chocolatey) +- Clones and sets up ralph-cli globally + +### Prerequisites (if installing manually) - Node.js 18+ - Git - An AI agent: [Claude Code](https://claude.ai/download), [Codex](https://github.com/openai/codex), or [Droid](https://factory.ai) -### Install Ralph +### Manual Install ```bash git clone https://github.com/AskTinNguyen/ralph-cli.git @@ -45,7 +62,24 @@ Ralph treats **files and git** as memory, not the model context: ## Installation -### From GitHub (Recommended) +### One-Command Install (Recommended) + +**macOS / Linux:** +```bash +curl -fsSL https://raw.githubusercontent.com/AskTinNguyen/ralph-cli/main/install.sh | bash +``` + +**Windows (PowerShell):** +```powershell +iwr -useb https://raw.githubusercontent.com/AskTinNguyen/ralph-cli/main/install.ps1 | iex +``` + +**Custom install directory:** +```bash +RALPH_INSTALL_DIR=/opt/ralph curl -fsSL https://raw.githubusercontent.com/AskTinNguyen/ralph-cli/main/install.sh | bash +``` + +### From GitHub (Manual) ```bash git clone https://github.com/AskTinNguyen/ralph-cli.git diff --git a/install.ps1 b/install.ps1 new file mode 100644 index 0000000..d8d69e4 --- /dev/null +++ b/install.ps1 @@ -0,0 +1,353 @@ +# Ralph CLI - One-Command Installer for Windows +# Usage: iwr -useb https://raw.githubusercontent.com/AskTinNguyen/ralph-cli/main/install.ps1 | iex +# +# This script will: +# 1. Check for required dependencies (Node.js, npm, git) +# 2. Install missing dependencies (via winget or chocolatey) +# 3. Clone ralph-cli repository +# 4. Install npm dependencies +# 5. Link ralph globally + +#Requires -Version 5.1 + +$ErrorActionPreference = "Stop" + +# Configuration +$RalphRepo = "https://github.com/AskTinNguyen/ralph-cli.git" +$RalphDir = if ($env:RALPH_INSTALL_DIR) { $env:RALPH_INSTALL_DIR } else { Join-Path $env:USERPROFILE "ralph-cli" } +$MinNodeVersion = 18 + +# Colors and formatting +function Write-ColorOutput($ForegroundColor, $Message) { + $fc = $host.UI.RawUI.ForegroundColor + $host.UI.RawUI.ForegroundColor = $ForegroundColor + Write-Output $Message + $host.UI.RawUI.ForegroundColor = $fc +} + +function Write-Info($Message) { Write-ColorOutput Blue "[INFO] $Message" } +function Write-Success($Message) { Write-ColorOutput Green "[OK] $Message" } +function Write-Warn($Message) { Write-ColorOutput Yellow "[WARN] $Message" } +function Write-Err($Message) { Write-ColorOutput Red "[ERROR] $Message" } +function Write-Step($Message) { Write-Output ""; Write-ColorOutput Cyan "==> $Message" } + +# Banner +function Show-Banner { + Write-ColorOutput Cyan @" + + ____ __ __ _________ ____ + / __ \____ _/ /___ / /_ / ____/ / / _/ + / /_/ / __ `/ / __ \/ __ \ / / / / / / + / _, _/ /_/ / / /_/ / / / / / /___/ /____/ / +/_/ |_|\__,_/_/ .___/_/ /_/ \____/_____/___/ + /_/ + +"@ + Write-Output "One-Command Installer for Windows" + Write-Output "" +} + +# Check if command exists +function Test-Command($Command) { + $null -ne (Get-Command $Command -ErrorAction SilentlyContinue) +} + +# Get Node.js major version +function Get-NodeVersion { + if (Test-Command "node") { + $version = (node -v) -replace 'v', '' + [int]($version.Split('.')[0]) + } else { + 0 + } +} + +# Check if winget is available +function Test-Winget { + Test-Command "winget" +} + +# Check if chocolatey is available +function Test-Chocolatey { + Test-Command "choco" +} + +# Install Chocolatey +function Install-Chocolatey { + Write-Step "Installing Chocolatey Package Manager" + Set-ExecutionPolicy Bypass -Scope Process -Force + [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 + Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) + + # Refresh PATH + $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") +} + +# Install Node.js +function Install-Node { + Write-Step "Installing Node.js" + + if (Test-Winget) { + Write-Info "Installing Node.js via winget..." + winget install OpenJS.NodeJS.LTS --silent --accept-package-agreements --accept-source-agreements + } elseif (Test-Chocolatey) { + Write-Info "Installing Node.js via Chocolatey..." + choco install nodejs-lts -y + } else { + Write-Warn "No package manager found. Installing Chocolatey first..." + Install-Chocolatey + + Write-Info "Installing Node.js via Chocolatey..." + choco install nodejs-lts -y + } + + # Refresh PATH + $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") + + # Verify installation + if (-not (Test-Command "node")) { + Write-Err "Node.js installation failed" + Write-Info "Please install Node.js manually from https://nodejs.org" + Write-Info "After installing, restart PowerShell and run this script again" + exit 1 + } + + Write-Success "Node.js installed: $(node -v)" +} + +# Install Git +function Install-Git { + Write-Step "Installing Git" + + if (Test-Winget) { + Write-Info "Installing Git via winget..." + winget install Git.Git --silent --accept-package-agreements --accept-source-agreements + } elseif (Test-Chocolatey) { + Write-Info "Installing Git via Chocolatey..." + choco install git -y + } else { + Write-Warn "No package manager found. Installing Chocolatey first..." + Install-Chocolatey + + Write-Info "Installing Git via Chocolatey..." + choco install git -y + } + + # Refresh PATH + $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") + + # Verify installation + if (-not (Test-Command "git")) { + Write-Err "Git installation failed" + Write-Info "Please install Git manually from https://git-scm.com" + Write-Info "After installing, restart PowerShell and run this script again" + exit 1 + } + + Write-Success "Git installed: $(git --version)" +} + +# Check dependencies +function Test-Dependencies { + Write-Step "Checking dependencies" + + $missing = @() + + # Check Git + if (Test-Command "git") { + Write-Success "Git: $(git --version)" + } else { + Write-Warn "Git: Not found" + $missing += "git" + } + + # Check Node.js + $nodeVersion = Get-NodeVersion + if ($nodeVersion -ge $MinNodeVersion) { + Write-Success "Node.js: $(node -v)" + } else { + if ($nodeVersion -gt 0) { + Write-Warn "Node.js: v$nodeVersion (need v$MinNodeVersion+)" + } else { + Write-Warn "Node.js: Not found" + } + $missing += "node" + } + + # Check npm + if (Test-Command "npm") { + Write-Success "npm: $(npm -v)" + } else { + Write-Warn "npm: Not found (will be installed with Node.js)" + if ($missing -notcontains "node") { + $missing += "node" + } + } + + return $missing +} + +# Install missing dependencies +function Install-Dependencies($deps) { + if ($deps.Count -eq 0) { + Write-Success "All dependencies satisfied" + return + } + + Write-Step "Installing missing dependencies: $($deps -join ', ')" + + # Check for package manager + if (-not (Test-Winget) -and -not (Test-Chocolatey)) { + Write-Info "No package manager found (winget or chocolatey)" + $response = Read-Host "Install Chocolatey? [Y/n]" + if ($response -notmatch '^[Nn]') { + Install-Chocolatey + } else { + Write-Err "Cannot proceed without a package manager" + exit 1 + } + } + + foreach ($dep in $deps) { + switch ($dep) { + "git" { Install-Git } + "node" { Install-Node } + } + } +} + +# Clone or update ralph-cli +function Install-RalphRepository { + Write-Step "Setting up Ralph CLI" + + if (Test-Path $RalphDir) { + Write-Info "Ralph CLI directory exists at $RalphDir" + $response = Read-Host "Update existing installation? [Y/n]" + if ($response -notmatch '^[Nn]') { + Write-Info "Updating Ralph CLI..." + Push-Location $RalphDir + git fetch origin + git pull origin main 2>$null + if ($LASTEXITCODE -ne 0) { + git pull origin master + } + Pop-Location + } + } else { + Write-Info "Cloning Ralph CLI to $RalphDir..." + git clone $RalphRepo $RalphDir + } +} + +# Install npm dependencies and link +function Install-RalphCLI { + Write-Step "Installing Ralph CLI" + + Push-Location $RalphDir + + Write-Info "Installing npm dependencies..." + npm install + + Write-Info "Linking ralph globally..." + npm link + + Pop-Location + + Write-Success "Ralph CLI installed successfully!" +} + +# Verify installation +function Test-Installation { + Write-Step "Verifying installation" + + # Refresh PATH to pick up npm global bin + $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") + + if (Test-Command "ralph") { + Write-Success "ralph command is available" + Write-Output "" + ralph --help | Select-Object -First 20 + } else { + Write-Warn "ralph command not found in PATH" + Write-Info "You may need to:" + Write-Output " 1. Restart PowerShell" + Write-Output " 2. Ensure npm global bin is in PATH" + + # Try to find npm global path + $npmPrefix = npm config get prefix 2>$null + if ($npmPrefix) { + Write-Info "Add to PATH: $npmPrefix" + } + } +} + +# Print post-install instructions +function Show-Instructions { + Write-Output "" + Write-ColorOutput Green "Installation Complete!" + Write-Output "" + Write-Output "Quick Start:" + Write-ColorOutput Cyan " cd your-project" + Write-ColorOutput Cyan " ralph install # Install Ralph templates" + Write-ColorOutput Cyan " ralph prd # Generate a PRD" + Write-ColorOutput Cyan " ralph plan # Create implementation plan" + Write-ColorOutput Cyan " ralph build 5 # Run 5 build iterations" + Write-Output "" + Write-Output "Documentation:" + Write-ColorOutput Cyan " ralph help # Show all commands" + Write-ColorOutput Cyan " https://github.com/AskTinNguyen/ralph-cli" + Write-Output "" + + # Note about bash requirement + Write-Output "Note for Windows users:" + Write-Output " Ralph's build scripts require bash. Options:" + Write-Output " 1. Git Bash (installed with Git)" + Write-Output " 2. WSL (Windows Subsystem for Linux)" + Write-Output " 3. Use Windows Terminal with Git Bash profile" + Write-Output "" +} + +# Main installation flow +function Main { + Show-Banner + + Write-Info "Detected: Windows $([Environment]::Is64BitOperatingSystem ? 'x64' : 'x86')" + Write-Output "" + + # Check admin privileges for package installation + $isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) + if (-not $isAdmin) { + Write-Warn "Not running as Administrator. Package installation may require elevated privileges." + Write-Info "If installation fails, try running PowerShell as Administrator" + Write-Output "" + } + + # Check dependencies + $missing = Test-Dependencies + + # Install missing dependencies + if ($missing.Count -gt 0) { + $response = Read-Host "Install missing dependencies? [Y/n]" + if ($response -notmatch '^[Nn]') { + Install-Dependencies $missing + } else { + Write-Err "Cannot proceed without required dependencies" + exit 1 + } + } + + # Clone ralph-cli + Install-RalphRepository + + # Install and link + Install-RalphCLI + + # Verify + Test-Installation + + # Instructions + Show-Instructions +} + +# Run main +Main diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..ce27ee8 --- /dev/null +++ b/install.sh @@ -0,0 +1,389 @@ +#!/bin/bash +# Ralph CLI - One-Command Installer +# Usage: curl -fsSL https://raw.githubusercontent.com/AskTinNguyen/ralph-cli/main/install.sh | bash +# +# This script will: +# 1. Check for required dependencies (Node.js, npm, git) +# 2. Install missing dependencies (with user confirmation) +# 3. Clone ralph-cli repository +# 4. Install npm dependencies +# 5. Link ralph globally + +set -e + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color +BOLD='\033[1m' + +# Configuration +RALPH_REPO="https://github.com/AskTinNguyen/ralph-cli.git" +RALPH_DIR="${RALPH_INSTALL_DIR:-$HOME/ralph-cli}" +MIN_NODE_VERSION=18 + +# Print functions +info() { echo -e "${BLUE}[INFO]${NC} $1"; } +success() { echo -e "${GREEN}[OK]${NC} $1"; } +warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } +error() { echo -e "${RED}[ERROR]${NC} $1"; } +step() { echo -e "\n${CYAN}${BOLD}==> $1${NC}"; } + +# Banner +print_banner() { + echo -e "${CYAN}" + cat << 'EOF' + ____ __ __ _________ ____ + / __ \____ _/ /___ / /_ / ____/ / / _/ + / /_/ / __ `/ / __ \/ __ \ / / / / / / + / _, _/ /_/ / / /_/ / / / / / /___/ /____/ / +/_/ |_|\__,_/_/ .___/_/ /_/ \____/_____/___/ + /_/ +EOF + echo -e "${NC}" + echo -e "${BOLD}One-Command Installer${NC}" + echo "" +} + +# Detect OS +detect_os() { + case "$(uname -s)" in + Darwin*) OS="macos" ;; + Linux*) OS="linux" ;; + MINGW*|MSYS*|CYGWIN*) OS="windows" ;; + *) OS="unknown" ;; + esac + + # Detect architecture + case "$(uname -m)" in + x86_64|amd64) ARCH="x64" ;; + arm64|aarch64) ARCH="arm64" ;; + *) ARCH="x64" ;; + esac +} + +# Check if command exists +has_cmd() { + command -v "$1" >/dev/null 2>&1 +} + +# Get Node.js version number +get_node_version() { + if has_cmd node; then + node -v 2>/dev/null | sed 's/v//' | cut -d. -f1 + else + echo "0" + fi +} + +# Check Node.js version +check_node_version() { + local version + version=$(get_node_version) + if [ "$version" -ge "$MIN_NODE_VERSION" ]; then + return 0 + else + return 1 + fi +} + +# Install Node.js via package manager or nvm +install_node() { + step "Installing Node.js" + + if [ "$OS" = "macos" ]; then + if has_cmd brew; then + info "Installing Node.js via Homebrew..." + brew install node + else + warn "Homebrew not found. Installing via nvm..." + install_node_via_nvm + fi + elif [ "$OS" = "linux" ]; then + # Try to detect distro and use appropriate package manager + if has_cmd apt-get; then + info "Installing Node.js via apt (NodeSource)..." + curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - + sudo apt-get install -y nodejs + elif has_cmd dnf; then + info "Installing Node.js via dnf..." + sudo dnf install -y nodejs npm + elif has_cmd yum; then + info "Installing Node.js via yum (NodeSource)..." + curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash - + sudo yum install -y nodejs + elif has_cmd pacman; then + info "Installing Node.js via pacman..." + sudo pacman -S --noconfirm nodejs npm + else + warn "No supported package manager found. Installing via nvm..." + install_node_via_nvm + fi + else + install_node_via_nvm + fi +} + +# Install Node.js via nvm (fallback) +install_node_via_nvm() { + info "Installing nvm (Node Version Manager)..." + + # Install nvm + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash + + # Load nvm + export NVM_DIR="$HOME/.nvm" + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + + # Install latest LTS Node.js + nvm install --lts + nvm use --lts + + success "Node.js installed via nvm" + warn "You may need to restart your terminal or run: source ~/.bashrc (or ~/.zshrc)" +} + +# Install Homebrew (macOS) +install_homebrew() { + step "Installing Homebrew" + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + + # Add to PATH for Apple Silicon Macs + if [ "$ARCH" = "arm64" ] && [ -f "/opt/homebrew/bin/brew" ]; then + eval "$(/opt/homebrew/bin/brew shellenv)" + echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> "$HOME/.zprofile" + fi +} + +# Install Git +install_git() { + step "Installing Git" + + if [ "$OS" = "macos" ]; then + if has_cmd brew; then + brew install git + else + # Xcode Command Line Tools includes git + xcode-select --install 2>/dev/null || true + info "Git will be installed with Xcode Command Line Tools" + fi + elif [ "$OS" = "linux" ]; then + if has_cmd apt-get; then + sudo apt-get update && sudo apt-get install -y git + elif has_cmd dnf; then + sudo dnf install -y git + elif has_cmd yum; then + sudo yum install -y git + elif has_cmd pacman; then + sudo pacman -S --noconfirm git + fi + fi +} + +# Check all dependencies +check_dependencies() { + step "Checking dependencies" + + local missing_deps=() + + # Check Git + if has_cmd git; then + success "Git: $(git --version)" + else + missing_deps+=("git") + warn "Git: Not found" + fi + + # Check Node.js + if has_cmd node && check_node_version; then + success "Node.js: $(node -v)" + else + if has_cmd node; then + warn "Node.js: $(node -v) (need v${MIN_NODE_VERSION}+)" + else + warn "Node.js: Not found" + fi + missing_deps+=("node") + fi + + # Check npm + if has_cmd npm; then + success "npm: $(npm -v)" + else + warn "npm: Not found (will be installed with Node.js)" + if [[ ! " ${missing_deps[*]} " =~ " node " ]]; then + missing_deps+=("node") + fi + fi + + echo "${missing_deps[@]}" +} + +# Install missing dependencies +install_dependencies() { + local deps=("$@") + + if [ ${#deps[@]} -eq 0 ]; then + success "All dependencies satisfied" + return 0 + fi + + step "Installing missing dependencies: ${deps[*]}" + + # On macOS, prefer Homebrew + if [ "$OS" = "macos" ] && ! has_cmd brew; then + read -p "Homebrew is recommended for installing dependencies. Install Homebrew? [Y/n] " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Nn]$ ]]; then + install_homebrew + fi + fi + + for dep in "${deps[@]}"; do + case "$dep" in + git) + install_git + ;; + node) + install_node + ;; + esac + done + + # Verify installation + if ! has_cmd node || ! check_node_version; then + error "Node.js installation failed or version too old" + error "Please install Node.js v${MIN_NODE_VERSION}+ manually: https://nodejs.org" + exit 1 + fi + + if ! has_cmd git; then + error "Git installation failed" + error "Please install Git manually: https://git-scm.com" + exit 1 + fi +} + +# Clone or update ralph-cli +clone_ralph() { + step "Setting up Ralph CLI" + + if [ -d "$RALPH_DIR" ]; then + info "Ralph CLI directory exists at $RALPH_DIR" + read -p "Update existing installation? [Y/n] " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Nn]$ ]]; then + info "Updating Ralph CLI..." + cd "$RALPH_DIR" + git fetch origin + git pull origin main || git pull origin master + fi + else + info "Cloning Ralph CLI to $RALPH_DIR..." + git clone "$RALPH_REPO" "$RALPH_DIR" + fi +} + +# Install npm dependencies and link +install_ralph() { + step "Installing Ralph CLI" + + cd "$RALPH_DIR" + + info "Installing npm dependencies..." + npm install + + info "Linking ralph globally..." + npm link + + success "Ralph CLI installed successfully!" +} + +# Verify installation +verify_installation() { + step "Verifying installation" + + if has_cmd ralph; then + success "ralph command is available" + echo "" + ralph --help | head -20 + else + warn "ralph command not found in PATH" + info "You may need to:" + echo " 1. Restart your terminal" + echo " 2. Add npm global bin to PATH: export PATH=\"\$(npm config get prefix)/bin:\$PATH\"" + fi +} + +# Print post-install instructions +print_instructions() { + echo "" + echo -e "${GREEN}${BOLD}Installation Complete!${NC}" + echo "" + echo "Quick Start:" + echo -e " ${CYAN}cd your-project${NC}" + echo -e " ${CYAN}ralph install${NC} # Install Ralph templates" + echo -e " ${CYAN}ralph prd${NC} # Generate a PRD" + echo -e " ${CYAN}ralph plan${NC} # Create implementation plan" + echo -e " ${CYAN}ralph build 5${NC} # Run 5 build iterations" + echo "" + echo "Documentation:" + echo -e " ${CYAN}ralph help${NC} # Show all commands" + echo -e " ${CYAN}https://github.com/AskTinNguyen/ralph-cli${NC}" + echo "" +} + +# Main installation flow +main() { + print_banner + detect_os + + info "Detected: $OS ($ARCH)" + echo "" + + # Check if running in a pipe (non-interactive) + if [ ! -t 0 ]; then + info "Running in non-interactive mode" + NONINTERACTIVE=1 + else + NONINTERACTIVE=0 + fi + + # Check dependencies + missing=($(check_dependencies)) + + # Install missing dependencies + if [ ${#missing[@]} -gt 0 ] && [ "${missing[0]}" != "" ]; then + if [ "$NONINTERACTIVE" = "1" ]; then + info "Installing missing dependencies automatically..." + install_dependencies "${missing[@]}" + else + read -p "Install missing dependencies? [Y/n] " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Nn]$ ]]; then + install_dependencies "${missing[@]}" + else + error "Cannot proceed without required dependencies" + exit 1 + fi + fi + fi + + # Clone ralph-cli + clone_ralph + + # Install and link + install_ralph + + # Verify + verify_installation + + # Instructions + print_instructions +} + +# Run main +main "$@"