Run npm ls -g --depth=0 to confirm the package installed, then npm bin -g to find the global bin directory and add it to your PATH. If you use nvm or fnm, a global install only exists for the Node version that was active when you ran it.
The install printed success, and the shell disagrees. Three causes account for nearly all of these, and one command distinguishes them.
Step 1 — did it actually install?
npm ls -g --depth=0Look for @deepseek-ai/dsh in the output.
Not listed? The install failed despite what scrolled past. Re-run it and read the tail of the output rather than the last line:
npm install -g @deepseek-ai/dshListed? The package is on disk and this is a PATH problem. Continue.
Step 2 — is npm's global bin on your PATH?
npm bin -gThat prints the directory npm puts global executables in — something like
/usr/local/bin, /opt/homebrew/bin, or ~/.npm-global/bin. Check whether it is in your PATH:
echo $PATH | tr ':' '\n' | grep -F "$(npm bin -g)"No output means the directory is missing from PATH. Add it to your shell profile — ~/.zshrc on
modern macOS, ~/.bashrc on most Linux:
export PATH="$(npm bin -g):$PATH"Then open a new shell, or source the file. An already-running shell will not re-read your profile
on its own.
Step 3 — are you on the Node version you installed into?
This one catches people who did everything right.
nvm, fnm and volta give each Node version its own global package directory. A global
install performed under Node 20 does not exist under Node 22. If you installed dsh, later switched
or upgraded Node, and the command vanished — this is why.
node -v
nvm ls # or: fnm listTwo ways out. Reinstall under the version you now use:
npm install -g @deepseek-ai/dshOr, with nvm, migrate your globals when upgrading:
nvm install 22 --reinstall-packages-from=20The EACCES variant
If the install itself fails with EACCES: permission denied, your npm prefix points at a
root-owned directory. The tempting fix is sudo. Don't — it writes root-owned files into your npm
cache and global tree, and the next non-sudo install fails in a much less obvious way.
Point the prefix somewhere you own:
mkdir -p ~/.npm-global
npm config set prefix ~/.npm-global
export PATH="$HOME/.npm-global/bin:$PATH" # add to your shell profile
npm install -g @deepseek-ai/dshOr install Node through a version manager, which puts everything under your home directory and makes the problem structurally impossible.
The escape hatch
While you sort out the shell, you are not blocked:
npx @deepseek-ai/dsh webnpx resolves and runs the package without touching your PATH at all.
Still nothing?
Confirm the binary exists where npm says it should:
ls -l "$(npm bin -g)/dsh"If the file is there but does not run, check it is executable (chmod +x) and that you are not
shadowing it with a shell alias or function:
type -a dshtype -a shows every dsh your shell can see, in resolution order — including an alias defined in
a profile you forgot about.
Frequently asked
Can I use dsh without fixing my PATH?
Yes — npx @deepseek-ai/dsh web works regardless of PATH. It is a good workaround while you sort out the shell configuration, and a fine permanent choice if you only use the harness occasionally.
Should I use sudo npm install -g?
No. It appears to fix EACCES errors but leaves root-owned files in your npm cache and global directory, which causes harder-to-diagnose failures on later installs. Reconfigure the npm prefix or use a Node version manager instead.