|
#Requires -RunAsAdministrator |
|
|
|
<# |
|
.SYNOPSIS |
|
Installs and configures Claude Code and its AI providers natively on Windows. |
|
.DESCRIPTION |
|
This script provides a full, Windows-native setup experience. It does NOT use WSL. |
|
1. Ensures Chocolatey and Node.js are installed. |
|
2. Installs the Claude Code CLI tool. |
|
3. Presents a menu to configure providers like Moonshot (Kimi), OpenAI, Anthropic, etc. |
|
4. Supports both API Key and Web Login methods for the official Anthropic provider. |
|
5. Prompts for API keys and endpoint details. |
|
6. Sets persistent environment variables for the current user. |
|
7. Can be re-run to switch providers or update keys. |
|
#> |
|
|
|
# --- Script Configuration --- |
|
$ErrorActionPreference = "Stop" |
|
|
|
# --- Helper Functions --- |
|
function Test-CommandExists { |
|
param($command) |
|
return (Get-Command $command -ErrorAction SilentlyContinue) |
|
} |
|
|
|
function Clear-PersistentEnvVars { |
|
# Clears all variables used by this script |
|
$envPath = "Registry::HKEY_CURRENT_USER\Environment" |
|
$vars = @("ANTHROPIC_API_KEY", "ANTHROPIC_BASE_URL") |
|
foreach ($var in $vars) { |
|
try { |
|
[System.Environment]::SetEnvironmentVariable($var, $null, "User") |
|
if (Get-ItemProperty -Path $envPath -Name $var -ErrorAction SilentlyContinue) { |
|
Remove-ItemProperty -Path $envPath -Name $var -Force -ErrorAction SilentlyContinue |
|
} |
|
} catch { |
|
Write-Warning "Could not fully remove environment variable '$var'. Manual removal may be required." |
|
} |
|
} |
|
} |
|
|
|
# --- Prerequisite Installation --- |
|
Write-Host "--- Step 1: Verifying Prerequisites (Windows Native) ---" -ForegroundColor Magenta |
|
|
|
# 1. Install Chocolatey |
|
if (-not (Test-CommandExists 'choco')) { |
|
Write-Host "Chocolatey not found. Installing..." -ForegroundColor Yellow |
|
Set-ExecutionPolicy Bypass -Scope Process -Force |
|
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 |
|
try { |
|
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) |
|
} catch { |
|
Write-Host "FATAL: Error installing Chocolatey. Please install it manually from https://chocolatey.org/install" -ForegroundColor Red; exit 1 |
|
} |
|
} else { |
|
Write-Host "✅ Chocolatey is installed." -ForegroundColor Green |
|
} |
|
|
|
# 2. Install Node.js |
|
if (-not (Test-CommandExists 'node')) { |
|
Write-Host "Node.js not found. Installing via Chocolatey..." -ForegroundColor Yellow |
|
choco install nodejs -y |
|
# Refresh environment to find npm |
|
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") |
|
} else { |
|
Write-Host "✅ Node.js is installed." -ForegroundColor Green |
|
} |
|
|
|
# 3. Install Claude Code |
|
if (-not (Test-CommandExists 'claude')) { |
|
Write-Host "Claude Code not found. Installing via npm..." -ForegroundColor Yellow |
|
npm install -g @anthropic-ai/claude-code |
|
} else { |
|
Write-Host "✅ Claude Code is installed." -ForegroundColor Green |
|
} |
|
Write-Host "✅ All prerequisites verified." -ForegroundColor Green |
|
|
|
|
|
# --- Provider Configuration --- |
|
$providers = @( |
|
[pscustomobject]@{ Name = "Moonshot (Kimi)"; BaseUrl = "https://api.moonshot.ai/anthropic/"; KeyName = "Moonshot API Key" } |
|
[pscustomobject]@{ Name = "OpenAI (GPT)"; BaseUrl = "https://api.openai.com/v1/"; KeyName = "OpenAI API Key (starts with 'sk-...')" } |
|
[pscustomobject]@{ Name = "Google (Gemini)"; BaseUrl = "https://generativelanguage.googleapis.com/v1beta/"; KeyName = "Gemini API Key" } |
|
[pscustomobject]@{ Name = "Anthropic (Official)"; BaseUrl = $null; KeyName = "Official Anthropic API Key" } |
|
[pscustomobject]@{ Name = "Azure OpenAI"; BaseUrl = "dynamic"; KeyName = "Azure API Key" } |
|
[pscustomobject]@{ Name = "Custom / Local Model"; BaseUrl = "custom"; KeyName = "API Key for your custom endpoint" } |
|
[pscustomobject]@{ Name = "Clear Configuration"; BaseUrl = "clear"; KeyName = "" } |
|
) |
|
|
|
Write-Host "" |
|
Write-Host "--- Step 2: Configure AI Provider ---" -ForegroundColor Magenta |
|
|
|
# Display menu |
|
Write-Host "" |
|
Write-Host "Please choose an AI provider to configure:" -ForegroundColor Yellow |
|
for ($i = 0; $i -lt $providers.Count; $i++) { |
|
Write-Host " $($i + 1). $($providers[$i].Name)" |
|
} |
|
|
|
# Get user choice |
|
$choice = 0 |
|
while ($choice -lt 1 -or $choice -gt $providers.Count) { |
|
try { $choice = [int](Read-Host "`nEnter your choice (1-$($providers.Count))") } catch {} |
|
} |
|
$selectedProvider = $providers[$choice - 1] |
|
$useWebLogin = $false |
|
|
|
# Process choice |
|
if ($selectedProvider.BaseUrl -eq "clear") { |
|
Write-Host "Clearing existing configuration..." -ForegroundColor Yellow |
|
Clear-PersistentEnvVars |
|
# Also clear alias from PowerShell profile |
|
if (Test-Path $PROFILE) { |
|
(Get-Content $PROFILE) | Where-Object { $_ -notmatch "# ANTHROPIC CONFIG START" -and $_ -notmatch "# ANTHROPIC CONFIG END" } | Set-Content $PROFILE |
|
} |
|
} elseif ($selectedProvider.Name -eq "Anthropic (Official)") { |
|
Write-Host "" |
|
Write-Host "How do you want to authenticate with Anthropic?" -ForegroundColor Yellow |
|
$authChoice = Read-Host " 1. Use an API Key`n 2. Use Web Login (opens a browser on first run)`nEnter your choice" |
|
if ($authChoice -eq '2') { |
|
$useWebLogin = $true |
|
Write-Host "Configuration set for Web Login. Clearing any existing API keys..." -ForegroundColor Cyan |
|
Clear-PersistentEnvVars |
|
} |
|
} |
|
|
|
# --- Get API Key and Model (if not Web Login) --- |
|
if (-not $useWebLogin -and $selectedProvider.BaseUrl -ne "clear") { |
|
$baseUrl = $selectedProvider.BaseUrl |
|
if ($baseUrl -eq "dynamic") { # Azure |
|
$resourceName = Read-Host "Enter your Azure Resource Name (e.g., 'my-azure-ai-resource')" |
|
$baseUrl = "https://$($resourceName).openai.azure.com/" |
|
} elseif ($baseUrl -eq "custom") { # Custom/Local |
|
$baseUrl = Read-Host "Enter the full Base URL for your custom endpoint (e.g., 'http://localhost:11434/v1/')" |
|
} |
|
|
|
Write-Host "" |
|
Write-Host "🔑 Please enter your $($selectedProvider.KeyName):" -ForegroundColor Yellow |
|
Write-Host " Note: Input is hidden. Paste your key and press Enter." |
|
$apiKeySecure = Read-Host -AsSecureString |
|
$apiKey = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($apiKeySecure)) |
|
|
|
if ([string]::IsNullOrWhiteSpace($apiKey)) { |
|
Write-Host "⚠️ API key cannot be empty. Aborting." -ForegroundColor Red; exit 1 |
|
} |
|
|
|
# Set environment variables |
|
Clear-PersistentEnvVars # Clear old ones first |
|
[Environment]::SetEnvironmentVariable("ANTHROPIC_API_KEY", $apiKey, "User") |
|
if ($baseUrl) { |
|
[Environment]::SetEnvironmentVariable("ANTHROPIC_BASE_URL", $baseUrl, "User") |
|
} |
|
|
|
# Set default model |
|
Write-Host "" |
|
Write-Host "--- Step 3: Set Default Model (Optional) ---" -ForegroundColor Magenta |
|
$setModelChoice = Read-Host "Do you want to set a default model alias in PowerShell? (y/N)" |
|
if ($setModelChoice -eq 'y') { |
|
$modelName = Read-Host "Default model name (e.g., 'kimi-k2-0711-preview' or 'claude-3-opus-20240229')" |
|
|
|
# Ensure profile exists |
|
if (-not (Test-Path $PROFILE)) { New-Item -Path $PROFILE -Type File -Force | Out-Null } |
|
|
|
# Clean up old alias and add new one |
|
$profileContent = Get-Content $PROFILE |
|
$newProfileContent = $profileContent | Where-Object { $_ -notmatch "# ANTHROPIC CONFIG START" -and $_ -notmatch "# ANTHROPIC CONFIG END" } |
|
$newProfileContent += "`n# ANTHROPIC CONFIG START" |
|
$newProfileContent += "function claude { & claude.cmd --model `"$modelName`" @args }" |
|
$newProfileContent += "# ANTHROPIC CONFIG END" |
|
$newProfileContent | Set-Content $PROFILE |
|
Write-Host "✅ Default model alias 'claude' set in your PowerShell profile." -ForegroundColor Green |
|
} |
|
} |
|
|
|
# --- Bypass Onboarding (skip for Web Login) --- |
|
if (-not $useWebLogin) { |
|
Write-Host "" |
|
Write-Host "--- Step 4: Configuring CLI Settings ---" -ForegroundColor Magenta |
|
$claudeConfigFile = Join-Path $HOME ".claude.json" |
|
$config = @{ hasCompletedOnboarding = $true } |
|
if (Test-Path $claudeConfigFile) { |
|
try { |
|
$existingConfig = Get-Content $claudeConfigFile | ConvertFrom-Json |
|
foreach ($key in $existingConfig.PSObject.Properties.Name) { |
|
if ($key -ne "hasCompletedOnboarding") { $config[$key] = $existingConfig.$key } |
|
} |
|
} catch { Write-Warning "Could not parse existing .claude.json. Overwriting." } |
|
} |
|
$config | ConvertTo-Json | Set-Content -Path $claudeConfigFile -Encoding UTF8 |
|
Write-Host "✅ Onboarding bypassed for API key usage." -ForegroundColor Green |
|
} else { |
|
Remove-Item (Join-Path $HOME ".claude.json") -ErrorAction SilentlyContinue |
|
} |
|
|
|
# --- Final Instructions --- |
|
Write-Host "" |
|
Write-Host "🎉 Configuration completed successfully!" -ForegroundColor Magenta |
|
Write-Host "" |
|
Write-Host "🔄 IMPORTANT: You MUST close and reopen this PowerShell window (and VS Code) for all changes to take effect." -ForegroundColor Yellow |
|
Write-Host "" |
|
Write-Host "🚀 You can now start using Claude Code from any PowerShell terminal." |