CLAUDE LABJP
FORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as OctoberFORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as October
Articles/Claude Code
Claude Code/2026-05-14Intermediate

Claude Code Doesn't Recognize nvm/pyenv/asdf — Shell Initialization and 4 Fixes

Fix 'node: command not found' and Python version mismatches in Claude Code when using nvm, pyenv, or asdf. Learn why shell initialization is skipped and how to solve it for good.

claude-code129nvmpyenvasdfPATH2troubleshooting87environment3

"Run npm run dev" — and Claude Code returns node: command not found.

Your local terminal works fine. The version manager is set up correctly. Yet every time Claude Code executes a shell command, it seems to forget that nvm, pyenv, or asdf even exists.

I've been developing indie apps since 2014, and environment variable issues have tripped me up more times than I'd like to admit. After working through this particular problem across multiple projects, I can say the fix is straightforward once you understand what's actually happening.

Why Claude Code Can't See Your Version Manager

When Claude Code runs Bash commands, it spawns a non-interactive, non-login shell. This means it doesn't execute your shell's initialization scripts: .bashrc, .zshrc, .bash_profile, or .zprofile.

Every version manager works the same way under the hood. It hooks into your shell's startup sequence. For nvm, that looks like this in your .zshrc:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

When you open a terminal, this runs automatically, adding the nvm-managed Node.js binary to your PATH. Claude Code's subprocess never runs this initialization, so it falls back to whatever node (if any) lives in the default system PATH — typically an older system-installed version, or nothing at all.

Diagnose Your Environment First

Before applying any fix, confirm the issue with these commands in Claude Code:

# What PATH does Claude Code's subprocess see?
echo "PATH: $PATH"
which node 2>/dev/null || echo "node: not found"
which python3 2>/dev/null || echo "python3: not found"
node --version 2>/dev/null || echo "node version: not found"
python3 --version 2>/dev/null || echo "python3 version: not found"

Run the same commands in your local terminal and compare. If the PATH values are significantly different — especially if you don't see paths like /home/user/.nvm/versions/node/v20.x.x/bin — that confirms the problem.

Fix 1: Use Absolute Paths (Fastest Resolution)

The quickest workaround is bypassing the version manager entirely and calling the binary directly.

For nvm:

# List your installed versions
ls ~/.nvm/versions/node/
 
# Use the absolute path
~/.nvm/versions/node/v20.11.0/bin/node --version
~/.nvm/versions/node/v20.11.0/bin/npm install
~/.nvm/versions/node/v20.11.0/bin/npm run dev

For pyenv:

# List your Python versions
ls ~/.pyenv/versions/
 
# Use the absolute path
~/.pyenv/versions/3.11.8/bin/python3 -m pip install requests
~/.pyenv/versions/3.11.8/bin/python3 script.py

This works immediately but has a downside: when you update your Node or Python version, you'll need to update these paths too. It's a solid temporary fix, but not something you want to maintain long-term.

Fix 2: Document the Paths in CLAUDE.md

Add the resolved paths to your project's CLAUDE.md file. Claude Code reads this file at session start, so once it's there, Claude will use the correct paths consistently across the project.

## Development Environment
 
This project uses the following environment:
 
- Node.js: v20.11.0 (managed via nvm)
  - `node` binary: `~/.nvm/versions/node/v20.11.0/bin/node`
  - `npm` binary: `~/.nvm/versions/node/v20.11.0/bin/npm`
- Python: 3.11.8 (managed via pyenv)
  - `python3` binary: `~/.pyenv/versions/3.11.8/bin/python3`
 
When running commands, either use absolute paths above or load the environment first:
```bash
export PATH="$HOME/.nvm/versions/node/v20.11.0/bin:$HOME/.pyenv/versions/3.11.8/bin:$PATH"

This approach benefits everyone working in the same repository. New team members won't hit the same confusion, and Claude Code will always know where to look.

## Fix 3: Wrap Commands in a Login Shell

For cases where you need a specific command to fully inherit your shell environment:

```bash
# Force login shell initialization
bash -l -c "node --version"
bash -l -c "npm run dev"

# zsh equivalent
zsh -l -c "python3 manage.py runserver"

A caveat: Claude Code executes each Bash tool call as a separate process, so you'd need the bash -l -c "..." wrapper every time. If you find yourself using this frequently, Fix 4 is worth considering.

Fix 4: Switch to volta or mise (Long-Term Solution)

The root cause here is that nvm, pyenv, and asdf all rely on shell initialization to function. The permanent fix is switching to a version manager that doesn't have this dependency.

volta manages Node.js at the project level via package.json. Any process that reads package.json — including Claude Code's subprocesses — automatically gets the right version:

{
  "volta": {
    "node": "20.11.0",
    "npm": "10.2.4"
  }
}

mise (formerly rtx) supports Node.js, Python, Go, Ruby, and more. It uses a .tool-versions file at the project root, and versions are resolved per-process without relying on shell hooks:

# .tool-versions
nodejs 20.11.0
python 3.11.8

The migration takes some time, but once done, this class of problem disappears. I made the switch to volta for my wallpaper and wellness app projects — the kind that require juggling multiple Node versions — and haven't lost time to PATH issues since.

Which Fix Is Right for You?

  • Need it working right now: Fix 1 (absolute paths)
  • Working on a specific project with a team: Fix 2 (CLAUDE.md documentation)
  • Long-term, cross-project solution: Fix 4 (switch to volta or mise)

Start with Fix 2 if you're in a project context. Add a few lines to CLAUDE.md, specify the paths, and Claude Code will handle the rest consistently without requiring you to think about it again.

One thing I've found useful: add the environment setup to CLAUDE.md early in any new project, before the problem surfaces. It takes two minutes and saves the frustration of debugging command not found errors mid-session.

Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Claude Code2026-06-18
When a Broken settings.json Stops Claude Code From Starting — Safe Mode and How to Split Your Config
How to find which config layer is broken when a settings.json syntax error stops Claude Code from starting, recover in minutes, and structure your settings so an automated pipeline can't quietly break itself.
Claude Code2026-06-10
When git add -A Sweeps Up .bak Backups — The Quiet Trap of In-Place Fix Scripts
How .bak backups left by sed -i and homegrown --fix scripts get silently swept into production by git add -A, why it is so easy to miss, and how scoped adds and .gitignore close the gap for good.
Claude Code2026-06-09
When Yesterday's Article Bleeds Into Today's — The Stale Fixed-Name Temp File Trap
In a Claude Code automation pipeline, a fixed-name temp file kept stale content from the previous run and leaked old body text into a completely different article. Here is why the write fails silently, and how unique names plus a post-write grep check prevent it.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →