# Okibi installer for Windows (PowerShell). # # irm https://okibi.ai/install.ps1 | iex # # Installs the public okibi thin client (okibi.exe + okibi-tui.exe). Public # release host, no auth. Detects the release, downloads + SHA-256 verifies # the zip, extracts under %LOCALAPPDATA%\okibi, and puts okibi on your PATH. # Re-run to upgrade to whatever latest.json now points at. # # Env overrides: OKIBI_RELEASE_BASE, OKIBI_INSTALL_ROOT, OKIBI_BIN_DIR. # # The public /install.ps1 route serves this source verbatim. The release base # is baked to prod; override with $env:OKIBI_RELEASE_BASE for staging. & { $ErrorActionPreference = 'Stop' $ReleaseBase = if ($env:OKIBI_RELEASE_BASE) { $env:OKIBI_RELEASE_BASE } else { 'https://releases.okibi.ai' } $InstallRoot = if ($env:OKIBI_INSTALL_ROOT) { $env:OKIBI_INSTALL_ROOT } else { Join-Path $env:LOCALAPPDATA 'okibi' } $BinDir = if ($env:OKIBI_BIN_DIR) { $env:OKIBI_BIN_DIR } else { Join-Path $InstallRoot 'bin' } function Info($m) { Write-Host "install: $m" } function Fail($m) { throw "install: $m" } # Only a windows-x64 build is published; it runs on ARM64 Windows via # emulation, so request it regardless of host arch. $platform = 'windows-x64' Info "platform: $platform" Info "fetching $ReleaseBase/latest.json" try { $manifest = Invoke-RestMethod -Uri "$ReleaseBase/latest.json" -UseBasicParsing } catch { Fail "could not reach the release host at $ReleaseBase" } $version = $manifest.version if (-not $version) { Fail 'latest.json is missing a version field' } # The version becomes a path segment that is Remove-Item -Recurse -Force'd # below, so a hostile or corrupt manifest must not be able to smuggle in # path separators or "..". if ($version -notmatch '^[A-Za-z0-9._+-]+$' -or $version -match '\.\.') { Fail "latest.json has an unsafe version string: $version" } $artifact = $manifest.artifacts | Where-Object { $_.platform -eq $platform } | Select-Object -First 1 if (-not $artifact) { Fail "no okibi build published for $platform yet" } $url = $artifact.url if ($url -notmatch '^https?://') { $url = "$ReleaseBase/$url" } $tmp = New-Item -ItemType Directory -Path (Join-Path $env:TEMP ('okibi-' + [guid]::NewGuid())) try { $zip = Join-Path $tmp 'okibi.zip' Info "downloading okibi $version" Invoke-WebRequest -Uri $url -OutFile $zip -UseBasicParsing $actual = (Get-FileHash -Algorithm SHA256 -Path $zip).Hash.ToLower() if ($actual -ne $artifact.sha256.ToLower()) { Fail "checksum mismatch: expected $($artifact.sha256), got $actual" } Info 'checksum verified' $verDir = Join-Path (Join-Path $InstallRoot 'versions') $version if (Test-Path $verDir) { Remove-Item -Recurse -Force $verDir } New-Item -ItemType Directory -Path $verDir | Out-Null Expand-Archive -Path $zip -DestinationPath $tmp -Force # The archive wraps everything in okibi-client--windows-x64\; lift its # contents into the version dir. $inner = Get-ChildItem $tmp -Directory | Select-Object -First 1 Copy-Item -Path (Join-Path $inner.FullName '*') -Destination $verDir -Recurse -Force if (-not (Test-Path (Join-Path $verDir 'okibi.exe'))) { Fail 'archive did not contain okibi.exe' } Info "installed to $verDir" # Windows symlinks need admin, so copy the current version's exes into the # stable bin dir on PATH (re-running the installer overwrites = upgrade). New-Item -ItemType Directory -Path $BinDir -Force | Out-Null Copy-Item -Path (Join-Path $verDir 'okibi.exe') -Destination (Join-Path $BinDir 'okibi.exe') -Force if (Test-Path (Join-Path $verDir 'okibi-tui.exe')) { Copy-Item -Path (Join-Path $verDir 'okibi-tui.exe') -Destination (Join-Path $BinDir 'okibi-tui.exe') -Force } $userPath = [Environment]::GetEnvironmentVariable('Path', 'User') if ($userPath -notlike "*$BinDir*") { [Environment]::SetEnvironmentVariable('Path', "$userPath;$BinDir", 'User') Info "added $BinDir to your user PATH (restart your shell to pick it up)" } $cfg = Join-Path $env:USERPROFILE '.okibi' New-Item -ItemType Directory -Path $cfg -Force | Out-Null Set-Content -Path (Join-Path $cfg 'installed-from') -Value $ReleaseBase -NoNewline Info "done - installed okibi $version. Get started with: okibi login" } finally { Remove-Item -Recurse -Force $tmp } }