# ProbeCodex Installer for Windows # Usage: irm https://probecodex.com/install.ps1 | iex # # Options: # -SkipMcpConfig Skip MCP client configuration # -AllClients Configure all detected MCP clients without prompting # -Client Configure specific client only (claude-code, claude-desktop, cursor, cline, continue, zed) param( [switch]$SkipMcpConfig, [switch]$AllClients, [string]$Client ) $ErrorActionPreference = "Stop" Write-Host "" Write-Host "======================================================" -ForegroundColor Cyan Write-Host " ProbeCodex Installer " -ForegroundColor Cyan Write-Host "======================================================" -ForegroundColor Cyan Write-Host "" # Check if running as Administrator $isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) if (-not $isAdmin) { Write-Host "Warning: Not running as Administrator. Some features may require elevation." -ForegroundColor Yellow Write-Host "" } # Detect architecture $arch = if ([Environment]::Is64BitOperatingSystem) { "x64" } else { "x86" } if ($arch -ne "x64") { Write-Host "Error: Unsupported architecture: $arch. ProbeCodex requires 64-bit Windows." -ForegroundColor Red exit 1 } Write-Host "Detected platform: Windows $arch" -ForegroundColor Green # ═══════════════════════════════════════════════════════════════════════════ # MCP Client Detection and Configuration # ═══════════════════════════════════════════════════════════════════════════ # Define MCP client config locations $McpClients = @{ "claude-code" = @{ Name = "Claude Code (CLI)" ConfigPath = "$env:USERPROFILE\.claude\settings.json" ConfigType = "claude-code" } "claude-desktop" = @{ Name = "Claude Desktop" ConfigPath = "$env:APPDATA\Claude\claude_desktop_config.json" ConfigType = "standard" } "cursor" = @{ Name = "Cursor" ConfigPath = "$env:APPDATA\Cursor\User\globalStorage\cursor.mcp\config.json" ConfigType = "standard" } "cline" = @{ Name = "Cline (VS Code)" ConfigPath = "$env:APPDATA\Code\User\globalStorage\saoudrizwan.claude-dev\settings\cline_mcp_settings.json" ConfigType = "standard" } "continue" = @{ Name = "Continue (VS Code)" ConfigPath = "$env:USERPROFILE\.continue\config.json" ConfigType = "continue" } "zed" = @{ Name = "Zed" ConfigPath = "$env:APPDATA\Zed\settings.json" ConfigType = "zed" } } # Function to detect installed MCP clients function Get-DetectedMcpClients { $detected = @() foreach ($clientId in $McpClients.Keys) { $client = $McpClients[$clientId] $configPath = $client.ConfigPath $parentDir = Split-Path -Parent $configPath # Check if parent directory exists (app is installed) or config file exists if ((Test-Path $parentDir) -or (Test-Path $configPath)) { $detected += $clientId } } return $detected } # Function to merge MCP server into existing config function Add-McpServerToConfig { param( [string]$ConfigPath, [string]$ServerName, [hashtable]$ServerConfig, [string]$ConfigType ) # Create parent directory if needed $parentDir = Split-Path -Parent $ConfigPath if (-not (Test-Path $parentDir)) { New-Item -ItemType Directory -Path $parentDir -Force | Out-Null } # Load existing config or create new if (Test-Path $ConfigPath) { # Backup original $backupPath = "$ConfigPath.backup.$(Get-Date -Format 'yyyyMMddHHmmss')" Copy-Item $ConfigPath $backupPath try { $config = Get-Content $ConfigPath -Raw | ConvertFrom-Json -AsHashtable } catch { $config = @{} } } else { $config = @{} } # Add/update server based on config type switch ($ConfigType) { "continue" { if (-not $config.ContainsKey("experimental")) { $config["experimental"] = @{} } if (-not $config["experimental"].ContainsKey("modelContextProtocolServers")) { $config["experimental"]["modelContextProtocolServers"] = @{} } $config["experimental"]["modelContextProtocolServers"][$ServerName] = $ServerConfig } "zed" { if (-not $config.ContainsKey("context_servers")) { $config["context_servers"] = @{} } $config["context_servers"][$ServerName] = $ServerConfig } "claude-code" { # Claude Code CLI uses mcpServers in settings.json if (-not $config.ContainsKey("mcpServers")) { $config["mcpServers"] = @{} } $config["mcpServers"][$ServerName] = $ServerConfig } default { # Standard mcpServers format (Claude Desktop, Cursor, Cline) if (-not $config.ContainsKey("mcpServers")) { $config["mcpServers"] = @{} } $config["mcpServers"][$ServerName] = $ServerConfig } } # Write config back $config | ConvertTo-Json -Depth 10 | Set-Content $ConfigPath -Encoding UTF8 return $true } # Function to configure a single MCP client function Set-McpClientConfig { param([string]$ClientId) $client = $McpClients[$ClientId] $clientName = $client.Name $configPath = $client.ConfigPath $configType = $client.ConfigType Write-Host " Configuring $clientName..." -ForegroundColor Gray # ProbeCodex MCP server configuration $mcpConfig = @{ command = "$env:LOCALAPPDATA\ProbeCodex\bin\probecodex-mcp.exe" args = @() env = @{} } try { Add-McpServerToConfig -ConfigPath $configPath -ServerName "probecodex" -ServerConfig $mcpConfig -ConfigType $configType Write-Host " + Added probecodex to $clientName" -ForegroundColor Green Write-Host " Config: $configPath" -ForegroundColor DarkGray return $true } catch { Write-Host " x Failed to configure $clientName : $_" -ForegroundColor Red return $false } } # ═══════════════════════════════════════════════════════════════════════════ # Binary Installation # ═══════════════════════════════════════════════════════════════════════════ # Fetch latest version from probecodex.com API $versionsUrl = "https://probecodex.com/api/downloads/versions" Write-Host "Fetching latest version info..." -ForegroundColor Cyan try { $versionJson = Invoke-RestMethod -Uri $versionsUrl -Method Get $version = $versionJson.latest $downloadUrl = $versionJson.versions[0].downloads.windows if (-not $version -or -not $downloadUrl) { throw "Failed to get version info" } } catch { Write-Host "Error: Failed to fetch version info: $_" -ForegroundColor Red exit 1 } Write-Host "Latest version: $version" -ForegroundColor Green # Set install directory $installDir = "$env:LOCALAPPDATA\ProbeCodex" $binDir = "$installDir\bin" Write-Host "Install directory: $installDir" -ForegroundColor Cyan # Create directories if (-not (Test-Path $installDir)) { New-Item -ItemType Directory -Path $installDir -Force | Out-Null } if (-not (Test-Path $binDir)) { New-Item -ItemType Directory -Path $binDir -Force | Out-Null } # Download ZIP $tempDir = Join-Path $env:TEMP "probecodex-install-$(Get-Random)" New-Item -ItemType Directory -Path $tempDir -Force | Out-Null $zipPath = Join-Path $tempDir "probecodex-win-x64.zip" Write-Host "Downloading from GitHub Releases..." -ForegroundColor Cyan Write-Host " $downloadUrl" -ForegroundColor DarkGray try { $ProgressPreference = 'SilentlyContinue' # Speed up download Invoke-WebRequest -Uri $downloadUrl -OutFile $zipPath -UseBasicParsing } catch { Write-Host "Error: Failed to download: $_" -ForegroundColor Red Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue exit 1 } # Extract ZIP Write-Host "Extracting archive..." -ForegroundColor Cyan $extractDir = Join-Path $tempDir "extracted" Expand-Archive -Path $zipPath -DestinationPath $extractDir -Force # Find and copy binaries $binaries = Get-ChildItem -Path $extractDir -Recurse -Include "probecodex-mcp.exe", "probecodex-agent.exe", "mcp-arm-debug.exe" foreach ($bin in $binaries) { $destPath = Join-Path $binDir $bin.Name Copy-Item -Path $bin.FullName -Destination $destPath -Force Write-Host " + Installed: $($bin.Name)" -ForegroundColor Green } # Cleanup temp files Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue # Add to PATH if not already present $userPath = [Environment]::GetEnvironmentVariable("Path", "User") if ($userPath -notlike "*$binDir*") { Write-Host "Adding to PATH..." -ForegroundColor Cyan [Environment]::SetEnvironmentVariable("Path", "$userPath;$binDir", "User") $env:Path = "$env:Path;$binDir" Write-Host " + Added $binDir to user PATH" -ForegroundColor Green Write-Host " Note: Restart your terminal for PATH changes to take effect" -ForegroundColor Yellow } Write-Host "" Write-Host "+ Installed to $binDir" -ForegroundColor Green # ═══════════════════════════════════════════════════════════════════════════ # MCP Client Configuration # ═══════════════════════════════════════════════════════════════════════════ if ($SkipMcpConfig) { Write-Host "" Write-Host ">> Skipping MCP client configuration (-SkipMcpConfig)" -ForegroundColor Yellow } else { Write-Host "" Write-Host "Detecting MCP-compatible AI clients..." -ForegroundColor Cyan $detectedClients = Get-DetectedMcpClients if ($detectedClients.Count -eq 0) { Write-Host " No MCP clients detected." -ForegroundColor Yellow Write-Host "" Write-Host " Supported clients:" -ForegroundColor Gray Write-Host " - Claude Code (CLI) - npm install -g @anthropic-ai/claude-code" -ForegroundColor Gray Write-Host " - Claude Desktop - https://claude.ai/download" -ForegroundColor Gray Write-Host " - Cursor - https://cursor.sh" -ForegroundColor Gray Write-Host " - Cline (VS Code) - VS Code Extension" -ForegroundColor Gray Write-Host " - Continue (VS Code) - VS Code Extension" -ForegroundColor Gray Write-Host " - Zed - https://zed.dev" -ForegroundColor Gray Write-Host "" Write-Host " You can configure MCP manually later. See:" -ForegroundColor Gray Write-Host " https://probecodex.com/docs/getting-started" -ForegroundColor Cyan } else { Write-Host " Found $($detectedClients.Count) client(s):" -ForegroundColor Green foreach ($clientId in $detectedClients) { Write-Host " - $($McpClients[$clientId].Name)" -ForegroundColor White } Write-Host "" if ($Client) { # Configure specific client only if ($detectedClients -contains $Client) { Write-Host "Configuring $Client..." -ForegroundColor Cyan Set-McpClientConfig -ClientId $Client } else { Write-Host "Warning: Client '$Client' not detected" -ForegroundColor Yellow } } elseif ($AllClients) { # Configure all detected clients Write-Host "Configuring all detected clients..." -ForegroundColor Cyan foreach ($clientId in $detectedClients) { Set-McpClientConfig -ClientId $clientId } } else { # Interactive: Ask user which clients to configure Write-Host "Configure MCP for AI clients?" -ForegroundColor White Write-Host "" Write-Host " This will ADD probecodex to your existing MCP servers." -ForegroundColor Gray Write-Host " Your other MCP servers will be preserved." -ForegroundColor Gray Write-Host "" for ($i = 0; $i -lt $detectedClients.Count; $i++) { $clientId = $detectedClients[$i] Write-Host " [$($i + 1)] $($McpClients[$clientId].Name)" -ForegroundColor White } Write-Host " [a] All of the above" -ForegroundColor White Write-Host " [s] Skip configuration" -ForegroundColor White Write-Host "" $choice = Read-Host " Select option(s) (e.g., 1,2 or a)" if ($choice -eq "s" -or $choice -eq "S") { Write-Host " Skipped MCP configuration." -ForegroundColor Yellow } elseif ($choice -eq "a" -or $choice -eq "A") { Write-Host "" foreach ($clientId in $detectedClients) { Set-McpClientConfig -ClientId $clientId } } else { Write-Host "" # Parse comma-separated choices $choices = $choice -split "," | ForEach-Object { $_.Trim() } foreach ($c in $choices) { if ($c -match "^\d+$") { $index = [int]$c - 1 if ($index -ge 0 -and $index -lt $detectedClients.Count) { $clientId = $detectedClients[$index] Set-McpClientConfig -ClientId $clientId } } } } } } } # ═══════════════════════════════════════════════════════════════════════════ # Run Agent Installer # ═══════════════════════════════════════════════════════════════════════════ Write-Host "" Write-Host "======================================================" -ForegroundColor Green Write-Host " + ProbeCodex $version installed! " -ForegroundColor Green Write-Host "======================================================" -ForegroundColor Green Write-Host "" # Run agent installer $agentExe = Join-Path $binDir "probecodex-agent.exe" if (Test-Path $agentExe) { Write-Host "Running agent installer for VPN, dependencies, and service setup..." -ForegroundColor Cyan Write-Host "" try { # Start the agent installer and wait for it to complete $process = Start-Process -FilePath $agentExe -ArgumentList "install" -NoNewWindow -Wait -PassThru if ($process.ExitCode -ne 0) { Write-Host "" Write-Host "Agent installer exited with code: $($process.ExitCode)" -ForegroundColor Yellow Write-Host "You can run it manually later: probecodex-agent install" -ForegroundColor Gray } } catch { Write-Host "Could not run agent installer: $_" -ForegroundColor Yellow Write-Host "" Write-Host "Run manually after restarting terminal:" -ForegroundColor Cyan Write-Host " probecodex-agent install" -ForegroundColor White } } else { Write-Host "probecodex-agent.exe not found in $binDir" -ForegroundColor Yellow Write-Host "" } Write-Host "" Write-Host "Installation complete! Next steps:" -ForegroundColor Cyan Write-Host " 1. Restart your terminal (for PATH changes)" -ForegroundColor White Write-Host " 2. Run 'probecodex-agent install' if it didn't run above" -ForegroundColor White Write-Host " 3. Activate your license in your AI client" -ForegroundColor White Write-Host " 4. Connect to your target hardware" -ForegroundColor White Write-Host ""