Skip to content
/ rfcs Public
Draft
Changes from 2 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
4801546
RFC 197: package set definitons initial commit
quantenzitrone Jan 24, 2026
9573e0f
Idea 1: easy transition advantage
quantenzitrone Jan 24, 2026
bb11e6a
collapsible idea sections test
quantenzitrone Jan 25, 2026
625449c
collapsible sections worked, so all of them now
quantenzitrone Jan 25, 2026
1d7fb7f
`tree` like output for visualization
quantenzitrone Jan 25, 2026
2c7fc9f
Update rfcs/0197-package-set-definitions.md
quantenzitrone Jan 25, 2026
b0c8c39
transform idea 1 to be more strict about the directory structure
quantenzitrone Jan 25, 2026
a2853b8
add python3Packages by-name to prior art
quantenzitrone Jan 25, 2026
84b5686
Idea3: attrpath in directory names drawback
quantenzitrone Jan 25, 2026
c592d41
Idea {2,3}: inaccessibility of sets like lixPackages
quantenzitrone Jan 25, 2026
ee5f96d
Idea {2,3}: package sets in pkgs/by-name is sketchy
quantenzitrone Jan 25, 2026
d47b2ad
more concrete numbers
quantenzitrone Jan 25, 2026
882c21a
Idea 1 only allows top-level package sets
quantenzitrone Jan 25, 2026
8f16dc0
another idea 3 drawback
quantenzitrone Jan 25, 2026
b26025e
scrap idea 3
quantenzitrone Jan 25, 2026
5c95506
improve goals
quantenzitrone Jan 25, 2026
2775b53
tooling has to be made to work for multiple directories
quantenzitrone Jan 25, 2026
53f107c
Update rfcs/0197-package-set-definitions.md
quantenzitrone Jan 25, 2026
3c4cbdd
Idea 1: redesign with auto called by-structure and without unsharded …
quantenzitrone Jan 25, 2026
2cf527e
Idea 2: drop, make idea 1 the default
quantenzitrone Jan 25, 2026
fa81fb3
minor fixes
quantenzitrone Jan 25, 2026
d0bb18b
move unresolved questions to proper location
quantenzitrone Jan 25, 2026
329891e
fix type
quantenzitrone Jan 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 151 additions & 0 deletions rfcs/0197-package-set-definitions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
---
feature: nixpkgs package set location
start-date: 2026-01-24
author: quantenzitrone
co-authors: (find a buddy later to help out with the RFC)
shepherd-team: (names, to be nominated and accepted by RFC steering committee)
shepherd-leader: (name to be appointed by RFC steering committee)
related-issues: (will contain links to implementation PRs)
---

# Summary
[summary]: #summary

Different ideas on how to handle package sets in nixpkgs.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is a package set? There are some that do not have a direct top-level name. I think in general some places of the text is written for a package set that comes with its set of expressions, while there are cases where meaningfully sets share a large fraction of the expressions.


# Motivation
[motivation]: #motivation

- get rid of the package categories as directories.
- make packages in package sets take advantage of the by-name greatness
- auto updates with r-ryantm + merge bot maintainer merging

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think our implementation plan should be separated into four stages:

  1. Create interfaces for package sets that uses the same functions as by-name to callPackage packages from sharded directories, with additional extensions for package set versioning.
  2. Update nixpkgs-vet to expand the existing linting checks to the new package sets.
  3. Migrate all package sets into the new interface when it makes sense to do so, or move the children of smaller sets into by-name as top-level packages.
  4. Add new rules to nixpkgs-merge-bot to allow unprivileged merging to package sets.

We can't move into the next stage before the previous one is complete, so let's not think about the later stages just now.

- *your goal here*

This comment was marked as off-topic.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updates across package sets are very different. I don't think this should be a goal of this RFC, but instead something that can be developed separately as an updateScript that nixpkgs-update can pick up.


# Idea 1: new directory for package sets

Proof-Of-Concept implementation in https://github.com/NixOS/nixpkgs/pull/482538 and https://github.com/NixOS/nixpkgs/pull/482543

## Detailed design

- Create a new directory under `pkgs/`, e.g. `pkgs/sets` that contains package sets.
- For example `pkgs/sets/fishPlugins` `pkgs/sets/python3Packages`.
- Each packageset has a `packageset.nix`, that functions as an entrypoint to the package set.
- The `packageset.nix` files are autocalled by some `pkgs/top-level/by-name-overlay.nix` like file.
- Versioned package sets like `python316Packages` are done in `all-packages.nix` by calling the
Copy link

@SigmaSquadron SigmaSquadron Jan 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems good to me. As mentioned in #197 (comment), this is conditional on the approval of the current versioned package set maintainers.

`packageset.nix` again with different arguments.

## Advantages

- flexibility
- easy transition
- for a lot of package sets just move the folder and rename the `default.nix` to `packageset.nix`

## Drawbacks

- all packagesets have to handle their shit themselves, so no maintainer merging, by-name
autocalling and stuff without the additional work
- *your drawback here*

## Unresolved Questions

- *your question here*

# Idea 2: nested by-name structure

Proof-Of-Concept implementation in https://github.com/NixOS/nixpkgs/pull/483432

## Detailed design

- Package sets are done in a nested `by-name` structure under `pkgs/by-name`, e.g.
`fishPlugins.puffer` would be in `by-name/fi/fishPlugins/pu/puffer`.
- To distinguish packages from packagesets we have to mark packagesets somehow, for example with a
file `by-name/fi/fishPlugins/.packageset`, if that file exists, it's called as a packageset,
if not the `package.nix` must exist and is called as a package.

## Advantages

- clear package separation
- reuse of RFC 140 concepts
- making maintainer merging work for this is probably relatively simple

## Drawbacks

- unresolved questions
- *your drawback here*

## Unresolved Questions

- How do we handle functions like `fishPlugins.buildFishPlugin`?
- How do we handle aliases?
- How do we handle versioned package sets?
- How do we move large package sets?

# Idea 3: package sets in `pkgs/by-name` (probably worse than Idea 2 in every way)

Proof-Of-Concept implementation in https://github.com/NixOS/nixpkgs/pull/483128

## Detailed design

- Instead of `by-name/<shard>/<pname>` we have `by-name/<shard>/<attrpath>`, so e.g.
`fishPlugins.puffer` would go in `by-name/fi/fishPlugins.puffer`.
- The `top-level/by-name-overlay.nix` will call all folders in a `<shard>` that contain a dot as a
package set.

## Advantages

- clear package separation
- reuse of RFC 140 concepts
- making maintainer merging work for this is probably easy

## Drawbacks

- huge shards due to package sets
- currently only few shards like `li` are too large for GitHubs UI, but with this idea a lot of
shards like `py` (`python3Packages`), `ha` (`haskellPackages`) or `vi` (`vimPlugins`) will be
huge as well.
- unresolved questions

## Unresolved Questions

- How do we handle functions like `fishPlugins.buildFishPlugin`?
Copy link

@SigmaSquadron SigmaSquadron Jan 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Answering because this applies to idea 1)

I never thought it made sense for functions and derivation builders to be inside package sets. I think our Go infrastructure has the right idea: move them to the top-level, and version them in the attribute name. fishPlugins.buildFishPlugin can just be moved to the top-level, while python313Packages.buildPythonApplication becomes buildPython313Application on the top-level. We can deal with this at stage 3, where we migrate everything over.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This proposal is awkward with Python where you have CPython and PyPy and then language version-dialects within them, and even worse for Common Lisp where you have same base language but multiple compatible implementations with their completely own versioning.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i also think keeping functions in package sets is fine

- How do we handle aliases?
- How do we handle versioned package sets?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Answering because this applies to idea 1)

I generally think it's a good idea to think of Nixpkgs as having three types of package infrastructure systems:

  1. Top-level packages, which nowadays go to by-name;
  2. Simple package sets, like fishPlugins, which are easier to implement in this new interface as we can simply call them as we do by-name packages and shove the resulting set into fishPlugins from the top-level.
  3. Versioned package sets, like python3Packages, which are by far the most complex. I think we should absolutely get the input of the primary maintainers of these sets here before we move forward. There are many concerns regarding updating versioned sets, and default aliases, as well as edge cases like python3.pkgs and python3Packages. In the end, having something that is no worse to maintain as it was before would be ideal.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Auto generated package sets like haskellPackages.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i want handle both 2 and 3 with this RFC

- How do we move large package sets?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Answering because this applies to idea 1)

Some of them are easy enough. If we resolve the aforementioned issues with the python edge cases, it should be a simple matter of moving and renaming files. OCaml should also be pretty simple.

The generated sets, like Haskell, Node, Lisp and R, will be impossible, though. Those packages don't actually exist as separate files in Nixpkgs, and are instead imported from some other upstream.

This is something that again, we'll have to get the input of package set maintainers on. Moving everything over will end up being a case-by-case basis.


# Detailed design
[design]: #detailed-design

TODO: decide for one of the above ideas

# Examples and Interactions
[examples-and-interactions]: #examples-and-interactions

TODO

# Drawbacks
[drawbacks]: #drawbacks

TODO

# Alternatives
[alternatives]: #alternatives

TODO: move other designs here once decided

# Prior art
[prior-art]: #prior-art

- https://github.com/NixOS/nixpkgs/issues/482537
- https://github.com/NixOS/nixpkgs/issues/432625
- `tclPackages` has their own `by-name` structure https://github.com/NixOS/nixpkgs/pull/344716
- attempt to move `nushellPlugins` to `by-name` https://github.com/NixOS/nixpkgs/pull/482961

# Unresolved questions
[unresolved]: #unresolved-questions

What parts of the design are still TBD or unknowns?

# Future work
[future]: #future-work

What future work, if any, would be implied or impacted by this feature without being directly part of the work?