If Claude Code says it failed to auto-update on macOS Sonoma, this is likely the exact error you're seeing.
Diagnose your npm setup
Before you start, it's important to know where your global npm modules are installed, because the fix depends on it:
Custom npm prefix (e.g., ~/.npm-global): Your global modules live in ~/.npm-global/lib/node_modules/
nvm (Node Version Manager): Your global modules live in ~/.nvm/versions/node/<version>/lib/node_modules/
Homebrew Node: Your global modules live in /usr/local/lib/node_modules/
To check which you have:
bash
npm config get prefix
This will show you the exact path where global installs go. The fix steps below cover all three cases.
Important: If npm config get prefix doesn't match where Claude actually lives (check with ls -l $(which claude)), you may have a prefix mismatch—see the Troubleshooting section for how to fix this.
Why this happens
The problem isn't Claude Code itself, but npm on macOS. During a global install or upgrade, npm tries to rename the existing claude-code folder to a temporary one (like .claude-code-XXXXXX). If any leftover files—or even hidden macOS files like .DS_Store—remain in the directory, npm can't finish the rename, and the install fails.
This issue is especially common on macOS Sonoma and later with npm 10+ and Node 22+, due to stricter APFS file locking and extended file attributes. The --no-bin-links npm flag and other rename operations exacerbate the problem.
Good news: This is npm-specific. Users on the native installer, Homebrew, or npx don't see this error. As of January 2026, npm installation is officially deprecated—the native installer is the recommended path forward.
Fix ENOTEMPTY (if you're using npm)
If you haven't seen the exact error ENOTEMPTY: directory not empty, rename, skip to the Troubleshooting section below to match your specific error. If this is your error, follow these steps:
For all users (before step 1)
First, check if you have leftover temporary directories from a failed install:
bash
ls -la $(npm config get prefix)/lib/node_modules/@anthropic-ai/ | grep "\.claude-code-"
If you see folders like .claude-code-xxxxx, note that these need to be removed too — they're what cause the ENOTEMPTY error.
Step 1: Remove the existing Claude Code folder
Replace $(npm config get prefix) with your actual prefix (it will auto-expand):
bash
rm -rf $(npm config get prefix)/lib/node_modules/@anthropic-ai/claude-code
Why this matters: These hidden .claude-code-* folders are what caused the original ENOTEMPTY error. Deleting them is safe and necessary to prevent the same error on reinstall.
Step 3: Clear the npm cache
bash
npm cache clean --force
Step 4: Reinstall Claude Code globally
bash
npm i -g @anthropic-ai/claude-code
That's it — the install should now complete cleanly.
Fallback 1: --no-bin-links (if reinstall still fails)
If you still hit an ENOTEMPTY error after these steps, try installing with the --no-bin-links flag, which bypasses npm's symlink creation (a common trigger for the rename failure on macOS):
This means npm is trying to write to a system-protected directory (/usr/local). You likely installed Node via an OS installer or Homebrew, which set a global prefix that your user account can't write to.
Do NOT use sudo. Instead, either:
Option 1: Reconfigure npm to use a user-writable directory
bash
mkdir -p ~/.npm-global
npm config set prefix ~/.npm-global
export PATH="$HOME/.npm-global/bin:$PATH"# Add this to ~/.zshrc or ~/.bashrc
Then retry the install:
bash
npm i -g @anthropic-ai/claude-code
Option 2: Use nvm (Node Version Manager) instead
nvm installs Node and npm in your home directory by default, avoiding system permission issues altogether.
Option 3: Use the native installer (recommended)
Better yet, skip npm entirely and use the native installer (see below). This avoids permission issues and is the officially recommended path.
Fallback 2: Use npx (temporary workaround)
If both the ENOTEMPTY cleanup and --no-bin-links still fail, you can temporarily run Claude Code via npx:
bash
npx @anthropic-ai/claude-code
This bypasses the npm global rename issue entirely because npx doesn't install globally—it fetches the package on-demand and runs it.
Pros:
Always runs the latest version
No global npm conflicts
Completely sidesteps ENOTEMPTY
Cons:
Slower first run (downloads the package)
Anthropic shows a deprecation notification recommending the native installer
Not suitable as a long-term solution
Use npx only as a short-term workaround while you migrate to the native installer (see below).
Recommended: Migrate to the native installer
The most reliable way to avoid ENOTEMPTY, EACCES, and npm-related issues is to use Anthropic's native installer. As of January 2026, npm installation is officially deprecated.
Install Claude Code via native (recommended)
bash
curl -fsSL https://claude.ai/install.sh | bash
Then ensure the binary is on your PATH:
bash
export PATH="$HOME/.local/bin:$PATH"# Add this to ~/.zshrc or ~/.bashrc
Verify the install:
bash
claude --version
Migrate from npm to native (if you already have npm installed)
If you've been using the npm package, switch to native:
Install the native version (curl command above)
Remove the npm package:
bash
npm uninstall -g @anthropic-ai/claude-code
Verify you're using the native binary:
bash
which claude # Should show ~/.local/bin/claude
Why native is better
No npm errors: No ENOTEMPTY, EACCES, or permission issues
Auto-updates: Native automatically updates in the background (npm and Homebrew require manual updates)
Works everywhere: Requires only curl and bash—no Node or npm required
Official recommendation: The path forward endorsed by Anthropic
Troubleshooting: Still hitting errors?
If the above steps don't work, match your error to one of the scenarios below:
"ENOTEMPTY: directory not empty, rename..."
You're in the right place. Follow the step-by-step fix above. The key is deleting the .claude-code-* temp directories—they're what actually trigger the loop. If you still see ENOTEMPTY after the cleanup:
Verify npm config get prefix points to where Claude actually lives: ls -l $(which claude)
Try the --no-bin-links fallback above
Or use npx @anthropic-ai/claude-code as a temporary workaround
Best option: migrate to the native installer (see below)
"EACCES: permission denied, mkdir..."
See the section "Fix EACCES: permission denied" above. This is a permissions issue, easily resolved by either reconfiguring npm or switching to the native installer.
"command not found: claude" after native install
Your PATH isn't set. Add this to your ~/.zshrc or ~/.bashrc:
bash
export PATH="$HOME/.local/bin:$PATH"
Then restart your terminal and try again.
Other errors
Run claude doctor (native install only) or check the official troubleshooting guide. If you see a different npm error string, paste it into the npm docs (npm.js.org) to understand the underlying issue—it's usually a permissions or network problem unrelated to Claude Code itself.
Summary: Why it happens and how to fix it
The ENOTEMPTY error occurs when npm on macOS (specifically with APFS, extended file attributes, and npm 10+) tries to rename your existing Claude Code installation during an auto-update or reinstall. The rename fails if leftover directories or hidden temp files block the operation—a combination of macOS file-system locking and npm's update mechanism.
The immediate fix: Clean up stale directories and reinstall (the steps above).
The long-term fix: Use the native installer, which avoids npm entirely. As of January 2026, npm installation is officially deprecated in favor of Anthropic's native installer.
Whichever path you choose—cleanup-and-reinstall or migrate to native—you'll be ready to use Claude Code without update failures.
Let me know in the comments if you've run into other update quirks on macOS, and subscribe for more practical dev fixes.