dsh-path-toolv1.0.0
zetako/dsh-path-tool
dsh plugin --profile web add github:zetako/dsh-path-tool#7d31a8e3781fd82024419987a114e5b2ce4380b3
介绍
为 DSH 的 shell 命令注入 PATH 目录,并放宽 workspace-write 沙盒的可写目录(Seatbelt / bwrap / Landlock),带图形配置页。 | Inject PATH for DSH shell commands and widen workspace-write sandbox roots, with a GUI config page.
标签
概述
dsh-path-tool
English | 中文
终端路径工具(插件页显示名)。让 DSH(DeepSeek Harness)里的 shell 命令找得到非默认 PATH 下的工具,并让受限沙盒下的构建写得了自己的缓存目录。两项能力都在 Plugins 页提供图形配置界面。
它解决什么问题
DSH 执行 shell 命令用的是 bash -c,非交互、非登录、不读任何 rc 文件。这意味着:
- macOS 上从 Finder/Dock 启动的 DSH 只继承
/usr/bin:/bin:/usr/sbin:/sbin,看不到/opt/homebrew/bin,于是git、go、rg、mysql这些 Homebrew 装的东西在模型眼里全部「不存在」; - 即使用
~/.zshenv设了 PATH 也没用,因为bash -c不加载它; - DSH 自己也不会读你的 shell 配置:
BOOTSTRAP_NAMES明确拒绝从.env设置PATH,ctx.shellEnv注册表只管DSH_*命名空间。
另一半问题是沙盒。workspace-write 模式只放行「会话工作区 + /tmp」,而 Go 必须写 GOCACHE(~/.cache/go-build)与 GOMODCACHE(~/go/pkg/mod)。这些目录在沙盒外,于是每条 go build 都会触发一次沙箱升权审批——本该只在你真正要改工作区外的文件时被打断。
本插件把这两件事变成一次性配置。
功能
| 能力 | 说明 |
|---|---|
| PATH 注入 | 把指定目录前置或后置进每条 shell 命令的 PATH,覆盖前台、run_in_background 与超时转后台三条执行路径 |
| 沙盒放宽 | workspace-write 下额外放行你指定的可写目录,后端自动适配 macOS Seatbelt、Linux bwrap 与 Landlock 回退 |
| 图形配置 | 在 Plugins 页逐条增删目录、切换前置/后置、一键恢复当前平台的默认项,保存后下一条命令即生效 |
| 平台默认值 | 默认目录按宿主平台生成(macOS /opt/homebrew/*、Linux /usr/local/*),不会给你塞一堆本机不存在的路径 |
| 零依赖 | 不打包、不构建,react 由 DSH 提供,其余控件自绘 |
工作原理
flowchart LR
subgraph Host["DSH Host"]
P["Plugins 页配置表单<br/>(client.js)"] -->|"PUT /dsh-path-tool/prefs"| R["偏好路由<br/>(index.mjs)"]
R -->|"prefs.json"| F[("$DSH_HOME/dsh-path-tool/prefs.json")]
R -->|"内存权威副本"| E["包装后的 ctx.shell<br/>resolve / execute"]
R --> S["包装后的 ctx.sandbox<br/>confine()"]
end
E -->|"spec.env.PATH"| B["bash -c"]
S -->|"改写 argv profile"| C["bwrap / Seatbelt / landlock-run"]
PATH 注入
插件包装 ctx.shell 实例上的 resolve 与 execute。execute(spec) 是所有执行请求的唯一收口,因此在这里改写 spec.env.PATH 就能覆盖全部执行路径,且不会重复合并。偏好保存在内存里,每次执行都读最新值——改完配置不需要重启。
不能通过重新provide一个同名 service 来替换ctx.shell:cordis 会抛service "shell" has been registered。
沙盒放宽
插件包装 ctx.sandbox 的 confine(),在它返回的 argv 里追加可写目录:
| 沙盒后端 | 追加方式 |
|---|---|
| Seatbelt(macOS) | 往 SBPL profile 末尾追加 (allow file-write* (subpath "…")) |
| bwrap(Linux 首选) | 在 -- 之前插入 --bind <dir> <dir>,靠后的挂载覆盖只读根 |
| Landlock(Linux 回退) | 在 -- 之前插入 --rw <dir> |
沙箱本身没有改变,只是可写集合变大。read-only 与 danger-full-access 完全不受影响。三种后端都要求授予的路径真实存在,插件会在保存偏好时自动创建缺失的目录。
只放宽 shell,不放宽文件工具。 文件工具(dsh-fs-sandbox)的可写集合仍按原规则计算,模型不能借这条路径读写你配置的缓存目录。这是有意为之。
安装
要求:DSH >=0.2.1-rc.5 <0.3.0(见 package.json 的 engines.dsh),Node.js ≥ 22。
方式一:从本地目录安装(推荐用于本仓库)
# 在 profile 里以 link 方式挂载本目录
dsh plugin --profile web add link:/绝对路径/dsh-path-tool
也可以直接把目录 link: 进 ~/.dsh/profiles/web/package.json 的 dependencies,并在 dsh.profile.bundles 里加上 "dsh-path-tool"。
方式二:在 Plugins 页操作
打开 DSH Web → Plugins → 安装,把 dsh-path-tool 指向本目录即可;安装器同样接受本地路径。
安装后重启 dsh web(或等 HMR 热加载),插件会自动插入自己的配置行。
配置
Plugins 页 → 已安装 → 终端路径工具(dsh-path-tool)→ 配置,或用该行右侧的 Configure 入口。
| 配置项 | 说明 | 默认值 |
|---|---|---|
| 追加的 PATH 目录 | 必须是绝对路径,非绝对路径会被忽略;重复项自动去重 | macOS:/opt/homebrew/bin、/opt/homebrew/sbin、/opt/homebrew/opt/mysql-client/binLinux:/usr/local/bin、/usr/local/sbin、~/.local/bin |
| 注入位置 | 「前置」让这些目录优先于系统 PATH;「后置」只在系统 PATH 找不到时才生效 | 前置 |
| workspace-write 额外可写目录 | 仅在 workspace-write 下生效;不存在的目录会自动创建 | GOCACHE 与 ~/go/pkg/mod |
偏好以 $DSH_HOME/dsh-path-tool/prefs.json 为权威(DSH_HOME 缺省为 ~/.dsh)。也可以直接编辑该文件,或用路由读写:
# 读取当前偏好、平台默认值与沙盒接入状态
curl -s http://127.0.0.1:3080/dsh-path-tool/prefs | jq
# 覆盖偏好(PUT 与 POST 等价)
curl -s -X PUT http://127.0.0.1:3080/dsh-path-tool/prefs
-H 'content-type: application/json'
-d '{"pathEntries":["/opt/homebrew/bin"],"mode":"prepend","sandboxRoots":["/Users/me/.cache/go-build"]}'
GET 的响应形如:
{
"ok": true,
"prefs": { "pathEntries": ["…"], "mode": "prepend", "sandboxRoots": ["…"] },
"defaults": { "pathEntries": ["…"], "mode": "prepend", "sandboxRoots": ["…"] },
"status": { "platform": "darwin", "sandboxAttached": true }
}
status.sandboxAttached 为 false 时配置界面上会出现提示——它表示 Host 侧没有可用的 ctx.sandbox,此时「额外可写目录」不生效(PATH 注入不受影响)。
安全提醒:dsh-host-webserver本身不做鉴权,它靠绑定回环地址(默认127.0.0.1)与 DSH 的 trusted-host 机制来限制访问。如果你用反向代理或--trusted-host把 Web UI 暴露给他人,那么任何能打开这个界面的人都能改写插件的偏好——包括往 PATH 里塞任意目录、放行任意可写路径。不要把带本插件的 DSH 暴露给不可信的用户。
验证
- PATH:在会话里让模型执行
which <你的工具>,应当命中你配置的目录。也可以直接看 Host 日志里的[dsh-path-tool] PATH prepend: …。 - 沙盒:把
workspace-write下的GOCACHE指向配置的目录,跑一次go build,不应再弹出沙盒审批。日志里的[dsh-path-tool] workspace-write 额外可写: …会列出实际授予的目录。 - 单元测试:
npm test
兼容性
- 声明
engines.dsh: ">=0.2.1-rc.5 <0.3.0"。DSH 在安装与 profile 启动时都会校验该范围,越界会要求显式豁免,而不是静默组合出问题。 - Windows 不支持:本插件针对 POSIX 的
PATH与 argv 形态实现,Windows 上会得到空的默认值、沙盒放宽不生效。DSH 官方 profile 目前也不以 Windows 为主目标。 - 沙盒后端由 DSH 的沙盒包动态选择;插件只识别上述三种 argv 形态,遇到不认识的形态会原样返回、不做改写(并打日志说明)。
lib/prefs.mjs在模块加载时读取DSH_HOME,修改DSH_HOME需要重启 DSH 才生效。
卸载
dsh plugin --profile web remove dsh-path-tool
插件不会改动 DSH 自身文件,卸载后 PATH 与沙盒立即恢复原生行为。偏好文件 $DSH_HOME/dsh-path-tool/prefs.json 会保留,如不需要可手动删除。
开发
npm test # 15 个用例,覆盖三种后端、偏好持久化与包装还原
node --check index.mjs
node --check client.js
维护本仓库前请先读 AGENTS.md,里面记录了包装幂等、可选注入、偏好隔离等硬约束。测试的夹具与 DSH_HOME 都落在临时目录,不会污染你本机的配置。
许可
MIT © 2026 Zhang Yexi (zetako)
星级评价
基本信息
插件信息来自公开 GitHub 仓库与 SkillHub,版权归原作者所有;安装前请自行审查仓库代码。