Your one-stop-cake-shop for everything Freshly Baked has to offer

feat(ingredients): extend to homes

Ingredients are a little tricker to use with homes than systems. That's
because in Nilla home arguments aren't special args (to allow their
portability to systems). Because this can't be changed, we previously
had special imports where we passed in inputs that needed to be
imported. As ingredients auto-import, this wouldn't be doable without
some sort of manual override functionality...

...instead of this, I've added a way to override some arguments that are
passed into ingredients. Doing this allows us to swap out our "project"
argument for a version that *can* be imported from/etc.

After doing this, moving homes to ingredients is a trivial refactor

+119 -305
+1 -2
packetmix/homes/catppuccin/catppuccin.nix
··· 2 2 # 3 3 # SPDX-License-Identifier: MIT 4 4 5 - { catppuccin }: 6 5 { project, lib, ... }: 7 6 { 8 - imports = [ catppuccin.result.homeModules.catppuccin ]; 7 + imports = [ project.inputs.catppuccin.result.homeModules.catppuccin ]; 9 8 config.catppuccin.enable = true; 10 9 11 10 config.catppuccin.cursors.enable = true;
-10
packetmix/homes/catppuccin/default.nix
··· 1 - # SPDX-FileCopyrightText: 2025 FreshlyBakedCake 2 - # 3 - # SPDX-License-Identifier: MIT 4 - 5 - { catppuccin }: 6 - { 7 - imports = [ 8 - (import ./catppuccin.nix { inherit catppuccin; }) 9 - ]; 10 - }
-18
packetmix/homes/coded/default.nix
··· 1 - # SPDX-FileCopyrightText: 2025 FreshlyBakedCake 2 - # 3 - # SPDX-License-Identifier: MIT 4 - 5 - # depends on niri flavor 6 - # depends on catppuccin flavor 7 - # depends on development flavor 8 - { 9 - imports = [ 10 - ./bitwarden.nix 11 - ./calendar.nix 12 - ./catppuccin.nix 13 - ./email.nix 14 - ./jujutsu.nix 15 - ./niri.nix 16 - ./sesh.nix 17 - ]; 18 - }
-7
packetmix/homes/collabora/default.nix
··· 1 - # SPDX-FileCopyrightText: 2025 FreshlyBakedCake 2 - # 3 - # SPDX-License-Identifier: MIT 4 - 5 - { 6 - imports = [ ./gtimelog.nix ]; 7 - }
-18
packetmix/homes/common/default.nix
··· 1 - # SPDX-FileCopyrightText: 2025 FreshlyBakedCake 2 - # 3 - # SPDX-License-Identifier: MIT 4 - 5 - { 6 - imports = [ 7 - ./bash.nix 8 - ./chromium.nix 9 - ./files.nix 10 - ./firefox.nix 11 - ./gtk.nix 12 - ./ghostty.nix 13 - ./helix.nix 14 - ./impermanence.nix 15 - ./thunderbird.nix 16 - ./zoxide.nix 17 - ]; 18 - }
+89 -67
packetmix/homes/default.nix
··· 6 6 { config, ... }: 7 7 let 8 8 nixpkgs = config.inputs.nixpkgs.result; 9 + 10 + modules = config.lib.ingredients.collectIngredientsModules ./. { project = config; }; 9 11 in 10 12 { 11 13 config.homes."maya:x86_64-linux" = { ··· 14 16 home.stateVersion = "24.11"; 15 17 home.homeDirectory = "/home/maya"; 16 18 } 17 - (import ./catppuccin { inherit (config.inputs) catppuccin; }) 18 - ./collabora 19 - ./common 20 - ./development 21 - ./espanso 22 - ./freshlybakedcake 23 - ./gaming 24 - ./maya 25 - (import ./niri { inherit (config.inputs) niri walker home-manager-unstable; }) 26 - (import ./nix-index { inherit (config.inputs) nix-index-database; }) 27 - ./remote 28 - ./scriptfs 29 - ]; 19 + { 20 + ingredient = { 21 + catppuccin.enable = true; 22 + collabora.enable = true; 23 + common.enable = true; 24 + development.enable = true; 25 + espanso.enable = true; 26 + freshlybakedcake.enable = true; 27 + gaming.enable = true; 28 + maya.enable = true; 29 + niri.enable = true; 30 + nix-index.enable = true; 31 + remote.enable = true; 32 + scriptfs.enable = true; 33 + }; 34 + } 35 + ] 36 + ++ modules; 30 37 args = { 31 38 system = "x86_64-linux"; 32 - project = config; 33 39 }; 34 40 }; 35 41 config.homes."minion:x86_64-linux" = { ··· 38 44 home.stateVersion = "24.11"; 39 45 home.homeDirectory = "/home/minion"; 40 46 } 41 - (import ./catppuccin { inherit (config.inputs) catppuccin; }) 42 - ./common 43 - ./development 44 - ./espanso 45 - ./freshlybakedcake 46 - ./gaming 47 - ./minion 48 - (import ./niri { inherit (config.inputs) niri walker home-manager-unstable; }) 49 - (import ./nix-index { inherit (config.inputs) nix-index-database; }) 50 - ./remote 51 - ./scriptfs 52 - ]; 47 + { 48 + ingredient = { 49 + catppuccin.enable = true; 50 + common.enable = true; 51 + development.enable = true; 52 + espanso.enable = true; 53 + freshlybakedcake.enable = true; 54 + gaming.enable = true; 55 + minion.enable = true; 56 + niri.enable = true; 57 + nix-index.enable = true; 58 + remote.enable = true; 59 + scriptfs.enable = true; 60 + }; 61 + } 62 + ] 63 + ++ modules; 53 64 args = { 54 65 system = "x86_64-linux"; 55 - project = config; 56 66 }; 57 67 }; 58 68 config.homes."minion@redhead:x86_64-linux" = { ··· 61 71 home.stateVersion = "24.11"; 62 72 home.homeDirectory = "/home/minion"; 63 73 } 64 - (import ./catppuccin { inherit (config.inputs) catppuccin; }) 65 - ./collabora 66 - ./common 67 - ./development 68 - ./espanso 69 - ./freshlybakedcake 70 - ./gaming 71 - ./minion 72 - (import ./niri { inherit (config.inputs) niri walker home-manager-unstable; }) 73 - (import ./nix-index { inherit (config.inputs) nix-index-database; }) 74 - (import ./redhead { inherit (config.inputs) impermanence; }) 75 - ./remote 76 - ./scriptfs 77 - ]; 74 + { 75 + ingredient = { 76 + catppuccin.enable = true; 77 + collabora.enable = true; 78 + common.enable = true; 79 + development.enable = true; 80 + espanso.enable = true; 81 + freshlybakedcake.enable = true; 82 + gaming.enable = true; 83 + minion.enable = true; 84 + niri.enable = true; 85 + nix-index.enable = true; 86 + redhead.enable = true; 87 + remote.enable = true; 88 + scriptfs.enable = true; 89 + }; 90 + } 91 + ] 92 + ++ modules; 78 93 args = { 79 94 system = "x86_64-linux"; 80 - project = config; 81 95 }; 82 96 }; 83 97 config.homes."coded:x86_64-linux" = { ··· 86 100 home.stateVersion = "25.05"; 87 101 home.homeDirectory = "/home/coded"; 88 102 } 89 - (import ./catppuccin { inherit (config.inputs) catppuccin; }) 90 - ./coded 91 - ./common 92 - ./development 93 - ./espanso 94 - ./freshlybakedcake 95 - ./gaming 96 - (import ./niri { inherit (config.inputs) niri walker home-manager-unstable; }) 97 - (import ./nix-index { inherit (config.inputs) nix-index-database; }) 98 - ./remote 99 - ./scriptfs 100 - ]; 103 + { 104 + ingredient = { 105 + catppuccin.enable = true; 106 + coded.enable = true; 107 + common.enable = true; 108 + development.enable = true; 109 + espanso.enable = true; 110 + freshlybakedcake.enable = true; 111 + gaming.enable = true; 112 + niri.enable = true; 113 + nix-index.enable = true; 114 + remote.enable = true; 115 + scriptfs.enable = true; 116 + }; 117 + } 118 + ] 119 + ++ modules; 101 120 args = { 102 121 system = "x86_64-linux"; 103 - project = config; 104 122 }; 105 123 }; 106 124 config.homes."pinea:x86_64-linux" = { ··· 109 127 home.stateVersion = "25.05"; 110 128 home.homeDirectory = "/home/pinea"; 111 129 } 112 - (import ./catppuccin { inherit (config.inputs) catppuccin; }) 113 - ./pinea 114 - ./common 115 - ./development 116 - ./espanso 117 - ./freshlybakedcake 118 - ./gaming 119 - (import ./nix-index { inherit (config.inputs) nix-index-database; }) 120 - ./remote 121 - ./scriptfs 122 - ]; 130 + { 131 + ingredient = { 132 + catppuccin.enable = true; 133 + common.enable = true; 134 + development = true; 135 + espanso = true; 136 + freshlybakedcake.enable = true; 137 + gaming.enable = true; 138 + nix-index.enable = true; 139 + pinea.enable = true; 140 + remote.enable = true; 141 + scriptfs.enable = true; 142 + }; 143 + } 144 + ] 145 + ++ modules; 123 146 args = { 124 147 system = "x86_64-linux"; 125 - project = config; 126 148 }; 127 149 }; 128 150 }
-17
packetmix/homes/development/default.nix
··· 1 - # SPDX-FileCopyrightText: 2025 FreshlyBakedCake 2 - # 3 - # SPDX-License-Identifier: MIT 4 - 5 - { 6 - # depends on scriptfs ingredient for jujutsu 7 - imports = [ 8 - ./collaboration.nix 9 - ./direnv.nix 10 - ./gpg.nix 11 - ./helix.nix 12 - ./hoppscotch.nix 13 - ./jujutsu.nix 14 - ./simplified-utilities.nix 15 - ./tmux.nix 16 - ]; 17 - }
-9
packetmix/homes/espanso/default.nix
··· 1 - # SPDX-FileCopyrightText: 2025 FreshlyBakedCake 2 - # 3 - # SPDX-License-Identifier: MIT 4 - 5 - { 6 - imports = [ 7 - ./espanso.nix 8 - ]; 9 - }
-6
packetmix/homes/freshlybakedcake/default.nix
··· 1 - # SPDX-FileCopyrightText: 2025 FreshlyBakedCake 2 - # 3 - # SPDX-License-Identifier: MIT 4 - { 5 - imports = [ ./ssh.nix ]; 6 - }
-11
packetmix/homes/gaming/default.nix
··· 1 - # SPDX-FileCopyrightText: 2025 FreshlyBakedCake 2 - # 3 - # SPDX-License-Identifier: MIT 4 - 5 - { 6 - imports = [ 7 - ./itch.nix 8 - ./minecraft.nix 9 - ./steam.nix 10 - ]; 11 - }
-21
packetmix/homes/maya/default.nix
··· 1 - # SPDX-FileCopyrightText: 2025 Collabora Productivity Limited 2 - # SPDX-FileCopyrightText: 2025 FreshlyBakedCake 3 - # 4 - # SPDX-License-Identifier: MIT 5 - 6 - # depends on niri flavor 7 - # depends on catppuccin flavor 8 - { 9 - imports = [ 10 - ./catppuccin.nix 11 - ./espanso.nix 12 - ./helix.nix 13 - ./jujutsu.nix 14 - ./keyboard.nix 15 - ./misc.nix 16 - ./nano.nix 17 - ./niri.nix 18 - ./ssh.nix 19 - ./zed.nix 20 - ]; 21 - }
-21
packetmix/homes/minion/default.nix
··· 1 - # SPDX-FileCopyrightText: 2025 FreshlyBakedCake 2 - # 3 - # SPDX-License-Identifier: MIT 4 - 5 - # depends on niri flavor 6 - # depends on catppuccin flavor 7 - { 8 - imports = [ 9 - ./catppuccin.nix 10 - ./espanso.nix 11 - ./helix.nix 12 - ./impermanence.nix 13 - ./jujutsu.nix 14 - ./keyboard.nix 15 - ./misc.nix 16 - ./niri.nix 17 - ./prompt.nix 18 - ./ssh.nix 19 - ./xdg.nix 20 - ]; 21 - }
-18
packetmix/homes/niri/default.nix
··· 1 - # SPDX-FileCopyrightText: 2025 FreshlyBakedCake 2 - # 3 - # SPDX-License-Identifier: MIT 4 - 5 - { 6 - niri, 7 - walker, 8 - home-manager-unstable, 9 - }: 10 - { 11 - imports = [ 12 - (import ./niri.nix { inherit niri walker; }) 13 - (import ./quickshell { inherit home-manager-unstable; }) 14 - ./scriptfs.nix 15 - ./ssh.nix 16 - ./swaync.nix 17 - ]; 18 - }
+2 -3
packetmix/homes/niri/niri.nix
··· 2 2 # 3 3 # SPDX-License-Identifier: MIT 4 4 5 - { niri, walker }: 6 5 { 7 6 project, 8 7 config, ··· 12 11 }: 13 12 { 14 13 imports = [ 15 - niri.result.homeModules.niri 16 - walker.result.homeManagerModules.walker 14 + project.inputs.niri.result.homeModules.niri 15 + project.inputs.walker.result.homeManagerModules.walker 17 16 ]; 18 17 19 18 options.niri = {
+1 -2
packetmix/homes/niri/quickshell/default.nix
··· 2 2 # 3 3 # SPDX-License-Identifier: MIT 4 4 5 - { home-manager-unstable }: 6 5 { 7 6 project, 8 7 system, ··· 11 10 ... 12 11 }: 13 12 { 14 - imports = [ "${home-manager-unstable.src}/modules/programs/quickshell.nix" ]; 13 + imports = [ "${project.inputs.home-manager-unstable.src}/modules/programs/quickshell.nix" ]; 15 14 16 15 programs.quickshell = { 17 16 enable = true;
-10
packetmix/homes/nix-index/default.nix
··· 1 - # SPDX-FileCopyrightText: 2025 FreshlyBakedCake 2 - # 3 - # SPDX-License-Identifier: MIT 4 - 5 - { nix-index-database }: 6 - { 7 - imports = [ 8 - (import ./nix-index.nix { inherit nix-index-database; }) 9 - ]; 10 - }
+2 -3
packetmix/homes/nix-index/nix-index.nix
··· 2 2 # 3 3 # SPDX-License-Identifier: MIT 4 4 5 - { nix-index-database }: 6 - { ... }: 5 + { project, ... }: 7 6 { 8 7 imports = [ 9 - nix-index-database.result.homeModules.nix-index 8 + project.inputs.nix-index-database.result.homeModules.nix-index 10 9 ]; 11 10 12 11 config = {
-14
packetmix/homes/pinea/default.nix
··· 1 - # SPDX-FileCopyrightText: 2025 FreshlyBakedCake 2 - # 3 - # SPDX-License-Identifier: MIT 4 - 5 - # depends on niri flavor 6 - # depends on catppuccin flavor 7 - { 8 - imports = [ 9 - ./catppuccin.nix 10 - ./keyboard.nix 11 - ./misc.nix 12 - ./zed.nix 13 - ]; 14 - }
-12
packetmix/homes/redhead/default.nix
··· 1 - # SPDX-FileCopyrightText: 2025 FreshlyBakedCake 2 - # 3 - # SPDX-License-Identifier: MIT 4 - 5 - # depends on niri flavor 6 - { impermanence }: 7 - { 8 - imports = [ 9 - (import ./impermanence.nix { inherit impermanence; }) 10 - ./niri.nix 11 - ]; 12 - }
+2 -3
packetmix/homes/redhead/impermanence.nix
··· 2 2 # 3 3 # SPDX-License-Identifier: MIT 4 4 5 - { impermanence }: 6 - { ... }: 5 + { project, ... }: 7 6 { 8 7 imports = [ 9 - impermanence.result.homeManagerModules.impermanence 8 + project.inputs.impermanence.result.homeManagerModules.impermanence 10 9 ]; 11 10 12 11 clicks.storage.impermanence.enable = true;
-9
packetmix/homes/remote/default.nix
··· 1 - # SPDX-FileCopyrightText: 2025 FreshlyBakedCake 2 - # 3 - # SPDX-License-Identifier: MIT 4 - 5 - { 6 - imports = [ 7 - ./ssh.nix 8 - ]; 9 - }
-9
packetmix/homes/scriptfs/default.nix
··· 1 - # SPDX-FileCopyrightText: 2025 FreshlyBakedCake 2 - # 3 - # SPDX-License-Identifier: MIT 4 - 5 - { 6 - imports = [ 7 - ./scriptfs.nix 8 - ]; 9 - }
+21 -14
packetmix/lib/ingredients.nix
··· 37 37 38 38 # Lets you wrap a module without worrying about if the module you're wrapping is a function or an attrset 39 39 # 40 - # this: {wrapper -> path -> moduleToWrap -> outModule} 40 + # this: {wrapper -> path -> overrideArgs -> moduleToWrap -> outModule} 41 41 # 42 42 # wrapper: {moduleArgs -> normalizedModuleAttrset -> moduleAttrset} a function which takes an applied module and returns an unapplied module 43 43 # path: {string} a "path" that'll appear as "virtual:packetmix/wrapped/${path}" in evaluation failures for this module 44 + # overrideArgs: an attrset of arguments to override the defaults. Similar to specialArgs and co 44 45 # moduleToWrap: {moduleArgs -> moduleAttrset | moduleAttrset} the module for which the wrapper will wrap the moduleAttrset 45 46 # outModule: {moduleArgs -> moduleAttrset} the wrapped module 46 47 # moduleArgs: the standard arguments to a module, including standard arguments (lib, pkgs, etc.), extraArgs, etc. ··· 48 49 # normalizedModuleAttrset: a module attrset that has been normalized to have either config or options as a top-level option 49 50 # shorthandModuleAttrset: a module attrset that has its config as shorthand properties (and contains no options) 50 51 wrapModule = 51 - wrapper: path: moduleToWrap: 52 + wrapper: path: overrideArgs: moduleToWrap: 52 53 if builtins.isFunction moduleToWrap then 53 54 let 54 55 wrapped = 55 56 args: 56 57 let 57 - moduleArgs = builtins.intersectAttrs (nixpkgs.lib.functionArgs moduleToWrap) args; 58 + moduleArgs = builtins.intersectAttrs (nixpkgs.lib.functionArgs moduleToWrap) (args // overrideArgs); 58 59 moduleAttrset = moduleToWrap moduleArgs; 59 60 60 - wrappedModule = this.wrapModule wrapper path moduleAttrset; 61 - wrapperArgs = builtins.intersectAttrs (nixpkgs.lib.functionArgs wrapper) args; 61 + wrappedModule = this.wrapModule wrapper path overrideArgs moduleAttrset; # overrideArgs doesn't really matter at this point since as the other branch won't use it ... but we may as well 62 + wrapperArgs = builtins.intersectAttrs (nixpkgs.lib.functionArgs wrapper) (args // overrideArgs); 62 63 in 63 64 wrappedModule wrapperArgs; 64 65 in ··· 82 83 # disabledModules, etc. *will always be applied* so they probably shouldn't have a 83 84 # visible effect on the system 84 85 # 85 - # this: {name -> subpath -> moduleToWrap -> outModule} 86 + # this: {name -> subpath -> overrideArgs -> moduleToWrap -> outModule} 86 87 # 87 88 # name: {string} the name of the ingredient, used as the enable option and as "virtual:packetmix/wrapped/ingredient/${name}/${subpath}" in evaluation failures for this module 88 89 # subpath: {string} a more specific name for the module - e.g. filename.nix - used as "virtual:packetmix/wrapped/ingredient/${name}/${subpath}" in evaluation failures for this module 90 + # overrideArgs: an attrset of arguments to override the defaults. Similar to specialArgs and co 89 91 # moduleToWrap: {moduleArgs -> moduleAttrset | moduleAttrset} the module which should be enabled by config.ingredient.${name}.enable 90 92 # outModule: {moduleArgs -> normalizedModuleAttrset} the wrapped module 91 93 # moduleArgs: the standard arguments to a module, including standard arguments (lib, pkgs, etc.), extraArgs, etc. ··· 103 105 } 104 106 ) "ingredient/${name}/${subpath}"; 105 107 106 - # Gets modules for a specific ingredient, based on a base directory and a name 108 + # Gets modules for a specific ingredient, based on a base directory, a name and any argument overrides 107 109 # Includes a declaration of options.ingredient.${name}.enable and auto-imports for all modules in ${ingredientDirectory}/${name}, mkIfed behind that enable option 108 110 # 109 - # this: {ingredientsDirectory -> name -> outModule[]} 111 + # this: {ingredientsDirectory -> overrideArgs -> name -> outModule[]} 110 112 # 111 113 # ingredientsDirectory: {path} the path in which your ingredients reside 114 + # overrideArgs: an attrset of arguments to override the defaults. Similar to specialArgs and co 112 115 # name: {string} the name of the ingredient 113 116 # outModule[]: {(moduleArgs -> normalizedModuleAttrset | normalizedModuleAttrset)[]} modules for the ingredient, with their config conditionally-enabled on the ingredient being enabled 114 117 # moduleArgs: the standard arguments to a module, including standard arguments (lib, pkgs, etc.), extraArgs, etc. 115 118 # normalizedModuleAttrset: a module attrset that has been normalized to have either config or options as a top-level option 116 119 collectIngredientModules = 117 - ingredientsDirectory: name: 120 + ingredientsDirectory: overrideArgs: name: 118 121 let 119 122 ingredientDirectoryListing = builtins.readDir "${ingredientsDirectory}/${name}"; 120 123 ingredientNixFiles = nilla.lib.attrs.filter ( ··· 122 125 ) ingredientDirectoryListing; 123 126 ingredientNixFileSubpaths = builtins.attrNames ingredientNixFiles; 124 127 modules = map ( 125 - subpath: this.mkIngredientModule name subpath (import "${ingredientsDirectory}/${name}/${subpath}") 128 + subpath: 129 + this.mkIngredientModule name subpath overrideArgs ( 130 + import "${ingredientsDirectory}/${name}/${subpath}" 131 + ) 126 132 ) ingredientNixFileSubpaths; 127 133 in 128 134 modules ··· 150 156 [ ] 151 157 ); 152 158 153 - # Gets modules for all ingredients, based on just a directory 159 + # Gets modules for all ingredients, based on just a directory and any argument overrides 154 160 # Includes all required option declarations (under options.ingredient.${name}.enable for each ingredient) and conditional auto-imports 155 161 # Includes any options, imports, etc. that are defined in *any* ingredient, even if it is not enabled 156 162 # 157 - # this: {ingredientsDirectory -> outModule[]} 163 + # this: {ingredientsDirectory -> overrideArgs -> outModule[]} 158 164 # ingredientsDirectory: {path} the path in which your ingredients reside 159 165 # name: {string} the name of the ingredient 166 + # overrideArgs: an attrset of arguments to override the defaults. Similar to specialArgs and co 160 167 # outModule[]: {(moduleArgs -> normalizedModuleAttrset | normalizedModuleAttrset)[]} modules for all ingredients, with their config conditionally-enabled on their ingredient being enabled 161 168 # moduleArgs: the standard arguments to a module, including standard arguments (lib, pkgs, etc.), extraArgs, etc. 162 169 # normalizedModuleAttrset: a module attrset that has been normalized to have either config or options as a top-level option 163 170 collectIngredientsModules = 164 - ingredientsDirectory: 171 + ingredientsDirectory: overrideArgs: 165 172 let 166 173 ingredientsDirectoryListing = builtins.readDir ingredientsDirectory; 167 174 ingredientSubdirectories = nilla.lib.attrs.filter ( 168 175 _: value: value == "directory" 169 176 ) ingredientsDirectoryListing; 170 177 ingredientNames = builtins.attrNames ingredientSubdirectories; 171 - modules = map (this.collectIngredientModules ingredientsDirectory) ingredientNames; 178 + modules = map (this.collectIngredientModules ingredientsDirectory overrideArgs) ingredientNames; 172 179 in 173 180 nilla.lib.lists.flatten modules; 174 181 };
+1 -1
packetmix/systems/default.nix
··· 7 7 let 8 8 nixpkgs = config.inputs.nixpkgs.result; 9 9 10 - modules = config.lib.ingredients.collectIngredientsModules ./.; 10 + modules = config.lib.ingredients.collectIngredientsModules ./. {}; 11 11 in 12 12 { 13 13 config.systems.nixos."redhead" = {