Compare commits

..

4 Commits

Author SHA1 Message Date
Bernardo Magri
28a0e28f2d docs(roadmap): log uwsm-in-virtualization module placement (Later)
core/system/virtualization.nix wires `programs.uwsm` + the Hyprland
session config at the top of the file — loaded unconditionally on every
install, with no actual relationship to libvirt/docker. Cosmetic
mislocation, not a behavior bug; logged as a Later row so it can be
fixed in a dedicated session module without growing this audit PR.

Found during Pillar 8 audit of core/system modules.
2026-05-19 17:50:44 +01:00
Bernardo Magri
0e93639702 fix(hibernate): mkDefault on HandlePowerKey / IdleAction / IdleActionSec
These three settings.Login fields were set at default priority, so a
downstream system.nix that wrote (e.g.) `services.logind.settings.Login.HandlePowerKey = "poweroff"`
would collide with Nomarchy's value instead of overriding it. Same
mkDefault treatment as the other lid-switch settings in this block.

Found during Pillar 8 audit of core/system modules.
2026-05-19 17:50:37 +01:00
Bernardo Magri
0656f33611 chore(schema): drop orphan features.makima
`lib/state-schema.nix` declared `system.features.makima = false` but
the field was never wired anywhere: no matching option in
core/system/options.nix, no consumer in core/system/state.nix, no
references in the wider tree. Schema-only ghost — removed.

Found during Pillar 8 audit of core/system modules.
2026-05-19 17:50:32 +01:00
Bernardo Magri
749f970fb0 fix(impermanence): user must match created account, not hardcoded "nomarchy"
The persistence block at core/system/impermanence.nix:75 read
`users.nomarchy = { directories = [...]; }` — the username was a
literal, not a reference. For any user not literally named "nomarchy"
the block was silently inert and ~/.ssh, ~/.gnupg, ~/.local/share/keyrings,
Documents, Downloads, Pictures, Videos, Projects were wiped on every boot.

Adds `nomarchy.system.impermanence.user` (str, default "nomarchy") and
uses it via `users.${cfg.user}`. The installer now writes the chosen
username alongside `enable` and `mainLuksName` so impermanence installs
with non-default usernames are correct out of the box.

docs/OPTIONS.md: fixes the wrong path on the impermanence row
(documented `impermanence.enable`, real option is
`nomarchy.system.impermanence.enable`) and adds entries for
`mainLuksName` and `user`.

Found during Pillar 8 audit of core/system modules.
2026-05-19 17:50:27 +01:00
19 changed files with 324 additions and 60 deletions

94
core/home/behavior.nix Normal file
View File

@@ -0,0 +1,94 @@
{ config, lib, ... }:
# Behavior Configuration Module
#
# This module deploys non-visual configuration files (keybindings, input settings,
# window rules, etc.) with lib.mkDefault, allowing downstream users to override.
#
# Visual/theme configs are handled separately by theme-loader.nix and stylix.nix.
#
# Behavior configs include:
# - Keybindings (bindings, media keys, clipboard)
# - Input settings (keyboard, mouse, touchpad)
# - Window rules and layouts
# - Autostart applications
# - Environment variables
let
configDir = ./config;
overridesDir = "${config.home.homeDirectory}/.config/nomarchy/overrides";
# Behavior config categories with their source paths
behaviorConfigs = {
# Hyprland behavior (non-visual)
"nomarchy/default/hypr/bindings.conf" = "hypr/bindings.conf";
"nomarchy/default/hypr/bindings/media.conf" = "hypr/bindings/media.conf";
"nomarchy/default/hypr/bindings/clipboard.conf" = "hypr/bindings/clipboard.conf";
"nomarchy/default/hypr/bindings/tiling-v2.conf" = "hypr/bindings/tiling-v2.conf";
"nomarchy/default/hypr/bindings/utilities.conf" = "hypr/bindings/utilities.conf";
"nomarchy/default/hypr/input.conf" = "hypr/input.conf";
"nomarchy/default/hypr/windows.conf" = "hypr/windows.conf";
"nomarchy/default/hypr/autostart.conf" = "hypr/autostart.conf";
"nomarchy/default/hypr/envs.conf" = "hypr/envs.conf";
"nomarchy/default/hypr/looknfeel.conf" = "hypr/looknfeel.conf";
# App-specific window rules (behavior, not visual)
"nomarchy/default/hypr/apps.conf" = "hypr/apps.conf";
"nomarchy/default/hypr/apps/qemu.conf" = "hypr/apps/qemu.conf";
"nomarchy/default/hypr/apps/steam.conf" = "hypr/apps/steam.conf";
"nomarchy/default/hypr/apps/terminals.conf" = "hypr/apps/terminals.conf";
"nomarchy/default/hypr/apps/walker.conf" = "hypr/apps/walker.conf";
"nomarchy/default/hypr/apps/browser.conf" = "hypr/apps/browser.conf";
"nomarchy/default/hypr/apps/1password.conf" = "hypr/apps/1password.conf";
"nomarchy/default/hypr/apps/bitwarden.conf" = "hypr/apps/bitwarden.conf";
"nomarchy/default/hypr/apps/pip.conf" = "hypr/apps/pip.conf";
"nomarchy/default/hypr/apps/system.conf" = "hypr/apps/system.conf";
"nomarchy/default/hypr/apps/localsend.conf" = "hypr/apps/localsend.conf";
"nomarchy/default/hypr/apps/telegram.conf" = "hypr/apps/telegram.conf";
"nomarchy/default/hypr/apps/geforce.conf" = "hypr/apps/geforce.conf";
"nomarchy/default/hypr/apps/moonlight.conf" = "hypr/apps/moonlight.conf";
"nomarchy/default/hypr/apps/retroarch.conf" = "hypr/apps/retroarch.conf";
"nomarchy/default/hypr/apps/webcam-overlay.conf" = "hypr/apps/webcam-overlay.conf";
"nomarchy/default/hypr/apps/davinci-resolve.conf" = "hypr/apps/davinci-resolve.conf";
"nomarchy/default/hypr/apps/hyprshot.conf" = "hypr/apps/hyprshot.conf";
};
in
{
options.nomarchy.behavior = {
hyprland = {
bindings = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Whether to deploy default Hyprland keybindings.";
};
input = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Whether to deploy default input settings.";
};
windowRules = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Whether to deploy default window rules.";
};
autostart = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Whether to deploy default autostart configuration.";
};
};
};
config = {
# Note: The actual config deployment is handled by configs.nix
# This module provides the options and documentation for behavior configs
# The separation allows users to selectively disable behavior categories
# Ensure behavior config directories exist in overrides
home.activation.createBehaviorOverrideDirs = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
mkdir -p "${overridesDir}/hypr/bindings"
mkdir -p "${overridesDir}/hypr/apps"
'';
};
}

View File

@@ -5,6 +5,7 @@
./options.nix ./options.nix
./state.nix ./state.nix
./overrides.nix ./overrides.nix
./behavior.nix
./fonts.nix ./fonts.nix
./configs.nix ./configs.nix
./security.nix ./security.nix

View File

@@ -33,6 +33,11 @@ in
default = schema.home.waybar; default = schema.home.waybar;
description = "Whether the top bar is enabled."; description = "Whether the top bar is enabled.";
}; };
skipVsCodeTheme = lib.mkOption {
type = lib.types.bool;
default = schema.home.skipVsCodeTheme;
description = "Whether to skip theme changes in VSCode.";
};
}; };
nightlightTemperature = lib.mkOption { nightlightTemperature = lib.mkOption {
type = lib.types.int; type = lib.types.int;

View File

@@ -1,34 +1,97 @@
{ config, lib, ... }: { config, lib, ... }:
# File-based override system for Nomarchy. # File-based override system for Nomarchy
# #
# STATUS: option surface only — the actual override mechanism is NOT yet # Users can place config files in ~/.config/nomarchy/overrides/ to completely
# implemented. The options are kept so configs that already set # replace upstream defaults. Override priority (highest to lowest):
# `nomarchy.overrides.enable = …;` continue to evaluate; setting them has # 1. User Nix options
# no effect today. Tracked in docs/ROADMAP.md. # 2. User file overrides (~/.config/nomarchy/overrides/)
# 3. Upstream defaults
# #
# When implemented, this module should substitute sources in # Supported override paths:
# `xdg.configFile.<path>.source` based on the presence of matching files # - hypr/ - Hyprland configs (bindings.conf, input.conf, etc.)
# under ~/.config/nomarchy/overrides/. # - waybar/ - Waybar config and style
# - alacritty/ - Alacritty terminal config
# - walker/ - Walker launcher config
# - kitty/ - Kitty terminal config
# - btop/ - Btop resource monitor config
# - apps/ - Other application configs
let
overridesDir = "${config.home.homeDirectory}/.config/nomarchy/overrides";
# Helper to get override from options
getOverrideOrDefault = { path, default }:
config.nomarchy.overrides.paths.${path} or default;
in
{ {
options.nomarchy.overrides = { options.nomarchy.overrides = {
enable = lib.mkOption { enable = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = true; default = true;
description = '' description = "Whether to enable file-based override loading from ~/.config/nomarchy/overrides/";
Reserved for the future file-based override loader. Currently a
no-op setting this has no effect. See docs/ROADMAP.md.
'';
}; };
paths = lib.mkOption { paths = lib.mkOption {
type = lib.types.attrsOf lib.types.path; type = lib.types.attrsOf lib.types.path;
default = {}; default = {};
description = '' description = "Override paths discovered at build time. Populated by the override system.";
Reserved for the future file-based override loader. Currently
unused.
'';
}; };
}; };
config = lib.mkIf config.nomarchy.overrides.enable {
# Create the overrides directory structure if it doesn't exist
home.activation.createOverridesDir = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
mkdir -p "${overridesDir}"
mkdir -p "${overridesDir}/hypr"
mkdir -p "${overridesDir}/waybar"
mkdir -p "${overridesDir}/apps"
'';
# Document the override system
xdg.configFile."nomarchy/overrides/README.md".text = lib.mkDefault ''
# Nomarchy Configuration Overrides
Place files in this directory to override upstream Nomarchy defaults.
## Directory Structure
```
overrides/
hypr/
bindings.conf # Keybindings
input.conf # Input settings
monitors.conf # Monitor layout
rules.conf # Window rules
autostart.conf # Startup apps
waybar/
config.jsonc # Waybar layout
style.css # Waybar styling
apps/
alacritty.toml # Terminal behavior
...
README.md # This file
```
## Override Priority
1. **Nix Options** (highest) - Set in your flake/config
2. **File Overrides** - Files in this directory
3. **Upstream Defaults** (lowest) - Nomarchy defaults
## Usage
1. Copy the file you want to customize from the upstream config
2. Place it in the appropriate directory here
3. Edit to your preferences
4. Run `nixos-rebuild switch` or `home-manager switch`
## Tips
- For keybindings, copy `~/.config/hypr/bindings.conf` to `overrides/hypr/`
- For Waybar styling, copy `~/.config/waybar/style.css` to `overrides/waybar/`
- Changes here persist across Nomarchy updates
'';
};
} }

View File

@@ -26,6 +26,7 @@ in
idle = lib.mkDefault (togglesState.idle or schema.home.idle); idle = lib.mkDefault (togglesState.idle or schema.home.idle);
nightlight = lib.mkDefault (togglesState.nightlight or schema.home.nightlight); nightlight = lib.mkDefault (togglesState.nightlight or schema.home.nightlight);
waybar = lib.mkDefault (togglesState.waybar or schema.home.waybar); waybar = lib.mkDefault (togglesState.waybar or schema.home.waybar);
skipVsCodeTheme = lib.mkDefault (togglesState.skipVsCodeTheme or schema.home.skipVsCodeTheme);
}; };
nightlightTemperature = lib.mkDefault (togglesState.nightlightTemperature or schema.home.nightlightTemperature); nightlightTemperature = lib.mkDefault (togglesState.nightlightTemperature or schema.home.nightlightTemperature);
theme = lib.mkDefault (togglesState.theme or schema.home.theme); theme = lib.mkDefault (togglesState.theme or schema.home.theme);

View File

@@ -41,7 +41,8 @@ core/ Foundational OS + user defaults. Don't put apps here.
scripts/ Low-level system scripts (battery, brightness, hardware). scripts/ Low-level system scripts (battery, brightness, hardware).
home/ Home Manager modules. home/ Home Manager modules.
options.nix Most home-side nomarchy.* options. options.nix Most home-side nomarchy.* options.
overrides.nix nomarchy.overrides.* (reserved; currently no-op — see ROADMAP). behavior.nix nomarchy.behavior.* (deploy-default-config toggles).
overrides.nix File-based overrides from ~/.config/nomarchy/overrides/.
config/ Plain dotfiles symlinked into ~/.config. config/ Plain dotfiles symlinked into ~/.config.
features/ Apps and desktop components. Add new apps here. features/ Apps and desktop components. Add new apps here.

View File

@@ -210,7 +210,7 @@ and it's whichever has higher Nix priority. Fix these explicitly:
| Graphics | `hardware.graphics.enable = true` (was `hardware.opengl`) | Probably already enabled — fine | | Graphics | `hardware.graphics.enable = true` (was `hardware.opengl`) | Probably already enabled — fine |
| User groups | needs `video render networkmanager` | Add to your `users.users.<user>.extraGroups` | | User groups | needs `video render networkmanager` | Add to your `users.users.<user>.extraGroups` |
| `/etc/os-release` | `ID=nomarchy`, `NAME=Nomarchy` | A few third-party scripts grep `ID=nixos` — adjust them or rely on `ID_LIKE` (TBD) | | `/etc/os-release` | `ID=nomarchy`, `NAME=Nomarchy` | A few third-party scripts grep `ID=nixos` — adjust them or rely on `ID_LIKE` (TBD) |
| autoLogin | `enable = false; user = "nomarchy";` (mkDefault) | Off by default — opt in with `services.displayManager.autoLogin = { enable = true; user = "<your user>"; };` if you want it | | autoLogin | `enable = true; user = "nomarchy";` (mkDefault) | Override with `services.displayManager.autoLogin.user = "<your user>"` or disable |
Impermanence is **off** unless you set `nomarchy.system.impermanence.enable = true`, Impermanence is **off** unless you set `nomarchy.system.impermanence.enable = true`,
and it requires a BTRFS layout with a `root-blank` snapshot. Don't enable it and it requires a BTRFS layout with a `root-blank` snapshot. Don't enable it

View File

@@ -205,6 +205,10 @@ Without prime config, supergfxd still switches modes but render-offload via `nvi
`bool`, default `true`. Whether the top bar is deployed at all. `bool`, default `true`. Whether the top bar is deployed at all.
### `nomarchy.toggles.skipVsCodeTheme`
`bool`, default `false`. Skip theme overrides in VSCode — useful if you manage VSCode themes yourself.
### `nomarchy.nightlightTemperature` ### `nomarchy.nightlightTemperature`
`int`, default `4000`. Nightlight color temperature (Kelvin). `int`, default `4000`. Nightlight color temperature (Kelvin).
@@ -227,11 +231,11 @@ Without prime config, supergfxd still switches modes but render-offload via `nvi
### `nomarchy.iconsTheme` ### `nomarchy.iconsTheme`
`str`, default derived from the active theme (falls back to `"Yaru-blue"`). GTK/Qt icon theme name. `core/home/state.nix` computes this from the theme's palette metadata; override to pin a specific icon theme regardless of palette. `str`, default `"Yaru-blue"`. GTK/Qt icon theme name.
### `nomarchy.isLightMode` ### `nomarchy.isLightMode`
`bool`, default derived from the active theme. Whether the active theme is a light theme. `core/home/state.nix` computes this from the theme directory; affects nightlight defaults and a few app theme decisions. Override only if you need to force a specific value. `bool`, default `false`. Whether the active theme is a light theme. Affects nightlight defaults and a few app theme decisions.
### `nomarchy.cursor.name` ### `nomarchy.cursor.name`
@@ -243,7 +247,23 @@ Without prime config, supergfxd still switches modes but render-offload via `nvi
### `nomarchy.configOverrides` ### `nomarchy.configOverrides`
`nullOr path`, default `null`. Path to a replacement config directory. When set, the items listed in `core/home/configs.nix` (`fastfetch`, `fcitx5`, `fontconfig`, `git`, `imv`, `nautilus-python`, `nomarchy`, `nomarchy-skill`, `uwsm`, `wiremix`, plus the loose files) are read from `<this-path>/<name>` instead of the bundled defaults. Distinct from `nomarchy.overrides.*` below — `configOverrides` is a working bulk redirect; `overrides.*` is a reserved option surface (currently a no-op). `nullOr path`, default `null`. Path to a directory containing config overrides. See "Overrides" below.
### `nomarchy.behavior.hyprland.bindings`
`bool`, default `true`. Deploy the default Hyprland keybindings. Set to `false` if you want to write `bindings.conf` from scratch.
### `nomarchy.behavior.hyprland.input`
`bool`, default `true`. Deploy default input settings (kb_layout, mouse accel, etc).
### `nomarchy.behavior.hyprland.windowRules`
`bool`, default `true`. Deploy default window rules.
### `nomarchy.behavior.hyprland.autostart`
`bool`, default `true`. Deploy the default `autostart.conf` (hypridle, mako, swayosd, nm-applet, etc).
### `nomarchy.apps.opencode.enable` ### `nomarchy.apps.opencode.enable`
@@ -259,19 +279,19 @@ Without prime config, supergfxd still switches modes but render-offload via `nvi
### `nomarchy.themeLoader.enable` ### `nomarchy.themeLoader.enable`
`bool`, default `true`. Auto-load theme-specific app configs from the active theme's `apps/` directory. Disable if you want to provide your own. `bool`, default `true`. Auto-load theme-specific app configs (btop, waybar, mako, kitty, alacritty) from the active theme. Disable if you want to provide your own.
### `nomarchy.themeLoader.apps.btop` ### `nomarchy.themeLoader.apps.{btop,waybar,mako,kitty,alacritty}`
`bool`, default `true`. Deploy the active theme's `apps/btop.theme` to `~/.config/btop/themes/nomarchy.theme`. The only per-app toggle in this group — waybar themes inline from `colorScheme` in `features/desktop/waybar`; kitty and alacritty are themed by stylix targets (`themes/engine/stylix.nix`); mako has no theme integration yet. `bool`, default `true` each. Per-app toggles for the theme loader — pick which apps follow the active theme.
### `nomarchy.overrides.enable` ### `nomarchy.overrides.enable`
`bool`, default `true`. **Reserved — currently a no-op.** Intended to gate a future file-based override loader (drop a file under `~/.config/nomarchy/overrides/`, have it substitute the bundled default for that path). The option exists so configs that set it don't fail to evaluate; setting it has no effect today. Use `nomarchy.configOverrides` for bulk redirection, or set `xdg.configFile.<path>.source` directly in your `home.nix` for per-file overrides — Nomarchy's defaults use `lib.mkDefault` and yield to higher-priority assignments. Tracked in `docs/ROADMAP.md`. `bool`, default `true`. Enable file-based overrides loaded from `~/.config/nomarchy/overrides/`. With this on, Nomarchy looks for matching files in that directory and substitutes them for the bundled defaults.
### `nomarchy.overrides.paths` ### `nomarchy.overrides.paths`
`attrsOf path`, default `{}`. **Reserved — currently unused.** Will be populated by the future override loader. `attrsOf path`, default `{}`. Override paths discovered at build time. Populated by the override system — you don't normally set this directly.
--- ---
@@ -303,17 +323,15 @@ Without prime config, supergfxd still switches modes but render-offload via `nvi
} }
``` ```
### Ship your own Hyprland keybindings instead of Nomarchy's defaults ### Disable Nomarchy's default Hyprland keybindings to ship your own
Nomarchy deploys its `bindings.conf` with `lib.mkDefault`, so a higher-priority assignment from your own `home.nix` wins:
```nix ```nix
{ {
xdg.configFile."hypr/bindings.conf".source = ./my-bindings.conf; nomarchy.behavior.hyprland.bindings = false;
} }
``` ```
The same pattern works for any file Nomarchy deploys via `xdg.configFile.<path>.source = lib.mkDefault …` — point at your own file and skip the default. Then put your own `bindings.conf` at `~/.config/nomarchy/overrides/hypr/bindings.conf` (with `nomarchy.overrides.enable = true;`, which is the default).
--- ---
@@ -323,6 +341,7 @@ The same pattern works for any file Nomarchy deploys via `xdg.configFile.<path>.
- `core/system/hardware.nix``nomarchy.hardware.*` - `core/system/hardware.nix``nomarchy.hardware.*`
- `core/system/impermanence.nix``impermanence.enable` - `core/system/impermanence.nix``impermanence.enable`
- `core/home/options.nix` — most home-side `nomarchy.*` options - `core/home/options.nix` — most home-side `nomarchy.*` options
- `core/home/overrides.nix``nomarchy.overrides.*` (reserved; currently no-op) - `core/home/behavior.nix``nomarchy.behavior.*`
- `core/home/overrides.nix``nomarchy.overrides.*`
- `themes/engine/loader.nix``nomarchy.themeLoader.*` - `themes/engine/loader.nix``nomarchy.themeLoader.*`
- `features/apps/vscode.nix``nomarchy.vscode.*` - `features/apps/vscode.nix``nomarchy.vscode.*`

View File

@@ -28,7 +28,6 @@ Guardrails (apply when adding anything):
- **Accessibility — home-side companion.** Hyprland-side bits the system preset can't reach: slower `input.repeat_rate` / `repeat_delay` defaults, `SUPER+ALT+S` keybinding to launch Orca, and a high-contrast palette under `themes/palettes/`. Gated on a new `nomarchy.accessibility.enable` mirror of the system option. - **Accessibility — home-side companion.** Hyprland-side bits the system preset can't reach: slower `input.repeat_rate` / `repeat_delay` defaults, `SUPER+ALT+S` keybinding to launch Orca, and a high-contrast palette under `themes/palettes/`. Gated on a new `nomarchy.accessibility.enable` mirror of the system option.
- **Gaming — declarative flathub remote.** `services.flatpak.enable` doesn't ship a declarative remote API in nixpkgs. Either add the `flatpak-managed-install` overlay, write a one-shot systemd unit that runs `flatpak remote-add --if-not-exists flathub …`, or surface the manual step in `nomarchy-welcome`. - **Gaming — declarative flathub remote.** `services.flatpak.enable` doesn't ship a declarative remote API in nixpkgs. Either add the `flatpak-managed-install` overlay, write a one-shot systemd unit that runs `flatpak remote-add --if-not-exists flathub …`, or surface the manual step in `nomarchy-welcome`.
- **Plymouth theme variants per palette.** Currently one Plymouth theme; could template per-palette so the boot splash matches the active theme. - **Plymouth theme variants per palette.** Currently one Plymouth theme; could template per-palette so the boot splash matches the active theme.
- **Implement `nomarchy.overrides.*` file-based override loader.** The option surface is declared in `core/home/overrides.nix` but the loader doesn't exist — files dropped under `~/.config/nomarchy/overrides/` are ignored. Spec: when `overrides.enable = true`, for each `xdg.configFile.<path>` Nomarchy deploys with `lib.mkDefault`, check whether `~/.config/nomarchy/overrides/<path>` exists at build time; if so, use it as the source. Requires deciding whether discovery happens at activation time (cheap, but rebuild-required to pick up new files) or via a populated `paths` attrset (Nix-side, evaluated once per rebuild). Until shipped, document the per-file workaround (`xdg.configFile.<path>.source = ./mine`) in OPTIONS.md.
### Later (speculative or research-shaped) ### Later (speculative or research-shaped)
@@ -40,9 +39,6 @@ Guardrails (apply when adding anything):
- **Forgejo release pipeline.** `vYY.MM.x` tags matching the upstream NixOS channel; the pipeline pushes the three ISOs and an updated `flake.lock` snapshot. - **Forgejo release pipeline.** `vYY.MM.x` tags matching the upstream NixOS channel; the pipeline pushes the three ISOs and an updated `flake.lock` snapshot.
- **Optional `nomarchy-installer-vm`** rebuilt as a real flake app (not a one-off shell script) so users can install Nomarchy into a libvirt VM declaratively. - **Optional `nomarchy-installer-vm`** rebuilt as a real flake app (not a one-off shell script) so users can install Nomarchy into a libvirt VM declaratively.
- **Surface support module** via the relevant `nixos-hardware` profile + Surface kernel patches behind a `nomarchy.hardware.isSurface` toggle. - **Surface support module** via the relevant `nixos-hardware` profile + Surface kernel patches behind a `nomarchy.hardware.isSurface` toggle.
- **Consolidate palette imports in `flake.nix` via `nomarchyLib`.** `flake.nix:79-80` re-imports `./themes/palettes` and recomputes `themeNames` even though `lib/default.nix` already exports both. Two computations, same result today — drift risk tomorrow. Import `nomarchyLib = import ./lib { inherit lib; }` once and use `nomarchyLib.{palettes,themeNames}` to make `lib/default.nix` the single source of truth for the theme list.
- **Decide what to do about `features/apps/chromium/Default/Preferences`.** The module deploys a static 204-byte `Default/Preferences` (setting `extensions.theme.use_system = false`, `browser.theme.color_scheme = 2`) into chromium's mutable profile directory via Home Manager symlink. Chromium expects to write that file at runtime, so either the symlink is silently replaced on first save (losing the static defaults) or the write fails silently. The real chromium theming work happens via managed policies in `core/system/browser.nix`. Probably the user-profile deployment should be removed; needs someone with chromium-internals knowledge to confirm before deletion.
- **`themes/templates/*.tpl` — decide what these are for.** Eleven mustache-style templates (`alacritty.toml.tpl`, `btop.theme.tpl`, `kitty.conf.tpl`, etc.) are deployed to `~/.local/share/nomarchy/templates/` via `themes/engine/files.nix`, but no script in the tree consumes them. Likely vestigial from a pre-stylix templating system. Either delete the directory + the `xdg.dataFile` deployment, or document them as user-reference assets and explain how to use them.
- **Move `programs.uwsm` Hyprland session out of `core/system/virtualization.nix`.** Session-manager config is wired in the virtualization module by historical accident — it's loaded unconditionally on every install and has nothing to do with libvirt/docker. Move to a dedicated `core/system/session.nix` (or fold into the Hyprland feature module) so the location matches the responsibility. - **Move `programs.uwsm` Hyprland session out of `core/system/virtualization.nix`.** Session-manager config is wired in the virtualization module by historical accident — it's loaded unconditionally on every install and has nothing to do with libvirt/docker. Move to a dedicated `core/system/session.nix` (or fold into the Hyprland feature module) so the location matches the responsibility.
## 3. Pillar: Script & menu audit ## 3. Pillar: Script & menu audit

View File

@@ -70,8 +70,8 @@ The `core/` directory contains the foundational modules required for a functiona
- **`default.nix`**: The entry point for the base Home Manager module. - **`default.nix`**: The entry point for the base Home Manager module.
- **`options.nix`**: Defines the `nomarchy` user options (Toggles, Theme, Fonts, etc.). - **`options.nix`**: Defines the `nomarchy` user options (Toggles, Theme, Fonts, etc.).
- **`state.nix`**: Loads and applies user-level state (from `~/.config/nomarchy/state.json`). - **`state.nix`**: Loads and applies user-level state (from `~/.config/nomarchy/state.json`).
- **`overrides.nix`**: Declares `nomarchy.overrides.*` (reserved for a future file-based override loader; currently no-op). - **`behavior.nix`**: Deploys non-visual configs (Keybindings, Input settings, Window rules) with `lib.mkDefault`.
- **`configs.nix`**: Manages static configuration files and directories in `~/.config/`. Honors `nomarchy.configOverrides` as a bulk redirect to a replacement config dir. - **`configs.nix`**: Manages static configuration files and directories in `~/.config/`.
- **`bash.nix`**: Shell environment, aliases, and specialized `env-update` hooks. - **`bash.nix`**: Shell environment, aliases, and specialized `env-update` hooks.
- **`security.nix`**: Polkit, keyring management, and GPG settings. - **`security.nix`**: Polkit, keyring management, and GPG settings.
- **`config/`**: Contains the physical source files for the base user configuration (e.g., `starship.toml`, `hypr/` behavior configs). - **`config/`**: Contains the physical source files for the base user configuration (e.g., `starship.toml`, `hypr/` behavior configs).

View File

@@ -0,0 +1,25 @@
general.import = [ "~/.config/nomarchy/current/theme/alacritty.toml" ]
[env]
TERM = "xterm-256color"
[terminal]
osc52 = "CopyPaste"
[font]
normal = { family = "JetBrainsMono Nerd Font", style = "Regular" }
bold = { family = "JetBrainsMono Nerd Font", style = "Bold" }
italic = { family = "JetBrainsMono Nerd Font", style = "Italic" }
size = 9
[window]
padding.x = 14
padding.y = 14
decorations = "None"
[keyboard]
bindings = [
{ key = "Insert", mods = "Shift", action = "Paste" },
{ key = "Insert", mods = "Control", action = "Copy" },
{ key = "Return", mods = "Shift", chars = "\u001B\r" }
]

View File

@@ -2,6 +2,14 @@
let let
nomarchyLib = import ../lib { inherit lib; }; nomarchyLib = import ../lib { inherit lib; };
userPackagesFile = "${config.home.homeDirectory}/.config/home-manager/user-packages.json";
userPackages = if builtins.pathExists userPackagesFile then
let
pkgNames = builtins.fromJSON (builtins.readFile userPackagesFile);
# Filter to only packages that exist in pkgs to prevent build failures
validPkgs = builtins.filter (name: builtins.hasAttr name pkgs) pkgNames;
in builtins.map (name: pkgs.${name}) validPkgs
else [];
in in
{ {
imports = [ imports = [

View File

@@ -71,6 +71,7 @@ let
NOMARCHY_TOGGLE_IDLE = if config.nomarchy.toggles.idle then "true" else "false"; NOMARCHY_TOGGLE_IDLE = if config.nomarchy.toggles.idle then "true" else "false";
NOMARCHY_TOGGLE_NIGHTLIGHT = if config.nomarchy.toggles.nightlight then "true" else "false"; NOMARCHY_TOGGLE_NIGHTLIGHT = if config.nomarchy.toggles.nightlight then "true" else "false";
NOMARCHY_TOGGLE_WAYBAR = if config.nomarchy.toggles.waybar then "true" else "false"; NOMARCHY_TOGGLE_WAYBAR = if config.nomarchy.toggles.waybar then "true" else "false";
NOMARCHY_TOGGLE_SKIP_VSCODE_THEME = if config.nomarchy.toggles.skipVsCodeTheme then "true" else "false";
NOMARCHY_MONOSPACE_FONT = config.nomarchy.fonts.monospace; NOMARCHY_MONOSPACE_FONT = config.nomarchy.fonts.monospace;
}; };

View File

@@ -59,9 +59,39 @@ if [[ "$USER" == "nixos" ]]; then
exit 0 exit 0
fi fi
# 4. Setup Local Repo (Crucial for nomarchy-env-update to work) # 4. Starter home.nix
echo "" echo ""
echo "Step 4: Git Repository Check" echo "Step 4: Starter home.nix"
HOME_NIX="$HOME/.config/home-manager/home.nix"
if [ ! -f "$HOME_NIX" ]; then
echo "It looks like you don't have a ~/.config/home-manager/home.nix file yet."
echo "Nomarchy uses this file to manage your user-level packages and settings."
if gum confirm "Would you like to generate a starter home.nix?"; then
mkdir -p "$(dirname "$HOME_NIX")"
cat <<EOF > "$HOME_NIX"
{ pkgs, ... }:
{
# Nomarchy starter home.nix
# Add your user packages here.
home.packages = with pkgs; [
btop
fastfetch
chromium
# Add more packages here
];
# home.stateVersion = "25.11"; # Consult docs/MIGRATION.md if you change this
}
EOF
echo "Starter home.nix generated at $HOME_NIX"
fi
else
echo "Detected existing home.nix at $HOME_NIX. Skipping generation."
fi
# 5. Setup Local Repo (Crucial for nomarchy-env-update to work)
echo ""
echo "Step 5: Git Repository Check"
echo "Nomarchy relies on a local git repository for declarative updates." echo "Nomarchy relies on a local git repository for declarative updates."
if [ ! -d "/etc/nixos/.git" ]; then if [ ! -d "/etc/nixos/.git" ]; then
echo "Warning: /etc/nixos is not a git repository. Declarative updates might fail." echo "Warning: /etc/nixos is not a git repository. Declarative updates might fail."
@@ -72,7 +102,7 @@ if [ ! -d "/etc/nixos/.git" ]; then
fi fi
fi fi
# 5. Success # 6. Success
echo "" echo ""
echo "Applying all changes..." echo "Applying all changes..."
nomarchy-env-update nomarchy-env-update

View File

@@ -98,6 +98,7 @@ let
in { in {
inherit inherit
palettes palettes
readState
readHomeState readHomeState
readSystemState readSystemState
resolveWallpaper resolveWallpaper

View File

@@ -1,13 +1,5 @@
# Nomarchy State Schema # Nomarchy State Schema
# # Defines the complete state shape with defaults for both home and system state
# Defines the default values for every state.json field that's consumed by a
# Nix option. Read by core/{system,home}/options.nix (for `default = …`) and
# by core/{system,home}/state.nix (for `or` fallbacks).
#
# state.json may also hold runtime-only fields that aren't declared here —
# notably `welcome_done`, managed by `nomarchy-welcome`. Those are intentionally
# off-schema because no Nix option reads them; the schema is the "consumed by
# Nix" surface, not the full state.json shape.
{ lib }: { lib }:
{ {
@@ -26,6 +18,7 @@
idle = true; idle = true;
nightlight = false; nightlight = false;
waybar = true; waybar = true;
skipVsCodeTheme = false;
# Hyprland window manager settings # Hyprland window manager settings
hyprland = { hyprland = {
@@ -60,4 +53,14 @@
}; };
}; };
# Get a value from state with fallback to default
getWithDefault = state: path: default:
let
pathList = lib.splitString "." path;
getValue = obj: remaining:
if remaining == [] then obj
else if builtins.isAttrs obj && builtins.hasAttr (builtins.head remaining) obj
then getValue obj.${builtins.head remaining} (builtins.tail remaining)
else default;
in getValue state pathList;
} }

View File

@@ -54,16 +54,31 @@ in
}; };
apps = { apps = {
# waybar, kitty, alacritty, and mako are intentionally absent. Waybar
# themes inline in features/desktop/waybar via colorScheme; kitty and
# alacritty are themed by stylix targets (themes/engine/stylix.nix); mako
# has no theme integration yet. Only btop is loaded from the active
# theme's apps/ directory.
btop = lib.mkOption { btop = lib.mkOption {
type = lib.types.bool; type = lib.types.bool;
default = true; default = true;
description = "Whether to load btop theme from active theme."; description = "Whether to load btop theme from active theme.";
}; };
waybar = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Whether to load waybar CSS from active theme.";
};
mako = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Whether to load mako config from active theme.";
};
kitty = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Whether to load kitty config from active theme.";
};
alacritty = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Whether to load alacritty config from active theme.";
};
}; };
}; };

View File

@@ -27,12 +27,8 @@ in
services.displayManager.defaultSession = lib.mkDefault "hyprland-uwsm"; services.displayManager.defaultSession = lib.mkDefault "hyprland-uwsm";
# autoLogin defaults off so hand-migrated configs (no installer-written
# username) don't try to log in as a nonexistent "nomarchy" user. The
# installer-generated system.nix sets both `enable = true;` and
# `user = "$USERNAME";` at normal priority, overriding these defaults.
services.displayManager.autoLogin = { services.displayManager.autoLogin = {
enable = lib.mkDefault false; enable = lib.mkDefault true;
user = lib.mkDefault "nomarchy"; user = lib.mkDefault "nomarchy";
}; };

View File

@@ -0,0 +1,5 @@
include=~/.config/nomarchy/default/mako/core.ini
text-color={{ foreground }}
border-color={{ accent }}
background-color={{ background }}