Compare commits

...

5 Commits

Author SHA1 Message Date
Edward Frazer
f26a3c8e74 fix: clarify Windows direct installer status 2026-02-25 16:43:21 -08:00
Edward Frazer
68ec43d213 fix: scope direct install docs to macOS and Linux 2026-02-25 16:41:52 -08:00
Edward Frazer
5dabc52e73 Document direct install commands 2026-02-25 09:35:25 -08:00
Edward Frazer
02525c193a Add Windows install script 2026-02-25 09:35:25 -08:00
Edward Frazer
0f570e20d5 Add macOS and Linux install script 2026-02-25 09:35:25 -08:00
5 changed files with 464 additions and 2 deletions

View File

@@ -494,6 +494,11 @@ jobs:
--package codex-responses-api-proxy \
--package codex-sdk
- name: Stage installer scripts
run: |
cp scripts/install/install.sh dist/install.sh
cp scripts/install/install.ps1 dist/install.ps1
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:

View File

@@ -1,4 +1,4 @@
<p align="center"><code>npm i -g @openai/codex</code><br />or <code>brew install --cask codex</code></p>
<p align="center"><code>curl -fsSL https://chatgpt.com/codex/install.sh | sh</code><br />or <code>npm i -g @openai/codex</code><br />or <code>brew install --cask codex</code></p>
<p align="center"><strong>Codex CLI</strong> is a coding agent from OpenAI that runs locally on your computer.
<p align="center">
<img src="https://github.com/openai/codex/blob/main/.github/codex-cli-splash.png" alt="Codex CLI splash" width="80%" />
@@ -14,7 +14,16 @@ If you want Codex in your code editor (VS Code, Cursor, Windsurf), <a href="http
### Installing and running Codex CLI
Install globally with your preferred package manager:
Install the latest Codex release directly on macOS or Linux:
```shell
# Install on macOS or Linux
curl -fsSL https://chatgpt.com/codex/install.sh | sh
```
Windows direct installer support is coming soon. Until then, run Codex on Windows 11 via WSL2.
You can also install with your preferred package manager:
```shell
# Install using npm

View File

@@ -8,6 +8,18 @@
| Git (optional, recommended) | 2.23+ for built-in PR helpers |
| RAM | 4-GB minimum (8-GB recommended) |
### Install the latest release on macOS or Linux
```bash
# macOS or Linux
curl -fsSL https://chatgpt.com/codex/install.sh | sh
```
Windows direct installer support is coming soon. Until then, run Codex on Windows 11 via WSL2.
The direct installer downloads the latest matching GitHub Release package for macOS or Linux and
places both `codex` and `rg` in a user-local directory.
### DotSlash
The GitHub Release also contains a [DotSlash](https://dotslash-cli.com/) file for the Codex CLI named `codex`. Using a DotSlash file makes it possible to make a lightweight commit to source control to ensure all contributors use the same version of an executable, regardless of what platform they use for development.

192
scripts/install/install.ps1 Normal file
View File

@@ -0,0 +1,192 @@
param(
[Parameter(Position=0)]
[string]$Version = "latest"
)
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
function Write-Step {
param(
[string]$Message
)
Write-Host "==> $Message"
}
function Normalize-Version {
param(
[string]$RawVersion
)
if ([string]::IsNullOrWhiteSpace($RawVersion) -or $RawVersion -eq "latest") {
return "latest"
}
if ($RawVersion.StartsWith("rust-v")) {
return $RawVersion.Substring(6)
}
if ($RawVersion.StartsWith("v")) {
return $RawVersion.Substring(1)
}
return $RawVersion
}
function Get-ReleaseUrl {
param(
[string]$AssetName,
[string]$ResolvedVersion
)
return "https://github.com/openai/codex/releases/download/rust-v$ResolvedVersion/$AssetName"
}
function Path-Contains {
param(
[string]$PathValue,
[string]$Entry
)
if ([string]::IsNullOrWhiteSpace($PathValue)) {
return $false
}
$needle = $Entry.TrimEnd("\")
foreach ($segment in $PathValue.Split(";", [System.StringSplitOptions]::RemoveEmptyEntries)) {
if ($segment.TrimEnd("\") -ieq $needle) {
return $true
}
}
return $false
}
function Resolve-Version {
$normalizedVersion = Normalize-Version -RawVersion $Version
if ($normalizedVersion -ne "latest") {
return $normalizedVersion
}
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/openai/codex/releases/latest"
if (-not $release.tag_name) {
Write-Error "Failed to resolve the latest Codex release version."
exit 1
}
return (Normalize-Version -RawVersion $release.tag_name)
}
if ($env:OS -ne "Windows_NT") {
Write-Error "install.ps1 supports Windows only. Use install.sh on macOS or Linux."
exit 1
}
if (-not [Environment]::Is64BitOperatingSystem) {
Write-Error "Codex requires a 64-bit version of Windows."
exit 1
}
$architecture = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture
$target = $null
$platformLabel = $null
$npmTag = $null
switch ($architecture) {
"Arm64" {
$target = "aarch64-pc-windows-msvc"
$platformLabel = "Windows (ARM64)"
$npmTag = "win32-arm64"
}
"X64" {
$target = "x86_64-pc-windows-msvc"
$platformLabel = "Windows (x64)"
$npmTag = "win32-x64"
}
default {
Write-Error "Unsupported architecture: $architecture"
exit 1
}
}
if ([string]::IsNullOrWhiteSpace($env:CODEX_INSTALL_DIR)) {
$installDir = Join-Path $env:LOCALAPPDATA "Programs\OpenAI\Codex\bin"
} else {
$installDir = $env:CODEX_INSTALL_DIR
}
$codexPath = Join-Path $installDir "codex.exe"
$installMode = if (Test-Path $codexPath) { "Updating" } else { "Installing" }
Write-Step "$installMode Codex CLI"
Write-Step "Detected platform: $platformLabel"
New-Item -ItemType Directory -Force -Path $installDir | Out-Null
$resolvedVersion = Resolve-Version
Write-Step "Resolved version: $resolvedVersion"
$packageAsset = "codex-npm-$npmTag-$resolvedVersion.tgz"
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) ("codex-install-" + [System.Guid]::NewGuid().ToString("N"))
New-Item -ItemType Directory -Force -Path $tempDir | Out-Null
try {
$archivePath = Join-Path $tempDir $packageAsset
$extractDir = Join-Path $tempDir "extract"
$url = Get-ReleaseUrl -AssetName $packageAsset -ResolvedVersion $resolvedVersion
Write-Step "Downloading Codex CLI"
Invoke-WebRequest -Uri $url -OutFile $archivePath
New-Item -ItemType Directory -Force -Path $extractDir | Out-Null
tar -xzf $archivePath -C $extractDir
$vendorRoot = Join-Path $extractDir "package/vendor/$target"
Write-Step "Installing to $installDir"
$copyMap = @{
"codex/codex.exe" = "codex.exe"
"codex/codex-command-runner.exe" = "codex-command-runner.exe"
"codex/codex-windows-sandbox-setup.exe" = "codex-windows-sandbox-setup.exe"
"path/rg.exe" = "rg.exe"
}
foreach ($relativeSource in $copyMap.Keys) {
$sourcePath = Join-Path $vendorRoot $relativeSource
$destinationPath = Join-Path $installDir $copyMap[$relativeSource]
Move-Item -Force $sourcePath $destinationPath
}
} finally {
Remove-Item -Recurse -Force $tempDir -ErrorAction SilentlyContinue
}
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
$pathNeedsNewShell = $false
if (-not (Path-Contains -PathValue $userPath -Entry $installDir)) {
if ([string]::IsNullOrWhiteSpace($userPath)) {
$newUserPath = $installDir
} else {
$newUserPath = "$userPath;$installDir"
}
[Environment]::SetEnvironmentVariable("Path", $newUserPath, "User")
if (-not (Path-Contains -PathValue $env:Path -Entry $installDir)) {
$env:Path = "$env:Path;$installDir"
}
Write-Step "PATH updated for future PowerShell sessions."
$pathNeedsNewShell = $true
} elseif (Path-Contains -PathValue $env:Path -Entry $installDir) {
Write-Step "$installDir is already on PATH."
} else {
Write-Step "PATH is already configured for future PowerShell sessions."
$pathNeedsNewShell = $true
}
if ($pathNeedsNewShell) {
Write-Step ('Run now: $env:Path = "{0};$env:Path"; codex' -f $installDir)
Write-Step "Or open a new PowerShell window and run: codex"
} else {
Write-Step "Run: codex"
}
Write-Host "Codex CLI $resolvedVersion installed successfully."

244
scripts/install/install.sh Executable file
View File

@@ -0,0 +1,244 @@
#!/bin/sh
set -eu
VERSION="${1:-latest}"
INSTALL_DIR="${CODEX_INSTALL_DIR:-$HOME/.local/bin}"
path_action="already"
path_profile=""
step() {
printf '==> %s\n' "$1"
}
normalize_version() {
case "$1" in
"" | latest)
printf 'latest\n'
;;
rust-v*)
printf '%s\n' "${1#rust-v}"
;;
v*)
printf '%s\n' "${1#v}"
;;
*)
printf '%s\n' "$1"
;;
esac
}
download_file() {
url="$1"
output="$2"
if command -v curl >/dev/null 2>&1; then
curl -fsSL "$url" -o "$output"
return
fi
if command -v wget >/dev/null 2>&1; then
wget -q -O "$output" "$url"
return
fi
echo "curl or wget is required to install Codex." >&2
exit 1
}
download_text() {
url="$1"
if command -v curl >/dev/null 2>&1; then
curl -fsSL "$url"
return
fi
if command -v wget >/dev/null 2>&1; then
wget -q -O - "$url"
return
fi
echo "curl or wget is required to install Codex." >&2
exit 1
}
add_to_path() {
path_action="already"
path_profile=""
case ":$PATH:" in
*":$INSTALL_DIR:"*)
return
;;
esac
profile="$HOME/.profile"
case "${SHELL:-}" in
*/zsh)
profile="$HOME/.zshrc"
;;
*/bash)
profile="$HOME/.bashrc"
;;
esac
path_profile="$profile"
path_line="export PATH=\"$INSTALL_DIR:\$PATH\""
if [ -f "$profile" ] && grep -F "$path_line" "$profile" >/dev/null 2>&1; then
path_action="configured"
return
fi
{
printf '\n# Added by Codex installer\n'
printf '%s\n' "$path_line"
} >>"$profile"
path_action="added"
}
release_url_for_asset() {
asset="$1"
resolved_version="$2"
printf 'https://github.com/openai/codex/releases/download/rust-v%s/%s\n' "$resolved_version" "$asset"
}
require_command() {
if ! command -v "$1" >/dev/null 2>&1; then
echo "$1 is required to install Codex." >&2
exit 1
fi
}
require_command mktemp
require_command tar
resolve_version() {
normalized_version="$(normalize_version "$VERSION")"
if [ "$normalized_version" != "latest" ]; then
printf '%s\n' "$normalized_version"
return
fi
release_json="$(download_text "https://api.github.com/repos/openai/codex/releases/latest")"
resolved="$(printf '%s\n' "$release_json" | sed -n 's/.*"tag_name":[[:space:]]*"rust-v\([^"]*\)".*/\1/p' | head -n 1)"
if [ -z "$resolved" ]; then
echo "Failed to resolve the latest Codex release version." >&2
exit 1
fi
printf '%s\n' "$resolved"
}
case "$(uname -s)" in
Darwin)
os="darwin"
;;
Linux)
os="linux"
;;
*)
echo "install.sh supports macOS and Linux. Use install.ps1 on Windows." >&2
exit 1
;;
esac
case "$(uname -m)" in
x86_64 | amd64)
arch="x86_64"
;;
arm64 | aarch64)
arch="aarch64"
;;
*)
echo "Unsupported architecture: $(uname -m)" >&2
exit 1
;;
esac
if [ "$os" = "darwin" ] && [ "$arch" = "x86_64" ]; then
if [ "$(sysctl -n sysctl.proc_translated 2>/dev/null || true)" = "1" ]; then
arch="aarch64"
fi
fi
if [ "$os" = "darwin" ]; then
if [ "$arch" = "aarch64" ]; then
npm_tag="darwin-arm64"
vendor_target="aarch64-apple-darwin"
platform_label="macOS (Apple Silicon)"
else
npm_tag="darwin-x64"
vendor_target="x86_64-apple-darwin"
platform_label="macOS (Intel)"
fi
else
if [ "$arch" = "aarch64" ]; then
npm_tag="linux-arm64"
vendor_target="aarch64-unknown-linux-musl"
platform_label="Linux (ARM64)"
else
npm_tag="linux-x64"
vendor_target="x86_64-unknown-linux-musl"
platform_label="Linux (x64)"
fi
fi
if [ -x "$INSTALL_DIR/codex" ]; then
install_mode="Updating"
else
install_mode="Installing"
fi
step "$install_mode Codex CLI"
step "Detected platform: $platform_label"
resolved_version="$(resolve_version)"
asset="codex-npm-$npm_tag-$resolved_version.tgz"
download_url="$(release_url_for_asset "$asset" "$resolved_version")"
step "Resolved version: $resolved_version"
tmp_dir="$(mktemp -d)"
cleanup() {
rm -rf "$tmp_dir"
}
trap cleanup EXIT INT TERM
archive_path="$tmp_dir/$asset"
step "Downloading Codex CLI"
download_file "$download_url" "$archive_path"
tar -xzf "$archive_path" -C "$tmp_dir"
step "Installing to $INSTALL_DIR"
mkdir -p "$INSTALL_DIR"
cp "$tmp_dir/package/vendor/$vendor_target/codex/codex" "$INSTALL_DIR/codex"
cp "$tmp_dir/package/vendor/$vendor_target/path/rg" "$INSTALL_DIR/rg"
chmod 0755 "$INSTALL_DIR/codex"
chmod 0755 "$INSTALL_DIR/rg"
add_to_path
case "$path_action" in
added)
step "PATH updated for future shells in $path_profile"
step "Run now: export PATH=\"$INSTALL_DIR:\$PATH\" && codex"
step "Or open a new terminal and run: codex"
;;
configured)
step "PATH is already configured for future shells in $path_profile"
step "Run now: export PATH=\"$INSTALL_DIR:\$PATH\" && codex"
step "Or open a new terminal and run: codex"
;;
*)
step "$INSTALL_DIR is already on PATH"
step "Run: codex"
;;
esac
printf 'Codex CLI %s installed successfully.\n' "$resolved_version"