This is a NixOS/Home Manager configuration repository structured as a Nix flake. It manages
multiple hosts (nixbook, macbook, macbook-cookunity) and a single user (christopher). The
entire config is written in Nix using flake-parts and import-tree to auto-import all modules
under modules/.
flake.nix # Entrypoint: delegates to flake-parts via import-tree
modules/
flake-modules.nix # Imports flake-parts and home-manager flake modules
helpers.nix # Shared utilities (mkAssetsPath, mkHybrid, etc.) and flake-level options
features/ # Feature modules (ai, browser, cli-tooling, coding, communication,
# design, desktop-shell, gaming, gnome-apps, graphics, homebrew,
# launcher, mise-fixes, productivity, security, sound, splashscreen,
# storage, streaming, terminal, theme, window-manager, …)
hosts/ # Per-host configurations
nixbook/ # Main Linux host (NixOS, x86_64-linux)
macbook/ # Personal macOS host (nix-darwin, aarch64-darwin)
macbook-cookunity/ # Work macOS host (nix-darwin, aarch64-darwin)
users/
christopher.nix # Home Manager base user config
assets/ # Static files symlinked into $HOME (nvim config, scripts, wallpapers, …)
nix flake checknix build .#nixosConfigurations.nixbook.config.system.build.toplevelsudo nixos-rebuild switch --flake .#nixbooksudo darwin-rebuild switch --flake .#macbook
# or from zsh alias:
switchnix flake updatenix flake update nixpkgsThe project uses nixfmt (version 1.2.0, the "RFC 166" style) for all .nix files.
nixfmt **/*.nix
# or per-file:
nixfmt modules/features/ai.nixThere is no formatter output defined in the flake yet, so nix fmt will error — use nixfmt
directly.
There is no automated test suite. The primary validation mechanism is:
nix flake check # Evaluates all nixosConfigurations and nixosModulesTo dry-run a configuration switch (build without activating):
sudo nixos-rebuild dry-activate --flake .#nixbookTo check a specific host evaluation only:
nix eval .#nixosConfigurations.nixbook.config.system.build.toplevel- 2 spaces for
.nix,.lua,.json,.jsoncfiles (enforced by.editorconfig). - LF line endings, files must end with a final newline.
nixfmtis the canonical formatter — run it before committing changes.
- Short argument lists go on one line:
{ inputs, ... }: - Longer lists use one argument per line with a trailing comma, closing brace on its own line:
{ inputs, config, ... }:
- Always define
let … inblocks at the top of a file or function body, not inline. - Destructure helpers and commonly-used values early:
let username = config.flake.username; helpers = config.flake.helpers; in
Each feature file exposes its configuration under three namespaces:
flake.modules.nixos.<name>— NixOS system-level moduleflake.modules.darwin.<name>— nix-darwin system-level moduleflake.modules.homeManager.<name>— Home Manager user-level module
Not every feature needs all three; omit namespaces that don't apply.
- Opening brace on the same line as the binding for short sets.
- Multi-line sets: opening brace at end of the assignment line, closing brace aligned with the binding keyword.
- Use
with pkgs;only insidehome.packages = with pkgs; [ … ]list expressions; avoidwithelsewhere.
- Short lists on one line:
[ "a" "b" ] - Longer lists: one element per line, brackets on their own lines:
home.packages = with pkgs; [ bat fzf ripgrep ];
- Use
helpers.mkAssetsPath "/subpath"to reference files underassets/as a Nix store path (evaluated at build time). - Use
helpers.mkAssetsStringPath hmConfig "/subpath"to referenceassets/files as a string path (~/NixConfig/assets/<path>) — use this for live symlinks that must not enter the store. - Use
helpers.mkConfigPath hmConfig "/subpath"for~/.config/paths. - Use
helpers.mkHomePath hmConfig "/subpath"for~/paths. - Prefer
config.lib.file.mkOutOfStoreSymlinkfor mutable/live-edited assets (e.g., the Neovim config) so changes don't require a rebuild. - Use
helpers.mkHybrid { linux? darwin? common? }to create a Home Manager module that conditionally applies config per platform —commonis always included,linux/darwinare guarded withlib.mkIffor the matching platform.
- Feature module names match their filename without extension (e.g.,
cli-tooling,window-manager). - NixOS module attributes use
camelCasefor multi-word names when the filename uses kebab-case (e.g.,nixbookConfiguration). - Options and config keys follow nixpkgs conventions:
camelCasefor option names.
- Define overlays as a top-level
letbinding when shared acrossnixosanddarwinmodules:let overlays = [ inputs.foo.overlays.default … ]; in { flake.modules.nixos.foo = { nixpkgs.overlays = overlays; }; flake.modules.darwin.foo = { nixpkgs.overlays = overlays; }; }
- Use
#inline comments to explain non-obvious choices (e.g., workaround links, performance rationale). - Section headers use a blank line above and a short
# Section titlecomment.
- Never hardcode usernames — always use
config.flake.username(resolves to"christopher"). - Never hardcode home paths — always use the
helpers.*path functions. allowUnfree = trueis set system-wide; proprietary packages are permitted.- Supported systems:
x86_64-linuxandaarch64-darwin(defined inhelpers.nix). nixpkgs.config.allowUnfreemust be set in the NixOS/darwin system module, not in Home Manager.- When adding a new feature, create
modules/features/<name>.nixand add it to the relevant host'sdefault.niximports under both the system-level andhome-manager.users.${username}.importslists. import-treeautomatically picks up any.nixfile added undermodules/; no manual registration inflake.nixis needed.- The
switchshell alias runs the correct rebuild command per platform (Linux vs. Darwin).