Codex · EN · Part 1

Ch 03 Installation And Configuration

03-ch-03-Installation-and-Configuration.md

第3章 Installation and Configuration

Installation Methods

Codex CLI offers multiple installation paths, each suited to different environments and workflows. The right choice depends on your platform, update preferences, and whether you need the absolute latest features.

npm installation

The simplest installation method uses npm, which auto-updates and works across platforms:

npm install -g @openai/codex

This command installs the latest release and registers the codex binary in your global path. The npm package wraps the platform-specific binary, so you get the right executable for your system automatically.

🤿 深入底层:The npm package lives in codex-cli/ at the repository root. It's a thin wrapper that downloads the appropriate pre-built binary for your platform during npm install—the actual Rust compilation happens upstream during the release process, not on your machine.

Homebrew installation

On macOS and Linux, Homebrew provides another managed installation path:

brew install --cask codex

Homebrew handles updates alongside your other cask applications. Use brew upgrade --cask codex to get the latest version.

Pre-built binaries

For maximum control or air-gapped environments, download binaries directly from GitHub Releases:

# Check the latest release at:
# https://github.com/openai/codex/releases/latest

# macOS (Apple Silicon)
curl -L https://github.com/openai/codex/releases/download/vX.X.X/codex-aarch64-apple-darwin.tar.gz | tar xz
mv codex-aarch64-apple-darwin codex
chmod +x codex
sudo mv codex /usr/local/bin/

# Linux (x86_64)
curl -L https://github.com/openai/codex/releases/download/vX.X.X/codex-x86_64-unknown-linux-musl.tar.gz | tar xz
mv codex-x86_64-unknown-linux-musl codex
chmod +x codex
sudo mv codex /usr/local/bin/

Each release contains executables for multiple platforms. Rename the downloaded file to simply codex after extraction—otherwise you'll be typing codex-x86_64-unknown-linux-musl every time you want to run a command.

Building from source

Building from source requires the Rust toolchain and is primarily for contributors:

# Install Rust if needed
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source "$HOME/.cargo/env"

# Clone and build
git clone https://github.com/openai/codex.git
cd codex/codex-rs
cargo build --release

# The binary is at target/release/codex

⚠️ 避坑指南:First-time Rust compilation can take 10-30 minutes depending on your hardware. The workspace has 90+ crates with complex dependencies. Use cargo build (without --release) during development for faster iteration—release builds optimize everything and take significantly longer.

Troubleshooting common issues

Problem: codex: command not found

Solution: Your PATH isn't configured correctly. Verify the installation location:

# For npm installations
which codex  # Should show something like /usr/local/bin/codex

# If not found, check npm's binary location
npm config get prefix  # Add bin/ subdirectory to your PATH

Problem: Permission denied when running codex

Solution: The binary lacks execute permissions:

chmod +x /path/to/codex

Problem: "Unable to load libstdc++" or similar system library errors

Solution: On older Linux distributions, you may need updated C++ standard libraries:

# Ubuntu/Debian
sudo apt-get update && sudo apt-get install -y libstdc++6

# CentOS/RHEL
sudo yum update libstdc++

Authentication: API Keys vs OAuth

Before Codex can process code, it needs credentials. Two authentication paths are available, each with different trade-offs.

API key authentication

The simplest method uses an OpenAI API key directly:

codex login
# Select: "Sign in with API key"
# Paste your key when prompted

The API key is stored in ~/.codex/auth.json:

{
  "auth_mode": "api_key",
  "OPENAI_API_KEY": "sk-proj-..."
}

You can also set the key via environment variable (no login required):

export OPENAI_API_KEY="sk-proj-..."
codex "hello world"

API keys work with any OpenAI API plan and are straightforward to revoke. However, they don't include ChatGPT subscription benefits like higher rate limits or access to certain models.

ChatGPT OAuth authentication

For ChatGPT Plus, Pro, Team, Edu, or Enterprise subscribers, OAuth integration provides seamless authentication:

codex login
# Select: "Sign in with ChatGPT"
# Browser opens to ChatGPT OAuth flow
# Complete authentication in browser

The stored credentials include an access token and refresh token:

{
  "auth_mode": "oauth",
  "tokens": {
    "access_token": "...",
    "refresh_token": "...",
    "expires_at": "2026-04-05T10:30:00Z"
  }
}

☕ 茶水间时间:OAuth tokens expire periodically. Codex handles refresh automatically using the stored refresh token, but if you see "refresh token expired" errors, you'll need to run codex login again to establish a fresh session.

Credential storage

Authentication credentials live at ~/.codex/auth.json by default, but the storage backend is configurable:

# In ~/.codex/config.toml
[auth]
store_mode = "file"       # Default: stores in ~/.codex/auth.json
# store_mode = "keyring"  # Use system keyring (fails if unavailable)
# store_mode = "auto"     # Try keyring, fall back to file
# store_mode = "ephemeral" # Memory-only for current process

On Unix systems, file-based storage uses mode 0o600 (read/write for owner only). Keyring storage uses the platform's secure credential manager (Keychain on macOS, Windows Credential Manager on Windows, secret-service on Linux).

Security implications

Each authentication method has different security considerations:

MethodCredential ExposureRevocationRate Limits
API KeyVisible in auth.json and shell historyRegenerate at platform.openai.comStandard API limits
ChatGPT OAuthToken stored securely, no manual key handlingRevoke via ChatGPT account settingsChatGPT plan limits (typically higher)

Key security practices:

  • Never commit auth.json to version control
  • Add ~/.codex/ to your .gitignore globally
  • Use environment variables for API keys in CI/CD environments
  • Rotate API keys periodically if using key-based auth

Switching methods

You can switch between authentication methods at any time:

# Currently using API key, want to switch to OAuth
codex login  # Select "Sign in with ChatGPT"
# Previous auth.json is overwritten with OAuth tokens

# Currently using OAuth, want to test with an API key
codex logout  # Clears existing credentials
codex login   # Select "Sign in with API key"

The codex logout command removes stored credentials entirely. No confirmation is prompted, so be certain before running it.

Configuration System Deep Dive

Codex uses a three-layer configuration system that merges settings from multiple sources, with well-defined precedence rules.

Three-layer configuration system

Configuration flows from three sources, in order of precedence (highest last):

  1. System defaults: Built into the binary
  2. User config: ~/.codex/config.toml
  3. Project config: .codex/config.toml in your project directory
  4. Session flags: CLI arguments like -c model=gpt-5

Rendering diagram...

The merge algorithm is recursive: later layers override specific keys rather than replacing entire sections. If your user config sets [tui] options and your project config sets [sandbox] options, both take effect simultaneously.

Configuration precedence

Understanding precedence is crucial when settings conflict. Consider this scenario:

User config (~/.codex/config.toml):

[model]
provider = "openai"
model = "gpt-5"
reasoning_effort = "medium"

[tui]
theme = "dark"

Project config (.codex/config.toml):

[model]
model = "gpt-5-codex-max"  # Overrides user's model choice

[tui]
theme = "light"  # Overrides user's theme preference

CLI flag:

codex -c model=gpt-5-codex -c reasoning_effort=high

Effective configuration:

  • model = "gpt-5-codex" (from CLI flag, highest precedence)
  • reasoning_effort = "high" (from CLI flag)
  • provider = "openai" (from user config, no override)
  • theme = "light" (from project config)

The rule: more specific wins. CLI flags beat project config, which beats user config, which beats defaults.

Common configuration patterns

Here's a minimal but functional configuration covering common needs:

# ~/.codex/config.toml

# Model selection
[model]
provider = "openai"
model = "gpt-5"              # Default model
reasoning_effort = "medium"  # For reasoning models

# Sandbox mode - start conservative
[sandbox]
mode = "read-only"           # See docs for workspace-write options

# TUI preferences
[tui]
theme = "auto"                # auto/dark/light, or custom theme name
notifications = true         # Desktop notifications when unfocused
alternate_screen = "auto"    # Disable in Zellij, enable elsewhere
animations = true            # Welcome screen effects, spinners

# Memory system (advanced)
[memories]
generate_memories = true     # Extract context from past threads
use_memories = true          # Inject relevant memories into new threads
max_rollout_age_days = 30    # Only use threads from last 30 days

# History tracking
[history]
persistence = "save-all"     # Write all history to disk
# max_bytes = 10485760       # Optional: cap history file size

Project-specific configurations typically override only what's necessary:

# .codex/config.toml (project-specific)

[model]
model = "gpt-5-codex-max"     # Use more capable model for this project

[sandbox]
mode = "workspace-write"     # Allow file writes in this project
writable_roots = ["."]        # Only write to project directory

[memories]
generate_memories = false    # Disable memory extraction for this project

CLI flag overrides

CLI flags provide temporary overrides without editing configuration files:

# Override model for a single session
codex -c model=gpt-5-codex-max "refactor this function"

# Combine multiple overrides
codex -c model=gpt-5 -c reasoning_effort=high -c sandbox.mode=danger-full-access

# Override nested config keys with dot notation
codex -c tui.theme=light -c sandbox.mode=workspace-write

The -c flag accepts dotted paths that mirror the TOML structure. Use this for one-off experiments or when you don't want to commit configuration changes to disk.

⚠️ 避坑指南:CLI overrides apply only to the current session. They don't modify your config files, but they also don't persist for future runs. For repeated needs, add them to your project's .codex/config.toml instead.

Running Your First Real Tasks

With Codex installed and configured, let's walk through three practical scenarios that demonstrate different aspects of the system.

Refactoring scenario

Start with a function that needs improvement:

// calculator.rs
fn calculate_price(base: f64, tax: f64, discount: f64) -> f64 {
    let with_tax = base * (1.0 + tax / 100.0);
    let with_discount = with_tax * (1.0 - discount / 100.0);
    with_discount
}

Run Codex with a refactoring request:

codex "Refactor calculate_price to use a Builder pattern for better readability"

What happens behind the scenes:

  1. Codex reads the current file contents
  2. Sends the code plus your request to the configured model
  3. The model proposes edits via the apply_patch tool
  4. You're prompted to approve the changes (or set approvals to auto-accept)
  5. The patch is applied and the file is updated

Expected output:

I'll refactor the calculate_price function to use a Builder pattern.
Let me create a new implementation...

[Proposed changes to calculator.rs]
+ pub struct PriceBuilder {
+     base: f64,
+     tax_rate: f64,
+     discount_rate: f64,
+ }
+ 
+ impl PriceBuilder {
+     pub fn new(base: f64) -> Self {
+         Self { base, tax_rate: 0.0, discount_rate: 0.0 }
+     }
+     
+     pub fn tax(mut self, percent: f64) -> Self {
+         self.tax_rate = percent;
+         self
+     }
+     
+     pub fn discount(mut self, percent: f64) -> Self {
+         self.discount_rate = percent;
+         self
+     }
+     
+     pub fn calculate(self) -> f64 {
+         let with_tax = self.base * (1.0 + self.tax_rate / 100.0);
+         let with_discount = with_tax * (1.0 - self.discount_rate / 100.0);
+         with_discount
+     }
+ }
+ 
+ fn calculate_price(base: f64, tax: f64, discount: f64) -> f64 {
+     PriceBuilder::new(base)
+         .tax(tax)
+         .discount(discount)
+         .calculate()
+ }

Approve these changes? [y/n]

Test generation scenario

Codex can generate tests for existing code. Given a function:

// lib.rs
pub fn fibonacci(n: u32) -> u64 {
    match n {
        0 => 0,
        1 => 1,
        _ => fibonacci(n - 1) + fibonacci(n - 2),
    }
}

Run:

codex "Generate comprehensive unit tests for the fibonacci function, including edge cases"

Behind the scenes:

  1. Codex locates the function in your codebase
  2. Analyzes the signature and implementation
  3. Creates a new test file or adds to existing tests
  4. Uses proper Rust testing conventions

Expected output:

I'll generate comprehensive tests for the fibonacci function.

[New file: lib_tests.rs]
+ #[cfg(test)]
+ mod tests {
+     use super::*;
+ 
+     #[test]
+     fn test_fibonacci_zero() {
+         assert_eq!(fibonacci(0), 0);
+     }
+ 
+     #[test]
+     fn test_fibonacci_one() {
+         assert_eq!(fibonacci(1), 1);
+     }
+ 
+     #[test]
+     fn test_fibonacci_small_values() {
+         assert_eq!(fibonacci(2), 1);
+         assert_eq!(fibonacci(5), 5);
+         assert_eq!(fibonacci(10), 55);
+     }
+ 
+     #[test]
+     #[should_panic]  # Known limitation: recursive implementation is slow
+     fn test_fibonacci_large_value() {
+         fibonacci(50);  # This will take a long time
+     }
+ }

Approve test file creation? [y/n]

Debugging scenario

When tests fail, Codex can help diagnose the issue:

cargo test
# Output: test test_fibonacci_small_values ... FAILED
# assert_eq!(fibonacci(10), 55) got 89 instead

Run Codex with the error context:

codex "The fibonacci test is failing. fibonacci(10) returns 89 but should return 55. Debug what's wrong."

Behind the scenes:

  1. Codex reads the test output you provide
  2. Examines the fibonacci implementation
  3. Identifies the off-by-one error or logic mistake
  4. Proposes a fix

Expected output:

Let me analyze the fibonacci function and the failing test.

[Reading lib.rs]
[Reading lib_tests.rs]

I found the issue! The test expectation is incorrect. The fibonacci sequence
is: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55...

So fibonacci(10) should actually be 55, but let me trace through the code:

fibonacci(10) = fibonacci(9) + fibonacci(8)
              = 34 + 21 = 55 ✓

The code is correct, but the test has the wrong expectation. The standard
fibonacci sequence gives:

Position: 0  1  2  3  4  5  6  7  8   9   10
Value:   0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55

[Proposed change to lib_tests.rs]
-     assert_eq!(fibonacci(10), 55);
+     assert_eq!(fibonacci(10), 55);  # This is correct!

Wait, let me recheck. The test expects 55 and the code returns 89.
Let me trace more carefully...

Actually, there may be an indexing issue. Let me add debug output:

Understanding output

Codex's output includes several key elements:

  • Tool calls: When Codex uses tools like apply_patch or shell, you'll see structured output showing what's happening
  • Streaming responses: Model responses stream in token-by-token, so you see progress in real-time
  • Approval prompts: For file edits and command execution, you'll be asked to confirm unless you've configured automatic approvals
  • Status indicators: The TUI shows context usage, model information, and current operation status

The JSONL log file at ~/.codex/history.jsonl records every session for later reference, which is useful for reviewing what changed when something breaks.


With Codex installed, authenticated, and configured, you've completed the setup phase. The three scenarios above demonstrate the core interaction loop: request, tool use, approval, and result. Part II dives into the core systems that power everything—the agent orchestration, tool execution, and state management that make this loop possible.