Nix 開發環境
使用 Nix flakes、nixpkgs unstable、devenv 和 direnv 建立和維護專案開發環境。保持 flake 的公開介面精簡,並將 shell 相關細節放在獨立的 Nix 檔案中。
互動合約
將 Nix 配置視為可執行的專案政策。請勿隱式修改或啟用它。
- 先檢查儲存庫並解釋提議的變更。
- 在建立、編輯、重新命名或刪除檔案之前,要求一次明確的許可。將相關編輯分組到一個清晰的請求中。
- 編輯完成並獲得批准後,提出驗證命令,並在執行任何命令之前要求單獨的許可。
- 不要未經明確指名並獲得許可就執行
direnv allow。它授權自動評估專案配置。
如果使用者拒絕任一許可,則僅提供計劃或命令,並在該邊界停止。
預設值與範圍
- 新工作須有 flake。除非專案已固定其他修訂版本且使用者要求更改,否則使用
nixpkgs/nixos-unstable。 - 支援所有語言。僅在專案需要時才添加語言套件、格式化工具、linter、服務和環境變數。
- 偏好將
nix develop和devShells.<system>.default作為可攜式介面。 - 當需要
devenv的聲明式模組、服務、腳本、測試和 git hooks 等功能時,使用它。不要在原始的mkShell和devenv中建立重複的定義,除非解釋哪一個是權威來源。 - 僅在請求時或專案已使用
direnv時,透過簽入的.envrc整合它。保留使用者僅限本機的環境設定。 - 不要僅僅因為偏好較新的佈局,就取代或刪除現有的
shell.nix、flake.nix、.envrc、devenv.nix、鎖定檔案或 CI 設定。
在提出變更前先檢查
至少尋找:
flake.nix、flake.lock、shell.nix、default.nix和nix/目錄devenv.nix、devenv.yaml和.envrc- 語言清單和鎖定檔案、格式化/linter 配置、任務執行器和 CI 工作流程
- 提及設定指令或支援平台的文件專案
在提出佈局之前,先閱讀現有的 Nix 表達式。確定專案是否已有 flake、支援哪些系統、如何固定依賴項、是否安裝或配置了 devenv,以及是否刻意排除了 direnv。
當某個指令有助於探索時,優先使用唯讀指令,例如 nix flake metadata 或 nix flake show。如果尚未獲得使用者批准執行命令,請在執行前先請求許可。
檔案佈局
對於新的或配置簡單的儲存庫,除非儲存庫已有更完善的慣例,否則建議採用此佈局:
.
├── flake.nix
├── flake.lock
├── devenv.nix # 使用時的 devenv 特定模組和服務
├── .envrc # 使用時的 direnv 入口點
└── nix/
└── devshell.nix # 套件、變數和 shell hooks
flake.nix 應包含 inputs、支援系統的管道設置和匯出的 outputs。將 mkShell 參數、套件列表、環境變數和 shell hooks 放在 nix/devshell.nix 中。當 shell 大幅增長時,在 nix/ 下使用更多專注的檔案,例如 nix/packages.nix 或 nix/hooks.nix。
新設定請勿使用 shell.nix。如果已存在,請保留它,除非使用者明確批准遷移計畫。在遷移期間,解釋對仍使用 nix-shell 的使用者所造成的相容性影響。
設計工作流程
1. 說明當前狀況
總結相關的現有檔案、偵測到的專案工具以及任何不確定之處。如果需求不完整,請提出有針對性的問題,例如:
- 必須支援哪些平台(例如,僅 Linux 還是 Linux 和 macOS)?
- shell 中應可執行哪些專案指令?
- 是否需要資料庫或其他本機服務?
devenv應該主導環境,還是應該在devShell周圍添加功能?
2. 提出實施方案
精確描述將添加或更改哪些檔案及其原因。包括 flake.lock 是否會變更、是否會建立或編輯 .envrc,以及每個相依項的來源由誰管理。
對於新的通用 flake,使用明確的支援系統策略,並公開 devShells.<system>.default。匯入單獨的 shell 表達式,而不是將整個 mkShell 主體放在 flake.nix 中。保持初始套件集合精簡:不要為了讓模板看起來完整而添加任意語言工具鏈。
如果使用者請求使用 devenv,請選擇與已安裝/固定版本之 devenv 設定相容的整合方式。將 devenv 宣告保留在 devenv.nix(或其匯入的重點檔案)中。明確說明使用者是透過 nix develop、devenv shell 還是兩者進入,並確保記錄的入口點不會默默分歧。
對於 direnv,使用專案現有的慣例。基於 flake 的 .envrc 通常依賴於 nix-direnv 支援;基於 devenv 的 .envrc 則依賴於適當的 devenv 整合。不要撰寫一個尚未確定所需 direnv 擴充功能的入口點。
將以下事項視為獨立事實:是否已安裝 nix-direnv、它是否與使用者的 direnv 整合,以及此專案的 .envrc 是否能成功評估。不要使用 direnv stdlib(或其輸出中缺少 use flake)作為安裝檢查:它反映的是該次調用可用的標準函式庫,對於聲明式的 NixOS 或 Home Manager 配置並非權威。特別地,空的 direnv stdlib | grep -F 'use flake' 結果並非缺少 nix-direnv 的證據。
當探索獲得批准時,檢查相關證據,但不要誇大其證明力:
- 在 NixOS 或可取得 Home Manager 配置時,尋找
programs.direnv.enable = true和programs.direnv.nix-direnv.enable = true(或等效的模組配置)。將其報告為聲明式配置,而非活躍的 shell 已載入它的證據。 - 檢查
nix-direnv和direnv在當前環境中是否可用,並在可存取時檢查適用的direnvrc或產生的 direnv 配置。將不可用的可執行檔或缺少整合檔案報告為當前環境的觀察結果,而非關於使用者聲明式配置的斷言。 - 讀取專案的
.envrc以識別其所需的擴充功能。使用direnv status檢查其目前的授權/載入狀態。不要推斷use flake入口點能起作用,直到它在該專案中經過評估。
僅在獲得明確許可後,才授權並測試專案的 .envrc。指出 direnv allow 會改變信任狀態;接著使用 direnv reload 或 direnv exec . <harmless-command> 來執行配置。如果無法執行評估,則應說明整合未經驗證,而非宣告 nix-direnv 未安裝。
3. 取得編輯許可
使用類似於以下的簡潔確認請求:
我將添加
nix/devshell.nix、更新flake.nix以匯出預設的開發 shell、添加/更新devenv.nix和.envrc,並在依賴解析需要時生成/更新flake.lock。我可以進行這些編輯嗎?
等待肯定的回答。如果提議的工作與批准的計劃不同,請在進行額外編輯前再次詢問。
4. 謹慎編輯
保留格式和區域性命名慣例。將註解重點放在不明顯的限制上,而不是重述 Nix 語法。透過 flake.lock 固定 flake 輸入;不要用浮動 URL 取代鎖定檔案。
添加 shell 套件時,優先使用專案固定 pkgs 提供的套件。避免使用 unfree 套件、不安全套件許可、二進位快取或 substitute 配置,除非使用者明確要求並批准。
5. 提出驗證並取得單獨許可
編輯完成後,僅列出相關的指令,說明其目的,並請求許可。可以從以下選項中選擇:
nix flake check
nix flake show
nix develop --command <project-check-or-tool-version-command>
devenv test
devenv shell -- <project-check-or-tool-version-command>
direnv allow
盡可能使用無害的指令進行 shell 進入驗證,例如所需工具的 --version 或專案格式化工具的檢查模式。在可能導致網路存取、建置、下載或鎖定檔案更新的指令之前,解釋預期的情況。除非使用者明確要求,否則絕不執行 nix flake update、廣泛的垃圾回收、儲存刪除或用於更改設定檔的指令。
6. 報告結果
說明已更改的檔案、入口指令、驗證結果以及任何剩餘的手動步驟。例如,指出使用者在審查 .envrc 後是否應執行 nix develop、devenv shell 和/或 direnv allow。
疑難排解原則
- 在更改固定版本或添加覆蓋之前,先重現並檢查實際錯誤。
- 區分評估錯誤、缺少屬性、平台支援問題、建置錯誤和執行期依賴問題。
- 在假設某個 unstable 套件存在或具有預期名稱之前,檢查固定的輸入和套件屬性。
- 偏好一個小範圍、有文件的修正,而非全域性的 Nix 配置更改。
- 當某項變更可能影響可重現性或所有貢獻者時,提出替代方案並在編輯前請求許可。
完成條件
僅在配置是模組化的、最終回應中說明了宣告的入口點、請求的檢查已通過或其結果已清楚報告,並且每次編輯和驗證指令都經過所需許可後,才將任務視為完成。