From 187938515d1602d194c3f0a0c22868927f3572bf Mon Sep 17 00:00:00 2001 From: sususu Date: Mon, 3 Nov 2025 11:46:18 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setup-claude-code.ps1 | 364 ++++++++++++++++++++++++++++++++++++++++++ setup-claude-code.sh | 332 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 696 insertions(+) create mode 100644 setup-claude-code.ps1 create mode 100644 setup-claude-code.sh diff --git a/setup-claude-code.ps1 b/setup-claude-code.ps1 new file mode 100644 index 0000000..b3069df --- /dev/null +++ b/setup-claude-code.ps1 @@ -0,0 +1,364 @@ +# Claude Code Configuration Script for XCodeCLI (Windows) +# This script configures Claude Code to use your XCodeCLI instance +# Run with: powershell -ExecutionPolicy Bypass -File setup-claude-code.ps1 -BaseUrl https://api.xcodecli.com -ApiKey YOUR_KEY +# Or via one-liner: & { $url='https://api.xcodecli.com'; $key='YOUR_KEY'; iwr -useb $url/setup-claude-code.ps1 | iex } + +param( + [string]$BaseUrl, + [string]$ApiKey, + [switch]$Test, + [switch]$Show, + [switch]$Help +) + +# Check for pre-set variables from one-liner command (use different names to avoid conflict) +if (-not $BaseUrl -and (Test-Path Variable:url)) { $BaseUrl = $url } +if (-not $ApiKey -and (Test-Path Variable:key)) { $ApiKey = $key } + +# Configuration +$DefaultBaseUrl = "https://api.xcodecli.com" +$ClaudeConfigDir = "$env:USERPROFILE\.claude" +$ClaudeSettingsFile = "$ClaudeConfigDir\settings.json" + +# Color functions for output +function Write-Info { + param([string]$Message) + Write-Host "[INFO]" -ForegroundColor Blue -NoNewline + Write-Host " $Message" +} + +function Write-Success { + param([string]$Message) + Write-Host "[SUCCESS]" -ForegroundColor Green -NoNewline + Write-Host " $Message" +} + +function Write-Warning { + param([string]$Message) + Write-Host "[WARNING]" -ForegroundColor Yellow -NoNewline + Write-Host " $Message" +} + +function Write-Error { + param([string]$Message) + Write-Host "[ERROR]" -ForegroundColor Red -NoNewline + Write-Host " $Message" +} + +# Function to show help +function Show-Help { + Write-Host @" +Claude Code Configuration Script for XCodeCLI (Windows) + +Usage: powershell -ExecutionPolicy Bypass -File setup-claude-code.ps1 [OPTIONS] + +Options: + -BaseUrl Set the XCodeCLI base URL (default: $DefaultBaseUrl) + -ApiKey Set the API key + -Test Test API connection only (requires -BaseUrl and -ApiKey) + -Show Show current settings and exit + -Help Show this help message + +Examples: + .\setup-claude-code.ps1 -BaseUrl https://api.xcodecli.com -ApiKey your-api-key-here + .\setup-claude-code.ps1 -Test -BaseUrl https://api.xcodecli.com -ApiKey your-api-key-here + .\setup-claude-code.ps1 -Show + +Interactive mode (no arguments): + .\setup-claude-code.ps1 + +PowerShell Execution Policy: + If you get an execution policy error, run: + powershell -ExecutionPolicy Bypass -File setup-claude-code.ps1 +"@ + exit 0 +} + +# Function to backup existing settings +function Backup-Settings { + if (Test-Path $ClaudeSettingsFile) { + $timestamp = Get-Date -Format "yyyyMMdd_HHmmss" + $backupFile = "$ClaudeSettingsFile.backup.$timestamp" + Copy-Item -Path $ClaudeSettingsFile -Destination $backupFile + Write-Info "Backed up existing settings to: $backupFile" + } +} + +# Function to create settings directory +function New-SettingsDirectory { + if (-not (Test-Path $ClaudeConfigDir)) { + New-Item -ItemType Directory -Path $ClaudeConfigDir -Force | Out-Null + Write-Info "Created Claude configuration directory: $ClaudeConfigDir" + } +} + +# Function to validate API key format +function Test-ApiKey { + param([string]$ApiKey) + + if ($ApiKey -match '^[A-Za-z0-9_-]+$') { + return $true + } else { + Write-Error "Invalid API key format. API key should contain only alphanumeric characters, hyphens, and underscores." + return $false + } +} + +# Function to test API connection +function Test-ApiConnection { + param( + [string]$BaseUrl, + [string]$ApiKey + ) + + Write-Info "Testing API connection..." + + try { + $headers = @{ + "Content-Type" = "application/json" + "X-API-Key" = $ApiKey + } + + # Determine the correct endpoint based on whether this is a team URL + if ($BaseUrl.EndsWith("/team")) { + $uri = "$BaseUrl/api/v1/team/stats/spending" + $balanceField = "daily_remaining" + $balanceLabel = "Daily remaining" + } else { + $uri = "$BaseUrl/api/v1/claude/balance" + $balanceField = "balance" + $balanceLabel = "Current balance" + } + + $response = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers -ErrorAction Stop + + if ($response.$balanceField) { + Write-Success "API connection successful! ${balanceLabel}: `$$($response.$balanceField)" + return $true + } else { + Write-Error "API test failed: Invalid response" + return $false + } + } + catch { + if ($_.Exception.Response -and $_.Exception.Response.StatusCode -eq 401) { + Write-Error "API key authentication failed. Please check your API key." + } elseif ($_.Exception.Message -like "*Unable to connect*" -or $_.Exception.Message -like "*could not be resolved*") { + Write-Error "Cannot connect to API server. Please check the URL and your internet connection." + } else { + Write-Error "API test failed: $($_.Exception.Message)" + } + return $false + } +} + +# Function to create Claude Code settings +function New-Settings { + param( + [string]$BaseUrl, + [string]$ApiKey + ) + + $settings = @{ + env = @{ + ANTHROPIC_BASE_URL = $BaseUrl + ANTHROPIC_AUTH_TOKEN = $ApiKey + CLAUDE_CODE_MAX_OUTPUT_TOKENS = 20000 + DISABLE_TELEMETRY = 1 + DISABLE_ERROR_REPORTING = 1 + CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC = 1 + CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR = 1 + MAX_THINKING_TOKENS = 12000 + } + model = "sonnet" + } + + try { + $json = $settings | ConvertTo-Json -Depth 10 + Set-Content -Path $ClaudeSettingsFile -Value $json -Encoding UTF8 + Write-Success "Claude Code settings written to: $ClaudeSettingsFile" + return $true + } + catch { + Write-Error "Failed to create settings file: $($_.Exception.Message)" + return $false + } +} + +# Function to display current settings +function Show-Settings { + if (Test-Path $ClaudeSettingsFile) { + Write-Info "Current Claude Code settings:" + Write-Host "----------------------------------------" + $settings = Get-Content $ClaudeSettingsFile -Raw | ConvertFrom-Json + $settings | ConvertTo-Json -Depth 10 + Write-Host "----------------------------------------" + } else { + Write-Info "No existing Claude Code settings found." + } + + Write-Host "" + Write-Info "Current environment variables:" + Write-Host "----------------------------------------" + $baseUrl = [Environment]::GetEnvironmentVariable("ANTHROPIC_BASE_URL", [EnvironmentVariableTarget]::User) + $authToken = [Environment]::GetEnvironmentVariable("ANTHROPIC_AUTH_TOKEN", [EnvironmentVariableTarget]::User) + + if ($baseUrl) { + Write-Info "ANTHROPIC_BASE_URL: $baseUrl" + } else { + Write-Info "ANTHROPIC_BASE_URL: (not set)" + } + + if ($authToken) { + $maskedToken = if ($authToken.Length -gt 12) { + "$($authToken.Substring(0, 8))...$($authToken.Substring($authToken.Length - 4))" + } else { + "$($authToken.Substring(0, [Math]::Min(4, $authToken.Length)))..." + } + Write-Info "ANTHROPIC_AUTH_TOKEN: $maskedToken" + } else { + Write-Info "ANTHROPIC_AUTH_TOKEN: (not set)" + } + Write-Host "----------------------------------------" +} + +# Main function +function Main { + Write-Info "Claude Code Configuration Script for XCodeCLI" + Write-Host "=======================================================" + Write-Host "" + + # Handle command line arguments + if ($Help) { + Show-Help + } + + if ($Show) { + Show-Settings + exit 0 + } + + # Interactive mode if no URL or Key provided + if (-not $BaseUrl -and -not $ApiKey) { + Write-Info "Interactive setup mode" + Write-Host "" + + # Get base URL + $inputUrl = Read-Host "Enter XCodeCLI URL [$DefaultBaseUrl]" + if ([string]::IsNullOrWhiteSpace($inputUrl)) { + $BaseUrl = $DefaultBaseUrl + } else { + $BaseUrl = $inputUrl + } + + # Get API key + while ([string]::IsNullOrWhiteSpace($ApiKey)) { + $ApiKey = Read-Host "Enter your API key" + if ([string]::IsNullOrWhiteSpace($ApiKey)) { + Write-Warning "API key is required" + } elseif (-not (Test-ApiKey $ApiKey)) { + $ApiKey = "" + } + } + } + + # Validate inputs + if ([string]::IsNullOrWhiteSpace($BaseUrl) -or [string]::IsNullOrWhiteSpace($ApiKey)) { + Write-Error "Both URL and API key are required" + Write-Info "Use -Help for usage information" + exit 1 + } + + # Validate API key + if (-not (Test-ApiKey $ApiKey)) { + exit 1 + } + + # Remove trailing slash from URL + $BaseUrl = $BaseUrl.TrimEnd('/') + + Write-Info "Configuration:" + Write-Info " Base URL: $BaseUrl" + $maskedKey = if ($ApiKey.Length -gt 12) { + "$($ApiKey.Substring(0, 8))...$($ApiKey.Substring($ApiKey.Length - 4))" + } else { + "$($ApiKey.Substring(0, [Math]::Min(4, $ApiKey.Length)))..." + } + Write-Info " API Key: $maskedKey" + Write-Host "" + + # Test API connection + $connectionSuccess = Test-ApiConnection -BaseUrl $BaseUrl -ApiKey $ApiKey + + if (-not $connectionSuccess) { + if ($Test) { + exit 1 + } + + $continue = Read-Host "API test failed. Continue anyway? (y/N)" + if ($continue -notmatch '^[Yy]$') { + Write-Info "Setup cancelled" + exit 1 + } + } + + # Exit if test only + if ($Test) { + Write-Success "API test completed successfully" + exit 0 + } + + # Create settings directory + New-SettingsDirectory + + # Backup existing settings + Backup-Settings + + # Create new settings + if (New-Settings -BaseUrl $BaseUrl -ApiKey $ApiKey) { + Write-Host "" + + # Also set environment variables for Windows + Write-Info "Setting environment variables..." + try { + # Set user environment variables (persistent across sessions) + [Environment]::SetEnvironmentVariable("ANTHROPIC_BASE_URL", $BaseUrl, [EnvironmentVariableTarget]::User) + [Environment]::SetEnvironmentVariable("ANTHROPIC_AUTH_TOKEN", $ApiKey, [EnvironmentVariableTarget]::User) + + # Also set for current session + $env:ANTHROPIC_BASE_URL = $BaseUrl + $env:ANTHROPIC_AUTH_TOKEN = $ApiKey + + Write-Success "Environment variables set successfully" + } + catch { + Write-Warning "Failed to set environment variables: $($_.Exception.Message)" + Write-Info "You may need to set them manually:" + Write-Info " ANTHROPIC_BASE_URL=$BaseUrl" + Write-Info " ANTHROPIC_AUTH_TOKEN=$ApiKey" + } + + Write-Host "" + Write-Success "Claude Code has been configured successfully!" + Write-Info "You can now use Claude Code with your API router." + Write-Info "" + Write-Info "To verify the setup, run:" + Write-Info " claude --version" + Write-Info "" + Write-Info "Configuration file location: $ClaudeSettingsFile" + Write-Info "Environment variables have been set for ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN" + + if (Test-Path $ClaudeSettingsFile) { + Write-Host "" + Write-Info "Current settings:" + $settings = Get-Content $ClaudeSettingsFile -Raw | ConvertFrom-Json + $settings | ConvertTo-Json -Depth 10 + } + } else { + Write-Error "Failed to create Claude Code settings" + exit 1 + } +} + +# Run main function +Main diff --git a/setup-claude-code.sh b/setup-claude-code.sh new file mode 100644 index 0000000..436a1c7 --- /dev/null +++ b/setup-claude-code.sh @@ -0,0 +1,332 @@ +#!/bin/bash + +# Claude Code Configuration Script for xcodecli +# This script configures Claude Code to use your xcodecli instance + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Configuration +DEFAULT_BASE_URL="https://api.xcodecli.com" +CLAUDE_CONFIG_DIR="$HOME/.claude" +CLAUDE_SETTINGS_FILE="$CLAUDE_CONFIG_DIR/settings.json" + +# Function to print colored output +print_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Function to check if jq is installed +check_jq() { + if ! command -v jq &> /dev/null; then + print_error "jq is required but not installed." + print_info "Please install jq:" + print_info " macOS: brew install jq" + print_info " Ubuntu/Debian: sudo apt-get install jq" + print_info " CentOS/RHEL: sudo yum install jq" + exit 1 + fi +} + +# Function to backup existing settings +backup_settings() { + if [ -f "$CLAUDE_SETTINGS_FILE" ]; then + local backup_file="${CLAUDE_SETTINGS_FILE}.backup.$(date +%Y%m%d_%H%M%S)" + cp "$CLAUDE_SETTINGS_FILE" "$backup_file" + print_info "Backed up existing settings to: $backup_file" + fi +} + +# Function to create settings directory +create_settings_dir() { + if [ ! -d "$CLAUDE_CONFIG_DIR" ]; then + mkdir -p "$CLAUDE_CONFIG_DIR" + print_info "Created Claude configuration directory: $CLAUDE_CONFIG_DIR" + fi +} + +# Function to validate API key format +validate_api_key() { + local api_key="$1" + if [[ ! "$api_key" =~ ^[A-Za-z0-9_-]+$ ]]; then + print_error "Invalid API key format. API key should contain only alphanumeric characters, hyphens, and underscores." + return 1 + fi + return 0 +} + +# Function to test API connection +test_api_connection() { + local base_url="$1" + local api_key="$2" + + print_info "Testing API connection..." + + # Determine the correct endpoint based on whether this is a team URL + local test_endpoint + local balance_field + if [[ "$base_url" == */team ]]; then + test_endpoint="$base_url/api/v1/team/stats/spending" + balance_field="daily_remaining" + else + test_endpoint="$base_url/api/v1/claude/balance" + balance_field="balance" + fi + + # Test a simple request to the API + local response + response=$(curl -s -w "%{http_code}" -o /tmp/claude_test_response \ + -X GET "$test_endpoint" \ + -H "Content-Type: application/json" \ + -H "X-API-Key: $api_key" \ + 2>/dev/null || echo "000") + + if [ "$response" = "200" ]; then + local balance + balance=$(cat /tmp/claude_test_response | jq -r ".${balance_field}" 2>/dev/null || echo "unknown") + if [[ "$base_url" == */team ]]; then + print_success "API connection successful! Daily remaining: \$${balance}" + else + print_success "API connection successful! Current balance: \$${balance}" + fi + rm -f /tmp/claude_test_response + return 0 + elif [ "$response" = "401" ]; then + print_error "API key authentication failed. Please check your API key." + rm -f /tmp/claude_test_response + return 1 + elif [ "$response" = "000" ]; then + print_error "Cannot connect to API server. Please check the URL and your internet connection." + rm -f /tmp/claude_test_response + return 1 + else + print_error "API test failed with HTTP status: $response" + rm -f /tmp/claude_test_response + return 1 + fi +} + +# Function to create Claude Code settings +create_settings() { + local base_url="$1" + local api_key="$2" + + local settings_json + settings_json=$(cat < /dev/null 2>&1; then + print_error "Generated settings JSON is invalid" + return 1 + fi + + # Write settings file + echo "$settings_json" > "$CLAUDE_SETTINGS_FILE" + print_success "Claude Code settings written to: $CLAUDE_SETTINGS_FILE" +} + +# Function to display current settings +display_settings() { + if [ -f "$CLAUDE_SETTINGS_FILE" ]; then + print_info "Current Claude Code settings:" + echo "----------------------------------------" + cat "$CLAUDE_SETTINGS_FILE" | jq . + echo "----------------------------------------" + else + print_info "No existing Claude Code settings found." + fi +} + +# Main function +main() { + print_info "Claude Code Configuration Script for xcodecli" + echo "=======================================================" + echo + + # Check dependencies + check_jq + + # Parse command line arguments + local base_url="" + local api_key="" + local test_only=false + local show_settings=false + + while [[ $# -gt 0 ]]; do + case $1 in + -u|--url) + base_url="$2" + shift 2 + ;; + -k|--key) + api_key="$2" + shift 2 + ;; + -t|--test) + test_only=true + shift + ;; + -s|--show) + show_settings=true + shift + ;; + -h|--help) + cat <