dsh-nix-dev-shell:讓 DSH 的 bash 自動進入工作區 Nix devShell

前言

在 DeepSeek Harness(DSH)裏,Agent 通過 bash 工具改代碼、跑構建。若項目用 Nix flake 定義 devShell,工具鏈和依賴都在 /nix/store 裏;而 Harness 默認在宿主 shell 裏執行命令,容易出現「本機沒裝 dune / ocaml」「PATH 不對」這類問題。手工每條命令前加 nix develop --command 不現實,模型也未必知道當前該不該用 Nix 環境。

下面介紹社區插件 dsh-nix-dev-shell(維護者 running-grass,分類:工作流):當命令工作目錄或其上級目錄存在 flake.nix 時,自動把 bash 放進該 flake 的 devShell,且不替換 DSH 自帶的 shell 執行器,沙箱、超時、後臺任務等行爲保持不變。

這是什麼

dsh-nix-dev-shell 是 Host 側 JS 插件(MIT,當前 package 版本 0.3.0,需 Node ≥ 20)。它修飾 Harness 的 ctx.shell.execute,在 dsh-bash-* 執行器之上做一層裝飾,而不是換掉執行器本身。

定位一句話:工作區有 flake 時,讓 DSH 的 bash 命令等價於在 nix develop 環境裏跑;沒有 flake、沒有 nix、或捕獲失敗時,原樣退回原生 bash 並打日誌告警。

核心功能

祖先目錄查找 flake

按 spec.workdir 向上查找 flake.nix(默認文件名可配置,最多向上 40 層),行爲類似 direnv 的祖先查找。命中後對該 flake 目錄的 devShell 生效;未命中則不注入任何東西。

兩種運行模式

  1. env(默認):對 flake 目錄一次性運行 nix print-dev-env(含 shellHook),與當前進程環境做差集後緩存,注入到每次 spawn 進程的 env。後續每條命令沒有 nix 啓動開銷,shellHook 的標準輸出也不會混進工具結果。
  2. wrap:把命令改寫成 nix develop <flakeDir> --command bash -c '…',語義與手工 nix develop 一致,但每條命令多一次 nix 求值(README 稱約 0.3–1s),且 shellHook 輸出會出現在結果裏。

與 Harness 其它能力的關係

因爲始終調用原執行器,以下不受影響:文件沙箱(workspace-write / read-only / danger-full-access)與提權審批;超時、onExpiry、abort、輸出截斷;後臺任務與 run_in_background;DSH_* 等受管環境變量(由 ctx.shellEnv 收集,優先級最高)。捕獲 devShell 時通過未修飾的原執行器跑 helper,沙箱策略與調用方相同,不會額外提權。

沙箱內的 Nix 緩存

workspace-write 沙箱下 ~/.cache 只讀,直接跑 nix develop 等會報 fetcher cache 無法打開。插件在 flake 工作區內、且命令受沙箱約束時,可注入 NIX_CACHE_HOME(默認相對 flake 根爲 .dsh-plugins/.cache/nix),隻影響 nix,不整體改 XDG_CACHE_HOME。danger-full-access 下不自動注入。

告訴模型「已在 devShell 裏」

可選地向系統提示詞貢獻一句正面陳述(promptContext,默認開啓):說明 bash 在指定 flake 的 nix develop 環境裏,IN_NIX_SHELL=impure、工具來自 /nix/store。僅在已成功捕獲 devShell 且 cwd 在 flake 子樹內纔出現;agent/created 時可預捕獲(最多約 2.5s),便於首條系統提示詞即準確。

緩存與失效

每個 flake 目錄的戳記由 flake.nix、flake.lock 及目錄三層內 *.nix(有界掃描)的 mtime/size 組成;捕獲失敗在 retryMs 內負緩存。刷新失敗時優先複用上次成功捕獲的環境,從未成功過纔回退原生 shell。

安裝與啓用

官方安裝命令(來自 README):

dsh plugin --profile web add github:running-grass/dsh-nix-dev-shell

Host 插件是 JS 模塊,安裝或更新後需要重啓 DSH 進程纔會加載新代碼。

開發時也可在會話裏通過 plugin_manager 從本地目錄安裝:

{ "action": "install_bundle", "target": "/abs/path/to/dsh-nix-dev-shell" }

安裝後執行 plugin_manager list_plugins,應看到 include:nix-dev-shell 且 fiberPhase=active。

驗證與典型用法

裝好後,在含 flake.nix 的目錄或其子目錄執行:

echo $IN_NIX_SHELL      # impure
command -v ocaml dune   # /nix/store/…(宿主機上沒有它們)
echo $NIX_CACHE_HOME    # 沙箱可寫的 nix 緩存目錄

在不含 flake 的目錄(例如 $HOME)應保持原生環境,插件不會注入。

常用配置項在 cordis.patch.yml 中已有默認值,可在行內 config 調整,例如:

鍵 默認 說明
enabled true 總開關
mode 'env' 'env' 注入環境 / 'wrap' 走 nix develop --command
flakeFile 'flake.nix' 向上查找的文件名
maxAncestors 40 最多向上查找層數
injectCacheHome true 沙箱內是否注入 NIX_CACHE_HOME
promptContext true 是否向系統提示詞說明 devShell 已生效
prefetch true agent/created 時預捕獲 devShell

完整表格與 captureTimeoutMs、ttlMs、cacheDir、nixCommand 等見倉庫 README。

卸載示例:

{ "action": "remove_bundle", "target": "dsh-nix-dev-shell" }

適用場景與注意

適合誰:用 Nix flake 管理 devShell 的倉庫,在 DSH 裏希望 Agent 的 bash 自動帶上 flake 裏的編譯器、包管理器和 shellHook 導出的變量,又不想改每條命令或換執行器。

安全與邊界:

  • 祖先查找意味着:若 $HOME 或上層目錄有 flake.nix,其子樹內每條 bash 都會進該 devShell,第三方倉庫首次命令也會跑其 shellHook。只在可信倉庫啓用,或設 enabled: false、調小 maxAncestors。
  • 只覆蓋 ctx.shell(bash 工具、子代理、hooks、後臺任務);PTY / tmux 不在範圍內。
  • env 模式不傳 shell 函數、別名;與「替換 ctx.shell 服務」的插件不兼容。
  • 插件以當前 DSH 進程權限運行;安裝前請閱讀源碼與 MIT 許可證,自行評估是否納入工作流。

DSH 生態是「一切皆插件」;SkillHub 等社區目錄爲獨立站點,與 DeepSeek / 幻方無官方從屬關係。

結尾

dsh-nix-dev-shell 把「工作區有 flake 就用 devShell」做成透明裝飾層:默認 env 模式低開銷注入,沙箱下配合 NIX_CACHE_HOME,並可選告知模型當前環境。需要完整配置、性能實測與安全說明時,以 GitHub README 爲準。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜