Skip to content
Oeiuwq Faith Blog OpenSource Porfolio

vic/flake-file.json
{
"defaultBranch": "main",
"description": "Generate flake.nix from module options.",
"fullName": "vic/flake-file",
"homepage": "https://vic.github.io/dendrix/Dendritic.html#minimal-and-focused-flakenix",
"language": "Nix",
"name": "flake-file",
"pushedAt": "2025-11-21T22:14:49Z",
"stargazersCount": 39,
"updatedAt": "2025-11-21T22:14:54Z",
"url": "https://github.com/vic/flake-file"
}

Sponsor Vic Dendritic Nix CI Status License

flake-file — Generate flake.nix from flake-parts modules.

Section titled “flake-file — Generate flake.nix from flake-parts modules.”

flake-file and vic’s dendritic libs made for you with Love++ and AI—. If you like my work, consider sponsoring

flake-file lets you generate a clean, maintainable flake.nix from modular options, using flake-parts.

It makes your flake configuration modular and based on the Nix module system. This means you can use lib.mkDefault or anything you normally do with Nix modules, and have them reflected in flake schema values.

  • Flake definition aggregated from all flake-parts modules.
  • Schema as options.
  • Syntax for nixConfig and follows is the same as in flakes.
  • flake check ensures files are up to date.
  • App for generator: nix run .#write-flake
  • Custom do-not-edit header.
  • Automatic flake.lock [flattening]!(#automatic-flakelock-flattening).
  • Incrementally add [flake-parts-builder]!(#parts_templates) templates.
  • Pick flakeModules for different feature sets.
  • Dendritic flake template.
image

this cute ouroboros is puking itself out.


  • [Who?]!(#who-is-this-for)
  • [What?]!(#what-is-flake-file)
  • [Getting Started]!(#getting-started-try-it-now)
  • [Usage]!(#usage)
  • [Available Options]!(#available-options)
  • [About the Flake output function]!(#about-the-flake-output-function)
  • [Automatic flake.lock flattening]!(#automatic-flakelock-flattening)
  • [Migration Guide]!(#migration-guide)
  • [Development]!(#development)

  • Nix users who want to keep their flake.nix modular and maintainable
  • Anyone using flake-parts and looking to automate or simplify flake input management
  • Teams or individuals who want to share and reuse flake modules across projects

flake-file lets you make your flake.nix dynamic and modular. Instead of maintaining a single, monolithic flake.nix, you define your flake inputs in separate modules close to where their inputs are used. flake-file then automatically generates a clean, up-to-date flake.nix for you.

  • Keep your flake modular: Manage flake inputs just like the rest of your Nix configuration.
  • Automatic updates: Regenerate your flake.nix with a single command whenever your options change.
  • Flake as dependency manifest: Use flake.nix only for declaring dependencies, not for complex Nix code.
  • Share and reuse modules: Teams can collaborate on and share flake modules across projects, including their dependencies.

Real-world examples: vic/vix uses flake-file. Our dev/ directory also uses flake-file to test this repo. More examples on GitHub.


To get started quickly, create a new flake based on our dendritic template:

Terminal window
nix flake init -t github:vic/flake-file#dendritic
nix run ".#write-flake" # regenerate flake.nix and flake.lock
cat flake.nix # flake.nix built from your options
nix flake check # check that flake.nix is up to date

[!TIP] See the [Migration Guide]!(#migration-guide) if you’re moving from an existing flake.


The following is a complete example from our templates/dendritic template. It imports all modules from flake-file.flakeModules.dendritic.

{ inputs, lib, ... }:
{
# That's it! Importing this module will add dendritic-setup inputs to your flake.
imports = [ inputs.flake-file.flakeModules.dendritic ];
# Define flake attributes on any flake-parts module:
flake-file = {
description = "My Awesome Flake";
inputs.nixpkgs.url = lib.mkDefault "github:NixOS/nixpkgs/nixpkgs-unstable";
inputs.nixpkgs-lib.follows = "nixpkgs";
};
}
  • Defines flake-file options.
  • Exposes packages.write-flake.
  • Exposes flake checks for generated files.
  • Includes flake-parts-builder’s _bootstrap.nix.
  • Uses bootstrap to load parts from ./flake-parts
  • Uses bootstrap to load ./flake-parts/_meta as flake-file configs.
  • Enables [automatic flake.lock flattening]!(#automatic-flakelock-flattening) using spikespaz/allfollow
  • Includes flakeModules.default.
  • Includes flakeModules.import-tree.
  • Enables flake-parts.
  • Sets outputs to inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } (inputs.import-tree ./modules).

Previously, this module included flake-aspects and den as dependencies. It now provides a pure flake-parts Dendritic setup. If you need the complete den functionality, use den’s flakeModules.dendritic instead.

A more basic, explicit setup.

# See templates/default
{ inputs, ... }: {
imports = [
inputs.flake-file.flakeModules.default
];
flake-file.inputs = {
flake-file.url = "github:vic/flake-file";
flake-parts.url = "github:hercules-ci/flake-parts";
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
systems.url = "github:nix-systems/default";
};
systems = import inputs.systems;
}

[!IMPORTANT] Use nix run .#write-flake to generate.

[!TIP] You can use the write-flake app as part of a devshell or git hook.

A template for dendritic setups; includes flakeModules.dendritic.

A template that uses lib.flakeModules.flake-parts-builder.


Options use the same attributes as the flake schema. See below for details.

OptionDescription
flake-file.descriptionSets the flake description
flake-file.nixConfigFlake-level nixConfig (typed attrset)
flake-file.outputsLiteral Nix code for outputs function
flake-file.formatterFunction: pkgs -> program to format generated flake.nix
flake-file.do-not-editHeader comment added atop generated file
flake-file.inputs.<name>.urlSource URL (e.g. github:owner/repo)
flake-file.inputs.<name>.typeReference type (github, path, etc.)
flake-file.inputs.<name>.ownerOwner (for typed VCS refs)
flake-file.inputs.<name>.repoRepo name
flake-file.inputs.<name>.pathLocal path reference
flake-file.inputs.<name>.idFlake registry id
flake-file.inputs.<name>.dirSubdirectory within repo/path
flake-file.inputs.<name>.narHashNAR hash pin
flake-file.inputs.<name>.revCommit hash pin
flake-file.inputs.<name>.refBranch or tag pin
flake-file.inputs.<name>.hostCustom host for git forges
flake-file.inputs.<name>.submodulesWhether to fetch git submodules
flake-file.inputs.<name>.flakeBoolean: is it a flake? (default true)
flake-file.inputs.<name>.followsFollow another input’s value
flake-file.inputs.<name>.inputs.<dep>.followsNested input follow tree
flake-file.inputs.<name>.inputs.<dep>.inputs...Recursively follow deeper deps
flake-file.write-hooksList of ordered hooks (by index) after writing
flake-file.check-hooksList of ordered hooks (by index) during check
flake-file.prune-lock.enableEnable automatic flake.lock pruning
flake-file.prune-lock.programFunction building pruning executable

Example:

flake-file = {
description = "my awesome flake";
nixConfig = {}; # attrset (free-form, typed as attrs)
inputs.<name>.url = "github:foo/bar";
inputs.<name>.flake = false;
inputs.<name>.inputs.nixpkgs.follows = "nixpkgs";
};

[!TIP] See also, options.nix.


The flake-file.outputs option is a literal Nix expression. You cannot convert a Nix function value into a string for including in the generated flake file.

It defaults to:

inputs: import ./outputs.nix inputs

We recommend using this default, as it keeps your flake file focused on definitions of inputs and nixConfig. All Nix logic is moved to outputs.nix. Set this option only if you want to load another file with a Nix one-liner, but not for including a large Nix code string in it.


Tired of endlessly repeating tiny flake-parts modules or copy-pasting snippets between your projects? No more!

flake-parts-builder lets you incrementally add templated parts. This is much better than normal flake templates, since flake-parts templates can be added or removed at any time, not only at project initialization.

{ inputs, ... }: {
imports = [
(inputs.flake-file.lib.flakeModules.flake-parts-builder ./flake-parts)
];
}

[!IMPORTANT] Use github:vic/flake-parts-builder/write-meta until flake-parts-builder#60 gets merged. This branch will also write each parts meta.nix file, so it can be used by flake-file to manage your flake.nix.

[!WARNING] Only use flake-parts-builder add subcommand, since init will overwrite the flake.nix file that is already being managed by flake-file.

Terminal window
nix run github:vic/flake-parts-builder/write-meta -- add --write-meta --parts systems,treefmt $PWD

You can add custom commands to be run whenever your flake.nix has been written or checked.

[!TIP] See flake-file.write-hooks and flake-file.check-hooks options.

You can use the prune-lock options to specify a command that flake-file will use whenever your flake.nix file is generated to flatten your flake.lock dependency tree.

For flattening mechanisms we provide:

{ inputs, ... }:
{
imports = [
inputs.flake-file.flakeModules.nix-auto-follow
# or optionally
# inputs.flake-file.flakeModules.allfollow
];
}

This section outlines the recommended steps for adopting flake-file in your own repository.

  1. Prerequisite: Ensure you have already adopted flake-parts.

  2. Add Inputs: In your current flake.nix, add the following input:

    flake-file.url = "github:vic/flake-file";
  3. Move Outputs: Copy the contents of your outputs function into a file ./outputs.nix:

    # outputs.nix -- this is the contents of your `outputs` function from the original flake.nix file.
    inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } {
    imports = [
    ./modules/inputs.nix # Add this for step 4.
    # Feel free to split ./modules/inputs.nix into other modules as you see fit.
    # If you end having lots of modules, consider using import-tree for auto importing them.
    ];
    }
  4. Move Inputs: Copy your current flake.nix file as a flake-parts module (e.g., modules/inputs.nix):

[!IMPORTANT] Make sure you git add so that new files are visible to Nix.

modules/inputs.nix
{ inputs, ... }:
{
imports = [
inputs.flake-file.flakeModules.default # flake-file options.
];
flake-file = {
inputs = {
flake-file.url = "github:vic/flake-file";
# ... all your other original flake inputs here.
};
nixConfig = { }; # if you had any.
description = "Your flake description";
};
}
  1. Backup: Back up your flake.nix into flake.nix.bak before regenerating it.
  2. Generate: Execute nix run .#write-flake to generate flake.nix.
  3. Verify: Check flake.nix and if everything is okay, remove the backup file.

You are done! Now you can split dependencies from modules/inputs.nix into other flake-part modules as you see fit:

# ./modules/<name>.nix -- Replace `<name>` with some dependency.
{ inputs, lib, ... }: {
flake-file.inputs.<name>.url = ...;
# Example usage: include the flakeModule once it has been added to flake.nix.
imports = lib.optionals (inputs ? <name>) [ inputs.<name>.flakeModule ];
}

Use nix develop ./dev or with direnv: use flake ./dev.

Terminal window
[[general commands]]
check - run flake check
fmt - format all files in repo
menu - prints this menu
regen - regenerate all flake.nix files in this repo

  • Found a bug or have a feature request? Open an issue.
  • Contributions are welcome!

Made with <3 by @vic