Running OpenClaw on a machine that ships an ancient Node.js is the fastest way to reproduce the classic “It works on my laptop” meme. OpenClaw requires Node 22 or newer. If you try to sneak in with Node 18 or even 21, the CLI refuses to start. This guide explains why that version gate exists, how to check what you have installed, and reliable upgrade paths on macOS, Linux, and Windows. I also cover optional runtimes (pnpm, bun) and the handful of native libraries that occasionally bite people on fresh systems.

Why OpenClaw pins to Node 22

A lot of projects advertise “Node 14+” and get away with it. OpenClaw does not. The maintainers locked the engines field to ^22.0.0 and here’s what that buys us:

  • Stable ESM loader. OpenClaw ships pure ES modules—no CommonJS wrapper, no conditional exports. Node 22 finally fixed the lingering import path edge cases (notably import.meta.resolve).
  • Performance bump. Node 22 runs V8 12.4 under the hood. The new JIT heuristics shave ~15-20% off cold start time for the agent gateway according to the GitHub Actions benchmarks.
  • Built-in Web Streams & fetch(). The agent uses fetch to talk to third-party APIs. Before Node 18 you needed node-fetch; pre-22 required a ponyfill in a few edge cases (AbortSignal timeouts). Gone now.
  • Permission flags. The experimental --permission model (sandboxing file, worker, and FFI access) is stable in 22. That’s what ClawCloud uses to lock down shell tools.
  • Intl Locale support needed for timezone math inside the scheduler. The newer ICU bundle ships only with Node 22 LTS.

You can absolutely fork OpenClaw and transpile it down to Node 20, but you’ll end up Babel-ing native assert patterns, losing performance, and maintaining a patch set forever. Upgrading Node is several orders of magnitude easier.

Checking your current Node.js version

First, find out where you stand. On most UNIX-y machines:

node -v

If the answer is v22.x.y, you’re done—skip to the checklist section. Anything else means you have homework. For completeness, check the package manager version too:

npm -v pnpm -v # optional bun -v # optional

OpenClaw’s installer (npx openclaw@latest) uses whichever package manager calls it. If you’re in doubt, sticking with stock npm works fine.

Upgrading Node on macOS

Option A: Homebrew (quick but global)

If you don’t care about juggling Node versions, Homebrew is the fastest path:

brew update brew install node@22 brew link --overwrite --force node@22

Homebrew moves /opt/homebrew/opt/node@22/bin into your $PATH. The --force flag clobbers any older brew-managed Node. If you manually installed Node via the .pkg installer, you might need to sudo rm -rf /usr/local/lib/node_modules first to avoid permission collisions.

Option B: nvm (recommended for dev boxes)

nvm lets you hop between Node versions without polluting /usr/local. Install it:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash source ~/.nvm/nvm.sh nvm install 22 nvm alias default 22

The alias step makes new shells default to 22. When Apple ships a major macOS, I pin a specific patch version to avoid surprise upgrades breaking native deps:

nvm install 22.4.0 nvm alias default 22.4.0

If Homebrew’s OpenSSL headers are missing you’ll see errors like ld: library not found for -lssl. Fix with:

brew install openssl@3 export LDFLAGS="-L/opt/homebrew/opt/openssl@3/lib" export CPPFLAGS="-I/opt/homebrew/opt/openssl@3/include"

Add those exports to ~/.zshrc or ~/.bash_profile so node-gyp can compile native modules.

Linux install: apt, dnf, or nvm

The distro repositories lag by design, so apt on Ubuntu 22.04 ships Node 18. That’s four majors behind. Two strategies:

Option A: Nodesource binary repos

curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - sudo apt-get install -y nodejs

The script adds a new APT source, pins Node 22, and installs both node and npm.

Option B: nvm (again)

sudo apt-get install -y build-essential curl curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash source ~/.bashrc nvm install 22

If you build inside Docker, keep your Dockerfile minimal:

# syntax=docker/dockerfile:1 FROM debian:bookworm-slim RUN apt-get update && apt-get install -y curl ca-certificates gnupg && rm -rf /var/lib/apt/lists/* RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \ apt-get update && apt-get install -y nodejs && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY package.json pnpm-lock.yaml ./ RUN npm ci --omit=dev COPY . . CMD ["node", "gateway.mjs"]

The official OpenClaw Docker image already bakes this, but knowing the recipe helps during CI debugging.

Windows paths: nvm-windows or Winget

On Windows 11 the Microsoft Store offers a one-click Node 22. The drawback: global, no version switching. Most devs I know use nvm-windows because it mirrors the UNIX workflow.

Install nvm-windows 1.1.12+

  1. Download nvm-setup.exe from the releases page.
  2. Run the installer, default path C:\nvm.
  3. Open PowerShell:
nvm install 22.4.0 nvm use 22.4.0

Double-check:

node -v # v22.4.0 npm -v # 10.5.0 at time of writing

If you see the dreaded node: bad option: --use-strict error, your PATH still points to an old node.exe. Remove it from C:\Program Files\nodejs or move that folder lower in the PATH order.

Winget fallback

If you’re on corporate lockdown and can’t run unsigned installers:

winget install OpenJS.NodeJS.LTS --override "INSTALLLEVEL=22"

The override flag forces the LTS channel to 22 once it’s the active LTS (expected 2024-10). Until then you’ll need nvm-windows.

Package manager choices: npm vs. pnpm vs. bun

OpenClaw core is tool-agnostic. The repo has package.json and pnpm-lock.yaml. At runtime the agent gateway just needs a node_modules folder. The trade-offs:

  • npm 10+ ships with Node 22. No extra install. Slower CI times but 100 % compatibility.
  • pnpm 9+ (install with npm i -g pnpm). Hard links cut disk usage by ~60 %. Watch out on Windows + WSL2 where older ntfs-3g drivers break hard links.
  • bun 1.1+ can install packages in ~2 s. The OpenClaw test suite passes on bun, but two optional dependencies (@serpapi/search and node-webcrypto-ossl) still rely on Node-specific APIs. If you use those integrations, stick to npm/pnpm.

I run pnpm install --frozen-lockfile in CI for speed, then npm run build to leverage the ecosystem’s expectation of npm scripts.

Other native dependencies you might hit

Python 3 and make

node-gyp compiles sharp (image resizing) and sqlite3. You need:

# Debian/Ubuntu sudo apt-get install -y python3 make g++ # macOS (already there via Xcode CLI tools)

libvips

The sharp prebuilds cover x64 and arm64 for Node 22. If you run OpenClaw on a funky CPU (Raspberry Pi Zero, AWS Graviton), set:

npm config set sharp_binary_host "https://npm.taobao.org/mirrors/sharp"

That forces a rebuild from source. Compile time ~10 minutes on a Pi 4B.

git >= 2.25

The installer fetches templates over git+https. On CentOS 7 the stock Git is 1.8 and chokes on shallow clones. Update:

sudo yum install https://repo.ius.io/ius-release-el7.rpm -y sudo yum install git236 -y

Common installation pitfalls & how to debug

  • TypeError: createSecureContext – You are running Node 16. Update.
  • ERR_REQUIRE_ESM when importing OpenClaw – Mixing CommonJS require() and ESM. Rename your file to .mjs or add "type": "module" in package.json.
  • npm ERR! code EBADENGINE – npm respects the engines field. Upgrade Node or pass --omit=optional if you really, really must install on older Node for a read-only audit.
  • gyp: No Xcode or CLT version detected – Run xcode-select --install on macOS.
  • ELIFECYCLE 1 during postinstall – Usually native module build failure. Scroll up to find which one, then install missing libraries.

Quick checklist before running npx openclaw@latest

  1. Node 22+: node -v should print v22.x.
  2. npm 10+ or pnpm 9+.
  3. git 2.25+ for template clone.
  4. build tools: Python 3, make, C/C++ compiler.
  5. $PATH sanity: No older Node lurking earlier in PATH.
  6. Disk space: At least 1 GB free for initial node_modules.

Pass all six and you’re 99 % guaranteed to watch the wizard prompt: “Give your new agent a name.”

Next step: Run npx openclaw@latest, answer the onboarding questions, then point your browser to http://localhost:3000. If you hit a snag that wasn’t covered here, open an issue on the GitHub repo—the maintainers triage Node-setup bugs quickly because everyone has hit them at least once.