dshkit

报错排查:全局安装 @deepseek-ai/dsh 报 EACCES 权限拒绝

npm install -g 报 EACCES 的原因、为什么 sudo 会让事情更糟,以及两个干净的修法——把 npm prefix 指到你自己的目录,或者用 Node 版本管理器。

更新于 2026-08-131 min
一句话结论

你的 npm 全局 prefix 指向了 root 拥有的目录。把 prefix 改到自己拥有的目录(npm config set prefix ~/.npm-global)并把它的 bin 加进 PATH,或者用 Node 版本管理器装 Node。别用 sudo——它会在 npm 缓存里留下 root 拥有的文件,让后续安装以更难查的方式失败。

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

npm 在往一个你的用户不拥有的目录写。这和 @deepseek-ai/dsh 一点关系都没有——这是你 npm 安装本身的 状态,在你修好之前,任何全局包都会这样失败。

确认成因

npm config get prefix

如果打印 /usr/local/usr 或别的系统路径,说明 npm 的全局目录在你的 home 之外,写它需要提权。

不会制造新问题的修法

把 prefix 指到你自己拥有的目录:

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

然后把它的 bin 加进 PATH——现代 macOS 写进 ~/.zshrc,多数 Linux 写进 ~/.bashrc

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

开一个 shell(已经开着的不会重读配置),重新安装:

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

为什么不该用 sudo

sudo npm install -g @deepseek-ai/dsh 看起来会成功。破坏要到后面才显形。

以 root 身份安装,会往你的 npm 缓存和全局目录里都写入 root 拥有的文件。下一次你不带 sudo 装 任何东西时,npm 撞上一个它写不了的缓存条目然后失败——而报错通常既不提权限、也不提当初那次 sudo。 于是人们再次伸手去够 sudo,问题复利。

如果你已经这么干过,把缓存要回来:

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

macOS 上用 Homebrew 装的 Node,可能还需要:

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

然后按上面把 prefix 改掉,从此不再需要 sudo

结构性的修法:版本管理器

如果你用 Node 不止为这一个工具,改用 nvmfnmvolta 装它。每个 Node 版本都住在你的 home 目录 下、各带一套全局包目录,全局安装报 EACCES 这件事就变得不可能了。

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

有个代价要知道:每个 Node 版本的全局目录是分开的,所以在 Node 20 下装的包,Node 22 下没有。如果 升级 Node 之后 dsh 不见了,原因就在这——见 dsh: command not found

不安装的那条路

捋这些的同时你并没有被卡住:

npx @deepseek-ai/dsh web

npx 解析并运行这个包,不往任何全局目录写。启动慢一点,零配置,不涉及权限。

常见问题

为什么不直接用 sudo?

它看起来能用,但会往 npm 缓存和全局目录里写入 root 拥有的文件。之后任何一次不带 sudo 的安装都会撞上它动不了的文件,而报错通常完全指不到真正的成因。

非要全局安装吗?

不必。npx @deepseek-ai/dsh web 不装任何全局包,也从不碰系统目录。

改 prefix 和用版本管理器,哪个更好?

只要你还算常用 Node,就用版本管理器——它从结构上消灭了这整类问题,还能并存多个 Node 版本。改 prefix 是更小、更快的那个修法。

接着看