14 Commits

Author SHA1 Message Date
zsol-openai
39a2438d16 Prefer releases.openai.com in standalone installers (#34910)
## What changed

- Make the shell and PowerShell installers download release metadata and assets from `releases.openai.com` by default, with bounded request timeouts.
- Fall back to GitHub Releases when metadata is unusable, required assets are missing, or downloaded assets fail checksum or manifest validation.
- Document `CODEX_INSTALLER_USE_RELEASES_OPENAI_COM=false` for opting out of the default release source.

## Testing

- Cover default-source installation, malformed and incomplete metadata, version mismatches, corrupt assets, invalid checksums, incomplete manifests, and GitHub fallback failures in the shell installer tests.

GitOrigin-RevId: 1c65d527ca79761358c3a4cd7a5fd675e1ef75b2
2026-07-23 09:21:31 +00:00
zsol-openai
765675a122 Add an optional releases.openai.com installer source (#34514)
## What changed

- Let the shell and PowerShell installers resolve metadata and download assets from `releases.openai.com` when `CODEX_INSTALLER_USE_RELEASES_OPENAI_COM` is enabled.
- Fall back to GitHub Releases when metadata or asset downloads from the alternate source are unavailable.
- Verify that an installed or cached Codex binary reports the resolved version before activating it.

## Testing

- Cover latest-release installation, asset fallback, mismatched binary versions, and reuse of a cached legacy package in the shell installer tests.

GitOrigin-RevId: 48c57d3377fbc6b0903570c665041bb465ca6f4c
2026-07-21 10:38:44 +00:00
Michael Bolin
9970cd706f Support alpha hotfix release versions (#34463)
## What changed

- Map Python `aN.postM` versions to Codex `-alpha.N.M` release tags through shared release-version helpers.
- Accept alpha hotfix versions in Python runtime workflows, Rust release validation, npm publishing, and the shell and PowerShell installers.

## Testing

- Cover version conversion, workflow output, runtime setup, artifact staging, and installer handling for alpha hotfix releases.

GitOrigin-RevId: b95edb56f7c93b435a8050c10f0202dc117e6669
2026-07-21 03:59:38 +00:00
Channing Conger
22781d4001 code-mode: fix installation on darwin (#31876)
Installer needs to symlink code-mode-host next to codex on install.
2026-07-09 13:11:28 -07:00
efrazer-oai
dc23c7bcc8 fix: parse compact release metadata in installer (#31667)
# Summary

GitHub's latest-release endpoint can return compact, single-line JSON.
The standalone installer treated release metadata as line-oriented text,
so those responses could make asset lookup fail even though the
requested assets were present.

The regression was introduced by
[#31056](https://github.com/openai/codex/pull/31056). That change reused
the `/releases/latest` metadata response for both version resolution and
asset lookup, exposing the existing formatting-sensitive asset parser to
compact responses from that endpoint.

This change parses the release metadata once with a one-pass POSIX awk
scanner. The scanner tracks JSON strings and nesting, extracts the root
release tag plus direct asset name/digest pairs, and produces the same
result regardless of whitespace or object field order. It uses POSIX
`fold` to bound awk record sizes so compact responses stay fast across
awk implementations.

Fixes #31520.

## Changes

- replace line-oriented release metadata matching with structure-aware
parsing
- reuse the parsed metadata for latest-version and asset-digest lookup
- add regression coverage for compact JSON, reordered fields, nested
decoys, and JSON-looking release text

## Design decisions

- Keep the installer dependency-free by using standard POSIX tools
already required by the shell installer.
- Parse only the GitHub release fields the installer consumes, in one
pass, instead of vendoring a general JSON library.
- Preserve asset-object boundaries so nested or string-encoded `name`
and `digest` fields cannot be mistaken for release assets.

## Testing

- Tests: focused installer suite locally and on Linux.
- Smoke tests: real pretty and compact GitHub release metadata,
latest-release resolution, and checksum-asset selection.
- Portability: macOS awk plus Linux gawk, mawk, and nawk.
- Stress coverage: randomized formatting and field order, adversarial
nested/string content, and a synthetic 2,000-asset compact response.
2026-07-08 22:08:00 -07:00
Channing Conger
3f61570044 [codex] bundle code mode host in release packages (#30202)
## Summary

- build, strip, sign, and publish `codex-code-mode-host` with the
primary Codex release binaries on Linux, macOS, and Windows
- place the host beside `codex[.exe]` in canonical package archives,
macOS DMGs, and the legacy Linux bundle so the runtime's sibling lookup
succeeds
- preserve and validate the host through standalone installers and
Python runtime wheel staging
- add package-builder coverage for source selection and the resulting
package layout

## Why

The process-owned code-mode client launches `codex-code-mode-host` as a
sibling of the running Codex executable. Release artifacts currently
build and bundle `codex` without that host, so code mode cannot start
from installed packages.
2026-07-06 16:58:05 -07:00
Michael Bolin
319d03056e fix(install): reuse GitHub release metadata (#31056)
## Why

The standalone installers currently perform separate unauthenticated
GitHub REST API lookups while resolving the latest version, locating the
platform package, locating its checksum manifest, and retrieving asset
digests. A single install can therefore make up to four release-metadata
requests.

When GitHub's shared unauthenticated rate limit is exhausted, valid
releases fail to install. The shell installer also suppresses the
metadata request failure while probing assets, so a `403` is misreported
as though the release assets do not exist. This makes the failure both
more likely and harder to diagnose.

Fixes #28538.

## What changed

- Resolve the selected version and fetch its release metadata together.
- Reuse that one metadata response for package, checksum, and
legacy-package selection in both `install.sh` and `install.ps1`.
- Report metadata fetch failures as possible GitHub availability or
rate-limit failures instead of missing assets.
- Add a mocked-`curl` regression suite covering exact releases,
`latest`, and a simulated metadata `403`, and run it in `repo-checks`.

For `latest`, the metadata returned by `/releases/latest` now supplies
both the resolved version and the asset list. For an explicitly selected
version, the installer makes one request to that release's tag endpoint.

## Verification

- `python3 -m unittest discover -s scripts/install -p 'test_*.py' -v`
- `sh -n scripts/install/install.sh`
- Parsed `scripts/install/install.ps1` with the PowerShell language
parser.

## Scope

This change reduces GitHub API usage and preserves the underlying error,
but it does not move release artifacts away from GitHub's CDN.
2026-07-03 15:11:19 -07:00
Felipe Coury
f22d15b679 fix(install): support older awk checksum parsing (#28784)
## Why

The standalone installer validates package checksums with an awk
interval expression. Older mawk releases do not support that expression,
so they reject valid 64-character digests and report that the release
manifest is missing an entry. This affects both x64 and ARM64 systems on
common Debian-derived environments.

Fixes #24219.

## What Changed

Replace the awk interval expression with an explicit length check plus
rejection of non-hexadecimal characters. This preserves the existing
SHA-256 validation and lowercase normalization while working with older
awk implementations.

## How to Test

1. Build and run the checksum predicate with mawk 1.3.4 20121129.
2. Confirm the old interval predicate rejects a valid 64-character
digest.
3. Confirm the updated predicate accepts that digest.
4. Put the old mawk binary first on PATH as awk and run
scripts/install/install.sh with an isolated HOME, CODEX_HOME, and
CODEX_INSTALL_DIR.
5. Confirm Codex installs successfully and the installed binary reports
version 0.140.0.
6. Verify the predicate rejects wrong-length digests, non-hexadecimal
digests, and entries for another asset while accepting uppercase
hexadecimal digests.
2026-06-17 22:12:02 -04:00
efrazer-oai
8ed38fe38e fix: add noninteractive install script mode (#21567)
# Summary

The Codex standalone installers can pause after installation to ask
about an older managed install or launching Codex. That makes unattended
bootstrap and update flows hard to complete reliably.

This PR adds noninteractive installer control on macOS/Linux and Windows
through `CODEX_NON_INTERACTIVE=1`. Noninteractive operation is
environment-only, which gives automated callers one stable way to
suppress prompts. When a noninteractive install leaves an older npm,
bun, or brew-managed Codex installed, the standalone bin is configured
ahead of that command on `PATH` so the newly installed Codex is the one
future launches select. It also supports `CODEX_RELEASE` for callers
that select a release through environment variables while retaining the
existing explicit release inputs. Release selection accepts `latest`,
stable `x.y.z` versions, and Codex prereleases written as
`rust-v0.134.0-alpha.3`, `v0.134.0-alpha.3`, or `0.134.0-alpha.3`; it
validates that shape before constructing release requests.

# Stack

1. [#21567](https://github.com/openai/codex/pull/21567) - Adds release
and noninteractive environment controls to the installers. (current)
2. [#24637](https://github.com/openai/codex/pull/24637) - Runs
standalone updater installs with `CODEX_NON_INTERACTIVE=1`.
3. [#24639](https://github.com/openai/codex/pull/24639) - Removes
explicit release argument inputs in favor of `CODEX_RELEASE`.

# Evidence

| Before | After |
| --- | --- |
| ![Interactive install
prompts](https://github.com/user-attachments/assets/feecb45a-7087-4681-8775-ba57b07e97fa)
| ![Noninteractive install completes without
prompts](https://github.com/user-attachments/assets/53dcc791-383a-46e2-9a95-3b37b80ae053)
|

Environment-controlled macOS install with an existing npm-managed Codex
on `PATH`:


https://github.com/user-attachments/assets/442e0b5b-4a32-4bf5-996b-68784777380d

# Design decisions

Windows installs using the older standalone bin layout still require an
interactive migration confirmation. Noninteractive mode does not
auto-migrate that existing directory because replacing it is a
destructive transition for an early, limited-use layout; unattended
installs on that layout fail with an instruction to rerun interactively.

# Testing

Tests: installer syntax validation, release-selector acceptance and
rejection coverage including PowerShell `Latest` compatibility, macOS
live-terminal installer smoke testing with environment-controlled stable
and prerelease installation and competing PATH precedence, shell
rejection of the omitted noninteractive flag, and Windows ARM64
PowerShell smoke testing with environment-only noninteractive behavior,
retained release input, and competing PATH precedence through Parallels.
2026-05-26 22:09:54 -07:00
Michael Bolin
110b30d545 install: consume Codex package archives (#23636)
## Summary

Standalone installs should exercise the same canonical package archive
layout that release builds produce, rather than unpacking npm platform
packages and reconstructing a parallel install tree.

This updates `install.sh` and `install.ps1` to prefer
`codex-package-<target>.tar.gz` plus `codex-package_SHA256SUMS`
introduced in https://github.com/openai/codex/pull/23635, authenticate
the checksum manifest against GitHub release metadata, verify the
selected package archive against the authenticated manifest, and install
the package archive directly.

## Compatibility Notes

Package installs still leave a compatibility command at `current/codex`
for managed daemon flows, while visible command shims point at
`bin/codex` inside the package layout.

Recent releases that predate package archives still publish per-platform
npm artifacts, so both installers keep a legacy platform npm fallback
for those versions and verify those archives against release metadata
directly.

Releases old enough to publish only the single root
`codex-npm-<version>.tgz` archive are intentionally out of scope. The
installers fail clearly when neither package archives nor per-platform
npm archives are present.

On Windows, the runtime helper lookups now recognize package-layout
installs where `codex.exe` runs from `bin/`, so
`codex-command-runner.exe` and `codex-windows-sandbox-setup.exe` resolve
from the top-level `codex-resources/` directory. The direct-sibling and
older sibling-resource fallbacks are preserved.

## Test plan

- `sh -n scripts/install/install.sh`
- `bash -n scripts/install/install.sh`
- `pwsh -NoProfile -Command '$tokens=$null; $errors=$null; $null =
[System.Management.Automation.Language.Parser]::ParseFile("scripts/install/install.ps1",
[ref]$tokens, [ref]$errors); if ($errors.Count) { $errors | Format-List
*; exit 1 }'`
- `HOME="$home_dir" CODEX_HOME="$tmp_dir/codex-home"
CODEX_INSTALL_DIR="$bin_dir" PATH="$bin_dir:$PATH" sh
scripts/install/install.sh --release 0.125.0`
- Verified the 0.125.0 isolated install leaves the visible command
pointed at `current/codex` and includes the legacy `codex-resources/rg`
payload.
- `cargo test -p codex-windows-sandbox`
- `just fix -p codex-windows-sandbox`

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/23636).
* #23638
* #23637
* __->__ #23636
2026-05-20 11:20:11 -07:00
Michael Bolin
a736cb55a2 release/npm: bundle standalone bwrap on Linux (#21257) 2026-05-05 18:21:52 -07:00
efrazer-oai
9d1bf002c6 Significantly improve standalone installer (#17022)
## Summary

This PR significantly improves the standalone installer experience.

The main changes are:

1. We now install the codex binary and other dependencies in a
subdirectory under CODEX_HOME.
(`CODEX_HOME/packages/standalone/releases/...`)

2. We replace the `codex.js` launcher that npm/bun rely on with logic in
the Rust binary that automatically resolves its dependencies (like
ripgrep)

## Motivation

A few design constraints pushed this work.

1. Currently, the entrypoint to codex is through `codex.js`, which
forces a node dependency to kick off our rust app. We want to move away
from this so that the entrypoint to codex does not rely on node or
external package managers.
2. Right now, the native script adds codex and its dependencies directly
to user PATH. Given that codex is likely to add more binary dependencies
than ripgrep, we want a solution which does not add arbitrary binaries
to user PATH -- the only one we want to add is the `codex` command
itself.
3. We want upgrades to be atomic. We do not want scenarios where
interrupting an upgrade command can move codex into undefined state (for
example, having a new codex binary but an old ripgrep binary). This was
~possible with the old script.
4. Currently, the Rust binary uses heuristics to determine which
installer created it. These heuristics are flaky and are tied to the
`codex.js` launcher. We need a more stable/deterministic way to
determine how the binary was installed for standalone.
5. We do not want conflicting codex installations on PATH. For example,
the user installing via npm, then installing via brew, then installing
via standalone would make it unclear which version of codex is being
launched and make it tough for us to determine the right upgrade
command.

## Design

### Standalone package layout

Standalone installs now live under `CODEX_HOME/packages/standalone`:

```text
$CODEX_HOME/
  packages/
    standalone/
      current -> releases/0.111.0-x86_64-unknown-linux-musl
      releases/
        0.111.0-x86_64-unknown-linux-musl/
          codex
          codex-resources/
            rg
```

where `standalone/current` is a symlink to a release directory.

On Windows, the release directory has the same shape, with `.exe` names
and Windows helpers in `codex-resources`:

```text
%CODEX_HOME%\
  packages\
    standalone\
      current -> releases\0.111.0-x86_64-pc-windows-msvc
      releases\
        0.111.0-x86_64-pc-windows-msvc\
          codex.exe
          codex-resources\
            rg.exe
            codex-command-runner.exe
            codex-windows-sandbox-setup.exe
```

This gives us:
- atomic upgrades because we can fully stage a release before switching
`standalone/current`
- a stable way for the binary to recognize a standalone install from its
canonical `current_exe()` path under CODEX_HOME
- a clean place for binary dependencies like `rg`, Windows sandbox
helpers, and, in the future, our custom `zsh` etc

### Command location

On Unix, we add a symlink at `~/.local/bin/codex` which points directly
to the `$CODEX_HOME/packages/standalone/current/codex` binary. This
becomes the main entrypoint for the CLI.

On Windows, we store the link at
`%LOCALAPPDATA%\Programs\OpenAI\Codex\bin`.

### PATH persistence

This is a tricky part of the PR, as there's no ~super reliable way to
ensure that we end up on PATH without significant tradeoffs.

Most Unix variants will have `~/.local/bin` on PATH already, which means
we *should* be fine simply registering the command there in most cases.
However, there are cases where this is not the case. In these cases, we
directly edit the profile depending on the shell we're in.

- macOS zsh: `~/.zprofile`
- macOS bash: `~/.bash_profile`
- Linux zsh: `~/.zshrc`
- Linux bash: `~/.bashrc`
- fallback: `~/.profile`

On Windows, we update the User `Path` environment variable directly and
we don't need to worry about shell profiles.

### Standalone runtime detection

This PR adds a new shared crate, `codex-install-context`, which computes
install ownership once per process and caches it in a `OnceLock`.

That context includes:
- install manager (`Standalone`, `Npm`, `Bun`, `Brew`, `Other`)
- the managed standalone release directory, when applicable
- the managed standalone `codex-resources` directory, when present
- the resolved `rg_command`

The standalone path is detected by canonicalizing `current_exe()`,
canonicalizing CODEX_HOME via `find_codex_home()`, and checking whether
the binary is running from under
`$CODEX_HOME/packages/standalone/releases`.

We intentionally do not use a release metadata file. The binary path is
the source of truth.

### Dependency resolution

For standalone installs, `grep_files` now resolves bundled `rg` from
`codex-resources` next to the Codex binary.

For npm/bun/brew/other installs, `grep_files` falls back to resolving
`rg` from PATH.

For Windows standalone installs, Windows sandbox helpers are still found
as direct siblings when present. If they are not direct siblings, the
lookup also checks the sibling `codex-resources` directory.

### TUI update path

The TUI now has `UpdateAction::StandaloneUnix` and
`UpdateAction::StandaloneWindows`, which rerun the standalone install
commands.

Unix update command:

```sh
sh -c "curl -fsSL https://chatgpt.com/codex/install.sh | sh"
```

Windows update command:

```powershell
powershell -c "irm https://chatgpt.com/codex/install.ps1|iex"
```

The Windows updater runs PowerShell directly. We do this because `cmd
/C` would parse the `|iex` as a cmd pipeline instead of passing it to
PowerShell.

## Additional installer behavior

- standalone installs now warn about conflicting npm/bun/brew-managed
`codex` installs and offer to uninstall them
- same-version reruns do not redownload the release if it is already
staged locally

## Testing

Installer smoke tests run:
- macOS: fresh install into isolated `HOME` and `CODEX_HOME` with
`scripts/install/install.sh --release latest`
- macOS: reran the installer against the same isolated install to verify
the same-version/update path and PATH block idempotence
- macOS: verified the installed `codex --version` and bundled
`codex-resources/rg --version`
- Windows: parsed `scripts/install/install.ps1` with PowerShell via
`[scriptblock]::Create(...)`
- Windows: verified the standalone update action builds a direct
PowerShell command and does not route the `irm ...|iex` command through
`cmd /C`

---------

Co-authored-by: Codex <noreply@openai.com>
2026-04-15 14:44:01 -07:00
EFRAZER-oai
168e35b6f2 Add Windows direct install script (#12741)
## Summary
- add a direct install script for Windows at
`scripts/install/install.ps1`
- extend release staging so `install.ps1` is published alongside
`install.sh`
- install the Windows runtime payload (`codex.exe`, `rg.exe`, and helper
binaries) from the existing platform npm package

## Dependencies
- Depends on https://github.com/openai/codex/pull/12740

## Testing
- Smoke-tested with powershell
2026-03-03 09:25:50 -08:00
EFRAZER-oai
a1cd78c818 Add macOS and Linux direct install script (#12740)
## Summary
- add a direct install script for macOS and Linux at
`scripts/install/install.sh`
- stage `install.sh` into `dist/` during release so it is published as a
GitHub release asset
- reuse the existing platform npm payload so the installer includes both
`codex` and `rg`

## Testing
- `bash -n scripts/install/install.sh`
- local macOS `curl | sh` smoke test against a locally served copy of
the script
2026-02-26 00:33:50 +00:00