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 prefixIf 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-globalThen 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 --helpWhy 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)" ~/.npmOn macOS with Homebrew-installed Node, you may also need:
sudo chown -R "$(whoami)" /usr/local/lib/node_modulesThen 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/dshThere 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 webnpx 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.