# Adding Modules Guide How to add new NixOS and Home Manager modules to m3ta-nixpkgs. ## Overview Modules extend your system or user configuration with reusable, declarative options. m3ta-nixpkgs uses the standard NixOS module system with a `m3ta.*` namespace. ## Quick Start Use a template for quick setup: ```bash # NixOS module nix flake init -t .#nixos-module my-module # Home Manager module nix flake init -t .#home-manager-module my-module ``` This copies the template into `templates/` — move it to the appropriate location and customize. ## Adding a NixOS Module ### 1. Create the Module File Create `modules/nixos/.nix`: ```nix {config, lib, pkgs, ...}: with lib; let cfg = config.m3ta.myModule; in { options.m3ta.myModule = { enable = mkEnableOption "my module description"; # Add custom options here someOption = mkOption { type = types.str; default = "default-value"; description = "Description of this option"; }; }; config = mkIf cfg.enable { # System configuration goes here environment.systemPackages = [pkgs.some-package]; # Or systemd services systemd.services.my-service = { enable = true; description = "My service"; wantedBy = ["multi-user.target"]; serviceConfig = { ExecStart = "${pkgs.some-package}/bin/some-daemon"; }; }; }; } ``` ### 2. Register in the Aggregator Add to `modules/nixos/default.nix`: ```nix { imports = [ ./ports.nix ./mem0.nix ./.nix # ← add your module ]; } ``` ### 3. Export from flake.nix Add to the `nixosModules` output in `flake.nix` (optional, for direct import): ```nix nixosModules = { default = ./modules/nixos; ports = ./modules/nixos/ports.nix; mem0 = ./modules/nixos/mem0.nix; my-module = ./modules/nixos/.nix; # ← add this }; ``` ## Adding a Home Manager Module Home Manager modules are organized by category under `modules/home-manager/`. ### Categories | Category | Purpose | Location | |----------|---------|----------| | `cli/` | Command-line tools and utilities | `modules/home-manager/cli/` | | `coding/` | Development tools, editors, agents | `modules/home-manager/coding/` | | Root | Cross-cutting concerns (e.g., ports) | `modules/home-manager/` | ### 1. Choose a Category - **CLI tools** (zsh plugins, tmux config, etc.) → `cli/` - **Development tools** (editor config, linters, etc.) → `coding/` - **System-wide settings** (ports, environment) → root level ### 2. Create the Module File Create `modules/home-manager//.nix`: ```nix {config, lib, pkgs, ...}: with lib; let cfg = config.m3ta.myModule; in { options.m3ta.myModule = { enable = mkEnableOption "my user module description"; someOption = mkOption { type = types.str; default = "value"; description = "An option for this module"; }; }; config = mkIf cfg.enable { home.packages = [pkgs.some-package]; # Or Home Manager-specific options programs.zsh.enable = true; }; } ``` ### 3. Register in the Category Aggregator For `cli/` modules, add to `modules/home-manager/cli/default.nix`: ```nix { imports = [ ./rofi-project-opener.nix ./stt-ptt.nix ./zellij-ps.nix ./.nix # ← add your module ]; } ``` For `coding/` modules, add to `modules/home-manager/coding/default.nix`: ```nix { imports = [ ./editors.nix ./opencode.nix ./agents ./.nix # ← add your module ]; } ``` ### 4. Export from flake.nix Add to `homeManagerModules` in `flake.nix`: ```nix homeManagerModules = { default = import ./modules/home-manager; my-module = import ./modules/home-manager//.nix; # ← add this }; ``` ## Module Patterns ### Standard Enable Option Always start with `mkEnableOption`: ```nix options.m3ta.myModule = { enable = mkEnableOption "my module"; }; ``` ### Conditional Configuration Use `mkIf` for conditional config: ```nix config = mkIf cfg.enable { # Only applied when enabled }; ``` ### Multiple Conditions Use `mkMerge` when combining multiple conditional blocks: ```nix config = mkMerge [ (mkIf cfg.feature1.enable { ... }) (mkIf cfg.feature2.enable { ... }) ]; ``` ### Nested Namespaces For logically grouped options, use nested namespaces: ```nix options.m3ta.coding = { myTool = { enable = mkEnableOption "my coding tool"; # ... }; }; ``` Usage: `m3ta.coding.myTool.enable = true;` ### Shared Library Functions For shared utilities (port helpers, etc.), import from `lib/`: ```nix let portsLib = import ../../lib/ports.nix {inherit lib;}; portHelpers = portsLib.mkPortHelpers { /* ... */ }; in { # use portHelpers } ``` ## Documentation Add documentation for your module: 1. Create `docs/modules/nixos/.md` (NixOS) or `docs/modules/home-manager//.md` (HM) 2. Follow the existing format in `docs/modules/` 3. Add it to the appropriate overview page's "Available Modules" list 4. Link it from `docs/guides/using-modules.md` ## Testing ```bash # Validate the module loads correctly nix flake check # Test with a minimal configuration (NixOS) nixos-rebuild dry-build -I nixpkgs=. --option experimental-features flakes # Format before commit nix fmt ``` ## Related - [Using Modules](./using-modules.md) - How to use existing modules - [Port Management](./port-management.md) - Centralized port management - [Development Workflow](./development-workflow.md) - Local development - [Adding Packages](./adding-packages.md) - Adding packages (not modules) - [Architecture](../ARCHITECTURE.md) - Repository structure