nix-flake-organization
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseNix flake organization
Nix flake 组织规范
Keep as the public output layer and as the implementation layer. The flake tree names, routes, and re-exports outputs; feature behavior, module bodies, package derivations, app scripts, and helper logic live under .
flake/src/src/<name>/...Apply codebase-design within those boundaries:
keep each feature's implementation together and extract only to hide complexity
or enable useful reuse. Nix output adapters are meaningful public entrypoints;
additional internal forwarding files need their own purpose. Preserve Nix's
roles rather than imposing TypeScript and directories.
models/services/将作为公共输出层,作为实现层。flake目录树负责输出的命名、路由和重导出;功能行为、模块主体、package derivation、应用脚本和辅助逻辑都存放在目录下。
flake/src/src/<name>/...在上述边界内应用代码库设计规范:将每个功能的实现代码放在一起,仅在需要隐藏复杂度或实现有效复用的时候才进行抽取。Nix输出适配器是有意义的公共入口;额外的内部转发文件需要有明确的用途。保留Nix的角色定位,不要强行套用TypeScript的和目录结构。
models/services/When to use
适用场景
- A user asks to reorganize or refactor a Nix flake layout.
- Flake outputs are crowded into or mixed with implementation code.
flake.nix - NixOS, nix-darwin, Home Manager, or flake-parts modules contain business logic directly in output wiring files.
- A repo needs a clear split between public flake API and implementation internals.
- 用户要求重组或重构Nix flake的布局。
- Flake输出都挤在中,或者与实现代码混在一起。
flake.nix - NixOS、nix-darwin、Home Manager或flake-parts模块的业务逻辑直接写在输出编排文件中。
- 代码仓库需要清晰划分公共flake API与内部实现。
When NOT to use
不适用场景
- The task is only to add one package, app, or module without changing repo layout.
- The repo is not a Nix flake.
- The user explicitly wants a different established project layout preserved.
- 任务只是添加一个包、应用或模块,不需要改变仓库布局。
- 该仓库不是Nix flake项目。
- 用户明确要求保留现有的其他项目布局。
Canonical prompt
标准提示词
Use this improved prompt when turning the request into an implementation plan:
Reorganize this repo so its public flake surface lives in a top-leveldirectory:flake/,flake/apps,flake/packages, andflake/libwhere applicable. Keepflake/modules/{flake-parts,home-manager,darwin,nixos}as a minimal entrypoint and keep every file underflake.nixthin: it may declare output names, import implementation files, compose flake-parts modules, and adapt public calling conventions, but it must not contain derivation logic, app scripts, option/config bodies, service behavior, or helper implementations. Keep those implementation details together in feature-orientedflake/paths. Preserve existing output attribute names during structural moves; follow the repository's compatibility policy when changing the public interface. Verify withsrc/<name>/...,nix flake show, and representative package/module evals or builds.nix flake check
将需求转化为实现方案时,使用以下优化后的提示词:
重组该仓库,使其公共flake表层位于顶层目录下:包括flake/、flake/apps、flake/packages,以及适用情况下的flake/lib。保持flake/modules/{flake-parts,home-manager,darwin,nixos}作为最小入口点,并且flake.nix下的所有文件都保持薄型:这些文件可以声明输出名称、导入实现文件、组合flake-parts模块、适配公共调用约定,但不得包含derivation逻辑、应用脚本、option/config主体、服务行为或辅助工具实现。将这些实现细节统一放在面向功能的flake/路径下。结构移动过程中保留现有的输出属性名称;更改公共接口时遵循仓库的兼容性策略。使用src/<name>/...、nix flake show以及有代表性的包/模块求值或构建进行验证。nix flake check
Target shape
目标结构
Prefer this structure, adapting names to the existing repo:
text
flake.nix
flake/default.nix
flake/apps/default.nix
flake/packages/default.nix
flake/lib/default.nix
flake/checks/default.nix # if checks exist
flake/devShells/default.nix # if devShells exist
flake/overlays/default.nix # if overlays exist
flake/modules/flake-parts/default.nix
flake/modules/home-manager/default.nix
flake/modules/darwin/default.nix
flake/modules/nixos/default.nix
src/<name>/app.nix
src/<name>/package.nix
src/<name>/lib.nix
src/<name>/modules/flake-parts.nix
src/<name>/modules/home-manager.nix
src/<name>/modules/darwin.nix
src/<name>/modules/nixos.nixflake/modules/flake-partsFeature-oriented means grouping by domain concept, not by output type. If a concept has a package, app, and NixOS module, keep them under . If a package has no associated modules, is fine. When a repo is already organized by platform, preserving that structure under is acceptable, but do not mechanically recreate the whole tree under .
vpnsrc/vpn/src/<pkg-name>/package.nixsrc/flake/src/优先采用以下结构,可根据现有仓库调整名称:
text
flake.nix
flake/default.nix
flake/apps/default.nix
flake/packages/default.nix
flake/lib/default.nix
flake/checks/default.nix # if checks exist
flake/devShells/default.nix # if devShells exist
flake/overlays/default.nix # if overlays exist
flake/modules/flake-parts/default.nix
flake/modules/home-manager/default.nix
flake/modules/darwin/default.nix
flake/modules/nixos/default.nix
src/<name>/app.nix
src/<name>/package.nix
src/<name>/lib.nix
src/<name>/modules/flake-parts.nix
src/<name>/modules/home-manager.nix
src/<name>/modules/darwin.nix
src/<name>/modules/nixos.nix当存在flake-parts模块时,应与平台模块系列放在一起,即使用户的简化示例中省略了它。
flake/modules/flake-parts面向功能指的是按领域概念分组,而不是按输出类型分组。如果这个概念有对应的包、应用和NixOS模块,就把它们都放在下。如果一个包没有关联的模块,放在也可以。如果仓库已经按平台组织,在下保留该结构是可以接受的,但不要机械地在下重建整个目录树。
vpnsrc/vpn/src/<pkg-name>/package.nixsrc/src/flake/Thin layer rule
薄层规则
| Location | Allowed | Not allowed |
|---|---|---|
| Inputs, minimal | Package/module implementation |
| App output names and imports | Shell scripts, wrappers, runtime behavior |
| Package output names and imports | |
| Public helper re-exports | Helper implementations |
| Check output names and imports | Test harness implementation |
| Dev shell output names and imports | Tool setup logic, shell hooks |
| Overlay output names and imports | Package overrides and build logic |
| flake-parts imports and module composition | |
| Public module exports and imports | Options, |
| All implementation details | Public output schema decisions |
Thin does not mean empty. A thin file can adapt calling conventions, pass , , or , and preserve public attribute names. It should be understandable without reading implementation details.
inputsselfpkgsKeep configured file limits. If a cohesive module exceeds one, first look for an
independent responsibility; otherwise document a narrow increase or exception.
Keep options, defaults, assertions, and configuration local when they explain
one feature, even when that makes a module longer.
For module outputs, thin means the file is a re-export point. It imports the full module from and wires it into the public output attribute. It does not mean splitting options from config inside a single module; options and config stay together in .
flake/modules/<platform>/default.nixsrc/src/<name>/modules/<platform>.nixnix
undefined| 位置 | 允许的内容 | 不允许的内容 |
|---|---|---|
| 输入、最小化的 | 包/模块实现 |
| 应用输出名称和导入 | Shell脚本、包装器、运行时行为 |
| 包输出名称和导入 | |
| 公共辅助函数重导出 | 辅助函数实现 |
| 检查输出名称和导入 | 测试框架实现 |
| 开发环境输出名称和导入 | 工具配置逻辑、shell钩子 |
| Overlay输出名称和导入 | 包覆盖和构建逻辑 |
| flake-parts导入和模块组合 | |
| 公共模块导出和导入 | Options、 |
| 所有实现细节 | 公共输出架构决策 |
薄并不意味着空。薄文件可以适配调用约定、传递、或,并保留公共属性名称。无需阅读实现细节就能理解薄文件的内容。
inputsselfpkgs遵守配置的文件大小限制。如果一个内聚模块超过了限制,首先寻找是否有可以独立的职责;否则记录下小范围的放宽或例外情况。当options、默认值、断言和配置仅用于解释单个功能时,将它们放在局部,即使这会让模块变长。
对于模块输出,薄意味着文件是一个重导出点。它从导入完整的模块,并将其接入公共输出属性。这并不意味着在单个模块中将options与config拆分;options和config要一起放在中。
flake/modules/<platform>/default.nixsrc/src/<name>/modules/<platform>.nixnix
undefinedflake/modules/nixos/default.nix
flake/modules/nixos/default.nix
{ ... }:
{
flake.nixosModules.vpn = import ../../../src/vpn/modules/nixos.nix;
}
{ ... }:
{
flake.nixosModules.vpn = import ../../../src/vpn/modules/nixos.nix;
}
src/vpn/modules/nixos.nix
src/vpn/modules/nixos.nix
{ config, lib, pkgs, ... }:
{
options.services.vpn = { ... };
config = lib.mkIf config.services.vpn.enable { ... };
}
In flake-parts repos, `perSystem` often owns `packages`, `apps`, `checks`, and `devShells`. Keep `perSystem` composition thin in `flake/modules/flake-parts`; package derivations still belong in `src/<name>/package.nix`, app behavior in `src/<name>/app.nix`, and dev shell/check implementation in `src/<name>/...`. Do not define the same output through both direct `flake/packages` wiring and flake-parts `perSystem` wiring.{ config, lib, pkgs, ... }:
{
options.services.vpn = { ... };
config = lib.mkIf config.services.vpn.enable { ... };
}
在使用flake-parts的仓库中,`perSystem`通常负责`packages`、`apps`、`checks`和`devShells`。在`flake/modules/flake-parts`中保持`perSystem`的组合层很薄;包derivation仍然属于`src/<name>/package.nix`,应用行为属于`src/<name>/app.nix`,开发环境/检查的实现属于`src/<name>/...`。不要同时通过直接的`flake/packages`接线和flake-parts的`perSystem`接线来定义同一个输出。Migration workflow
迁移工作流
- Inventory current public outputs: ,
packages,apps,lib,checks,devShells,overlays,nixosModules,darwinModules, and flake-parts imports.homeManagerModules - Preserve the public output schema first. Move files without renaming output attributes unless the user requested a breaking change.
- If current outputs are interleaved in one file, first separate each output family enough that it can move independently; avoid a big-bang rewrite.
- Create the directories as output shims and move one output family at a time.
flake/ - Move implementation into feature-oriented ; avoid recreating the
src/<name>/...tree underflake/unless the repo is already platform-oriented.src/ - Keep shared implementation in or
src/<name>/lib.nix, not insrc/shared/<name>.nix.flake/lib - Follow the repository's compatibility policy for renamed outputs. Keep aliases only when that policy requires them; otherwise update consumers and remove obsolete paths.
- Give outputs without an example directory, such as , their own thin
formattershim or leave them in the nearest existing composition file; do not fold them into unrelated directories.flake/<output>/ - Verify after each family move with ,
nix flake show, and targeted builds/evals.nix flake check
- 盘点当前的公共输出:、
packages、apps、lib、checks、devShells、overlays、nixosModules、darwinModules以及flake-parts导入。homeManagerModules - 优先保留公共输出架构。移动文件时不要重命名输出属性,除非用户要求进行破坏性变更。
- 如果当前的输出都混在一个文件中,首先将每个输出系列分离到可以独立移动的程度;避免一次性大重构。
- 创建目录作为输出垫片,每次移动一个输出系列。
flake/ - 将实现代码移动到面向功能的中;避免在
src/<name>/...下重建src/目录树,除非仓库本身就是按平台组织的。flake/ - 将共享实现代码放在或
src/<name>/lib.nix中,不要放在src/shared/<name>.nix里。flake/lib - 对于重命名的输出,遵循仓库的兼容性策略。仅当策略要求时才保留别名;否则更新使用方并移除过时路径。
- 对于没有对应示例目录的输出(例如),为它们创建单独的薄型
formatter垫片,或者放在最近的现有组合文件中;不要把它们塞进不相关的目录里。flake/<output>/ - 每次移动一个输出系列后,使用、
nix flake show以及针对性的构建/求值进行验证。nix flake check
Common mistakes
常见错误
- Moving into
flake.nix; Nix expectsflake/at the repo root.flake.nix - Treating as the new implementation home instead of a thin public layer.
flake/ - Hiding implementation in because it feels like a shared bucket.
flake/lib - Putting option declarations, , assertions, or services in
config.flake/modules/* - Forgetting that and
packages.${system}are system-specific while module outputs usually are not.apps.${system} - Putting build logic in
perSysteminstead of importing implementations fromflake/modules/flake-parts.src/<name>/... - Creating both direct output wiring and flake-parts wiring for the same derivation without a deliberate compatibility reason.
perSystem - Creating circular imports between ,
flake/lib, andflake/modules.src - Changing public output names during a move-only refactor.
- Skipping verification because the change looks like only path shuffling.
- 将移到
flake.nix目录下;Nix要求flake/位于仓库根目录。flake.nix - 将当作新的实现存放目录,而不是薄的公共层。
flake/ - 因为觉得像个共享桶,就把实现代码藏在里面。
flake/lib - 将option声明、、断言或服务放在
config中。flake/modules/* - 忘记和
packages.${system}是系统相关的,而模块输出通常不是。apps.${system} - 将构建逻辑放在
perSystem中,而不是从flake/modules/flake-parts导入实现。src/<name>/... - 没有明确的兼容性理由,就为同一个derivation同时创建直接输出接线和flake-parts的接线。
perSystem - 在、
flake/lib和flake/modules之间造成循环导入。src - 在仅移动的重构中更改公共输出名称。
- 因为改动看起来只是路径调整,就跳过验证。
Templated scripts
模板化脚本
When packaging shell scripts, keep reusable script logic in its own source file instead of embedding long scripts inline in Nix strings. Use Nix only to substitute package-specific defaults.
Prefer nixpkgs-style placeholders with :
@name@replaceVarsnix
writeTextFile {
name = "tool";
destination = "/bin/tool";
executable = true;
text = builtins.readFile (replaceVars ./tool.sh {
default_config = builtins.toJSON config;
});
}In the script, group all Nix substitutions at the top and make runtime values overrideable by arguments or environment variables:
sh
default_config() {
cat <<'JSON'
@default_config@
JSON
}
: "${TOOL_JQ:=jq}"
tool_config() {
if [ -n "${TOOL_CONFIG_JSON:-}" ]; then
printf '%s\n' "$TOOL_CONFIG_JSON"
else
default_config
fi
}This keeps scripts usable outside Nix, makes the Nix coupling easy to audit, avoids quote-heavy inline shell strings, and matches current nixpkgs conventions now that has been replaced by .
substituteAllreplaceVars打包Shell脚本时,将可复用的脚本逻辑放在单独的源文件中,不要把长脚本内联在Nix字符串里。仅使用Nix来替换包特定的默认值。
推荐使用nixpkgs风格的占位符搭配:
@name@replaceVarsnix
writeTextFile {
name = "tool";
destination = "/bin/tool";
executable = true;
text = builtins.readFile (replaceVars ./tool.sh {
default_config = builtins.toJSON config;
});
}在脚本中,将所有Nix替换内容集中放在顶部,并让运行时值可以通过参数或环境变量覆盖:
sh
default_config() {
cat <<'JSON'
@default_config@
JSON
}
: "${TOOL_JQ:=jq}"
tool_config() {
if [ -n "${TOOL_CONFIG_JSON:-}" ]; then
printf '%s\n' "$TOOL_CONFIG_JSON"
else
default_config
fi
}这样可以让脚本在Nix之外也能使用,使Nix耦合易于审计,避免了大量引号的内联Shell字符串,并且符合当前nixpkgs的约定——因为已经被取代了。
substituteAllreplaceVarsReview checklist
审查清单
- files are mostly imports, attr names, re-exports, and public calling-convention adapters.
flake/ - contains derivations, scripts, options, config, services, assertions, and helpers.
src/<name>/... - Existing public output names still work or have deliberate migration notes.
- Module families are separated: ,
home-manager,darwin, andnixosdo not leak platform-specific logic into each other.flake-parts - Verification commands cover both system-specific outputs and module evaluation paths.
- Templated scripts live in standalone files, use placeholders via
@name@, and keep Nix-specific defaults grouped at the top with environment/argument overrides for reusable behavior.replaceVars
- 下的文件主要包含导入、属性名、重导出和公共调用约定适配器。
flake/ - 包含derivations、脚本、options、config、服务、断言和辅助函数。
src/<name>/... - 现有的公共输出名称仍然可用,或者有明确的迁移说明。
- 模块系列相互分离:、
home-manager、darwin和nixos之间不会互相泄漏平台特定的逻辑。flake-parts - 验证命令同时覆盖系统相关输出和模块求值路径。
- 模板化脚本存放在独立文件中,通过使用
replaceVars占位符,并将Nix特定的默认值集中放在顶部,同时支持通过环境变量/参数覆盖以实现可复用行为。@name@
Tools
工具
None. This is a pure prompt and review skill. Use the repo's existing Nix commands for verification.
无。这是纯提示词和审查技能。使用仓库现有的Nix命令进行验证。
Reference
参考
No separate reference files. Use the canonical prompt, thin layer rule, migration workflow, and review checklist above.
无单独的参考文件。使用上文的标准提示词、薄层规则、迁移工作流和审查清单即可。