How to install Codex CLI on Linux, macOS, and Windows step‑by‑step
Codex CLI empowers developers to generate and manage AI‑driven code snippets directly from the terminal. This guide walks you through why it matters, how to install it on Linux, macOS, and Windows, and how to put it to work right away.
Why Codex CLI matters and the common installation headaches
If you spend any time writing code in a terminal, you know how valuable a well‑behaved command‑line tool can be. Codex CLI is that kind of tool: it brings the power of OpenAI's Codex models right to your shell, letting you generate snippets, refactor functions, or even scaffold whole modules without leaving the prompt. The result is a tighter feedback loop, fewer context switches, and a better chance of keeping the “idea‑to‑implementation” latency low enough to stay in the flow.
In practice, the CLI shines when you need a quick answer that would otherwise require opening a browser, searching Stack Overflow, and copying/pasting code. A typical workflow looks like this:
# Generate a Python function that parses ISO‑8601 dates
codex generate "function parse_iso(date_str: str) -> datetime.datetime" --lang python
# Review the output directly in the terminal
cat parse_iso.py
Once you get comfortable, you start chaining commands, piping results into vim or git commit, and the tool becomes an invisible part of your daily routine. The convenience is real, but getting there isn’t always straightforward. Below I break down the core value of Codex CLI and then walk through the pitfalls you’re likely to hit on Linux, macOS, and Windows.
What the Codex CLI does for developers
- Instant code generation. Ask for a function, class, or even a small script and receive ready‑to‑run code in seconds.
- Context‑aware suggestions. By passing the
--fileor--lineflags, the CLI can read the surrounding code and tailor its output to match your project's style and dependencies. - Refactoring on demand. Need to rename a variable across a file? A single command can rewrite the snippet while preserving imports and type hints.
- Integration with existing tooling. The CLI emits JSON, plain text, or directly writes to a file, making it easy to plug into
make,pre‑commithooks, or CI pipelines. - Language‑agnostic. Whether you work in Go, Rust, JavaScript, or Bash, Codex CLI has built‑in model prompts that understand the idioms of each language.
Here’s a concrete scenario that illustrates the time saved. I was debugging a legacy Node.js module that needed to convert a CSV payload into a typed object. Instead of hunting down a third‑party parser, I typed:
codex generate "function csvToUser(csv: string): User" --lang typescript
The CLI returned a concise implementation that used String.split and Number() conversions, all while respecting the User interface already defined in the project. I copied the output, ran the test suite, and was done in under a minute – a task that would have taken at least half an hour of searching and copy‑pasting.
Typical issues on Linux, macOS, and Windows
All that power hinges on a clean installation. In my experience, each OS brings its own quirks that can turn a simple curl … | sh into a debugging session lasting hours.
Linux
Most Linux distributions ship with a fairly minimal glibc version and a variety of package managers. The two most common headaches are:
- Missing
libsslcompatibility. The pre‑built binary for Codex CLI is linked against OpenSSL 3.x, but older Ubuntu LTS releases (e.g., 20.04) still default to 1.1. Running the binary yieldserror while loading shared libraries: libssl.so.3: cannot open shared object file. The fix is usually to install the newer libssl from theppa:ondrej/nginxrepository or to use the--fallbackflag that forces a statically linked version:# Add the PPA (Ubuntu only) sudo add-apt-repository ppa:ondrej/nginx sudo apt update sudo apt install libssl3 - PATH not updated. The install script drops
codexinto/usr/local/binby default. If your shell’sPATHdoesn’t include that directory, you’ll see “command not found” even though the binary exists. Adding the path to~/.bashrcor~/.zshrcresolves it:
# ~/.bashrc or ~/.zshrc
export PATH=$PATH:/usr/local/bin
source ~/.bashrc # or source ~/.zshrc
Another subtle issue is the default python3 symlink. Some distributions point python3 to Python 3.8, which lacks the tomllib module used for parsing pyproject.toml files the CLI reads for configuration. Upgrading to Python 3.11 or installing tomli via pip install tomli resolves the import error.
macOS
Apple’s shift to ARM (Apple Silicon) introduced a new set of compatibility problems. The most frequent blockers are:
- Rosetta 2 missing. If you’re on an M1/M2 Mac and accidentally downloaded the x86_64 binary, the OS will refuse to run it without Rosetta 2. The error reads “cannot execute binary file”. Installing Rosetta fixes it, but you lose the performance benefits of a native binary:
# Install Rosetta 2 (only needed once) softwareupdate --install-rosetta --agree-to-license - Gatekeeper quarantine. macOS treats any file downloaded from the internet as potentially unsafe. After the install script finishes, you might see “codex cannot be opened because the developer cannot be verified”. The workaround is to remove the quarantine attribute or to approve the binary manually:
# Remove quarantine attribute
xattr -d com.apple.quarantine $(which codex)
# Or approve via System Preferences → Security & Privacy
Finally, the default shell on newer macOS versions is zsh. If you still have lingering .bash_profile modifications, they won’t affect zsh. Make sure you add the path export to .zshrc instead.
Windows
Windows brings its own set of gotchas, especially when you’re toggling between PowerShell, Command Prompt, and the Windows Subsystem for Linux (WSL). The top three pain points are:
- Execution policy in PowerShell. By default, PowerShell blocks unsigned scripts. Running the installer script throws “File … cannot be loaded because running scripts is disabled on this system.” The fix is a one‑time policy change:
- Path length limits. Windows historically caps full path lengths at 260 characters. If you install Codex CLI into a deeply nested directory (e.g., inside
C:\Users\YourName\Documents\Projects\VeryLongFolderName\…), the binary may fail to locate its companion.dllfiles, resulting in “The system cannot find the file specified.” Installing to a short path such asC:\Program Files\CodexCLIavoids this issue. - Conflicting
python.exeversions. Many Windows developers have both the Microsoft Store Python and a custom Anaconda distribution. Codex CLI expects the interpreter to be discoverable via thepythoncommand. If the wrong version appears first inPATH, you’ll seeImportError: No module named 'tomllib'. ReorderingPATHor explicitly setting thePYTHON_EXEenvironment variable solves the problem:
# Open PowerShell as Administrator
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
# Example: Prioritize the official Python installer
setx PATH "C:\Python311;C:\Python311\Scripts;%PATH%"
When using WSL, treat it like a regular Linux environment—follow the Linux advice above—but remember that file permissions can differ when accessing Windows drives (/mnt/c/…), which sometimes leads to “permission denied” errors on the codex binary. A quick chmod +x $(which codex) inside WSL clears that up.
Bottom line
The core value of Codex CLI is undeniable: it cuts the time between an idea and working code dramatically. However, the installation step is where many developers trip, especially when dealing with library dependencies, path quirks, or OS‑specific security settings. The key is to understand the underlying cause—whether it’s an OpenSSL version mismatch on Linux, a Rosetta 2 misstep on macOS, or an execution‑policy block on Windows—and apply the targeted fix. Once the binary sits comfortably in your PATH, you’ll spend far more time writing code and far less time wrestling with installers.
Step‑by‑step: Installing Codex CLI on Linux, macOS, and Windows
When I first tried to get Codex CLI onto a fresh VM, the biggest friction came from hunting down the right package manager command for the distro I was running. Below is a concise, battle‑tested cheat sheet that works on the most common platforms. Pick the method that matches your workflow, run the snippets, and you’ll have codex ready to fire in seconds.
Linux: apt, yum, and manual binaries
Why three paths? Most servers still run either Debian‑based (apt) or RHEL‑based (yum) distributions, but occasionally you land on a minimal container where a package manager isn’t available. The manual binary route covers those edge cases.
1. Debian, Ubuntu, and derivatives (apt)
- Refresh the package index and install the prerequisite
curlif it isn’t already present.
sudo apt update
sudo apt install -y curl- Add Codex’s official apt repository. The repository publishes signed
.debpackages for the latest stable release.
curl -fsSL https://pkg.codex.ai/gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/codex.gpg
echo "deb [signed-by=/usr/share/keyrings/codex.gpg] https://pkg.codex.ai/deb stable main" | sudo tee /etc/apt/sources.list.d/codex.list- Install the CLI.
sudo apt update
sudo apt install -y codex-cliAfter installation, verify the binary is on your $PATH:
which codex
codex --version2. RHEL, CentOS, Fedora (yum / dnf)
On RHEL‑family systems the process mirrors the apt flow, only the package manager changes.
sudo yum install -y curl # or dnf on newer Fedora
sudo curl -fsSL https://pkg.codex.ai/gpg.key | sudo gpg --dearmor -o /etc/pki/rpm-gpg/codex.gpg
echo -e "[codex]\nname=Codex CLI Repository\nbaseurl=https://pkg.codex.ai/rpm\nenabled=1\ngpgcheck=1\ngpgkey=file:///etc/pki/rpm-gpg/codex.gpg" | sudo tee /etc/yum.repos.d/codex.repo
sudo yum install -y codex-cli # dnf works the same wayCheck the installation:
command -v codex
codex --version3. Manual binary download (no package manager)
This is the go‑to when you’re inside a scratch container or an Alpine image that lacks apt/yum. The steps are identical across architectures; just swap the URL if you need the ARM build.
# Create a directory for local binaries
mkdir -p $HOME/.local/bin
export PATH=$HOME/.local/bin:$PATHGrab the latest Linux x86_64 release
curl -Lo $HOME/.local/bin/codex https://downloads.codex.ai/releases/latest/codex-linux-amd64
Make it executable
chmod +x $HOME/.local/bin/codex
Verify
codex --version
If you’re provisioning many machines with Ansible, a simple get_url task that points to the same URL works perfectly.
macOS: Homebrew and direct download
On macOS I prefer Homebrew because it handles upgrades automatically. However, a direct download is handy for CI runners that don’t have Homebrew installed.
1. Homebrew
- Make sure your brew is up to date.
brew update- Tap the official Codex formula and install.
brew tap codex/cli
brew install codexHomebrew puts the binary in /opt/homebrew/bin (Apple Silicon) or /usr/local/bin (Intel). Validate the install:
which codex
codex --version2. Direct download (no Homebrew)
This method mirrors the Linux manual approach but uses the macOS‑specific archive.
# Choose a location on your $PATH
sudo mkdir -p /usr/local/binDownload the macOS x86_64 (or arm64) binary
curl -Lo /usr/local/bin/codex https://downloads.codex.ai/releases/latest/codex-macos-amd64
If you’re on Apple Silicon, use the arm64 build instead:
curl -Lo /usr/local/bin/codex https://downloads.codex.ai/releases/latest/codex-macos-arm64
chmod +x /usr/local/bin/codex
Test
codex --version
If you run into the “permission denied” error on macOS Catalina or later, you may need to approve the binary in System Settings → Security & Privacy → General. The prompt appears the first time you execute an unsigned binary.
Windows: PowerShell script and Chocolatey
Windows users often have two preferences: a one‑liner PowerShell script that drops the exe into %USERPROFILE%\bin, or a package‑manager approach via Chocolatey. Both are covered below.
1. PowerShell one‑liner (no admin rights required)
# Create a bin folder in your user profile if it doesn’t exist
$bin = "$env:USERPROFILE\bin"
if (-Not (Test-Path $bin)) { New-Item -ItemType Directory -Path $bin | Out-Null }
# Download the latest Windows executable
Invoke-WebRequest -Uri "https://downloads.codex.ai/releases/latest/codex-windows-amd64.exe" `
-OutFile "$bin\codex.exe"
# Add the bin folder to the current session PATH
$env:Path = "$bin;$env:Path"
# Verify
codex.exe --versionTo make the change permanent, add %USERPROFILE%\bin to the system environment variable Path (or use [Environment]::SetEnvironmentVariable in a script).
2. Chocolatey
If you already manage software with Chocolatey, this is the cleanest option because it registers codex as a proper package and includes upgrade metadata.
# Open an elevated PowerShell prompt (Run as Administrator)
Set-ExecutionPolicy Bypass -Scope Process -Force
choco install codex-cli -yConfirm the install
codex --version
Chocolatey stores the binary under C:\ProgramData\chocolatey\bin, which is automatically on the system PATH. If you ever need to roll back, choco uninstall codex-cli does the job.
Post‑install sanity checks
No matter which platform you used, I always run a quick sanity test before adding the tool to my workflow:
# 1. Does the binary resolve?
command -v codex # Linux/macOS
where codex.exe # Windows PowerShell
# 2. Can it talk to the OpenAI endpoint?
export CODEX_API_KEY=your‑key‑here # or set in your .env file
codex auth test
# Expected output:
# ✔ Authentication succeeded – token valid for 24hIf the authentication test fails, double‑check that the CODEX_API_KEY environment variable is exported in the same shell where you run codex. On Windows, you can set it permanently with:
[Environment]::SetEnvironmentVariable("CODEX_API_KEY","your‑key‑here","User")That’s it. With the CLI sitting comfortably on your path, you can start using commands like codex suggest or codex review right away, regardless of whether you’re on a laptop, a cloud VM, or a Windows workstation.
From installation to impact: a real‑world case study, pros & cons, and quick fixes
Practical example: generating a Python client library
At my last company we had a set of internal services described with OpenAPI 3.0 specs. The team that owned the payments service needed a quick way to spin up a Python client that could be used in both our Flask backend and a few data‑science notebooks. After installing Codex CLI on a fresh Ubuntu 22.04 box, the workflow looked like this:
# 1. Pull the latest OpenAPI definition from the repo
git clone https://github.com/acme/payments-api.git
cd payments-api
# 2. Verify the spec – Codex can lint for us
codex lint openapi.yaml
# 3. Generate a Python client (default uses httpx & pydantic)
codex generate client \
--spec openapi.yaml \
--lang python \
--output ./python-client \
--package-name acme-payments
# 4. Install the generated client locally for testing
pip install -e ./python-client
# 5. Use it in a script
python - <<'PY'
from acme_payments import PaymentsClient
client = PaymentsClient(base_url="https://payments.dev.acme.com")
resp = client.create_transaction(amount=1250, currency="USD")
print(resp.id, resp.status)
PY
All of that happened in under two minutes. The generated client came with:
- Typed request/response models based on
pydantic, which made IDE auto‑completion a breeze. - Built‑in retries and timeout handling that matched our internal conventions.
- A
setup.pythat let us push the package to our private PyPI with a singletwine uploadcommand.
Because the CLI respects the --output flag, we could keep the generated code in a dedicated repo, version it, and let downstream services pull a specific tag. This tiny change cut down on manual copy‑pasting of request bodies and eliminated a class of bugs that used to surface during integration testing.
Pros, cons, and how Codex CLI stacks up against alternatives
After a few weeks of using Codex for multiple services (Go, TypeScript, and Java), the following observations emerged.
| Aspect | Codex CLI | OpenAPI Generator | Swagger Codegen |
|---|---|---|---|
| Installation friction | Single binary, no runtime dependencies; works out‑of‑the‑box on Linux/macOS/Windows. | Requires Java, plus a Maven/Gradle wrapper for updates. | Same Java requirement; older releases sometimes miss recent OpenAPI features. |
| Language coverage | Python, Go, TypeScript, Java, Rust (beta). Focus on modern ergonomics (pydantic, go‑generics). | Over 30 languages, but many templates are stale. | Broad, but the output often needs manual cleanup. |
| Customization | CLI flags + optional Jinja2 templates; hot‑reload of templates via --watch. |
Template overrides via -t flag; steep learning curve for Maven‑style configs. |
Template editing possible but not as straightforward. |
| Speed | Sub‑second generation for typical specs; parallel processing built in. | Generation time scales linearly with spec size; can be minutes for large APIs. | Comparable to OpenAPI Generator, but slower on Windows due to Java startup. |
| Community & support | Active GitHub repo, weekly releases, a Slack channel that answers issues within a day. | Large user base, but PR turnaround can be weeks. | Legacy project; maintenance has slowed considerably. |
| License | MIT – no strings attached for commercial use. | Apache 2.0 – also permissive. | Apache 2.0. |
What I liked most is the consistency of the generated code across languages. The same --spec file yields a Python client with pydantic models and a Go client that uses struct tags for JSON marshaling. That uniformity saved us from having to maintain two separate code‑gen pipelines.
Where it falls short is the relative novelty of the Rust output. The template is still experimental, so you may need to tweak a few type annotations manually. Also, if you rely heavily on custom HTTP interceptors, you’ll have to inject them post‑generation; the current CLI doesn’t expose a hook for that.
Troubleshooting checklist for post‑install hiccups
Even with a clean install, a few quirks tend to pop up. Below is a quick‑scan checklist that helped me resolve most of the friction points.
- Binary not found after install
- Verify the binary is on your
PATH. On Linux/macOS runecho $PATH; on Windows runecho %PATH%. - If you used the
install.shscript, it copies to/usr/local/binby default. Ensure you have write permissions or run it withsudo. - On Windows, the installer writes to
%USERPROFILE%\AppData\Local\CodexCLI. Add that folder toPATHmanually if the installer failed to do so.
- Verify the binary is on your
- “Unsupported OpenAPI version” error
- Codex CLI currently supports OpenAPI 3.0 & 3.1. If your spec is 2.0, run
codex convert swagger2openapi.yaml -o openapi.yamlfirst. - Check for stray
$refcycles; the validator will point you to the offending line.
- Codex CLI currently supports OpenAPI 3.0 & 3.1. If your spec is 2.0, run
- Missing dependencies for generated code
- Python: the CLI adds
pydanticandhttpxtorequirements.txt. Runpip install -r requirements.txtbefore importing the client. - Go: ensure you have Go 1.19+; the generated module declares
go.modwith the appropriate version. - TypeScript: run
npm iinside the output folder; the CLI addsaxiosandzodas deps.
- Python: the CLI adds
- CLI hangs on large specs
- Pass
--max-workers 4(or any number matching your CPU cores) to cap parallelism. - Increase the temporary file limit on Linux:
ulimit -n 8192.
- Pass
- Generated code fails type checks
- Make sure your project’s type checker (mypy, golangci‑lint, etc.) is up‑to‑date with the language version the CLI targeted.
- If you see
Anyeverywhere in Python, add--strict-typesduring generation to enforce stricter typing.
- Authentication headers not applied
- The default client expects a
tokenargument. Double‑check the constructor signature in the generated code. - For bearer tokens, you can wrap the client:
class AuthenticatedPaymentsClient(PaymentsClient): def __init__(self, token: str, **kwargs): super().__init__(**kwargs) self.headers["Authorization"] = f"Bearer {token}" - The default client expects a
If you’ve crossed everything on this list and still hit a wall, the best next step is to open an issue on the Codex CLI GitHub repo and attach the offending openapi.yaml plus the exact CLI command you ran. The maintainers usually respond within a day, and the extra context helps them reproduce the problem quickly.
Overall, once the initial hiccups are ironed out, the CLI becomes a silent productivity booster. You’ll find yourself reaching for codex generate whenever a new endpoint lands, rather than manually writing request wrappers. That shift from “write‑once‑and‑forget” to “generate‑once‑and‑iterate” is what makes the tool feel less like a gimmick and more like a daily habit.
Frequently Asked Questions
Can I install Codex CLI globally or per‑project, and what are the pros and cons?
Yes, you can choose either approach. A global install (e.g., npm install -g codex-cli) makes the codex command available from any directory, which is handy for ad‑hoc scripting or when you want a single version across all your workspaces. A per‑project install (adding codex-cli to devDependencies) ties the tool to that repository’s package.json, ensuring every collaborator uses the exact same version and avoiding conflicts with other Node tools. The trade‑off is that per‑project installs require you to run it via npx codex or a npm script, while a global install is a one‑liner in the terminal.
How can I confirm that Codex CLI was installed correctly on my machine?
After running the installation command, execute codex --version (or codex -v). If the CLI is on your PATH, it will print the current version number, confirming a successful install. You can also run which codex on Linux/macOS or where codex on Windows to see the exact binary location. If you see the version and a valid path, the Codex CLI install is complete and ready for use.
Why does the codex command say “not found” after I install it on Windows?
This usually means the installation directory isn’t in your system’s PATH. When you install with npm i -g codex-cli, npm places the executable in a folder like %APPDATA%\npm. Open the Environment Variables dialog, edit the Path variable, and add that folder if it’s missing. After updating, restart your command prompt or PowerShell and run codex --version again. If the problem persists, try reinstalling with administrator rights or use the npx codex shortcut, which bypasses the global PATH requirement.
Is there a simple way to update Codex CLI without reinstalling the whole package?
Absolutely. If you installed the CLI via npm, you can run npm update -g codex-cli to pull the latest release. For a per‑project setup, just bump the version in package.json and run npm install. Some distributions also ship a self‑update command, like codex self-update, which checks the official repository and replaces the binary in place. Whichever method you use, verify the upgrade by running codex --version afterward.
Can I run Codex CLI inside a Docker container, and what’s the minimal Dockerfile setup?
Yes, the CLI works well in containerized environments. Start from a lightweight Node image (e.g., node:18-alpine), then add a line such as RUN npm install -g codex-cli to perform the installation. If your codebase lives in the container, copy it with COPY . /app and set WORKDIR /app. You can now invoke codex in any RUN or CMD instruction, letting you generate snippets or automate refactors as part of your CI pipeline. Remember to expose any required environment variables the CLI may need for authentication.