# Claudible Installer for Codex CLI (Windows PowerShell 5.1+) # Configures Codex CLI to use Claudible # Compatible with Windows 10/11 (PowerShell 5.1) and PowerShell 7+ $ErrorActionPreference = "Stop" # Configuration (auto-populated by server) $SERVER_URL = "https://claudible.io" $API_KEY = '' $ENDPOINT_URL = "" $CODEX_MODEL = "" $e = [char]27 Write-Host "" Write-Host "${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m" Write-Host " ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m" Write-Host "${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m" Write-Host "${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m" Write-Host "${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m" Write-Host " ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m" Write-Host " ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m ${e}[42m ${e}[0m" Write-Host "" Write-Host " Codex CLI Setup" -ForegroundColor Green Write-Host "" # Validate API key if ($API_KEY -eq "__" + "API_KEY__" -or [string]::IsNullOrEmpty($API_KEY)) { Write-Host "Error: API key not configured" -ForegroundColor Red Write-Host "Please use the install link from your Claudible dashboard." exit 1 } # Fetch endpoints from model-hub API Write-Host "Đang tải danh sách endpoints..." -ForegroundColor Blue try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls13 } catch { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 } try { $response = Invoke-WebRequest -Uri "$SERVER_URL/api/model-hub" -UseBasicParsing -TimeoutSec 10 $hubData = $response.Content | ConvertFrom-Json } catch { Write-Host "Error: Không thể kết nối tới server" -ForegroundColor Red exit 1 } # Filter endpoints with codexEnabled=true and status=active $endpoints = @($hubData.endpoints | Where-Object { $_.codexEnabled -eq $true -and $_.status -eq "active" }) if ($endpoints.Count -eq 0) { Write-Host "Error: Không có endpoint nào bật Codex" -ForegroundColor Red exit 1 } if ($endpoints.Count -eq 1) { $ep = $endpoints[0] $ENDPOINT_URL = $ep.url $CODEX_MODEL = $ep.codexModels[0] Write-Host " OK $($ep.name)" -ForegroundColor Green } else { Write-Host "" Write-Host "Chọn cổng kết nối:" -ForegroundColor Cyan Write-Host "" for ($i = 0; $i -lt $endpoints.Count; $i++) { Write-Host " $($i+1)) " -NoNewline -ForegroundColor Green Write-Host "$($endpoints[$i].name) " -NoNewline Write-Host "— $($endpoints[$i].url)" -ForegroundColor Yellow } Write-Host "" $choice = Read-Host "Nhập lựa chọn [1-$($endpoints.Count)]" $idx = 0 if ([int]::TryParse($choice, [ref]$idx) -and $idx -ge 1 -and $idx -le $endpoints.Count) { $idx = $idx - 1 } else { Write-Host "Lựa chọn không hợp lệ, dùng mặc định: 1" -ForegroundColor Yellow $idx = 0 } $ep = $endpoints[$idx] $ENDPOINT_URL = $ep.url $CODEX_MODEL = $ep.codexModels[0] } # Ensure https:// prefix and strip trailing slash if ($ENDPOINT_URL -notmatch '^https?://') { $ENDPOINT_URL = "https://$ENDPOINT_URL" } $ENDPOINT_URL = $ENDPOINT_URL.TrimEnd('/') # Fallback default model if ([string]::IsNullOrEmpty($CODEX_MODEL)) { $CODEX_MODEL = "o3" } # Mask API key for display $MASKED_KEY = $API_KEY.Substring(0, [Math]::Min(10, $API_KEY.Length)) Write-Host "Endpoint URL: " -NoNewline Write-Host "$ENDPOINT_URL" -ForegroundColor Green Write-Host "API Key: " -NoNewline Write-Host "$MASKED_KEY..." -ForegroundColor Green Write-Host "Default Model: " -NoNewline Write-Host "$CODEX_MODEL" -ForegroundColor Green Write-Host "" # Check Node.js >= 22 Write-Host "Checking prerequisites..." -ForegroundColor Blue try { $nodeVersion = node --version 2>$null } catch { $nodeVersion = $null } if (-not $nodeVersion) { Write-Host "Error: Node.js is not installed" -ForegroundColor Red Write-Host "" Write-Host "Codex CLI requires Node.js 22 or later." Write-Host "Download from: https://nodejs.org" exit 1 } $nodeMajor = [int]($nodeVersion -replace '^v','').Split('.')[0] if ($nodeMajor -lt 22) { Write-Host "Error: Node.js 22+ is required (found $nodeVersion)" -ForegroundColor Red Write-Host "Download from: https://nodejs.org" exit 1 } Write-Host " " -NoNewline Write-Host "OK" -ForegroundColor Green -NoNewline Write-Host " Node.js $nodeVersion" # Check npm try { $npmVersion = npm --version 2>$null } catch { $npmVersion = $null } if (-not $npmVersion) { Write-Host "Error: npm is not installed" -ForegroundColor Red Write-Host "Please install npm (usually comes with Node.js)." exit 1 } Write-Host " " -NoNewline Write-Host "OK" -ForegroundColor Green -NoNewline Write-Host " npm $npmVersion" # Install Codex CLI if not found Write-Host "" # Ensure npm global prefix is on PATH (Windows shims live at prefix dir directly) $npmGlobalBin = try { (npm config get prefix 2>$null).Trim() } catch { $null } if ($npmGlobalBin -and (Test-Path $npmGlobalBin)) { $env:PATH = "$npmGlobalBin;$env:PATH" } $codexCmd = Get-Command codex -ErrorAction SilentlyContinue if ($codexCmd) { Write-Host "Codex CLI already installed" -ForegroundColor Blue } else { Write-Host "Installing Codex CLI..." -ForegroundColor Blue npm install -g @openai/codex $codexCmd = Get-Command codex -ErrorAction SilentlyContinue if ($codexCmd) { Write-Host " " -NoNewline Write-Host "OK" -ForegroundColor Green -NoNewline Write-Host " Codex CLI installed" } else { Write-Host "Warning: Codex CLI installed but not found on PATH" -ForegroundColor Yellow Write-Host "You may need to restart your terminal or add npm global bin to PATH." } } # Setup ~/.codex directory Write-Host "" Write-Host "Configuring Codex CLI..." -ForegroundColor Blue $codexDir = Join-Path $env:USERPROFILE ".codex" if (-not (Test-Path $codexDir)) { New-Item -ItemType Directory -Path $codexDir -Force | Out-Null } # Backup existing config.toml $configPath = Join-Path $codexDir "config.toml" if (Test-Path $configPath) { $backupPath = "$configPath.backup.$(Get-Date -Format 'yyyyMMddHHmmss')" Copy-Item $configPath $backupPath Write-Host " Backed up: $configPath" -ForegroundColor Yellow } # Write config.toml $configContent = @" model = "$CODEX_MODEL" model_provider = "claudible" model_catalog_json = "~/.codex/models.json" [model_providers.claudible] name = "Claudible" base_url = "$ENDPOINT_URL/v1" experimental_bearer_token = "$API_KEY" wire_api = "responses" [features] apps = false "@ [System.IO.File]::WriteAllText($configPath, $configContent, [System.Text.UTF8Encoding]::new($false)) Write-Host " " -NoNewline Write-Host "OK" -ForegroundColor Green -NoNewline Write-Host " Written config.toml" # Write models.json from endpoint's codexModels list $modelsPath = Join-Path $codexDir "models.json" $priority = 0 $modelEntries = @($ep.codexModels | ForEach-Object { $priority++ [ordered]@{ slug=$_ display_name=$_ description="$_ - cung cấp bởi Claudible" default_reasoning_level="medium" supported_reasoning_levels=@([ordered]@{effort="low";description="Minimal reasoning"},[ordered]@{effort="medium";description="Balanced reasoning"},[ordered]@{effort="high";description="Deep reasoning"},[ordered]@{effort="xhigh";description="Maximum reasoning"}) shell_type="shell_command" visibility="list" supported_in_api=$true priority=$priority availability_nux=$null upgrade=$null base_instructions="" model_messages=$null supports_reasoning_summaries=$false default_reasoning_summary="auto" support_verbosity=$true default_verbosity=$null apply_patch_tool_type=$null web_search_tool_type="text" truncation_policy=[ordered]@{mode="tokens";limit=200000} supports_parallel_tool_calls=$true supports_image_detail_original=$false context_window=200000 auto_compact_token_limit=$null effective_context_window_percent=95 experimental_supported_tools=@() input_modalities=@("text","image") supports_search_tool=$false } }) $modelsContent = [ordered]@{models=$modelEntries} | ConvertTo-Json -Depth 5 [System.IO.File]::WriteAllText($modelsPath, $modelsContent, [System.Text.UTF8Encoding]::new($false)) Write-Host " " -NoNewline Write-Host "OK" -ForegroundColor Green -NoNewline Write-Host " Written models.json" # Write auth.json only if missing or empty (preserve existing auth state) $authPath = Join-Path $codexDir "auth.json" if (-not (Test-Path $authPath) -or (Get-Item $authPath).Length -eq 0) { [System.IO.File]::WriteAllText($authPath, "{}", [System.Text.UTF8Encoding]::new($false)) Write-Host " " -NoNewline Write-Host "OK" -ForegroundColor Green -NoNewline Write-Host " Written auth.json" } else { Write-Host " " -NoNewline Write-Host "OK" -ForegroundColor Green -NoNewline Write-Host " Kept existing auth.json" } # Remove models cache to prevent stale OpenAI models $cachePath = Join-Path $codexDir "models_cache.json" if (Test-Path $cachePath) { Remove-Item $cachePath -Force Write-Host " " -NoNewline Write-Host "OK" -ForegroundColor Green -NoNewline Write-Host " Removed models_cache.json" } Write-Host "" Write-Host "================================" -ForegroundColor Green Write-Host " Configuration Complete!" -ForegroundColor Green Write-Host "================================" -ForegroundColor Green Write-Host "" Write-Host "Codex CLI is now configured to use Claudible:" Write-Host " Endpoint: " -NoNewline Write-Host "$ENDPOINT_URL/v1" -ForegroundColor Blue Write-Host " API Key: " -NoNewline Write-Host "$MASKED_KEY..." -ForegroundColor Blue Write-Host " Model: " -NoNewline Write-Host "$CODEX_MODEL" -ForegroundColor Blue Write-Host "" Write-Host "Next steps:" -ForegroundColor Yellow Write-Host " Run: " -NoNewline Write-Host "codex" -ForegroundColor Blue Write-Host ""