This document describes the build system, CI/CD pipeline, release process, and distribution mechanisms for Codex. It covers the Cargo workspace structure, GitHub Actions workflows that build and test the codebase, platform-specific code signing procedures, and how binaries reach end users through npm, Homebrew, and GitHub Releases.
For information about setting up a local development environment, see Development Setup. For testing strategies, see Testing Strategies.
Codex is distributed as a native executable built from Rust code. The build system supports eight platform/architecture combinations and produces signed, compressed artifacts for each. The release pipeline automatically packages these binaries into npm modules, uploads them to GitHub Releases, and publishes to npm for stable and alpha versions.
The build infrastructure consists of:
shell-tool-mcp that bundles patched Bash interpretersSources: codex-rs/Cargo.toml1-321 .github/workflows/rust-release.yml1-649 codex-rs/README.md1-99
The Codex codebase is organized as a Cargo workspace containing 52 member crates. The workspace uses Rust edition 2024 and enforces strict Clippy lints to maintain code quality.
Sources: codex-rs/Cargo.toml1-374 codex-rs/cli/Cargo.toml1-65 codex-rs/core/Cargo.toml1-170 codex-rs/tui/Cargo.toml1-137
<old_str>
Sources: .github/workflows/rust-ci.yml1-528
<new_str>
Sources: .github/workflows/rust-ci.yml1-528
| Crate | Path | Purpose |
|---|---|---|
codex-cli | codex-rs/cli | Multitool CLI dispatcher (the codex binary) |
codex-core | codex-rs/core | Core agent logic: Session, ModelClient, tool registry |
codex-tui | codex-rs/tui | Interactive terminal UI using Ratatui |
codex-exec | codex-rs/exec | Headless non-interactive execution mode |
codex-app-server | codex-rs/app-server | JSON-RPC server for IDE extensions |
codex-protocol | codex-rs/protocol | Shared protocol types (EventMsg, Op) |
codex-api | codex-rs/codex-api | OpenAI API wire protocol implementations |
codex-apply-patch | codex-rs/apply-patch | Unified diff parser with tree-sitter validation |
codex-linux-sandbox | codex-rs/linux-sandbox | Landlock + seccomp sandbox implementation |
codex-windows-sandbox | codex-rs/windows-sandbox-rs | Windows restricted token sandbox |
codex-state | codex-rs/state | SQLite-backed state persistence |
Sources: codex-rs/Cargo.toml1-53 codex-rs/core/Cargo.toml1-158 codex-rs/cli/Cargo.toml1-63 codex-rs/tui/Cargo.toml1-133
The workspace defines unified dependency versions, Clippy lints, and build profiles:
Sources: codex-rs/Cargo.toml56-63 codex-rs/Cargo.toml295-302 codex-rs/rust-toolchain.toml1-4
The CI pipeline runs on every pull request and push to main. It performs change detection, runs format/lint checks, builds for all platforms, and executes tests.
Sources: .github/workflows/rust-ci.yml1-528
The CI workflow uses a custom change detection step to skip unnecessary jobs:
The detection script (.github/workflows/rust-ci.yml23-49) compares the base and head commits for PRs, checking if files match patterns like codex-rs/* or .github/*. Jobs conditionally run based on these outputs.
Sources: .github/workflows/rust-ci.yml11-49
The lint_build job builds for all supported targets in parallel:
| Runner | Target | Profile |
|---|---|---|
| macos-15-xlarge | aarch64-apple-darwin | dev |
| macos-15-xlarge | x86_64-apple-darwin | dev |
| ubuntu-24.04 (custom) | x86_64-unknown-linux-musl | dev |
| ubuntu-24.04 (custom) | x86_64-unknown-linux-gnu | dev |
| ubuntu-24.04-arm (custom) | aarch64-unknown-linux-musl | dev |
| ubuntu-24.04-arm (custom) | aarch64-unknown-linux-gnu | dev |
| windows-x64 (custom) | x86_64-pc-windows-msvc | dev |
| windows-arm64 (custom) | aarch64-pc-windows-msvc | dev |
Additionally, representative release builds run for macOS aarch64, Linux x86_64 musl, and Windows x86_64/arm64 to catch release-specific issues and pre-populate the cache.
Sources: .github/workflows/rust-ci.yml88-177
The CI uses multiple caching layers:
~/.cargo/bin/, ~/.cargo/registry/index/, ~/.cargo/registry/cache/, ~/.cargo/git/db/ (.github/workflows/rust-ci.yml226-241)RUSTC_WRAPPER=sccache with GitHub Actions cache backend or local disk fallback (.github/workflows/rust-ci.yml244-276)codex-rs/target/ (excluded for gnu-dev jobs to reduce cache size) (.github/workflows/rust-ci.yml280-294)Cache keys use format: cargo-home-${{ matrix.runner }}-${{ matrix.target }}-${{ matrix.profile }}-${{ steps.lockhash.outputs.hash }}-${{ steps.lockhash.outputs.toolchain_hash }} where lockhash.outputs.hash is the SHA256 of Cargo.lock and lockhash.outputs.toolchain_hash is the SHA256 of rust-toolchain.toml.
Sources: .github/workflows/rust-ci.yml215-294
Linux musl builds require special toolchain setup to enable static linking with Zig as the linker:
$GITHUB_WORKSPACE/.cargo-home to avoid host contamination (.github/workflows/rust-ci.yml204-213)uses: mlugg/setup-zig@v2 for cross-compilation linker (.github/workflows/rust-ci.yml296-300).github/scripts/install-musl-build-tools.sh which:
musl-tools, pkg-config, libcap-dev via aptlibcap 2.75 from kernel.org (.github/scripts/install-musl-build-tools.sh35-89)zigcc and zigcxx wrapper scripts that invoke Zig with -target ${zig_target} (.github/scripts/install-musl-build-tools.sh92-186).cargo/config.toml with linker = "zigcc" for musl targets (.github/scripts/install-musl-build-tools.sh188-216)rustc-ubsan-wrapper that preloads libubsan.so.1 for host proc-macro builds (.github/workflows/rust-ci.yml302-333)-fsanitize=undefined from CFLAGS/CXXFLAGS and all CARGO_TARGET_*_RUSTFLAGS to prevent UBSan from being linked into the musl binaries (.github/workflows/rust-ci.yml335-362)Sources: .github/workflows/rust-ci.yml204-362 .github/scripts/install-musl-build-tools.sh1-226
Tests run on four platforms with platform-specific configurations:
WSL tests require special setup via Biswa96/wsl-setup action to install the WSL distribution inside the CI runner.
Sources: .github/workflows/rust-ci.yml440-521
The release workflow triggers on tags matching rust-v*.*.* and produces signed binaries for all supported platforms.
Sources: .github/workflows/rust-release.yml1-649
The release starts with validation steps:
rust-v[0-9]+\.[0-9]+\.[0-9]+(-(alpha|beta)(\.[0-9]+)?)? (.github/workflows/rust-release.yml33)Cargo.toml (.github/workflows/rust-release.yml36-39)core/config.schema.json matches current schema (.github/workflows/rust-release.yml48-55)Sources: .github/workflows/rust-release.yml19-55
The release build matrix mirrors CI but always uses release profile:
| Runner | Target | Special Setup |
|---|---|---|
| macos-15-xlarge | aarch64-apple-darwin | Code signing + DMG creation |
| macos-15-xlarge | x86_64-apple-darwin | Code signing + DMG creation |
| ubuntu-24.04 | x86_64-unknown-linux-musl | Zig + musl-tools + Cosign |
| ubuntu-24.04 | x86_64-unknown-linux-gnu | Cosign |
| ubuntu-24.04-arm | aarch64-unknown-linux-musl | Zig + musl-tools + Cosign |
| ubuntu-24.04-arm | aarch64-unknown-linux-gnu | Cosign |
| windows-latest | x86_64-pc-windows-msvc | Azure Trusted Signing |
| windows-11-arm | aarch64-pc-windows-msvc | Azure Trusted Signing |
Each job builds codex, codex-responses-api-proxy, and on Windows also builds codex-windows-sandbox-setup and codex-command-runner.
Sources: .github/workflows/rust-release.yml57-221
Linux binaries are signed using Sigstore's Cosign with GitHub OIDC authentication via a composite action:
The action (.github/actions/linux-code-sign/action.yml) runs cosign sign-blob for each binary (codex, codex-responses-api-proxy) and produces .sigstore bundles containing:
The bundles can be verified with cosign verify-blob --certificate-identity=... to ensure the binary was built by the official GitHub Actions workflow.
Sources: .github/workflows/rust-release.yml217-223
Windows executables are signed using Azure Trusted Signing with OIDC authentication via a composite action:
The action (.github/actions/windows-code-sign/action.yml1-58) performs:
azure/login@v2 with OIDCazure/trusted-signing-action@v0:
codex.execodex-responses-api-proxy.execodex-windows-sandbox-setup.execodex-command-runner.exeThe signed executables embed Authenticode signatures that Windows validates during execution.
Sources: .github/workflows/rust-release-windows.yml1-210 .github/actions/windows-code-sign/action.yml1-58
macOS binaries undergo two-stage signing via a composite action:
Sign binaries with developer certificate and submit for notarization:
This runs codesign --sign "Developer ID Application" and xcrun notarytool submit --apple-id for codex and codex-responses-api-proxy.
Build DMG containing signed binaries via hdiutil create:
Sign and notarize DMG:
The resulting DMG passes Gatekeeper validation when users download and mount it.
Sources: .github/workflows/rust-release.yml224-294
After signing, artifacts are compressed into multiple formats:
.zst: Zstandard compression (existing behavior).tar.gz: Gzip tarball (for compatibility).zip: Windows-only, bundles sandbox helper binaries (.github/workflows/rust-release.yml366-394)Windows .zip archives bundle the sandbox helpers (codex-command-runner.exe, codex-windows-sandbox-setup.exe) alongside the main codex.exe to ensure WinGet installs include required dependencies.
Sources: .github/workflows/rust-release.yml324-403
The release job downloads all build artifacts and creates a GitHub Release:
Sources: .github/workflows/rust-release.yml422-562
Codex binaries reach users through four primary distribution channels: npm, GitHub Releases, Homebrew, and DotSlash.
Sources: .github/workflows/rust-release.yml422-649
The npm packages are generated by scripts/stage_npm_packages.py, which:
optionalDependencies for each targetpnpm pack to create tarball@openai/codex/
├── bin/
│ └── codex.js # Platform dispatcher
├── vendor/
│ ├── aarch64-apple-darwin/
│ │ └── codex
│ ├── x86_64-unknown-linux-musl/
│ │ └── codex
│ └── ...
└── package.json # With optionalDependencies
The dispatcher script (codex-rs/cli/npm/bin/codex.js) detects the platform and executes the appropriate binary from vendor/.
Sources: .github/workflows/rust-release.yml521-530
The publish-npm job publishes to npm using OpenID Connect authentication (no long-lived tokens):
Stable releases (x.y.z) publish to the latest tag; alpha releases (x.y.z-alpha.N) publish to the alpha tag.
Sources: .github/workflows/rust-release.yml563-629 .github/workflows/rust-release.yml488-505
Homebrew installation is supported via a cask that points to GitHub Release DMGs. The cask definition lives in a separate Homebrew tap repository (not shown in provided files).
Users install via:
Sources: codex-rs/README.md14
Users can download signed binaries directly from GitHub Releases. Each release includes:
.zst, .tar.gz, .zip (Windows only).sigstore (Linux only).dmg (macOS only)config-schema.jsonSources: .github/workflows/rust-release.yml532-541
DotSlash support is provided via facebook/dotslash-publish-release action:
This allows users with DotSlash installed to run ./codex from a checked-in DotSlash file that automatically downloads the correct platform binary.
Sources: .github/workflows/rust-release.yml543-548
The shell-tool-mcp package is a specialized MCP server that bundles Codex's exec server binaries with patched Bash interpreters for multiple OS variants. This ensures consistent shell behavior across different Linux distributions and macOS versions.
Sources: .github/workflows/shell-tool-mcp.yml1-450
The shell-tool-mcp workflow is triggered either standalone or as part of the main release:
Sources: .github/workflows/shell-tool-mcp.yml1-19
The workflow builds codex-exec-mcp-server and codex-execve-wrapper for four targets:
| Target | Runner | Setup |
|---|---|---|
| aarch64-apple-darwin | macos-15-xlarge | Standard macOS toolchain |
| x86_64-apple-darwin | macos-15-xlarge | Standard macOS toolchain |
| x86_64-unknown-linux-musl | ubuntu-24.04 | Zig + musl-tools |
| aarch64-unknown-linux-musl | ubuntu-24.04-arm | Zig + musl-tools |
Musl targets require the same Zig-based cross-compilation setup as the main release workflow.
Sources: .github/workflows/shell-tool-mcp.yml70-189
Bash is built from a custom fork with an exec wrapper patch:
This builds inside container images for each target distribution:
Linux Variants:
| Variant | Container Image | Target |
|---|---|---|
| ubuntu-24.04 | ubuntu:24.04 | x86_64-unknown-linux-musl |
| ubuntu-22.04 | ubuntu:22.04 | x86_64-unknown-linux-musl |
| debian-12 | debian:12 | x86_64-unknown-linux-musl |
| debian-11 | debian:11 | x86_64-unknown-linux-musl |
| centos-9 | quay.io/centos/centos:stream9 | x86_64-unknown-linux-musl |
| ubuntu-24.04 | arm64v8/ubuntu:24.04 | aarch64-unknown-linux-musl |
| ubuntu-22.04 | arm64v8/ubuntu:22.04 | aarch64-unknown-linux-musl |
| ubuntu-20.04 | arm64v8/ubuntu:20.04 | aarch64-unknown-linux-musl |
| debian-12 | arm64v8/debian:12 | aarch64-unknown-linux-musl |
| debian-11 | arm64v8/debian:11 | aarch64-unknown-linux-musl |
| centos-9 | quay.io/centos/centos:stream9 | aarch64-unknown-linux-musl |
macOS Variants:
| Variant | Runner | Target |
|---|---|---|
| macos-15 | macos-15-xlarge | aarch64-apple-darwin |
| macos-14 | macos-14 | aarch64-apple-darwin |
Each Bash binary is uploaded as a separate artifact to be combined later.
Sources: .github/workflows/shell-tool-mcp.yml190-328
The package job downloads all Rust and Bash artifacts and assembles the final npm module:
vendor/
├── aarch64-apple-darwin/
│ ├── codex-exec-mcp-server
│ ├── codex-execve-wrapper
│ └── bash/
│ ├── macos-15/bash
│ └── macos-14/bash
└── x86_64-unknown-linux-musl/
├── codex-exec-mcp-server
├── codex-execve-wrapper
└── bash/
├── ubuntu-24.04/bash
├── debian-12/bash
└── ...
pnpm --filter @openai/codex-shell-tool-mcp run buildpnpm packSources: .github/workflows/shell-tool-mcp.yml330-418
The dispatcher script (shell-tool-mcp/bin/mcp-server.js) implements platform-specific detection:
macOS Detection:
Linux Detection:
Fallback Strategy:
If no exact match is found, the dispatcher selects the newest available Bash variant for the target architecture by sorting the vendor/<target>/bash/ directory entries lexicographically in reverse order.
Sources: .github/workflows/shell-tool-mcp.yml1-450
The workflow publishes @openai/codex-shell-tool-mcp to npm for stable and alpha releases:
Sources: .github/workflows/shell-tool-mcp.yml420-450
Summary: The Codex build and distribution system is a sophisticated multi-platform pipeline that produces signed native binaries for eight target architectures, packages them into npm modules, and distributes through multiple channels. The specialized shell-tool-mcp build demonstrates advanced cross-platform compatibility engineering by bundling distribution-specific Bash interpreters alongside the core Rust binaries.
Refresh this wiki