From 2e0f7fe68c63739d11f2a75fc94210be7a0397a7 Mon Sep 17 00:00:00 2001 From: johnQ Date: Wed, 7 Oct 2026 07:41:51 +0800 Subject: [PATCH] =?UTF-8?q?feat(dev-coding):=20=E6=96=B0=E5=A2=9E=E3=80=8C?= =?UTF-8?q?Step=200.5=20Shell=20=E7=8E=AF=E5=A2=83=E8=87=AA=E6=A3=80?= =?UTF-8?q?=E3=80=8D=E2=80=94=20node/npm=20=E7=BC=BA=20PATH=20+=20HOME=20?= =?UTF-8?q?=E6=9C=AA=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在 macOS + Slark/DSH 实测定位到:bash 工具以 bash -c(非登录非交互)执行, 子进程环境等于宿主进程环境(PATH 不被清洗,HOME/USER/TMPDIR/LANG 未设置), 宿主由 GUI 应用拉起继承最小 PATH → node/npm/git 直接不可用。 沉淀内容: - 5 条根因(不读 rc / PATH 不被清洗 / GUI 宿主 / HOME 未设置 / shell-env 只认 DSH_*) - 两行 export 模板:HOME + node v22.22.3 PATH(勿混用 homebrew 的 v26) - HOME 必须补的理由:~ 靠 passwd 展开易误判,git 报 fatal: $HOME not set, set -u 脚本报 unbound variable;「node 能跑」≠ 环境完整 - 交付纪律:禁止把「没有 shell / 不能构建」写成交付结论,未跑构建就如实标注 --- skills-dev/dev-coding-plugin/skills/SKILL.md | 52 ++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/skills-dev/dev-coding-plugin/skills/SKILL.md b/skills-dev/dev-coding-plugin/skills/SKILL.md index 41a63e8..2c50e20 100644 --- a/skills-dev/dev-coding-plugin/skills/SKILL.md +++ b/skills-dev/dev-coding-plugin/skills/SKILL.md @@ -608,3 +608,55 @@ fi ### 非阻断原则 架构信息缺失时**仅警告不阻止**。用户仍可继续,但会被告知"生成的建议可能不够准确"。 + +--- + +## Step 0.5:Shell 环境自检(node/npm command not found 先看这里) + +**在任何 `npm` / `pnpm` / `node` 命令之前,先确认解释器可解析。** 报 `command not found` 时 +**不要**下结论"当前环境没有 shell",也**不要**去找"给 agent 配 shell"的开关(DSH 没有这个开关)。 + +### 根因(不要重复侦察;已在 macOS + Slark/DSH 上定位到代码) + +| # | 事实 | +|---|------| +| 1 | DSH 的 bash 工具(`@deepseek-ai/dsh-bash-local`)一律以 **`bash -c`(非登录、非交互)** 执行 → **不读** `~/.zprofile` / `~/.zshrc` / `~/.profile` | +| 2 | 子进程环境 = **宿主进程环境** − 凭据类变量 − `DSH_*`(`@deepseek-ai/dsh-subprocess`)→ **PATH 不被清洗**,它等于启动宿主那个进程的 PATH | +| 3 | 宿主由 GUI 应用(Slark.app)拉起 → 继承 macOS GUI 的最小 PATH(`/usr/local/bin:/bin:/usr/bin:...`)→ node 不在里面 | +| 4 | `HOME` **未设置**(不是空值);`USER` / `TMPDIR` / `LANG` 同样未设置 | +| 5 | `@deepseek-ai/dsh-shell-env` 只注册/注入 **`DSH_*`** 变量,`PATH` 是保留键 → 改 profile/`cordis.patch.yml` 加 PATH **无效** | + +### 正确做法(两行 export,别多一步) + +```bash +export HOME="/Users/johnq" # 必须补:git 等直接读 $HOME +export PATH="/Users/johnq/.local/node-v22.22.3-darwin-arm64/bin:$PATH" # node/npm/pnpm +cd <项目> && npm install && npm run build +``` + +**为什么 `HOME` 必须补**(实测): + +- `~` 在 bash 里靠 passwd 查表展开,所以 `ls ~`、`cd ~/x` 仍能用 → **容易误判环境正常**; +- 直接读 `$HOME` 的会崩:`git` → `fatal: $HOME not set`(`status` / `commit` / `config --global` 全废); + 带 `set -u` 的脚本 → `HOME: unbound variable`(例:ai-proj-helper 的 `install-skills.sh`); +- node 侧多数无事(`os.homedir()` 走 passwd 兜底,只有 `process.env.HOME` 是 `undefined`) + → **「node 能跑」≠ 环境完整**,别据此跳过 `HOME`。 + +- **本机 node 必须用这一支**(定义在 `~/.zprofile`,对齐项目 `engines.node`): + `/Users/johnq/.local/node-v22.22.3-darwin-arm64/bin/node` = v22.22.3,npm 10.9.8。 +- `/opt/homebrew/bin/node` 是**另一支 v26**,不要混用;`/usr/local/bin/node` 不存在。 +- 备选①:`/bin/zsh -lic '<命令>'`(登录 zsh 会读 `~/.zprofile`)。 +- 备选②:绝对路径直调 `/Users/johnq/.local/node-v22.22.3-darwin-arm64/bin/node build.mjs`。 +- 路径变了先 `ls -d /Users/johnq/.local/node-v*-darwin-arm64/bin` 重新取**真实版本号**,不要猜。 + +### 交付纪律(配合「Step 0:验证优先」) + +- **禁止**把"没有 shell / 不能构建"写成交付结论:bash 工具是好的,缺的只是 `HOME` + `PATH`。 + 正确表述是"我未执行构建(缺 node PATH,已给用户补 PATH 后的构建命令)"。 +- 构建/测试没跑就说没跑(`未经构建与实机验证`),**不要**用"构建配置已就绪"之类中间信号冒充验收。 +- 校验环境的最快方式(输出直接贴进交付): + +```bash +export HOME="/Users/johnq"; export PATH="/Users/johnq/.local/node-v22.22.3-darwin-arm64/bin:$PATH" +node -v && npm -v && git status --short | head -3 +```