# Understanding the Registries Option in twist.nix: Configuration Guide

> Discover the purpose of the registries option in twist.nix. Learn how it sources Emacs packages, manages dependencies, and generates lock-files for your emacs-twist configuration.

- Repository: [Emacs Twist/twist.nix](https://github.com/emacs-twist/twist.nix)
- Tags: how-to-guide
- Published: 2026-03-01

---

**The `registries` option in twist.nix is a required configuration list that defines where to source Emacs packages, replacing the deprecated `inventories` parameter and driving package discovery, dependency resolution, and lock-file generation.**

The `registries` option serves as the central configuration hook in **twist.nix**, an open-source Nix flake for managing reproducible Emacs configurations. Defined in `pkgs/emacs/default.nix`, this mandatory argument tells the system exactly where to locate package sources ranging from ELPA and MELPA to private Git repositories, enabling the build pipeline to discover, parse, and compile every Emacs Lisp dependency.

## What Is the Registries Option in twist.nix?

In `pkgs/emacs/default.nix` (lines 9-13), `registries` is declared as a mandatory function argument with strict validation. If omitted, the evaluation aborts with a clear error message. If the legacy `inventories` parameter is supplied instead, the system emits a deprecation warning and uses that value temporarily:

```nix
registries ?
  if inventories == null
  then builtins.abort "emacsTwist: registries is a required argument"
  else lib.warn "emacsTwist: inventories is deprecated. Use registries instead." inventories,

```

This design ensures that every twist.nix configuration explicitly declares its package sources while providing a migration path for existing setups using the old naming convention.

## How the Registries Option Works

The value passed to `registries` flows directly into the data layer responsible for materializing the concrete package set. At line 116 of `pkgs/emacs/default.nix`, the parameter is passed to the enumeration logic:

```nix
inventories = registries;

```

This list is consumed by the `enumerateConcretePackageSet` function (imported from `pkgs/emacs/data/default.nix`), which interprets each registry entry as an **inventory** mapping package names to concrete sources. The function walks through these inventories to read metadata files—such as `-pkg.el` descriptors, MELPA recipes, or `archive-contents` indices—and produces a normalized attribute set of available packages.

## Registry Entry Structure and Supported Types

Each element in the `registries` list is an attribute set defining a package source. Based on the reference implementation in `test/twist.nix` (lines 18-45), twist.nix supports four primary registry types via the `type` attribute:

- **`elpa`** – For GNU ELPA or NonGNU ELPA archives
- **`melpa`** – For MELPA recipe collections
- **`archive-contents`** – For archive index files (e.g., ELPA mirrors)
- **`gitmodules`** – For Git submodule-based repositories (e.g., EmacsMirror)

A comprehensive registry configuration typically includes multiple sources:

```nix
registries = [
  {
    type = "elpa";
    path = inputs.gnu-elpa.outPath + "/elpa-packages";
    core-src = emacsPackage.src;
    auto-sync-only = true;
  }
  {
    name = "melpa";
    type = "melpa";
    path = inputs.melpa.outPath + "/recipes";
  }
  {
    name = "gnu";
    type = "archive-contents";
    path = inputs.gnu-elpa-archive.outPath;
    base-url = "https://raw.githubusercontent.com/d12frosted/elpa-mirror/master/gnu/";
  }
  {
    name = "emacsmirror";
    type = "gitmodules";
    path = inputs.epkgs.outPath + "/.gitmodules";
  }
];

```

## Architectural Role of the Registries Option

The `registries` option drives four critical functions in the twist.nix architecture:

1. **Package Discovery** – The `enumerateConcretePackageSet` function walks each registry to read metadata files (e.g., `-pkg.el`, MELPA recipes, `archive-contents`), producing a normalized attribute set of available packages.

2. **Dependency Resolution** – Parsed registry data feeds the `allDependencies` graph builder, which determines the build order and required dependencies for the complete Emacs environment.

3. **Lock-File Generation** – Each registry corresponds to a flake input or pinned archive, directly influencing the generated `flake.lock` and `archive.lock` files that ensure reproducible builds.

4. **Extensibility** – Users append custom registries (e.g., private Git repositories) to the list without modifying core twist.nix code, enabling seamless integration of proprietary or experimental packages.

## Practical Configuration Examples

### Minimal Configuration with Empty Registries

For testing built-in packages only:

```nix
{
  pkgs,
  emacsPackage,
  inputs,
}: {
  inherit pkgs emacsPackage;
  initFiles = [ ./init.el ];
  lockDir   = ./lock;
  registries = [ ];   # No external sources – only built-in libraries available

}

```

### Adding a Private Registry

To integrate proprietary packages, append a custom registry to your existing list:

```nix
{
  # ... other arguments ...

  registries = existingRegistries ++ [
    {
      name = "my-private";
      type = "gitmodules";
      path = "/run/user/1000/git/my-private-packages/.gitmodules";
    }
  ];
}

```

This integrates your private packages into the same discovery and dependency resolution pipeline as public registries like MELPA.

## Summary

- The **`registries`** option in twist.nix is a required list argument that defines where to source Emacs packages, replacing the deprecated `inventories` parameter.
- Defined in `pkgs/emacs/default.nix`, it accepts a list of attribute sets specifying package sources such as **ELPA**, **MELPA**, **archive-contents**, and **gitmodules**.
- The option drives **package discovery**, **dependency resolution**, and **lock-file generation** through the `enumerateConcretePackageSet` function in `pkgs/emacs/data/default.nix`.
- Users can extend the list with private registries to integrate proprietary packages without modifying core twist.nix code.

## Frequently Asked Questions

### What happens if I omit the registries option in twist.nix?

If you omit the `registries` argument, the evaluation aborts with the error message `"emacsTwist: registries is a required argument"`. This check occurs in `pkgs/emacs/default.nix` where the option is defined with a fallback to `builtins.abort` when both `registries` and the legacy `inventories` are null.

### Can I use the old inventories parameter instead of registries?

While twist.nix still accepts `inventories` for backward compatibility, using it triggers a deprecation warning: `"emacsTwist: inventories is deprecated. Use registries instead."`. The system automatically assigns the `inventories` value to the internal `registries` parameter, but you should migrate to `registries` to avoid future breakage.

### What registry types are supported in twist.nix?

twist.nix supports four primary registry types via the `type` attribute: **`elpa`** for GNU and NonGNU ELPA archives, **`melpa`** for MELPA recipes, **`archive-contents`** for archive index files such as ELPA mirrors, and **`gitmodules`** for Git submodule-based repositories like EmacsMirror. Each type requires specific attributes such as `path`, and optionally `name`, `core-src`, or `base-url`.

### How do I add a private package registry to my twist.nix configuration?

To add a private registry, append a new attribute set to your `registries` list with the appropriate `type` (typically `"gitmodules"` for Git-based sources) and a `path` pointing to your registry definition. For example: `registries = existingRegistries ++ [{ name = "my-private"; type = "gitmodules"; path = "/path/to/.gitmodules"; }]`. This integrates your private packages into the same discovery and dependency resolution pipeline as public registries.