#!/bin/bash # CLIProxyAPI Linux Installer # Linux-specific script that installs, upgrades, and manages CLIProxyAPI # Downloads, installs, and upgrades CLIProxyAPI while preserving configuration set -euo pipefail # Configuration REPO_OWNER="router-for-me" REPO_NAME="CLIProxyAPI" INSTALL_DIR="$HOME/cliproxyapi" API_URL="https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/releases/latest" SCRIPT_NAME="cliproxyapi-installer" # Colors for output 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 # Logging functions log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } log_step() { echo -e "${CYAN}[STEP]${NC} $1" } # Display authentication information for first-time setup show_authentication_info() { echo echo -e "${YELLOW}🔐 IMPORTANT: Authentication Setup Required${NC}" echo echo -e "${BLUE}CLIProxyAPI supports authentication for multiple providers:${NC}" echo echo -e "${GREEN}📚 Full Documentation:${NC} https://github.com/router-for-me/CLIProxyAPI" echo echo -e "${YELLOW}Authentication Commands:${NC}" echo echo -e "${GREEN}Gemini (Google):${NC}" echo " ./cli-proxy-api --login" echo " ./cli-proxy-api --login --project_id " echo " (OAuth callback on port 8085)" echo echo -e "${GREEN}OpenAI (Codex/GPT):${NC}" echo " ./cli-proxy-api --codex-login" echo " (OAuth callback on port 1455)" echo echo -e "${GREEN}Claude (Anthropic):${NC}" echo " ./cli-proxy-api --claude-login" echo " (OAuth callback on port 54545)" echo echo -e "${GREEN}Qwen (Qwen Chat):${NC}" echo " ./cli-proxy-api --qwen-login" echo " (Uses OAuth device flow)" echo echo -e "${GREEN}iFlow:${NC}" echo " ./cli-proxy-api --iflow-login" echo " (OAuth callback on port 11451)" echo echo -e "${YELLOW}💡 Tip: Add --no-browser to any login command to print URL instead" echo " of automatically opening a browser." echo } # Generate OpenAI-format API key generate_api_key() { # OpenAI API keys follow the format: sk-... (48 characters total) # Generate 48-character random string starting with "sk-" local prefix="sk-" local chars="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" local key="" # Generate 45 random characters (48 - 3 for "sk-") for i in {1..45}; do key="${key}${chars:$((RANDOM % ${#chars})):1}" done echo "${prefix}${key}" } # Manage documentation intelligently manage_documentation() { echo "Documentation Management" echo "========================" if ! is_installed; then log_error "CLIProxyAPI is not installed. Install it first to manage documentation." exit 1 fi local version_dir version_dir=$(get_current_version_dir) local readme_file="${version_dir}/README.md" local install_readme="${INSTALL_DIR}/README.md" echo "📚 Documentation Status:" echo # Check for README files if [[ -f "$readme_file" ]]; then echo "✅ Project README: Found ($readme_file)" else echo "❌ Project README: Missing" fi if [[ -f "$install_readme" ]]; then echo "✅ Installer README: Found ($install_readme)" else echo "❌ Installer README: Missing" fi # Check version consistency local current_version current_version=$(get_current_version) echo echo "🔄 Version Consistency Check:" if [[ -f "$readme_file" ]] && grep -q "$current_version" "$readme_file"; then echo "✅ Project README: Version $current_version referenced" else echo "âš ī¸ Project README: Version $current_version not found or outdated" fi if [[ -f "$install_readme" ]] && grep -q "$current_version" "$install_readme"; then echo "✅ Installer README: Version $current_version referenced" else echo "âš ī¸ Installer README: Version $current_version not found or outdated" fi # Check for common documentation issues echo echo "🔍 Documentation Quality Check:" local issues_found=0 # Check for broken links (basic check) if [[ -f "$install_readme" ]]; then if grep -q "https://" "$install_readme"; then echo "✅ External links: Present" else echo "â„šī¸ External links: None found" fi fi # Check for TODO items or placeholders if [[ -f "$install_readme" ]] && grep -q -i "todo\|placeholder\|your-repo" "$install_readme"; then echo "âš ī¸ Placeholders found: Update repository URLs and TODO items" ((issues_found++)) fi # Check for consistent formatting if [[ -f "$install_readme" ]]; then local header_count=$(grep -c "^#" "$install_readme") echo "📊 Headers found: $header_count" if [[ $header_count -lt 5 ]]; then echo "âš ī¸ Documentation structure: May need more sections" ((issues_found++)) fi fi # Provide recommendations echo echo "💡 Recommendations:" if [[ ! -f "$install_readme" ]]; then echo "â€ĸ Create installer README.md with usage instructions" fi if [[ $issues_found -gt 0 ]]; then echo "â€ĸ Review and update $issues_found documentation issues" fi echo "â€ĸ Ensure version numbers are current ($current_version)" echo "â€ĸ Update repository URLs if changed" echo "â€ĸ Add cross-references between documents" echo echo "📖 Quick Documentation Tasks:" echo "â€ĸ View project docs: cat $readme_file" echo "â€ĸ View installer docs: cat $install_readme" echo "â€ĸ Edit installer docs: nano $install_readme" } # Check if API keys are configured check_api_keys() { local config_file="${INSTALL_DIR}/config.yaml" if [[ ! -f "$config_file" ]]; then return 1 fi # Check for default/placeholder API keys if grep -q '"your-api-key-1"' "$config_file" || grep -q '"your-api-key-2"' "$config_file"; then return 1 fi # Check if api-keys section exists and has non-empty values that look like real API keys if grep -A 10 "^api-keys:" "$config_file" | grep -v "^#" | grep -v "^api-keys:" | grep -q '"sk-[^"]*"'; then return 0 fi return 1 } # Show API key setup guidance show_api_key_setup() { echo echo -e "${YELLOW}🔑 IMPORTANT: API Keys Required Before First Run${NC}" echo echo -e "${BLUE}Before starting CLIProxyAPI, you need to configure API keys in config.yaml:${NC}" echo echo -e "${GREEN}1. Edit the configuration file:${NC}" echo -e " ${CYAN}nano ${INSTALL_DIR}/config.yaml${NC}" echo echo -e "${GREEN}2. Find the 'api-keys' section and replace placeholder keys:${NC}" echo echo -e " ${YELLOW}# Replace this:${NC}" echo -e " ${YELLOW}api-keys:${NC}" echo -e " ${YELLOW} - \"your-api-key-1\"${NC}" echo -e " ${YELLOW} - \"your-api-key-2\"${NC}" echo echo -e " ${GREEN}# With your actual API keys:${NC}" echo -e " ${GREEN}api-keys:${NC}" echo -e " ${GREEN} - \"sk-your-real-openai-key-here\"${NC}" echo -e " ${GREEN} - \"your-custom-secure-key-12345\"${NC}" echo echo -e "${GREEN}3. Save the file (Ctrl+X, then Y, then Enter in nano)${NC}" echo echo -e "${BLUE}💡 Tips:${NC}" echo -e " â€ĸ Use strong, unique keys for security" echo -e " â€ĸ You can add multiple keys for different users/services" echo -e " â€ĸ Keys are used for authenticating requests to your proxy" echo -e " â€ĸ These are NOT your provider API keys (those are set via login commands)" echo } # Show quick start guide show_quick_start() { local install_dir="$1" echo echo -e "${GREEN}🚀 Quick Start Guide:${NC}" echo -e "${BLUE}1. Navigate to CLIProxyAPI:${NC}" echo -e " ${CYAN}cd $install_dir${NC}" echo # Check if API keys are configured if ! check_api_keys; then show_api_key_setup echo -e "${BLUE}2. Set up authentication (choose one or more):${NC}" else echo -e "${BLUE}2. Set up authentication (choose one or more):${NC}" fi echo -e " ${CYAN}./cli-proxy-api --login${NC} # For Gemini" echo -e " ${CYAN}./cli-proxy-api --codex-login${NC} # For OpenAI" echo -e " ${CYAN}./cli-proxy-api --claude-login${NC} # For Claude" echo -e " ${CYAN}./cli-proxy-api --qwen-login${NC} # For Qwen" echo -e " ${CYAN}./cli-proxy-api --iflow-login${NC} # For iFlow" echo if check_api_keys; then echo -e "${BLUE}Your API keys:${NC}" grep -A 10 "^api-keys:" "${install_dir}/config.yaml" | grep -v "^#" | head -10 echo fi if ! check_api_keys; then echo -e "${BLUE}3. Configure API keys (REQUIRED):${NC}" echo -e " ${CYAN}nano config.yaml${NC} # Edit API keys" echo echo -e "${BLUE}4. Start the service:${NC}" echo -e " ${CYAN}./cli-proxy-api${NC}" echo echo -e "${BLUE}5. Or run as a systemd service:${NC}" echo -e " ${CYAN}systemctl --user enable cliproxyapi.service${NC}" echo -e " ${CYAN}systemctl --user start cliproxyapi.service${NC}" echo -e " ${CYAN}systemctl --user status cliproxyapi.service${NC}" echo echo -e "${BLUE}6. Read the full documentation:${NC}" echo -e " ${CYAN}https://github.com/router-for-me/CLIProxyAPI${NC}" else echo -e "${BLUE}3. Start the service:${NC}" echo -e " ${CYAN}./cli-proxy-api${NC}" echo echo -e "${BLUE}4. Or run as a systemd service:${NC}" echo -e " ${CYAN}systemctl --user enable cliproxyapi.service${NC}" echo -e " ${CYAN}systemctl --user start cliproxyapi.service${NC}" echo -e " ${CYAN}systemctl --user status cliproxyapi.service${NC}" echo echo -e "${BLUE}5. Read the full documentation:${NC}" echo -e " ${CYAN}https://github.com/router-for-me/CLIProxyAPI${NC}" fi echo } # Detect Linux architecture detect_linux_arch() { # Detect architecture case "$(uname -m)" in x86_64|amd64) echo "linux_amd64" ;; arm64|aarch64) echo "linux_arm64" ;; *) log_error "Unsupported architecture: $(uname -m). Only x86_64 and arm64 are supported on Linux." exit 1 ;; esac } # Check if required tools are available check_dependencies() { local missing_tools=() if ! command -v curl >/dev/null 2>&1 && ! command -v wget >/dev/null 2>&1; then missing_tools+=("curl or wget") fi if ! command -v tar >/dev/null 2>&1; then missing_tools+=("tar") fi if [[ ${#missing_tools[@]} -gt 0 ]]; then log_error "Missing required tools: ${missing_tools[*]}" log_info "Please install the missing tools and try again" log_info "On Ubuntu/Debian: sudo apt-get install curl wget tar" log_info "On CentOS/RHEL: sudo yum install curl wget tar" exit 1 fi } # Fetch latest release info from GitHub API fetch_release_info() { log_info "Fetching latest release information..." local release_info if command -v curl >/dev/null 2>&1; then release_info=$(curl -s "$API_URL") else release_info=$(wget -qO- "$API_URL") fi if [[ -z "$release_info" ]]; then log_error "Failed to fetch release information from GitHub API" exit 1 fi echo "$release_info" } # Extract version and download URL from release info extract_release_info() { local release_info="$1" local os_arch="$2" local version version=$(echo "$release_info" | grep -o '"tag_name": *"[^"]*"' | cut -d'"' -f4 | sed 's/^v//') if [[ -z "$version" ]]; then log_error "Failed to extract version from release info" exit 1 fi local expected_filename="CLIProxyAPI_${version}_${os_arch}" local download_url="" # Handle different file extensions if [[ "$os_arch" == windows_* ]]; then expected_filename="${expected_filename}.zip" else expected_filename="${expected_filename}.tar.gz" fi download_url=$(echo "$release_info" | grep -o "\"browser_download_url\": *\"[^\"]*${expected_filename}[^\"]*\"" | cut -d'"' -f4) if [[ -z "$download_url" ]]; then log_error "Failed to find download URL for ${expected_filename}" exit 1 fi echo "${version}|${download_url}" } # Check if CLIProxyAPI is already installed is_installed() { [[ -f "${INSTALL_DIR}/version.txt" ]] } # Get currently installed version get_current_version() { if is_installed; then cat "${INSTALL_DIR}/version.txt" 2>/dev/null || echo "unknown" else echo "none" fi } # Get current version directory get_current_version_dir() { local current_version current_version=$(get_current_version) if [[ "$current_version" != "none" ]]; then echo "${INSTALL_DIR}/${current_version}" else echo "" fi } # Backup existing configuration backup_config() { local config="${INSTALL_DIR}/config.yaml" if [[ -f "$config" ]]; then local backup_dir="${INSTALL_DIR}/config_backup" mkdir -p "$backup_dir" local timestamp timestamp=$(date +"%Y%m%d_%H%M%S") local backup_file="${backup_dir}/config_${timestamp}.yaml" cp "$config" "$backup_file" log_info "Configuration backed up to: $backup_file" echo "$backup_file" else echo "" fi } # Restore configuration to new version restore_config() { local new_version_dir="$1" local backup_file="$2" if [[ -n "$backup_file" && -f "$backup_file" ]]; then cp "$backup_file" "${new_version_dir}/config.yaml" log_success "Configuration restored from backup" fi } # Check if systemd service is running is_service_running() { systemctl --user is-active --quiet cliproxyapi.service 2>/dev/null } # Check if any CLIProxyAPI processes are running is_cliproxyapi_running() { pgrep -f "cli-proxy-api" >/dev/null 2>&1 } # Stop any running CLIProxyAPI processes stop_cliproxyapi_processes() { local pids pids=$(pgrep -f "cli-proxy-api" 2>/dev/null || true) if [[ -n "$pids" ]]; then log_info "Stopping running CLIProxyAPI processes..." echo "$pids" | while read -r pid; do if [[ -n "$pid" ]]; then kill "$pid" 2>/dev/null || true log_info "Sent TERM signal to process $pid" fi done # Wait a moment for graceful shutdown sleep 2 # Check if any processes are still running and force kill if needed local remaining_pids remaining_pids=$(pgrep -f "cli-proxy-api" 2>/dev/null || true) if [[ -n "$remaining_pids" ]]; then log_warning "Some processes didn't stop gracefully, force killing..." echo "$remaining_pids" | while read -r pid; do if [[ -n "$pid" ]]; then kill -9 "$pid" 2>/dev/null || true log_info "Force killed process $pid" fi done sleep 1 fi log_success "All CLIProxyAPI processes stopped" else log_info "No CLIProxyAPI processes are running" fi } # Stop systemd service if running stop_service() { if is_service_running; then log_info "Stopping CLIProxyAPI service..." systemctl --user stop cliproxyapi.service log_success "Service stopped" else log_info "Service is not running" fi } # Start systemd service start_service() { log_info "Starting CLIProxyAPI service..." systemctl --user start cliproxyapi.service # Wait a moment and check if it started successfully sleep 2 if is_service_running; then log_success "Service started successfully" else log_warning "Service may not have started properly. Check with: systemctl --user status cliproxyapi.service" fi } # Restart systemd service restart_service() { log_info "Restarting CLIProxyAPI service..." systemctl --user restart cliproxyapi.service # Wait a moment and check if it started successfully sleep 2 if is_service_running; then log_success "Service restarted successfully" else log_warning "Service may not have started properly. Check with: systemctl --user status cliproxyapi.service" fi } # Create systemd service file create_systemd_service() { local install_dir="$1" local service_file="${install_dir}/cliproxyapi.service" local systemd_dir="$HOME/.config/systemd/user" local systemd_service_file="${systemd_dir}/cliproxyapi.service" log_info "Creating systemd service file..." # Create systemd user directory mkdir -p "$systemd_dir" # Create service file content with basic working configuration cat > "$service_file" << EOF [Unit] Description=CLIProxyAPI Service After=network.target [Service] Type=simple WorkingDirectory=$install_dir ExecStart=$install_dir/cli-proxy-api Restart=always RestartSec=10 Environment=HOME=$HOME [Install] WantedBy=default.target EOF # Copy to systemd user directory cp "$service_file" "$systemd_service_file" # Reload systemd daemon systemctl --user daemon-reload || log_warning "Could not reload systemd daemon (this is normal on first run)" log_success "Systemd service file created: $service_file" log_success "Systemd service installed: $systemd_service_file" log_info "To enable and start the service:" log_info " systemctl --user enable cliproxyapi.service" log_info " systemctl --user start cliproxyapi.service" log_info " systemctl --user status cliproxyapi.service" } # Copy example config if no existing config and setup main directory structure setup_config() { local version_dir="$1" local backup_file="$2" log_info "Setting up configuration..." local config="${INSTALL_DIR}/config.yaml" local example_config="${version_dir}/config.example.yaml" local executable="${version_dir}/cli-proxy-api" # Copy executable to main directory if [[ -f "$executable" ]]; then cp "$executable" "${INSTALL_DIR}/cli-proxy-api" log_success "Copied executable to ${INSTALL_DIR}/cli-proxy-api" fi # PRIORITY 1: If we have a backup from this upgrade, restore it if [[ -n "$backup_file" && -f "$backup_file" ]]; then cp "$backup_file" "$config" log_success "Restored configuration from backup" return fi # PRIORITY 2: Check for existing config in main directory (NEVER overwrite) if [[ -f "$config" ]]; then log_success "Preserved existing user configuration (config.yaml)" log_info "User modifications are protected during upgrades" return fi # PRIORITY 3: Check for existing config in previous version directory local current_version_dir current_version_dir=$(get_current_version_dir) if [[ -n "$current_version_dir" && -f "${current_version_dir}/config.yaml" ]]; then cp "${current_version_dir}/config.yaml" "$config" log_success "Preserved existing configuration from previous version" return fi # PRIORITY 4: Only create from example if NO existing config found if [[ -f "$example_config" ]]; then cp "$example_config" "$config" # Generate and replace API key local generated_key1 local generated_key2 generated_key1=$(generate_api_key) generated_key2=$(generate_api_key) # Replace placeholder API keys with generated keys sed -i "s/\"your-api-key-1\"/\"$generated_key1\"/g" "$config" sed -i "s/\"your-api-key-2\"/\"$generated_key2\"/g" "$config" log_success "Created config.yaml from example with generated API keys" log_info "Generated API keys: $generated_key1, $generated_key2" log_info "You can find your API keys in: $config" else log_warning "config.example.yaml not found, you may need to create config.yaml manually" fi } # Download file download_file() { local url="$1" local output="$2" log_info "Downloading $(basename "$url")..." if command -v curl >/dev/null 2>&1; then curl -L -o "$output" "$url" else wget -O "$output" "$url" fi if [[ ! -f "$output" ]]; then log_error "Failed to download file" exit 1 fi log_success "Download completed" } # Extract tar.gz archive extract_archive() { local archive="$1" local dest_dir="$2" log_info "Extracting archive to $dest_dir..." mkdir -p "$dest_dir" tar -xzf "$archive" -C "$dest_dir" log_success "Extraction completed" } # Write version file write_version_file() { local install_dir="$1" local version="$2" echo "$version" > "${install_dir}/version.txt" log_success "Version $version written to version.txt" } # Clean up old versions (keep last 2 versions) cleanup_old_versions() { local current_version="$1" if [[ ! -d "$INSTALL_DIR" ]]; then return fi log_info "Cleaning up old versions..." # Get all version directories, sort them, and remove all but the latest 2 local old_versions old_versions=$(find "$INSTALL_DIR" -maxdepth 1 -type d -name "*.*.*" -printf "%f\n" | sort -V | head -n -2) if [[ -n "$old_versions" ]]; then echo "$old_versions" | while read -r version; do if [[ "$version" != "$current_version" && -n "$version" ]]; then rm -rf "${INSTALL_DIR}/${version}" log_info "Removed old version: $version" fi done fi } # Make binary executable make_executable() { local version_dir="$1" local binary binary=$(find "$version_dir" -name "CLIProxyAPI" -o -name "cli-proxy-api" -type f | head -1) if [[ -n "$binary" ]]; then chmod +x "$binary" log_success "Made CLIProxyAPI binary executable" fi } # Main installation function install_cliproxyapi() { local current_version current_version=$(get_current_version) local is_upgrade=false local service_was_running=false if [[ "$current_version" != "none" ]]; then log_info "Current CLIProxyAPI version: $current_version" is_upgrade=true # Check if service is running before upgrade if is_service_running; then service_was_running=true log_info "Service is currently running and will be restarted after upgrade" fi else log_info "CLIProxyAPI not installed, performing fresh installation" fi # Check dependencies check_dependencies # Detect Linux architecture local os_arch os_arch=$(detect_linux_arch) log_step "Detected platform: $os_arch" # Fetch release info local release_info release_info=$(fetch_release_info) # Extract version and download URL local release_data release_data=$(extract_release_info "$release_info" "$os_arch") local version=$(echo "$release_data" | cut -d'|' -f1) local download_url=$(echo "$release_data" | cut -d'|' -f2) log_step "Latest version: $version" # Check if already up to date if [[ "$is_upgrade" == true && "$current_version" == "$version" ]]; then log_success "CLIProxyAPI is already up to date (version $version)" return fi # Stop service and processes if running (for upgrades) if [[ "$is_upgrade" == true ]]; then if is_service_running; then stop_service fi if is_cliproxyapi_running; then stop_cliproxyapi_processes fi fi # Backup existing configuration if upgrading local backup_file="" if [[ "$is_upgrade" == true ]]; then backup_file=$(backup_config) fi # Create installation directory local version_dir="${INSTALL_DIR}/${version}" mkdir -p "$INSTALL_DIR" # Download and extract local temp_file temp_file=$(mktemp) download_file "$download_url" "$temp_file" extract_archive "$temp_file" "$version_dir" # Cleanup temp file rm -f "$temp_file" # Make binary executable make_executable "$version_dir" # Setup configuration and copy executable to main directory setup_config "$version_dir" "$backup_file" # Make main executable executable chmod +x "${INSTALL_DIR}/cli-proxy-api" # Create/update systemd service file create_systemd_service "$INSTALL_DIR" # Write version file write_version_file "$INSTALL_DIR" "$version" # Clean up old versions cleanup_old_versions "$version" # Restart service if it was running before upgrade if [[ "$is_upgrade" == true && "$service_was_running" == true ]]; then restart_service fi # Success message if [[ "$is_upgrade" == true ]]; then log_success "CLIProxyAPI upgraded from $current_version to $version!" log_info "Installation directory: $INSTALL_DIR" if [[ "$service_was_running" == true ]]; then log_info "Service has been restarted automatically" elif is_service_running; then log_info "Service is running" else log_info "To start the service: systemctl --user start cliproxyapi.service" fi # Check if this is the first time setup (no existing config) if [[ ! -f "${INSTALL_DIR}/config.yaml" ]]; then show_authentication_info show_quick_start "$INSTALL_DIR" else log_info "Your existing configuration has been preserved" log_info "To use CLIProxyAPI: cd $INSTALL_DIR && ./cli-proxy-api --help" fi else log_success "CLIProxyAPI $version installed successfully!" log_info "Installation directory: $INSTALL_DIR" # Show authentication information for first-time setup show_authentication_info show_quick_start "$INSTALL_DIR" fi } # Show current installation status show_status() { local current_version current_version=$(get_current_version) echo "CLIProxyAPI Installation Status" echo "==============================" echo "Install Directory: $INSTALL_DIR" echo "Current Version: $current_version" if [[ "$current_version" != "none" ]]; then local current_version_dir current_version_dir=$(get_current_version_dir) echo "Version Directory: $current_version_dir" if [[ -f "${INSTALL_DIR}/config.yaml" ]]; then echo "Configuration: Present (at ${INSTALL_DIR}/config.yaml)" else echo "Configuration: Missing" fi if [[ -f "${INSTALL_DIR}/cli-proxy-api" ]]; then echo "Executable: Present (at ${INSTALL_DIR}/cli-proxy-api)" else echo "Executable: Missing" fi if [[ -f "${INSTALL_DIR}/cliproxyapi.service" ]]; then echo "Systemd Service: Available" echo " To enable: systemctl --user enable cliproxyapi.service" echo " To start: systemctl --user start cliproxyapi.service" else echo "Systemd Service: Missing" fi # Check API keys status if check_api_keys; then echo "API Keys: Configured" else echo -e "API Keys: ${YELLOW}NOT CONFIGURED${NC} - Edit config.yaml to add API keys" fi # Show available versions if [[ -d "$INSTALL_DIR" ]]; then echo "Installed Versions:" find "$INSTALL_DIR" -maxdepth 1 -type d -name "*.*.*" -printf " %f\n" | sort -V fi else echo "Status: Not installed" fi } # Uninstall function uninstall_cliproxyapi() { if [[ ! -d "$INSTALL_DIR" ]]; then log_warning "CLIProxyAPI installation directory not found: $INSTALL_DIR" exit 0 fi log_info "CLIProxyAPI installation found at: $INSTALL_DIR" # Show what will be removed echo log_info "The following will be removed:" find "$INSTALL_DIR" -type f -exec echo " {}" \; echo # Ask for confirmation read -p "Are you sure you want to remove CLIProxyAPI? (y/N): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then log_info "Uninstallation cancelled" exit 0 fi # Remove installation directory log_info "Removing CLIProxyAPI installation..." rm -rf "$INSTALL_DIR" log_success "CLIProxyAPI has been uninstalled successfully" } # Cleanup function on exit cleanup() { local temp_files temp_files=$(find /tmp -name "tmp.*" -user "$(whoami)" 2>/dev/null || true) if [[ -n "$temp_files" ]]; then echo "$temp_files" | xargs rm -f 2>/dev/null || true fi } # Set up cleanup trap trap cleanup EXIT # Main script logic main() { case "${1:-install}" in "install"|"upgrade") install_cliproxyapi ;; "status") show_status ;; "auth") show_authentication_info if is_installed; then local current_version_dir current_version_dir=$(get_current_version_dir) if [[ -n "$current_version_dir" ]]; then show_quick_start "$current_version_dir" fi fi ;; "check-config") if is_installed; then echo "Configuration Check" echo "==================" echo "Config file: ${INSTALL_DIR}/config.yaml" if check_api_keys; then echo -e "✅ API Keys: ${GREEN}Configured${NC}" echo -e "✅ Status: ${GREEN}Ready to run${NC}" echo echo -e "${BLUE}Current API keys in config.yaml:${NC}" grep -A 10 "^api-keys:" "${INSTALL_DIR}/config.yaml" | grep -v "^#" | head -10 echo echo -e "${BLUE}You can now start CLIProxyAPI:${NC}" echo -e " ${CYAN}cd ${INSTALL_DIR}${NC}" echo -e " ${CYAN}./cli-proxy-api${NC}" echo echo -e "${BLUE}Or run as a service:${NC}" echo -e " ${CYAN}systemctl --user start cliproxyapi.service${NC}" else echo -e "❌ API Keys: ${RED}NOT CONFIGURED${NC}" echo -e "❌ Status: ${RED}Not ready to run${NC}" echo show_api_key_setup fi else log_error "CLIProxyAPI is not installed" echo "Install it first with: $SCRIPT_NAME install" fi ;; "generate-key") local new_key new_key=$(generate_api_key) echo "Generated OpenAI-format API Key:" echo "================================" echo -e "${GREEN}$new_key${NC}" echo echo -e "${BLUE}To use this key, add it to your config.yaml:${NC}" echo -e "${CYAN}api-keys:${NC}" echo -e "${CYAN} - \"$new_key\"${NC}" echo echo -e "${YELLOW}Note: This generates a new key but doesn't modify your config file.${NC}" echo -e "${YELLOW}Edit ${INSTALL_DIR}/config.yaml manually to add this key.${NC}" ;; "manage-docs") manage_documentation ;; "uninstall") uninstall_cliproxyapi ;; "-h"|"--help") cat << EOF CLIProxyAPI Linux Installer Usage: $SCRIPT_NAME [COMMAND] [OPTIONS] Commands: install, upgrade Install or upgrade CLIProxyAPI (default) status Show current installation status auth Show authentication setup information check-config Check configuration and API keys generate-key Generate new API key and show it manage-docs Manage documentation (update, organize, check consistency) uninstall Remove CLIProxyAPI completely -h, --help Show this help message Description: This Linux-specific script installs, upgrades, or removes CLIProxyAPI. It can be run from anywhere and automatically detects your Linux architecture. During upgrades, your config.yaml file is preserved automatically. Features: - Automatic Linux architecture detection (amd64/arm64) - Downloads latest version from GitHub releases - Preserves configuration during upgrades - Automatic API key generation - Systemd service file creation - Cleans up old versions (keeps latest 2) Installation Directory: ~/cliproxyapi/ Supported Platforms: - Linux: amd64, arm64 Examples: $SCRIPT_NAME # Install or upgrade $SCRIPT_NAME status # Show current status $SCRIPT_NAME auth # Show authentication info $SCRIPT_NAME check-config # Check configuration $SCRIPT_NAME generate-key # Generate new API key $SCRIPT_NAME uninstall # Remove completely EOF ;; *) log_error "Unknown command: $1" echo "Use '$SCRIPT_NAME --help' for usage information" exit 1 ;; esac } # Run main function with all arguments main "$@"