Skip to content

Commit a594cc2

Browse files
committed
Add Windows install script
1 parent 60d533f commit a594cc2

File tree

2 files changed

+194
-1
lines changed

2 files changed

+194
-1
lines changed

.github/workflows/rust-release.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,9 +488,10 @@ jobs:
488488
--package codex-responses-api-proxy \
489489
--package codex-sdk
490490
491-
- name: Stage macOS and Linux installer script
491+
- name: Stage installer scripts
492492
run: |
493493
cp scripts/install/install.sh dist/install.sh
494+
cp scripts/install/install.ps1 dist/install.ps1
494495
495496
- name: Create GitHub Release
496497
uses: softprops/action-gh-release@v2

scripts/install/install.ps1

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
param(
2+
[Parameter(Position=0)]
3+
[string]$Version = "latest"
4+
)
5+
6+
Set-StrictMode -Version Latest
7+
$ErrorActionPreference = "Stop"
8+
$ProgressPreference = "SilentlyContinue"
9+
10+
function Write-Step {
11+
param(
12+
[string]$Message
13+
)
14+
15+
Write-Host "==> $Message"
16+
}
17+
18+
function Normalize-Version {
19+
param(
20+
[string]$RawVersion
21+
)
22+
23+
if ([string]::IsNullOrWhiteSpace($RawVersion) -or $RawVersion -eq "latest") {
24+
return "latest"
25+
}
26+
27+
if ($RawVersion.StartsWith("rust-v")) {
28+
return $RawVersion.Substring(6)
29+
}
30+
31+
if ($RawVersion.StartsWith("v")) {
32+
return $RawVersion.Substring(1)
33+
}
34+
35+
return $RawVersion
36+
}
37+
38+
function Get-ReleaseUrl {
39+
param(
40+
[string]$AssetName,
41+
[string]$ResolvedVersion
42+
)
43+
44+
return "https://github.com/openai/codex/releases/download/rust-v$ResolvedVersion/$AssetName"
45+
}
46+
47+
function Path-Contains {
48+
param(
49+
[string]$PathValue,
50+
[string]$Entry
51+
)
52+
53+
if ([string]::IsNullOrWhiteSpace($PathValue)) {
54+
return $false
55+
}
56+
57+
$needle = $Entry.TrimEnd("\")
58+
foreach ($segment in $PathValue.Split(";", [System.StringSplitOptions]::RemoveEmptyEntries)) {
59+
if ($segment.TrimEnd("\") -ieq $needle) {
60+
return $true
61+
}
62+
}
63+
64+
return $false
65+
}
66+
67+
function Resolve-Version {
68+
$normalizedVersion = Normalize-Version -RawVersion $Version
69+
if ($normalizedVersion -ne "latest") {
70+
return $normalizedVersion
71+
}
72+
73+
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/openai/codex/releases/latest"
74+
if (-not $release.tag_name) {
75+
Write-Error "Failed to resolve the latest Codex release version."
76+
exit 1
77+
}
78+
79+
return (Normalize-Version -RawVersion $release.tag_name)
80+
}
81+
82+
if ($env:OS -ne "Windows_NT") {
83+
Write-Error "install.ps1 supports Windows only. Use install.sh on macOS or Linux."
84+
exit 1
85+
}
86+
87+
if (-not [Environment]::Is64BitOperatingSystem) {
88+
Write-Error "Codex requires a 64-bit version of Windows."
89+
exit 1
90+
}
91+
92+
$architecture = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture
93+
$target = $null
94+
$platformLabel = $null
95+
$npmTag = $null
96+
switch ($architecture) {
97+
"Arm64" {
98+
$target = "aarch64-pc-windows-msvc"
99+
$platformLabel = "Windows (ARM64)"
100+
$npmTag = "win32-arm64"
101+
}
102+
"X64" {
103+
$target = "x86_64-pc-windows-msvc"
104+
$platformLabel = "Windows (x64)"
105+
$npmTag = "win32-x64"
106+
}
107+
default {
108+
Write-Error "Unsupported architecture: $architecture"
109+
exit 1
110+
}
111+
}
112+
113+
if ([string]::IsNullOrWhiteSpace($env:CODEX_INSTALL_DIR)) {
114+
$installDir = Join-Path $env:LOCALAPPDATA "Programs\OpenAI\Codex\bin"
115+
} else {
116+
$installDir = $env:CODEX_INSTALL_DIR
117+
}
118+
119+
$codexPath = Join-Path $installDir "codex.exe"
120+
$installMode = if (Test-Path $codexPath) { "Updating" } else { "Installing" }
121+
122+
Write-Step "$installMode Codex CLI"
123+
Write-Step "Detected platform: $platformLabel"
124+
125+
New-Item -ItemType Directory -Force -Path $installDir | Out-Null
126+
127+
$resolvedVersion = Resolve-Version
128+
Write-Step "Resolved version: $resolvedVersion"
129+
$packageAsset = "codex-npm-$npmTag-$resolvedVersion.tgz"
130+
131+
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) ("codex-install-" + [System.Guid]::NewGuid().ToString("N"))
132+
New-Item -ItemType Directory -Force -Path $tempDir | Out-Null
133+
134+
try {
135+
$archivePath = Join-Path $tempDir $packageAsset
136+
$extractDir = Join-Path $tempDir "extract"
137+
$url = Get-ReleaseUrl -AssetName $packageAsset -ResolvedVersion $resolvedVersion
138+
139+
Write-Step "Downloading Codex CLI"
140+
Invoke-WebRequest -Uri $url -OutFile $archivePath
141+
142+
New-Item -ItemType Directory -Force -Path $extractDir | Out-Null
143+
tar -xzf $archivePath -C $extractDir
144+
145+
$vendorRoot = Join-Path $extractDir "package/vendor/$target"
146+
Write-Step "Installing to $installDir"
147+
$copyMap = @{
148+
"codex/codex.exe" = "codex.exe"
149+
"codex/codex-command-runner.exe" = "codex-command-runner.exe"
150+
"codex/codex-windows-sandbox-setup.exe" = "codex-windows-sandbox-setup.exe"
151+
"path/rg.exe" = "rg.exe"
152+
}
153+
154+
foreach ($relativeSource in $copyMap.Keys) {
155+
$sourcePath = Join-Path $vendorRoot $relativeSource
156+
$destinationPath = Join-Path $installDir $copyMap[$relativeSource]
157+
Move-Item -Force $sourcePath $destinationPath
158+
}
159+
} finally {
160+
Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue
161+
}
162+
163+
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
164+
$pathNeedsNewShell = $false
165+
if (-not (Path-Contains -PathValue $userPath -Entry $installDir)) {
166+
if ([string]::IsNullOrWhiteSpace($userPath)) {
167+
$newUserPath = $installDir
168+
} else {
169+
$newUserPath = "$userPath;$installDir"
170+
}
171+
172+
[Environment]::SetEnvironmentVariable("Path", $newUserPath, "User")
173+
if (-not (Path-Contains -PathValue $env:Path -Entry $installDir)) {
174+
$env:Path = "$env:Path;$installDir"
175+
}
176+
Write-Step "PATH updated for future PowerShell sessions."
177+
$pathNeedsNewShell = $true
178+
} elseif (Path-Contains -PathValue $env:Path -Entry $installDir) {
179+
Write-Step "$installDir is already on PATH."
180+
} else {
181+
Write-Step "PATH is already configured for future PowerShell sessions."
182+
$pathNeedsNewShell = $true
183+
}
184+
185+
if ($pathNeedsNewShell) {
186+
Write-Step ('Run now: $env:Path = "{0};$env:Path"; codex' -f $installDir)
187+
Write-Step "Or open a new PowerShell window and run: codex"
188+
} else {
189+
Write-Step "Run: codex"
190+
}
191+
192+
Write-Host "Codex CLI $resolvedVersion installed successfully."

0 commit comments

Comments
 (0)