前言¶
在 DeepSeek Harness(DSH)里,模型通过 shell、subprocess 等工具在仓库里跑命令。若项目用 direnv 管理 .envrc,本机终端里 cargo、DATABASE_URL 等往往已经就绪,但 Harness 默认启动的子进程未必带上同一套环境。常见做法是手动 export、写 wrapper,或在对话里反复提醒模型「先 source」。dsh-direnv 接管 Harness 的 subprocess 接缝,按每次 spawn 的实际工作目录执行 direnv export json,把差异合并进子进程环境,使同一 session 下不同目录可以各自对应各自的 direnv 状态。
这是什么¶
dsh-direnv 是社区插件,维护者为 Snowy117,在 DSH 插件目录中归类为工作流。一句话:让 DSH 为每个工作区(按 resolved cwd)自动加载 direnv,无需在每条命令前手工激活。插件不替你执行 direnv allow;.envrc 仍须按 direnv 惯例事先批准。
- 目录页:https://www.skillhub.cn/plugins/Snowy117/dsh-direnv
- 源码与文档:https://github.com/Snowy117/dsh-direnv
- 许可证:MIT(见仓库
package.json)
社区目录为独立站点,与 DeepSeek / 幻方无官方从属关系;DSH 生态理念是「一切皆插件」,本插件通过 bundle patch 扩展官方 subprocess 能力。
核心功能¶
README 将行为归纳为三条共用同一数据源、互不阻塞的链路:
| 链路 | 行为 |
|---|---|
| Injection(注入) | spawn 从缓存按目录查找 direnv 差异并合并到子进程环境。未知目录先原样转发,后台异步求值;spawnTerminal(你打开的 PTY)会等待求值完成后再 spawn。 |
| Gate(门控) | 当 session 环境尚未知时,工具调用会被短暂 hold——模型仍可对话和请求工具,但调用会像工具本身很慢一样等待。每个 session 门控最多等 loadTimeoutMs;超时、确定结果或取消都会释放,且不会取消仍在进行的 direnv 求值。 |
| Surfaces(展示) | 向模型发送一条带来源的 notice(说明加载了什么);右侧边栏 tab 展示变量名、PATH diff(增删未变)及凭证列表,UI 组件来自 DSH 自身以跟随主题。 |
锚点是每次 spawn 的自身 resolved cwd:命令 cd 到子目录会用该子目录的环境;任意 .envrc 变更在下一次工具调用时生效。
覆盖范围(README Limits):Harness 的 shell、subprocess、search、git 与 PTY 消费者走该接缝;MCP SDK 或 host 进程侧 spawn 不经过此路径。仅一个 subprocess provider 占座;若被其它 provider 取代,插件会明显报错。
安装与启用¶
前置:本机 PATH 上须有 direnv,且插件不会替你 direnv allow。
1、确认 direnv 可用:
direnv version
若失败,请先安装 direnv,再继续下面步骤。
2、安装插件(官方 README 命令):
dsh plugin add dsh-direnv
README 另说明:从 checkout 安装时需先构建出 lib/(exports 指向该目录):
npm install && dsh plugin add "file:$PWD"
3、确认 patch 已落地;期望看到 disabled: true(README 原文表述,表示 subprocess 相关 patch 条目存在):
dsh --profile <name> --dump-config | grep -A3 'id: subprocess'
package.json 声明 Node >=22.18,并对 @deepseek-ai/dsh-subprocess-local 有 peer 范围;若启动出现 dsh: skipping profile bundle "dsh-direnv",需升级 DSH 或使用 dsh plugin allow-version(见 Troubleshooting)。
默认配置片段(可在 profile 中按 id direnv-subprocess 调整):
- id: direnv-subprocess
name: 'dsh-direnv'
config:
enabled: true
direnvPath: '' # 空则从 PATH 解析 direnv
loadTimeoutMs: 300000 # 工具调用最多等待这么久后仍继续执行
evaluateTimeoutMs: 0 # direnv 子进程超时后 kill(0 = 不 kill)
gateTools: all # all | spawning | none
injectSensitive: all # all | filter
notifyModel: true # 每个工作区状态变更一条 sourced 消息
sidebar: true # 右侧边栏 tab 与 composer placeholder
disabledDirs: [] # 不处理的绝对路径列表
injectSensitive: filter 会 withhold 名称像凭证的变量(/KEY|PASSWORD|SECRET|TOKEN/i);谨慎场景可用,但会破坏依赖这些变量名的 dev shell。
典型用法¶
README 用目录树说明行为:~/.dsh 下跑 dsh web 时若无 .envrc,session 进入 ~/projects/api 后,bash: build 等命令应带上该目录 direnv 提供的 cargo、DATABASE_URL 等。
验证是否生效:
1、在已有已批准 .envrc 的工作区打开 session。
2、让模型执行(将 SOME_VAR_YOUR_ENVRC_SETS 换成你 .envrc 里设置的变量名):
bash -c 'echo $SOME_VAR_YOUR_ENVRC_SETS'
3、查看右侧边栏 direnv tab:状态、变量名、按优先级排列的 PATH diff。
若第 2 步输出为空,表示环境未加载,应查 Troubleshooting 与边栏 tab(blocked、unreadable、absent 等状态分开报告)。
适用场景与注意¶
适合谁:多仓库、多 flake/devshell、或各子目录独立 .envrc 的团队;希望 DSH 里模型执行的命令与你在该目录下 direnv 加载后的 shell 一致,而不在 prompt 里重复 export。
安全与权限(务必阅读 README Security):
.envrc是任意代码;求值时在你的用户身份下跑 bash,插件只求值 direnv 本来就会求值的文件,且不会替你 approve。安装前请检查源码与 MIT 许可证,并理解插件以当前dsh进程权限运行。- 变量值默认不以明文进入模型上下文;notice 只有计数、路径与警告,具体值在边栏按需 reveal。
- 默认
injectSensitive: all,凭证形态的变量名会进入命令环境(叠加在 Harness 已 scrub 的环境之上);若需保守可设filter,但可能破坏依赖。 - 求值前会从交给
direnv的环境中剥离所有DIRENV_*,避免从 direnv 加载过的 shell 启动 Harness 时「复活」已被 scrub 的变量。
常见静默失败(节选):peer 不匹配导致整包 skip;patch 未落在 @deepseek-ai/dsh-base 之后;checkout 安装未 npm install 导致缺少 lib/;Web 客户端需 dsh.client.platform 恰为 "web" 且 inject 包名精确匹配,否则边栏 tab 可能不出现。启动日志与 --dump-config stderr 都应看——二者预测能力不完全相同。
其它限制:不可读的 .envrc 或与「无 .envrc」在输出上可能难以区分;失败的 .envrc 可能部分变量已生效(degraded 状态会在 notice 与边栏体现)。
结尾¶
dsh-direnv 把 direnv 的「按目录_walk_环境」接到 DSH 的 subprocess 上:安装命令是 dsh plugin add dsh-direnv,前提是本机已有 direnv 且各目录 .envrc 已按惯例允许。若你已在用 direnv 管开发环境,可在 DSH session 里用 echo 变量与右侧 direnv tab 做一次对照验证。
- 插件目录:https://www.skillhub.cn/plugins/Snowy117/dsh-direnv
- GitHub:https://github.com/Snowy117/dsh-direnv