$ErrorActionPreference = 'Stop' Set-StrictMode -Version Latest $Channel = 'stable' $DownloadUrl = if ($env:WARP_TUI_DOWNLOAD_URL) { $env:WARP_TUI_DOWNLOAD_URL } else { 'https://app.warp.dev/download/agent-cli/artifact' } $LocalAppData = [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::LocalApplicationData) if (-not $LocalAppData) { throw 'Could not determine the current user local application data directory' } $WarpDataDir = Join-Path $LocalAppData 'Warp' $DefaultInstallDir = Join-Path $WarpDataDir 'tui' $InstallDir = if ($env:WARP_TUI_INSTALL_DIR) { $env:WARP_TUI_INSTALL_DIR } else { $DefaultInstallDir } $BinDir = if ($env:WARP_TUI_BIN_DIR) { $env:WARP_TUI_BIN_DIR } else { Join-Path $WarpDataDir 'bin' } $SkipPathUpdate = [bool] $env:WARP_TUI_SKIP_PATH_UPDATE function Get-TuiArchitecture { $architecture = if ($env:PROCESSOR_ARCHITEW6432) { $env:PROCESSOR_ARCHITEW6432 } else { $env:PROCESSOR_ARCHITECTURE } if (-not $architecture) { $architecture = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString() } switch ($architecture) { 'AMD64' { return 'x86_64' } 'X64' { return 'x86_64' } 'ARM64' { return 'aarch64' } default { throw "Unsupported Windows architecture: $architecture" } } } function Resolve-TuiArtifactUrl { param([string] $Url) Add-Type -AssemblyName System.Net.Http $handler = [System.Net.Http.HttpClientHandler]::new() $handler.AllowAutoRedirect = $false $client = [System.Net.Http.HttpClient]::new($handler) try { $response = $client.GetAsync($Url).GetAwaiter().GetResult() try { if ( [int] $response.StatusCode -lt 300 -or [int] $response.StatusCode -ge 400 -or -not $response.Headers.Location ) { throw "Artifact endpoint returned HTTP $([int] $response.StatusCode) without a redirect" } return [System.Uri]::new([System.Uri] $Url, $response.Headers.Location) } finally { $response.Dispose() } } finally { $client.Dispose() $handler.Dispose() } } function Assert-ValidSignature { param([string] $Path) $signature = Get-AuthenticodeSignature -LiteralPath $Path if ("$($signature.Status)" -ne 'Valid') { throw "Installer does not have a valid Authenticode signature: $Path ($($signature.Status))" } $signer = $signature.SignerCertificate.GetNameInfo( [System.Security.Cryptography.X509Certificates.X509NameType]::SimpleName, $false ) if ($signer -cne 'Denver Technologies, Inc. dba Warp') { throw "Installer has an unexpected Authenticode signer: $Path ($signer)" } } $architecture = Get-TuiArchitecture $url = "${DownloadUrl}?os=windows&arch=$architecture" if ($env:WARP_TUI_VERSION) { $url += "&version=$($env:WARP_TUI_VERSION)" } $artifactUrl = Resolve-TuiArtifactUrl $url $installerPath = Join-Path ( [System.IO.Path]::GetTempPath() ) "warp-agent-cli-$([System.Guid]::NewGuid().ToString('N')).exe" $installerExitCode = 0 try { Write-Output "Downloading the Warp Agent CLI installer ($Channel, windows/$architecture)..." Invoke-WebRequest -UseBasicParsing -Uri $artifactUrl -OutFile $installerPath Assert-ValidSignature $installerPath $arguments = @( '/SP-', '/VERYSILENT', '/SUPPRESSMSGBOXES', '/NOCANCEL', '/NORESTART', '/CURRENTUSER', "/DIR=`"$InstallDir`"", "/WARP_BIN_DIR=`"$BinDir`"" ) if ($SkipPathUpdate) { $arguments += '/SKIP_PATH_UPDATE=1' } $installer = Start-Process -FilePath $installerPath ` -ArgumentList $arguments -Wait -PassThru $installerExitCode = $installer.ExitCode } finally { if (Test-Path -LiteralPath $installerPath) { Remove-Item -LiteralPath $installerPath -Force } } if ($installerExitCode -ne 0) { [Console]::Error.WriteLine("Warp Agent CLI installer exited with code $installerExitCode") exit $installerExitCode } Write-Output '' Write-Output 'Warp Agent CLI installed successfully.' Write-Output 'Open a new terminal and run: warp' if ($SkipPathUpdate) { Write-Output 'PATH was not changed because WARP_TUI_SKIP_PATH_UPDATE is set.' }