Skip to main content
OpenAIbeginner

Fix "EACCES: permission denied" — npm install -g @openai/codex

Resolve `npm error code EACCES` and `EACCES: permission denied` when running npm install -g @openai/codex. Move npm's global prefix off root-owned directories without sudo, then fix the follow-on "codex: command not found".

8 min readUpdated August 2026

If npm install -g @openai/codex fails before Codex CLI is ever installed, you will see one of these:

npm error code EACCES
npm error syscall mkdir
npm error path /usr/local/lib/node_modules/@openai
npm error errno -13
npm error Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/@openai'
npm error The operation was rejected by your operating system.
npm error It is likely you do not have the permissions to access this file as the current user

On npm 9 and earlier the same failure is printed with the older prefix:

npm ERR! code EACCES
npm ERR! syscall mkdir
npm ERR! path /usr/local/lib/node_modules/@openai
npm ERR! errno -13
npm ERR! Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/@openai'

Same cause, same fix. This guide resolves it without sudo, then deals with the "command not found" error that frequently follows.

Why This Happens

npm install -g writes into npm's global prefix. Check yours:

npm config get prefix

If that prints /usr/local or /usr, the directories npm needs to write — lib/node_modules, bin, share — are owned by root. npm itself is running as you. The very first step of installing a scoped package is creating the scope directory @openai, that mkdir is rejected by the OS, and npm reports errno -13 (EACCES).

This is not specific to Codex. It affects every global npm install on a system where Node was installed from the nodejs.org .pkg installer, from apt-get install nodejs, or from any method that places Node under a root-owned prefix.

Fix 1: Move the Global Prefix to a Directory You Own

This is the fix that works on every platform and survives Node upgrades.

# 1. Create a user-owned directory for global packages
mkdir -p ~/.npm-global

# 2. Tell npm to use it
npm config set prefix ~/.npm-global

# 3. Add its bin directory to PATH (zsh — the macOS default)
echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

# 4. Install Codex CLI — no sudo
npm install -g @openai/codex

# 5. Confirm
codex --version

If your shell is bash, use ~/.bashrc (Linux) or ~/.bash_profile (macOS) in step 3 instead of ~/.zshrc.

Fix 2: Use a Node Version Manager

If you expect to install more global CLIs, install Node through a version manager. Both nvm and fnm place Node and its global node_modules inside your home directory, so the permission problem cannot recur.

# nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
exec $SHELL
nvm install 22
nvm use 22

npm install -g @openai/codex
codex --version

Codex CLI ships prebuilt binaries as optional dependencies per platform, so make sure the install completes rather than being interrupted. A truncated install produces a different error on first run:

Missing optional dependency @openai/codex-linux-x64. Reinstall Codex: npm install -g @openai/codex

Re-running the install with a working network connection resolves that.

Fix 3: Homebrew Node (macOS)

On Apple Silicon, Homebrew installs into /opt/homebrew, which is owned by your user account, so the global prefix is already writable:

brew install node
npm config delete prefix   # drop any earlier override
npm install -g @openai/codex
codex --version

On Intel Macs Homebrew uses /usr/local, which it also chowns to your user during setup, so the same applies.

Advertisement

Fix 4: Take Ownership of the Existing Prefix

If you would rather keep the current prefix, npm's documented alternative is to change its owner:

sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}
npm install -g @openai/codex

This works, but a Node upgrade that recreates those directories can re-introduce root ownership. Prefer Fix 1 or Fix 2 for a machine you use daily.

Why Not Just Use sudo

sudo npm install -g @openai/codex usually appears to work, and it is the reason many people hit EACCES again a week later. It causes three problems:

  • Files land in ~/.npm (your cache) owned by root, so your next non-sudo npm install fails with EACCES on the cache instead of the prefix.
  • Package lifecycle scripts execute as root.
  • The installed binary may not be readable or executable by your user in the way you expect.

If you have already run a sudo install, reset the cache ownership before continuing:

sudo chown -R $(whoami) ~/.npm

Windows

Windows reports this as EPERM or EACCES on a path under %AppData%\npm or C:\Program Files\nodejs. Two working approaches:

# Option A: elevate for the install only
# (right-click PowerShell -> Run as Administrator)
npm install -g @openai/codex
codex --version
# Option B (preferred): nvm-windows, which installs under your user profile
nvm install 22
nvm use 22
npm install -g @openai/codex

If the file is locked rather than permission-denied, close any editor or terminal that has Node running and retry.

If npm is not the problem and the standalone installer is the one failing — with Could not find Codex package or platform npm release assets for Codex — see that installer error; switching to npm is one of its documented workarounds.

The Follow-On Error: "codex: command not found"

After you change the prefix, the install succeeds but the shell may still report:

zsh: command not found: codex

The binary exists; your PATH does not include the new prefix's bin directory. Confirm the location and fix PATH:

# Where did it actually install?
npm config get prefix          # e.g. /Users/you/.npm-global
ls $(npm config get prefix)/bin/codex

# Add it permanently — substitute the real path, do not leave a command
# substitution in your profile or every new shell will run npm on startup
echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

# zsh caches command locations — clear it if the path is right but the error persists
hash -r

Then open a new terminal window and run codex --version.

Verify the Fix

npm config get prefix              # a path inside your home directory
npm ls -g --depth=0                # should list @openai/codex
which codex                        # resolves to <prefix>/bin/codex
codex --version                    # prints the installed version

If all four succeed, authenticate and you are done:

codex

Prevent It Coming Back

  • Never install global npm packages with sudo.
  • Keep npm config get prefix pointing inside your home directory, or manage Node with nvm/fnm.
  • Put the PATH export in your shell profile, not just the current session, so new terminals inherit it.
  • After a major Node upgrade, re-run npm config get prefix and which codex — an upgrade can reset both.

Next Steps

Frequently Asked Questions

Find answers to common questions

npm's global prefix points at a root-owned directory such as /usr/local/lib/node_modules or /usr/lib/node_modules, but npm is running as your user. The mkdir for the @openai scope fails with errno -13. Change the prefix to a directory you own instead of escalating with sudo.

No. sudo installs leave root-owned files in your npm cache and global tree, which causes EACCES on the next non-sudo install or update, and it runs package install scripts as root. Move the global prefix to a user-owned directory instead.

Run 'npm config set prefix ~/.npm-global', create the directory with 'mkdir -p ~/.npm-global', then add ~/.npm-global/bin to your PATH in ~/.zshrc or ~/.bashrc and reload the shell.

The install succeeded into your new prefix, but that prefix's bin directory is not on your PATH yet. Run 'npm config get prefix', add its /bin subdirectory to PATH in your shell profile, then open a new terminal.

They are the same failure printed by different npm versions. npm 10 and later prints 'npm error'; npm 9 and earlier prints 'npm ERR!'. The cause and the fix are identical.

Yes. Node version managers install Node and the global node_modules tree inside your home directory, so the global prefix is user-owned by construction and EACCES cannot occur.

Windows reports EPERM or EACCES when the npm prefix under %AppData%\npm or Program Files is locked or requires elevation. Open PowerShell as Administrator for the install, or use nvm-windows so the prefix lives in your user profile.

Yes. Run 'sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}'. This is npm's documented alternative, but a user-owned prefix or a version manager is more durable across Node upgrades.