# flake-parts: a module system for Nix Flakes

> flake-parts provides a small module layer for composing Nix Flakes, with built-in handling for systems and standard flake attributes. It suits maintainers who want to split a `flake.nix` into reusable modules without turning their project into a NixOS-style monorepo.

**hercules-ci/flake-parts** — ❄️ Simplify Nix Flakes with the module system

- Repository: https://github.com/hercules-ci/flake-parts
- Website: https://flake.parts
- Stars: 1,512 · Forks: 84
- Language: Nix
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/hercules-ci-flake-parts

## Why flake-parts reorganizes an existing flake.nix

flake-parts addresses a specific problem: a Flake is configuration, but ordinary `flake.nix` files often accumulate custom Nix glue because each project has to define standard attributes and coordinate them manually. The project describes itself as a minimal mirror of the Nix Flake schema. Its core provides options for standard Flake attributes and establishes a way to work with `system`; separate ecosystem modules supply opinionated features.

The intended users are maintainers of Nix Flakes who want to split configuration into focused files, share project logic, or let a library Flake expose generated outputs that another Flake can integrate. This is a configuration architecture rather than a build tool. It does not replace Nix, Flakes, derivations, or the outputs produced by those systems. It changes how the Flake is assembled and connected to modules.

That boundary is important. Used by itself, the documentation calls flake-parts lightweight. A substantial increase in configuration machinery would come from importing additional modules, not from the minimal core described in the README. Projects with only a few outputs may gain little from that abstraction.

## The mkFlake module and perSystem data flow

Migration replaces the existing `outputs` function body with `flake-parts.lib.mkFlake`. The `inputs` argument remains available, including `flake-parts`, and the selected systems list supplies the platforms for which `perSystem` attributes are assembled. Standard `flake` attributes stay under the `flake` key, while system-specific configuration belongs under `perSystem` as defined by the imported modules.

The repository layout supports this modular design. Public library code is represented by `lib.nix` and `lib/`, module definitions by `modules/`, starter configuration by `template/`, and usage examples by `examples/`. There are also directories named `extras/`, `dev/`, and `vendor/`. Based on that layout, flake-parts is not a single monolithic `flake.nix` implementation. It exposes a library and composes module inputs through the Flake interface.

The README does not explain the internal evaluation order of every option or module. It instead directs users to the external options reference and the default template. For exact option declarations, those locations are the relevant sources. This distinction matters because imported modules can add opinionated behavior that is not part of flake-parts itself.

## Creating a first flake-parts project

For a project without an existing Flake, the README gives one initialization command. It asks Nix to initialize a Flake from the flake-parts template, which is the documented starting point for a new project.

```bash
nix flake init -t github:hercules-ci/flake-parts
```

After initialization, the repository directs users to `template/default/flake.nix` for the complete starter structure. The README does not provide a separate command for opening the files, running a build, or selecting an output, so this article does not infer one. The first verifiable state is the generated Flake configuration based on that template.

The template is especially relevant for first use because the migration snippet is intentionally abbreviated. It shows where the standard Flake attributes and systems go, while `template/default/flake.nix` supplies the full configuration the project expects. Users should inspect those files before adding third-party modules.

## Moving an existing flake into flake-parts

An existing project first adds flake-parts as an input. The documented input declaration is shown below. Place it in the existing Flake input declarations without replacing unrelated inputs.

```nix
flake-parts.url = "github:hercules-ci/flake-parts";
```

Next, adapt `outputs` to call `mkFlake`. In this structure, `flake` holds the standard Flake attributes, while `systems` selects the systems used for `perSystem`.

```nix
outputs = inputs@{ flake-parts, ... }:
  flake-parts.lib.mkFlake { inherit inputs; } {
    flake = {
    };
    systems = [
      "x86_64-linux"
    ];
  };
```

The README describes this as sliding `mkFlake` between the outputs function head and body. It then directs users to place the original Flake attributes in the `flake` section.

## What splitting Flake modules does and does not solve

The clearest benefit is structural. A large `flake.nix` can be divided into units with specific responsibilities, and shared logic can live in a library Flake. Modules also let maintainers integrate generated outputs from such a library into a consuming Flake. These are configuration reuse and composition problems, and flake-parts targets them directly.

The design has a deliberate boundary. Unlike NixOS, the README says flake-parts is not a monorepo intended to absorb all related open source code. It follows the Flake spirit by remaining a module that other repositories can build upon while preserving a baseline of core Flake compatibility. That makes the package narrower than NixOS, but it also means common organization does not automatically provide every feature available in the NixOS module ecosystem.

A second limitation is documentation scope. The README points to `examples/project-commands/` and `examples/shell-environments/` only as example directories. It does not claim that those directories define mandatory integrations, nor does it document rollback behavior for the migration. Adopters must compare their existing output schema against the current options reference and template.

## Maintenance, releases, and MIT licensing costs

The repository is not archived, and its last push was on 2026-10-01. However, the repository has no GitHub releases, so the README and repository do not provide a numbered release history that can be used as an upgrade guide. The project does contain `ChangeLog.md`, which is the repository file a maintainer should inspect for recorded changes before modifying an established Flake configuration.

The upgrade cost is primarily configuration review rather than binary replacement. Module imports and option assignments may need to change when their upstream modules evolve, while the repository layout separates core code in `lib.nix` and `lib/` from modules in `modules/`. The presence of `flake.lock` also means a project should account for Nix Flake input locking when reviewing dependency changes.

flake-parts is distributed under the MIT License. The repository includes a `LICENSE` file. That identifier informs source reuse and redistribution conditions, but this review does not provide legal advice or compatibility guidance for a particular distribution model.

## Conclusion

flake-parts is appropriate for teams that already use Nix Flakes and want their configuration divided into focused, reusable modules. It is a poor fit for a trivial one-file Flake or for maintainers seeking NixOS module breadth. Before adoption, inspect the current `flake.nix`, the default template at `template/default/flake.nix`, and any imported ecosystem modules to confirm that the added module layer fits the project.

## FAQ

### How do I create a new project with flake-parts?

The README gives `nix flake init -t github:hercules-ci/flake-parts` for a project that does not already have a Flake. It then directs users to `template/default/flake.nix` for the starter configuration.

### How do I add flake-parts to an existing flake.nix?

Add the `flake-parts.url` input, then place `flake-parts.lib.mkFlake` between the `outputs` function head and body. Keep standard Flake attributes in its `flake` section and declare the systems for which `perSystem` attributes should be built.

### Is flake-parts intended to replace NixOS modules?

No. The README explicitly contrasts it with NixOS and describes flake-parts as a focused Flake module with a baseline level of compatibility. Additional opinionated features are expected to come from ecosystem modules.

## Sources

- [hercules-ci/flake-parts on GitHub](https://github.com/hercules-ci/flake-parts)
- [Issues](https://github.com/hercules-ci/flake-parts/issues)
- [License: MIT](https://github.com/hercules-ci/flake-parts/blob/main/LICENSE)
- [Project website](https://flake.parts)
- [README](https://github.com/hercules-ci/flake-parts/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/hercules-ci-flake-parts
