What does npm install -g actually do?
The -g flag installs a package once for the whole machine and puts its command on your PATH. Where globals live, the EACCES fix, and npm 12's install-script approval flag.
The -g flag switches npm install into global mode: instead of installing into the current project’s node_modules folder, the package goes into npm’s system-wide prefix, and its executables are linked onto your PATH, turning a package into a command you can run from anywhere. So npm install -g openclaw@latest means: fetch the package called openclaw at whatever version its latest tag points to, install it once for this whole machine, and make openclaw work as a terminal command.
Local vs global, in one rule
npm’s docs compress the decision to two lines: install it locally if you’re going to require() it, install it globally if you’re going to run it on the command line. A local install serves one project: dependencies land in ./node_modules, versioned per-project, listed in its package.json. A global install serves you: CLI tools you invoke by name. On Unix systems globals land in {prefix}/lib/node_modules with executables linked into {prefix}/bin; on Windows both live directly under the prefix. Agent CLIs (OpenClaw, Claude Code, and friends) are the command-line case, which is why their installs start with -g.
Seeing what your machine actually has
npm prefix -g # where "global" is on this machine
npm root -g # the global node_modules folder
npm ls -g # every globally installed packageWorth running once just to demystify things: the global prefix is an ordinary folder, the packages in it are ordinary directories, and the commands on your PATH are links into them. When a tool misbehaves, these three commands tell you what’s really installed and where, including the classic two-Node-installations confusion, where each Node has its own prefix and your globals seem to vanish after an upgrade.
The permissions trap
On systems where the global prefix is root-owned (common with OS-packaged Node), npm install -g fails with EACCES. npm’s own guidance is to reinstall Node with a version manager (“the best way to avoid permissions issues”) or to move npm’s default directory somewhere you own. Resist the reflex to sudo your way past it: routinely installing packages as root means every install script runs as root, which is more trust than a package registry deserves. A version manager solves it permanently and makes Node version requirements painless at the same time.
What npm 12 changed for global installs
Since npm 12 (July 2026), dependency lifecycle scripts (the postinstall hooks packages can ship) are blocked by default and skipped with a warning unless you approve them. For global installs the approval is the --allow-scripts flag, which the npm docs describe as intended exactly for npm install -g and npx. Name the packages whose install scripts you’re choosing to trust:
npm install -g openclaw@latest --allow-scripts openclawNote the failure mode is quiet: without the flag the install succeeds but the scripts silently don’t run, which can leave a tool half-set-up with no error to Google. If a freshly installed CLI behaves oddly under npm 12+, check the end of the install output for the skipped-scripts list before debugging anything else.
The rest of the lifecycle
@latest in the install command is a dist-tag: a pointer the publisher moves, and the same place a bare npm install resolves to anyway; pinning an exact version ([email protected]) is how you opt out of surprises. Later, npm update -g <pkg> moves you forward deliberately and npm uninstall -g <pkg> removes “everything npm installed on its behalf.” For agent software specifically, the global npm route is one of several install shapes: the source-vs-Docker comparison covers when a container beats a global install and vice versa.