让每条命令自动继承工作区的 direnv 环境变量
28.7/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/16 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add Snowy117/dsh-direnv该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:需留意
是什么
dsh 原生插件 · other
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 29 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
⚠︎ 实装验证未通过(unknown · 2026/10/16) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 3 处,展示前 3 条)
- 写入剪贴板client/env-details.ts:118
Promise.resolve(UI.writeClipboard(value)) - 发起网络请求client/hub.ts:163
fetch(url, { - 执行外部命令来自配置/变量src/evaluator/spawn.ts:82
child = spawn(file, [...args], {
扫描于 2026/11/2(0 天前) · 范围 全包扫描(包内未声明入口) · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/schemastery@deepseek-ai/dsh-subprocess-local给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
让 DeepSeek Harness 每条命令都加载对应工作区的 direnv 环境,使 DSH 每个工作区的子进程自动带上该工作区的 direnv 环境。
README
由 DeepSeek 最新模型翻译生成dsh-direnv
dsh plugin add dsh-direnv
装好之后,harness 运行的每条命令都会继承它自己工作目录的 direnv 环境。安装约两分钟;需要 PATH 里有 direnv。
~/.dsh $ dsh web # no .envrc here
└── session in ~/projects/api
└── bash: build → has cargo, DATABASE_URL, …
安装
1. 先跑 direnv version。失败就先装 direnv——本插件绝不会替你执行 direnv allow。
2. 装上插件:
once it is on npm
dsh plugin add dsh-direnv
from a checkout instead: npm install runs the build that produces lib/
npm install && dsh plugin add "file:$PWD"
3. 确认补丁生效。期望看到 disabled: true:
dsh --profile <name> --dump-config | grep -A3 'id: subprocess'
检查它是否生效
1. 在一个有已批准 .envrc 的工作区里开一个会话。
展开完整文档(README 剩余 1 节)
dsh-direnv
dsh plugin add dsh-direnv
装好之后,harness 运行的每条命令都会继承它自己工作目录的 direnv 环境。安装约两分钟;需要 PATH 里有 direnv。
~/.dsh $ dsh web # no .envrc here
└── session in ~/projects/api
└── bash: build → has cargo, DATABASE_URL, …
安装
1. 先跑 direnv version。失败就先装 direnv——本插件绝不会替你执行 direnv allow。
2. 装上插件:
once it is on npm
dsh plugin add dsh-direnv
from a checkout instead: npm install runs the build that produces lib/
npm install && dsh plugin add "file:$PWD"
3. 确认补丁生效。期望看到 disabled: true:
dsh --profile <name> --dump-config | grep -A3 'id: subprocess'
检查它是否生效
1. 在一个有已批准 .envrc 的工作区里开一个会话。
2. 让模型执行 bash -c 'echo $SOME_VAR_YOUR_ENVRC_SETS'。
3. 看右侧栏的 direnv tab:状态、变量名,以及按优先级排列的 PATH 差分。
第 2 步打印出空行,就说明环境没加载进来,去「排障」。
它做什么
插件接管 harness 的 subprocess 缝隙,按工作目录求值 direnv export json。
三条流程共用这一个事实来源,且互不阻塞:
| 流程 | 行为 |
| 注入 | spawn 在缓存里查这个目录,把差量并进子进程环境。查找是同步的、永不等待:未知目录原样放行,求值在后台跑;而 spawnTerminal(你自己开的 PTY)会先等求值完成。 |
| 门闸 | 会话环境还未知时,工具调用会被拦下等待——模型可以说话、也可以请求工具,只是这些调用会像工具本身很慢一样停在原地。门闸每个会话只武装一次,最多等 loadTimeoutMs,而且它是延迟而不是过滤器:确定结果、超时、被取消,三者都会放行。放行不会取消求值,求值带着自己的预算继续跑(evaluateTimeoutMs,0 = 永不杀)。 |
| 界面 | 一条 sourced 提示告诉模型加载了什么。右侧栏的 tab 告诉你变量名、PATH 差分(新增/移除/不变)与凭据名单——全部由 DSH 官方组件绘制,所以跟着你装的主题走。 |
上溯交给 direnv 自己:锚点是每次 spawn 自己解析出来的 cwd,所以 cd 进子目录的命令拿到的是那个子目录的环境,任何 .envrc 的改动都在下一次工具调用时生效。
配置
- id: direnv-subprocess
name: 'dsh-direnv'
config:
enabled: true
direnvPath: '' # empty = resolve direnv from PATH
loadTimeoutMs: 300000 # tool calls wait at most this long, then proceed
evaluateTimeoutMs: 0 # kill the direnv child after this long (0 = never kill)
gateTools: all # all | spawning | none ('spawning' currently behaves like 'all')
injectSensitive: all # all | filter
notifyModel: true # one sourced message per workspace state change
sidebar: true # right-sidebar tab and composer placeholder
disabledDirs: [] # absolute paths to leave alone
- injectSensitive: filter 会扣下名字像凭据的变量(/KEY|PASSWORD|SECRET|TOKEN/i)。只适合谨慎场景——它会让需要这些值的 dev shell 半残。
- loadTimeoutMs 是门闸的预算:一次工具调用最多被拦多久,超过就带着当时已知的信息放行。
- evaluateTimeoutMs 约束 direnv 子进程本身。0 表示永不杀,因为冷启动的 use flake 时长不可预测。代价是:一个永不结束的 .envrc 会在每个目录留一个 direnv 进程活到会话结束。
排障
这里几乎每一种失败都是安静的。别假定它工作了,先读启动输出。下面五条覆盖绝大多数情况:
| 你看到的 | 含义 | 怎么办 |
| dsh: skipping profile bundle "dsh-direnv" | peer 版本范围不匹配,整个 bundle 被跳过。它的补丁从未执行,--dump-config 看起来和一次干净安装一模一样。 | 换一个版本范围能接受的 DSH,或用 dsh plugin allow-version 接受风险。 |
| dsh: disabling profile plugin row "direnv-subprocess" | 行级预检把它禁用了。--dump-config 不显示这件事。 | 同上。 |
| dsh: warning: N entries did not activate 加 … pending (waiting for service: subprocess) | 补丁生效了但插件没起来,于是命令连 bash 工具都没有。 | 找 direnv-subprocess (…): failed to import;确认包已安装、exports 能解析。 |
| Error: service "subprocess" has been registered at <LocalSubprocessRuntime> | 两行补丁没有一起生效,或者补丁没找到目标行。 | 两行都要留,并让 bundle 排在 @deepseek-ai/dsh-base 之后。 |
| 从源码检出安装后,web app 直接非零退出、不打印 URL | exports 指向 lib/,而它只有在构建后才存在。 | 跑 npm install(它的 prepare 会构建)或 npm run build。 |
另外两条
| 你看到的 | 含义 | 怎么办 |
| patch: entry "subprocess" not found(只出现在 --dump-config 的 stderr) | bundle 被排到了它要修改的那一行之前。 | 在 dsh.profile.bundles 里把它移到 @deepseek-ai/dsh-base 之后。 |
| 右侧栏的 tab 从来不出现 | client 半边被静默丢弃了。 | dsh.client.platform 必须精确等于 "web",而 dsh.client.inject 的每一项都必须是精确的包名——<pkg>/client 这种后缀不会被归一化,什么都匹配不到。 |
--dump-config 并不能预测一切:它只组合补丁、不跑行级预检。补丁类警告只在它那里出现,兼容性拒绝只在启动时出现。两处都要读。
如果插件起来了、但某个工作区没有环境,就打开侧边栏那个 tab:它把 blocked、 unreadable、absent 分开报告,也会告诉你某个目录只是与「这里没有 .envrc」无法区分。
安全
- .envrc 就是任意代码。 求值会以你的身份在沙箱之外跑 bash。插件只求值 direnv 本来就会求值的文件,且绝不替你批准任何一个。
- 变量值不会以文本形式进模型上下文。 提示里只有数量、路径与警告;要看名字、要按需展开值,去侧边栏。
- 名字像凭据的变量默认照注入。 overlay 叠在 harness 已清洗的环境之上。这正是插件的意义——也正是 injectSensitive 存在的原因。
- 求值器会剔除全部 DIRENV_,所以从一个 direnv 加载过的 shell 里启动的 harness,无法复活它已经清洗掉的变量。
- 状态路由自带围栏。 请求走 harness 自己的连接校验,不像零围栏的 /plugins/ 载体。
局限
- MCP server 与 host 侧辅助进程绕过这个缝隙。 任何经 MCP SDK 或 host 进程直接 spawn 的东西都看不到工作区环境。覆盖到的是 harness 自己的 shell、subprocess、搜索、git 与 PTY 消费方。
- 另一个 subprocess provider 会把它挤掉。 一个 context 只能有一个实现;插件输掉时会响亮报错。
- 有些目录看起来就是空的。 不可读的 .envrc(chmod 000)或被 direnv deny 的目录,与「这里没有 .envrc」产出的空输出一模一样。
- 失败的 .envrc 可能半成功。 source 找不到文件、语法错误时 direnv 仍然退出 0,而更早的变量已经生效。侧边栏与模型提示都会把它标成 degraded。
- harness 自己的名字过滤会赢两次。 环境里名字含有 KEY、PASSWORD、SECRET、TOKEN 的变量(包括 TURKEY_MODE 这种无辜名字)会在 overlay 之前被清洗掉。只有 .envrc 显式设置的值能活下来。
另外三条
- 求值不是免费的。 direnv 没有跨进程缓存,所以一个 use nix 的工作区每次工具调用都要重跑约 0.2 秒(缓存冷时是数秒)。便宜目录改用重新指纹来验证:.envrc、.env、direnv.toml、lib/.sh 与 nix-direnv 会重写的 .direnv/ 文件取内容哈希,普通 watch_file 目标取 mtime+size。
- 挂住的 .envrc 默认不会被杀。 想给它兜底就设一个有限的 evaluateTimeoutMs。
- 超时或中止是「不再等」,不是「没有副作用」。 整个进程组会被 SIGKILL——direnv、source .envrc 的 bash、以及它的后代——但那个 .envrc 可能已经写了文件或起了服务。这里没有任何东西阻止 .envrc 运行;那是 allow 库和 enabled: false 的职责。
开发
npm run typecheck # three projects: host, browser half, tests and harness
npm test # unit tests: evaluator (real direnv) + host wiring
npm run test:client # client half: boot row, byte-identical module, and the fenced status route
test/harness/run.sh --all # end-to-end cases, no API key needed
严格 TypeScript;装已发布的包不需要你这边构建:src//.ts 逐文件编译到 lib/ (host 半边),client//.ts 打成单文件 lib/client.js 交给浏览器。npm install 会通过 prepare 构建;lib/ 不入库。DESIGN.md 记录了架构与每个决策背后的实测证据。
npm test 故意用显式的 test/.test.ts glob:裸 node --test 会顺带执行 test/harness/ 下的脚本。测试台要走 run.sh,而不是 node test/harness/run.ts——包装会先清掉 DSH_HOME/DSH_PROFILE_DIR,而测试台按设计拒绝对一个活着的 DSH home 运行。
测试台用一个桩 LLM 驱动 dsh headless,所以真实的一轮对话与真实工具执行可以离线跑。
亲手试一试——一次性 home,不写 ~/.dsh
build the checkout once (npm install runs the build through prepare)
cd /path/to/dsh-direnv && npm install
a demo workspace in a scratch home
export DSH_HOME=$(mktemp -d)/dsh-home && mkdir -p "$DSH_HOME" /tmp/demo/proj
cd /tmp/demo/proj && printf 'export HANDS_ON=yes-from-envrc\n' > .envrc && direnv allow
dsh --profile demo --from-default-profile web --dump-config # seed a profile
dsh plugin --profile demo add "file:/path/to/dsh-direnv" # appends our bundle last
dsh --profile demo --no-open --port 30100 # open the printed URL
打开那个 URL,在 /tmp/demo/proj 里开一个会话,看右边的 direnv tab。host 半边也可以从外部验证——cookie 来自打印出来的 ?token= 链接:
curl -s -H "Cookie: $COOKIE" \
"http://127.0.0.1:30100/plugins/dsh-direnv/status.json?dir=/tmp/demo/proj&force=1"
{"ok":true,…,"status":{"state":"ok","envrcPath":"/tmp/demo/proj/.envrc","variables":[{"name":"HANDS_ON",…}]}}
一次性 home 没有配模型,所以侧边栏能渲染、真实对话发不出去。想看模型侧行为(那条 sourced 提示、以及命令继承环境),就让你自己那份已配好的 home 跑一次——绝对路径条目只挂 host 半边(它不是包,没有清单,也就没有侧边栏 tab):
cat > /tmp/dsh-direnv.yml <<'EOF'
- id: subprocess
disabled: true
- insert:
- id: direnv-subprocess
name: '/path/to/dsh-direnv/lib/index.js'
EOF
dsh --profile web --patch /tmp/dsh-direnv.yml --no-open --port 30100
then, in a workspace with an .envrc, ask the model to run:
bash -c 'echo $YOUR_VAR'
绝对不要对 nix 托管的 profile 跑 dsh plugin add:它会把 profile 的软链替换成普通文件。
上面那种绝对路径 insert,或 DESIGN.md §6.3 的 nix 侧做法,才是非破坏性的路。
许可证
MIT预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
Snowy117/dsh-direnv
让每条命令自动继承工作区的 direnv 环境变量
相关插件 · 其他
模型破甲清洗YuJunZhiXue/dsh-purge
⚔️ DeepSeek Harness 网络安全红队工具dsh-purge
★ 14,822已汉化DeepSeek 客户端
73
逆向分析桥接Fanqi89/dsh-rea
REA(Reverse Engineer Anything)MCP 桥接,用来把 REA 逆向工具接入 DSH 插件
★ 51已汉化DSH
72
红队越狱测试套件Minglink/dsh-infinite-gen-5
DeepSeek v4.1 flash 逆向工具无限五代 求 Star 收藏 ⭐欢迎大家提交项目的改进
★ 3,759已汉化DSH
71.4
语音女友beiyege-01/dsh-voice-ai-girlfriend
语音 AI 女友Voice AI girlfriend for DeepSeek Harness:Whisper…
★ 718已汉化DSH
71.2
协同办公空间dream-num/univer-workspace
一个让人类与 AI Agent 共同创作、协作和审阅的开源 Office 工作空间。
★ 2,261已汉化DSH
70.7
破甲评测WoYun520/dsh-purge
在本机分离宿主拦截与模型拒绝,做受控红队评测
★ 199已汉化DSH
69.7