|
| 1 | +# OpenAnalyst CLI Installer — Windows PowerShell |
| 2 | +# Usage: irm https://raw.githubusercontent.com/OpenAnalystInc/cli/main/install.ps1 | iex |
| 3 | + |
| 4 | +$ErrorActionPreference = "Continue" |
| 5 | +$ProgressPreference = "SilentlyContinue" |
| 6 | +try { [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 } catch {} |
| 7 | + |
| 8 | +$Repo = "OpenAnalystInc/cli" |
| 9 | +$BinaryName = "openanalyst.exe" |
| 10 | +$InstallDir = "$env:USERPROFILE\.openanalyst\bin" |
| 11 | +$ConfigDir = "$env:USERPROFILE\.openanalyst" |
| 12 | + |
| 13 | +# ── Helpers ── |
| 14 | +function Rp([string]$c, [int]$n) { if ($n -le 0) { return "" }; return ($c * $n) } |
| 15 | +function Pad([int]$n) { if ($n -le 0) { return "" }; return (" " * $n) } |
| 16 | +function W([string]$t) { Write-Host $t -NoNewline -ForegroundColor White } |
| 17 | +function Dim([string]$t) { Write-Host $t -NoNewline -ForegroundColor DarkGray } |
| 18 | +function Br([string]$t) { Write-Host $t -NoNewline -ForegroundColor DarkCyan } |
| 19 | +function Grn([string]$t) { Write-Host $t -NoNewline -ForegroundColor Green } |
| 20 | +function Yl([string]$t) { Write-Host $t -NoNewline -ForegroundColor Yellow } |
| 21 | +function Acc([string]$t) { Write-Host $t -NoNewline -ForegroundColor Cyan } |
| 22 | +function Nl { Write-Host "" } |
| 23 | +$H = [string][char]0x2500 # ─ |
| 24 | +$TL = [string][char]0x250C # ┌ |
| 25 | +$TR = [string][char]0x2510 # ┐ |
| 26 | +$BL = [string][char]0x2514 # └ |
| 27 | +$BR = [string][char]0x2518 # ┘ |
| 28 | +$VL = [string][char]0x2502 # │ |
| 29 | + |
| 30 | +# ── Fetch version ── |
| 31 | +$GhHeaders = @{ "User-Agent" = "openanalyst-cli" } |
| 32 | +if ($env:GITHUB_TOKEN) { $GhHeaders["Authorization"] = "Bearer $env:GITHUB_TOKEN" } |
| 33 | +elseif ($env:GH_TOKEN) { $GhHeaders["Authorization"] = "Bearer $env:GH_TOKEN" } |
| 34 | +else { try { $t = (gh auth token 2>$null); if ($t) { $GhHeaders["Authorization"] = "Bearer $t" } } catch {} } |
| 35 | + |
| 36 | +$Version = "latest" |
| 37 | +$Release = $null |
| 38 | +try { |
| 39 | + $Release = Invoke-RestMethod -Uri "https://api.github.com/repos/$Repo/releases/latest" -Headers $GhHeaders -ErrorAction Stop |
| 40 | + $Version = $Release.tag_name -replace "^v", "" |
| 41 | +} catch {} |
| 42 | + |
| 43 | +# ── Header ── |
| 44 | +Nl; Nl |
| 45 | +Dim " "; Br "######## "; Acc " #### "; Nl |
| 46 | +Dim " "; Br "## ## "; Acc " ## ## "; Nl |
| 47 | +Dim " "; Br "## ## "; Acc "## ## "; Nl |
| 48 | +Dim " "; Br "## ## "; Acc "######## "; Nl |
| 49 | +Dim " "; Br "## ## "; Acc "## ## "; Nl |
| 50 | +Dim " "; Br "######## "; Acc "## ## "; Nl |
| 51 | +Nl |
| 52 | +Write-Host " " -NoNewline |
| 53 | +Write-Host "OpenAnalyst CLI" -NoNewline -ForegroundColor White |
| 54 | +Dim " v$Version" |
| 55 | +Nl |
| 56 | +Dim " The Universal AI Agent for Your Terminal" |
| 57 | +Nl; Nl |
| 58 | +Dim " $(Rp $H 44)"; Nl; Nl |
| 59 | + |
| 60 | +# ── System info ── |
| 61 | +$OsLabel = "Windows" |
| 62 | +$ArchLabel = if ([Environment]::Is64BitOperatingSystem) { "x64" } else { "x86" } |
| 63 | +$BoxW = 42 |
| 64 | + |
| 65 | +Dim " $TL$(Rp $H $BoxW)$TR"; Nl |
| 66 | +Dim " $VL"; W " System "; Dim "$OsLabel $ArchLabel"; Dim (Pad ($BoxW - 15 - "$OsLabel $ArchLabel".Length)); Dim $VL; Nl |
| 67 | +Dim " $VL"; W " Install to "; Dim "~\.openanalyst\bin"; Dim (Pad ($BoxW - 15 - 18)); Dim $VL; Nl |
| 68 | +Dim " $VL"; W " Config at "; Dim "~\.openanalyst"; Dim (Pad ($BoxW - 15 - 14)); Dim $VL; Nl |
| 69 | +Dim " $BL$(Rp $H $BoxW)$BR"; Nl |
| 70 | +Nl |
| 71 | + |
| 72 | +# ── Setup ── |
| 73 | +New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null |
| 74 | +New-Item -ItemType Directory -Force -Path $ConfigDir | Out-Null |
| 75 | + |
| 76 | +# ── Step 1: Download ── |
| 77 | +$Downloaded = $false |
| 78 | +Get-Process -Name "openanalyst" -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue |
| 79 | +Start-Sleep -Milliseconds 300 |
| 80 | + |
| 81 | +Dim " "; Acc "$([char]0x203A)"; Dim " Downloading binary..." |
| 82 | +if ($Release) { |
| 83 | + $Asset = $Release.assets | Where-Object { $_.name -eq "openanalyst.exe" } | Select-Object -First 1 |
| 84 | + if (-not $Asset) { $Asset = $Release.assets | Where-Object { $_.name -like "*.exe" } | Select-Object -First 1 } |
| 85 | + if ($Asset -and $Asset.browser_download_url) { $AssetUrl = $Asset.browser_download_url } |
| 86 | + else { $AssetUrl = "https://github.com/$Repo/releases/download/$($Release.tag_name)/openanalyst.exe" } |
| 87 | + try { |
| 88 | + Invoke-WebRequest -Uri $AssetUrl -OutFile "$InstallDir\$BinaryName" -UseBasicParsing -ErrorAction Stop |
| 89 | + $Downloaded = $true |
| 90 | + Write-Host " " -NoNewline; Grn "$([char]0x2713)"; Dim " done"; Nl |
| 91 | + } catch { |
| 92 | + Write-Host " " -NoNewline; Yl "failed"; Nl |
| 93 | + } |
| 94 | +} else { |
| 95 | + Write-Host " " -NoNewline; Yl "no release found"; Nl |
| 96 | +} |
| 97 | + |
| 98 | +if (-not $Downloaded) { |
| 99 | + Nl |
| 100 | + Yl " Download failed. Visit:" |
| 101 | + Nl |
| 102 | + Acc " github.com/$Repo/releases" |
| 103 | + Nl; Nl |
| 104 | + exit 1 |
| 105 | +} |
| 106 | + |
| 107 | +# ── Step 2: PATH ── |
| 108 | +Dim " "; Acc "$([char]0x203A)"; Dim " Configuring PATH..." |
| 109 | +$CurrentPath = [Environment]::GetEnvironmentVariable("Path", "User") |
| 110 | +if ($CurrentPath -notlike "*$InstallDir*") { |
| 111 | + [Environment]::SetEnvironmentVariable("Path", "$InstallDir;$CurrentPath", "User") |
| 112 | + $env:Path = "$InstallDir;$env:Path" |
| 113 | + Write-Host " " -NoNewline; Grn "$([char]0x2713)"; Dim " added"; Nl |
| 114 | +} else { |
| 115 | + Write-Host " " -NoNewline; Grn "$([char]0x2713)"; Dim " already configured"; Nl |
| 116 | +} |
| 117 | + |
| 118 | +# ── Step 3: Config ── |
| 119 | +Dim " "; Acc "$([char]0x203A)"; Dim " Creating config..." |
| 120 | +$EnvFile = "$ConfigDir\.env" |
| 121 | +if (-not (Test-Path $EnvFile)) { |
| 122 | + @" |
| 123 | +# OpenAnalyst CLI — Environment Configuration |
| 124 | +# OPENANALYST_API_KEY= |
| 125 | +# ANTHROPIC_API_KEY=sk-ant-... |
| 126 | +# OPENAI_API_KEY=sk-... |
| 127 | +# GEMINI_API_KEY=AIza... |
| 128 | +"@ | Out-File -FilePath $EnvFile -Encoding utf8 |
| 129 | + Write-Host " " -NoNewline; Grn "$([char]0x2713)"; Dim " ~\.openanalyst\.env"; Nl |
| 130 | +} else { |
| 131 | + Write-Host " " -NoNewline; Grn "$([char]0x2713)"; Dim " already exists"; Nl |
| 132 | +} |
| 133 | + |
| 134 | +# ── Summary ── |
| 135 | +Nl; Nl |
| 136 | +Dim " $(Rp $H 44)"; Nl; Nl |
| 137 | +Write-Host " $([char]0x2713) Installation complete" -ForegroundColor Green |
| 138 | +Nl; Nl |
| 139 | + |
| 140 | +$BinPath = "~\.openanalyst\bin\openanalyst" |
| 141 | +$CfgPath = "~\.openanalyst\.env" |
| 142 | +$VerStr = "v$Version" |
| 143 | + |
| 144 | +Dim " $TL$(Rp $H $BoxW)$TR"; Nl |
| 145 | +Dim " $VL$(Pad $BoxW)$VL"; Nl |
| 146 | +Dim " $VL"; W " Binary "; Dim $BinPath; Dim (Pad ($BoxW - 13 - $BinPath.Length)); Dim $VL; Nl |
| 147 | +Dim " $VL"; W " Config "; Dim $CfgPath; Dim (Pad ($BoxW - 13 - $CfgPath.Length)); Dim $VL; Nl |
| 148 | +Dim " $VL"; W " Version "; Dim $VerStr; Dim (Pad ($BoxW - 13 - $VerStr.Length)); Dim $VL; Nl |
| 149 | +Dim " $VL$(Pad $BoxW)$VL"; Nl |
| 150 | +Dim " $BL$(Rp $H $BoxW)$BR"; Nl |
| 151 | +Nl |
| 152 | + |
| 153 | +# ── Next steps ── |
| 154 | +Write-Host " Next steps" -ForegroundColor White |
| 155 | +Nl |
| 156 | +Acc " 1."; W " Login to your LLM provider"; Nl |
| 157 | +Nl |
| 158 | +Acc " `$ openanalyst login"; Nl |
| 159 | +Nl |
| 160 | +Dim " Select a provider, use the free model" |
| 161 | +Nl |
| 162 | +Dim " or paste your API key." |
| 163 | +Nl; Nl |
| 164 | +Acc " 2."; W " Start coding"; Nl |
| 165 | +Nl |
| 166 | +Acc " `$ openanalyst"; Nl |
| 167 | +Nl; Nl |
| 168 | + |
| 169 | +# ── Provider list ── |
| 170 | +Dim " $TL$(Rp $H $BoxW)$TR"; Nl |
| 171 | +Dim " $VL$(Pad $BoxW)$VL"; Nl |
| 172 | +Dim " $VL"; W " 7 LLM Providers. One Interface."; Dim (Pad ($BoxW - 34)); Dim $VL; Nl |
| 173 | +Dim " $VL$(Pad $BoxW)$VL"; Nl |
| 174 | + |
| 175 | +$providers = @( |
| 176 | + @{ n="OpenAnalyst"; d="(default)" }, |
| 177 | + @{ n="Anthropic / Claude"; d="direct API" }, |
| 178 | + @{ n="OpenAI / Codex"; d="direct API" }, |
| 179 | + @{ n="Google Gemini"; d="direct API" }, |
| 180 | + @{ n="xAI / Grok"; d="" }, |
| 181 | + @{ n="OpenRouter"; d="350+ models" }, |
| 182 | + @{ n="Amazon Bedrock"; d="" } |
| 183 | +) |
| 184 | +foreach ($p in $providers) { |
| 185 | + $name = $p.n |
| 186 | + $desc = $p.d |
| 187 | + Dim " $VL" |
| 188 | + Acc " $([char]0x25A0)" |
| 189 | + W " $name" |
| 190 | + if ($desc) { |
| 191 | + $used = 4 + $name.Length + 3 + $desc.Length |
| 192 | + Dim (Pad ($BoxW - $used)) |
| 193 | + Dim $desc |
| 194 | + } else { |
| 195 | + Dim (Pad ($BoxW - 4 - $name.Length)) |
| 196 | + } |
| 197 | + Dim $VL; Nl |
| 198 | +} |
| 199 | +Dim " $VL$(Pad $BoxW)$VL"; Nl |
| 200 | +Dim " $BL$(Rp $H $BoxW)$BR"; Nl |
| 201 | +Nl |
| 202 | + |
| 203 | +Dim " Documentation: " |
| 204 | +Acc "github.com/OpenAnalystInc/cli" |
| 205 | +Nl |
| 206 | +Dim " Support: " |
| 207 | +Acc "anit@openanalyst.com" |
| 208 | +Nl; Nl |
0 commit comments