7 Commits

  • 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.
  • 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.
  • 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
  • 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>
  • 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
  • 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