# ============================================================ # Router One · Claude Code 一键接入 / one-click setup (Windows) # Docs: https://router.one/docs/guides/cli-setup # # 用法 / Usage (PowerShell): # $env:ROUTER_ONE_API_KEY = "sk-your-api-key"; irm https://router.one/install/claude-code.ps1 | iex # ============================================================ $ErrorActionPreference = "Stop" function Write-RouterOk([string]$Message) { Write-Host "[OK] $Message" -ForegroundColor Green } function Write-RouterWarn([string]$Message) { Write-Host "[!] $Message" -ForegroundColor Yellow } function Write-RouterErr([string]$Message) { Write-Host "[X] $Message" -ForegroundColor Red } function Write-RouterInfo([string]$Message) { Write-Host "> $Message" -ForegroundColor DarkGray } # PS 5.1 Set-Content -Encoding UTF8 writes a BOM, which breaks JSON/TOML # parsers downstream — always write config files BOM-less. function Write-RouterFile([string]$FilePath, [string]$Content) { $Utf8NoBom = New-Object System.Text.UTF8Encoding($false) [System.IO.File]::WriteAllText($FilePath, $Content, $Utf8NoBom) } Write-Host "" Write-Host "Router One · Claude Code 一键接入" -ForegroundColor Cyan Write-Host "" $ApiKey = $env:ROUTER_ONE_API_KEY if ([string]::IsNullOrWhiteSpace($ApiKey)) { $ApiKey = Read-Host "请输入你的 Router One API Key / Enter your API key (sk-...)" } $ApiKey = "$ApiKey".Trim() if ([string]::IsNullOrWhiteSpace($ApiKey)) { Write-RouterErr "缺少 API Key / missing API key" Write-RouterInfo "先在 https://router.one/dashboard/api-keys 创建 API Key" return } if ($ApiKey -eq "sk-your-api-key") { Write-RouterErr "请把 sk-your-api-key 替换成你的真实 API Key / replace the placeholder with your real key" return } if (-not $ApiKey.StartsWith("sk-")) { Write-RouterWarn "API Key 一般以 sk- 开头,请确认复制完整 / keys usually start with sk-" } # ---- 1. Claude Code CLI ------------------------------------ $ClaudeCommand = Get-Command claude -ErrorAction SilentlyContinue if ($ClaudeCommand) { Write-RouterOk "检测到 Claude Code / found Claude Code: $($ClaudeCommand.Source)" } else { $NpmCommand = Get-Command npm -ErrorAction SilentlyContinue if ($NpmCommand) { Write-RouterInfo "未检测到 Claude Code,通过 npm 安装 / installing @anthropic-ai/claude-code via npm..." npm install -g @anthropic-ai/claude-code } if (-not (Get-Command claude -ErrorAction SilentlyContinue)) { Write-RouterInfo "通过官方安装器安装(无需 Node.js)/ installing via the official installer..." try { irm https://claude.ai/install.ps1 | iex } catch { Write-RouterWarn "官方安装器执行失败 / official installer failed" } $UserPath = [System.Environment]::GetEnvironmentVariable("Path", "User") $MachinePath = [System.Environment]::GetEnvironmentVariable("Path", "Machine") $env:Path = "$MachinePath;$UserPath;$env:Path" } if (Get-Command claude -ErrorAction SilentlyContinue) { Write-RouterOk "Claude Code 安装完成 / installed" } else { Write-RouterWarn "未能确认 claude 命令可用:安装可能未完成,或需重开 PowerShell 后生效 / could not confirm claude on PATH — reopen PowerShell if needed" } } # ---- 2. ~/.claude/settings.json ---------------------------- $ClaudeDir = Join-Path $env:USERPROFILE ".claude" $SettingsPath = Join-Path $ClaudeDir "settings.json" New-Item -ItemType Directory -Force -Path $ClaudeDir | Out-Null $Settings = $null if (Test-Path $SettingsPath) { $Stamp = Get-Date -Format "yyyyMMddHHmmss" Copy-Item $SettingsPath "$SettingsPath.bak.$Stamp" Write-RouterInfo "已备份原配置 / backed up existing settings: $SettingsPath.bak.$Stamp" try { $Settings = Get-Content $SettingsPath -Raw | ConvertFrom-Json } catch { $Settings = $null } } if ($null -eq $Settings) { $Settings = New-Object PSObject } $HasEnv = $Settings.PSObject.Properties.Name -contains "env" if (-not $HasEnv -or $null -eq $Settings.env) { $Settings | Add-Member -MemberType NoteProperty -Name env -Value (New-Object PSObject) -Force } $Settings.env | Add-Member -MemberType NoteProperty -Name ANTHROPIC_BASE_URL -Value "https://api.router.one" -Force $Settings.env | Add-Member -MemberType NoteProperty -Name ANTHROPIC_AUTH_TOKEN -Value $ApiKey -Force Write-RouterFile $SettingsPath (($Settings | ConvertTo-Json -Depth 16) + "`n") Write-RouterOk "已写入 $SettingsPath (ANTHROPIC_BASE_URL + ANTHROPIC_AUTH_TOKEN)" # ---- 3. Verify --------------------------------------------- Write-RouterInfo "发送一次 1 token 测试请求验证网关连通 / verifying gateway..." try { [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 } catch {} $VerifyBody = '{"model":"auto","max_tokens":1,"messages":[{"role":"user","content":"ping"}]}' $VerifyFailed = $false try { Invoke-RestMethod -Method Post -Uri "https://api.router.one/v1/chat/completions" ` -Headers @{ Authorization = "Bearer $ApiKey" } ` -ContentType "application/json" -Body $VerifyBody -TimeoutSec 60 | Out-Null Write-RouterOk "网关连通,API Key 有效 / gateway reachable, key valid" } catch { $StatusCode = 0 if ($_.Exception.Response) { try { $StatusCode = [int]$_.Exception.Response.StatusCode } catch { $StatusCode = 0 } } if ($StatusCode -eq 401) { Write-RouterErr "API Key 无效 (401)。配置已写入,但请到 https://router.one/dashboard/api-keys 检查或重新生成 Key。" $VerifyFailed = $true } elseif ($StatusCode -eq 402) { Write-RouterWarn "API Key 有效但余额不足 (402)。请先充值 / top up first: https://router.one/dashboard" } elseif ($StatusCode -eq 0) { Write-RouterWarn "网络请求失败,跳过验证(配置已写入)/ network error, skipped verification" } else { Write-RouterWarn "验证请求返回 HTTP $StatusCode (配置已写入)。排查见 / troubleshooting: https://router.one/docs/guides/cli-setup" } } Write-Host "" if ($VerifyFailed) { Write-RouterErr "配置完成,但 API Key 验证未通过 / setup finished but key verification failed" } else { Write-RouterOk "全部完成!运行 claude 开始使用 / all set — run: claude" } Write-RouterInfo "文档 / docs: https://router.one/docs/guides/cli-setup"