dshkit

Fix: EACCES permission denied installing @deepseek-ai/dsh globally

Why npm install -g fails with EACCES, why sudo makes it worse, and the two clean fixes — repointing the npm prefix to a directory you own, or using a Node version manager.

Updated 2026-08-132 min
Short answer

Your npm global prefix points at a root-owned directory. Fix it by setting the prefix to a directory you own (npm config set prefix ~/.npm-global) and adding its bin to your PATH, or by installing Node through a version manager. Do not use sudo — it leaves root-owned files in your npm cache that break later installs.

npm ERR! code EACCES
npm ERR! syscall mkdir
npm ERR! path /usr/local/lib/node_modules/@deepseek-ai
npm ERR! errno -13

npm is trying to write to a directory your user does not own. Nothing about this is specific to @deepseek-ai/dsh — it is the state of your npm installation, and it will fail for every global package until you fix it.

Confirm the cause

npm config get prefix

If that prints /usr/local, /usr, or another system path, npm's global directory lives outside your home and requires elevated permission to write.

The fix that does not create new problems

Point the prefix at a directory you own:

mkdir -p ~/.npm-global
npm config set prefix ~/.npm-global

Then put its bin on your PATH — add this to ~/.zshrc on modern macOS, ~/.bashrc on most Linux:

export PATH="$HOME/.npm-global/bin:$PATH"

Open a new shell (an existing one will not re-read the file), and install again:

npm install -g @deepseek-ai/dsh
dsh --help

Why not sudo

sudo npm install -g @deepseek-ai/dsh will appear to succeed. The damage is not visible until later.

Installing as root writes root-owned files into your npm cache as well as the global tree. The next time you install anything without sudo, npm hits a cache entry it cannot write and fails — usually with an error that mentions neither permissions nor the original sudo. People then reach for sudo again, and the problem compounds.

If you have already done this, hand the cache back to yourself:

sudo chown -R "$(whoami)" ~/.npm

On macOS with Homebrew-installed Node, you may also need:

sudo chown -R "$(whoami)" /usr/local/lib/node_modules

Then set the prefix as above so you never need sudo again.

The structural fix: a version manager

If you use Node for anything beyond this one tool, install it through nvm, fnm or volta instead. Every Node version then lives under your home directory with its own global package directory, and EACCES on a global install becomes impossible.

# with fnm
fnm install --lts
fnm use --lts
npm install -g @deepseek-ai/dsh

There is a tradeoff to know about: each Node version has a separate global directory, so a package installed under Node 20 is not present under Node 22. If dsh disappears after a Node upgrade, that is why — see dsh: command not found.

The no-install path

You are not blocked while you sort this out:

npx @deepseek-ai/dsh web

npx resolves and runs the package without writing to any global directory. Slower to start, nothing to configure, no permissions involved.

Frequently asked

Why not just use sudo?

It appears to work, but it writes root-owned files into your npm cache and global tree. The next install you run without sudo then fails on files it cannot touch, with an error that points nowhere near the real cause.

Do I need a global install at all?

No. npx @deepseek-ai/dsh web runs without installing anything globally and never touches a system directory.

Which is better, changing the prefix or using a version manager?

A version manager, if you work with Node at all regularly — it makes the whole class of problem structurally impossible and lets you keep several Node versions. Changing the prefix is the smaller, faster fix.

Keep reading