Agent shell uses stale Node version vs active terminal

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

Agent shell uses stale Node version vs active terminal. My project uses a dev container with node v24.14.0 with Astro 6.1.8 which requires node >=22.12.0.

Steps to Reproduce

Repro:
Interactive terminal is on Node v24.14.0
Agent runs node -v and gets v20.18.2
Agent build fails with Astro Node requirement error (>=22.12.0)

Expected Behavior

Agent shell should inherit workspace terminal/runtime (or clearly expose/select runtime source)

Operating System

MacOS

Version Information

Version: 3.2.11
VSCode Version: 1.105.1
Commit: e9ee1339915a927dfb2df4a836dd9c8337e17cc0
Date: 2026-04-24T14:36:47.933Z
Layout: editor
Build Type: Stable
Release Track: Default
Electron: 39.8.1
Chromium: 142.0.7444.265
Node.js: 22.22.1
V8: 14.2.231.22-electron.0
OS: Darwin arm64 25.4.0

Additional Information

The agent offers misleading, potentially corrupting commands:

Verification attempt:

pnpm -F web build failed due to local Node version mismatch, not code errors:
Astro requires >=22.12.0
Current environment is v20.18.2
What to run on your machine to validate end-to-end:

Upgrade/switch Node to >=22.12.0
Start normally (without force): pnpm turbo run dev
Hard refresh once and confirm the hydration error is gone

Does this stop you from using Cursor

No - Cursor works, but with this issue

Hey, thanks for the detailed report. This is a known issue. cursor-server prepends its bundled Node v20.18.2 to PATH, and the agent shell inherits that env. The interactive terminal in the devcontainer resolves the environment later, so it picks up the correct Node version. The symptom is exactly the same as in this Remote SSH thread: cursor-server locked to Node.js 20.18.2 breaking odoo and all extensions requiring node js 22 ! Cursor Remote SSH regression: cursor-server locked to Node.js 20.18.2, breaking Odoo and all extensions requiring Node.js 22+

We’re tracking this on our side, but I can’t share an ETA yet. When there’s an update, I’ll post it here.

As a workaround for now, any of these should help:

  • Add nvm use 24 (or the equivalent for fnm or mise) to ~/.bashrc or ~/.zshrc inside the container. This runs after the prepend and will override PATH to the right Node.
  • In devcontainer.json, add "remoteEnv": { "PATH": "/path/to/node24/bin:${containerEnv:PATH}" } to explicitly set the priority.
  • Or use a symlink /usr/local/bin/node → Node 24, so the cursor-server prepended binary won’t win priority. It lives in a different path, but please double-check with which node.

Let me know if none of this works in your setup and I’ll suggest what else to check.

Cursor Remote SSH is not using node from PATH (nvm, .bashrc, remoteEnv, /usr/local/bin/node), so those workarounds do not solve the real issue.

The remote server already has Node 22.22.0 installed:
which node
/home/ubuntu/.nvm/versions/node/v22.22.0/bin/node

But Cursor launches the extension host directly using its own bundled binary:
/home/ubuntu/.cursor-server/bin/.../node

Verification:
find ~/.cursor-server/bin/linux-x64 -type f -name node -exec {} -v \;
v20.18.2

So this is not a PATH, shell, or Ubuntu issue — Cursor Remote SSH is forcibly using its bundled Node 20.18.2 runtime.

Because of that:

  1. nvm use
  2. .bashrc
  3. remoteEnv
  4. system node symlinks
  5. do not change the actual extension host runtime.

The real fix requires updating or overriding the bundled ~/.cursor-server/.../node binary itself. Otherwise Cursor will continue running the remote extension host on Node 20.18.2 regardless of PATH configuration.

Thanks Alex, spot-on reply. The workarounds Dean suggests do not solve the problem.

Hope the Cursor team make this a priority as it’ll cause problems for anyone developing with Astrojs v6.1.x as it requires node v22+ as well as Oodo and other tools. As more apps require newer node versions, the Cursor agent will fail them and offer misleading, potentially damaging instructions.

Hey Alex and Cipherbert, you’re right, and thanks for calling it out. My earlier suggestions nvm, remoteEnv, and a symlink in /usr/local/bin don’t fix it for the reason Alex mentioned: cursor-server re-adds its bundled bin/ to PATH after shell env resolution, and for the extension host it uses the bundled binary directly, skipping PATH entirely. Sorry for the noise.

This is an architectural limitation on our side, not a config issue. We’re tracking it, but I can’t give an honest ETA yet. When there’s an update, I’ll post back in the thread.

What can actually unblock you right now all of this is hacky, not a permanent fix:

  • Replace the bundled binary directly: mv ~/.cursor-server/bin/<hash>/node ~/.cursor-server/bin/<hash>/node.bak && ln -s $(which node) ~/.cursor-server/bin/<hash>/node after reconnect cursor-server may overwrite it, so check node -v after restart. On macOS dev containers the path will be inside the container.
  • Run pnpm -F web build manually in an interactive terminal instead of asking the agent. The agent can then see the result without running the build itself.
  • If an agentless build flow is critical, temporarily downgrade Astro to a version that works with Node 20 until the fix lands.

I get the prioritization pain. The more tooling requires Node 22+, the worse this gets. It’s on the team’s radar.9

We hit this too in a devcontainer and ended up automating the “replace the bundled binary directly” workaround mentioned above.

What we did was add a devcontainer postStartCommand step that:

  1. Checks whether ~/.cursor-server/bin exists.
  2. Finds every ~/.cursor-server/bin/<hash>/node.
  3. Loads NVM.
  4. Resolves the active NVM Node via nvm which node.
  5. Replaces each Cursor bundled node binary with a symlink to that NVM Node.

Example:

start/cursor-server-node:
	@bash -lc 'set -euo pipefail; \
		cursor_bin="$$HOME/.cursor-server/bin"; \
		[ -d "$$cursor_bin" ] || exit 0; \
		shopt -s nullglob; \
		cursor_nodes=("$$cursor_bin"/*/node); \
		[ $${#cursor_nodes[@]} -gt 0 ] || exit 0; \
		export NVM_DIR="$${NVM_DIR:-/usr/local/share/nvm}"; \
		. "$$NVM_DIR/nvm.sh"; \
		nvm_node="$$(nvm which node)"; \
		for cursor_node in "$${cursor_nodes[@]}"; do \
			rm -f "$$cursor_node"; \
			ln -s "$$nvm_node" "$$cursor_node"; \
			echo "Linked $$cursor_node -> $$nvm_node"; \
		done'