Compare commits

...

8 Commits

Author SHA1 Message Date
Bernardo Magri
83218a01f3 docs: add "Working on Nomarchy" orientation guide
Some checks failed
Check / eval-and-lint (push) Failing after 6m21s
A short, task-indexed guide for navigating the repo: the core/features/themes
mental model, the two app-config namespaces, the four script locations (incl.
themes/engine/scripts/), the build/test loop, how theming works, and a
Walker+elephant deep-dive covering the dmenu vs custom-provider menu paths.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 13:32:24 +01:00
Bernardo Magri
9fe6d9e405 fix(walker): don't spawn a duplicate elephant alongside the service
nomarchy-launch-walker guarded its manual elephant start with
`pgrep -x elephant`, which never matches the Home Manager service's actual
process name `.elephant-wrapped` (Linux truncates comm to 15 chars). So every
menu invocation spawned a second elephant that races elephant.service for the
socket — a latent source of menus intermittently coming up empty.

Gate on `systemctl --user is-active elephant.service` first, with a working
`pgrep -f elephant-wrapped` fallback for non-service setups; do the same for
walker.service. Verified in a headless system.build.vm: opening the theme menu
now keeps the elephant process count at 1 (was 2) and the menu still renders.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 13:32:12 +01:00
Bernardo Magri
8a302e8771 chore: drop omarchy pkg-* compatibility shims
Some checks failed
Check / eval-and-lint (push) Failing after 6m15s
These existed only to ease muscle-memory from Arch-based distros and add
no behavior on a Nix-native system:

- nomarchy-pkg-install — alias for nomarchy-pkg-add
- nomarchy-pkg-drop    — alias for nomarchy-pkg-remove
- nomarchy-pkg-aur-add — stub that only printed "AUR doesn't exist on NixOS"

The single code caller (nomarchy-voxtype-remove) was removed in the prior
commit, so the shims have no remaining references. SKILL.md updated to use
nomarchy-pkg-add and to point at `nix search nixpkgs` instead of the AUR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 19:52:19 +01:00
Bernardo Magri
698d8593cd feat: remove unused voxtype dictation feature
Voxtype voice-typing was a full feature (5 scripts, a waybar widget, a
keybind, and a NixOS option) that this install does not use. The
nomarchy.system.voxtype option had no consumer — nothing read it — so the
widget and SUPER+CTRL+X bind were never actually gated by it.

Removes the scripts, default config, the SUPER+CTRL+X bind, the waybar
module (main + summer-night theme + css), the dead option, the installer
comment, and the docs. SCRIPTS.md/KEYBINDINGS.md regenerated; OPTIONS.md
and SKILL.md hand-updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 19:51:46 +01:00
Bernardo Magri
4b509c271a fix(scripts): remove stale duplicate nomarchy-update
Some checks failed
Check / eval-and-lint (push) Failing after 6m14s
Two scripts named nomarchy-update shipped from different derivations
(core/system/scripts + features/scripts/utils), both landing on PATH so
which one ran depended on PATH ordering. The core/system one never stripped
the install-time `?rev=` pin and rebuilt a nonexistent `#default` attr,
silently keeping installs frozen instead of following rolling main. Keep the
features/scripts/utils version (unpins, queries upstream HEAD, calls
nomarchy-sys-update) and drop the stale one. Regenerated docs/SCRIPTS.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 20:55:04 +01:00
Bernardo Magri
2bdcc0aba0 fix(live): enable VM guest agents so Hyprland boots at full resolution
The nomarchy-live ISO imported ./core and hosts/nomarchy-live.nix but not
core/system/vm-guest.nix, which is the only place spice-vdagentd/qemuGuest
were enabled. Without those agents a VM's virtio-gpu only advertises its
1024x768 fallback mode, so Hyprland's `monitor = , highres, auto` rule picks
that as the highest mode and the live session boots tiny.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 20:55:04 +01:00
Bernardo Magri
27821c270f fix(impermanence): mark /persist and /home neededForBoot
Some checks failed
Check / eval-and-lint (push) Failing after 5m56s
The impermanence module asserts that the persistent-storage volume and
every volume it bind-mounts into are available in early boot. Persisted
user dirs land under /home, so both /persist and the @home subvolume
must have neededForBoot = true. disko and nixos-generate-config leave it
at the default (false), so a fresh install with impermanence enabled
aborted with:

    All filesystems used for persistent storage must have the option
    "neededForBoot" set to true.
    Please fix the following filesystems: /persist /home

Declare neededForBoot in the module that imposes the requirement.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 19:34:04 +01:00
Bernardo Magri
a84e903ae1 fix(live): allow empty-password hyprlock unlock on live ISO
pam_unix rejects empty passwords by default, so if hypridle locked the
live session there was nothing the user could type to unlock it. Set
allowNullPassword on the hyprlock PAM service so a bare Enter dismisses
the locker, matching the empty live account passwords. Scoped to the
live host so installed systems still reject empty unlocks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 19:24:42 +01:00
24 changed files with 258 additions and 311 deletions

View File

@@ -109,7 +109,7 @@ cat $(which nomarchy-theme-set)
| `nomarchy-install-*` | Install optional software | `nomarchy-install-docker-dbs` |
| `nomarchy-launch-*` | Launch apps | `nomarchy-launch-browser` |
| `nomarchy-cmd-*` | System commands | `nomarchy-cmd-screenshot` |
| `nomarchy-pkg-*` | Package management | `nomarchy-pkg-install <pkg>` |
| `nomarchy-pkg-*` | Package management | `nomarchy-pkg-add <pkg>` |
| `nomarchy-setup-*` | Initial setup tasks | `nomarchy-setup-fingerprint` |
| `nomarchy-update-*` | System updates | `nomarchy-update` |
@@ -334,16 +334,6 @@ nomarchy-tui-remove-all # Bulk-remove every TUI launcher
Both families write `.desktop` files into `~/.local/share/applications/` so they appear in the app launcher (walker / rofi).
### Voice dictation (Voxtype)
```bash
nomarchy-voxtype-install # Install Voxtype + AI model (~150MB)
nomarchy-voxtype-remove # Uninstall Voxtype
nomarchy-voxtype-status # Running state (also shown in waybar)
```
Toggle dictation with `SUPER+CTRL+X` after install.
### Virtualization
```bash
@@ -387,7 +377,7 @@ When user requests system changes:
2. **Is it a config edit?** Edit in `~/.config/`, never `~/.local/share/nomarchy/`
3. **Is it a theme customization?** Create a NEW custom theme directory
4. **Is it automation?** Use hooks in `~/.config/nomarchy/hooks/`
5. **Is it a package install?** Use `nomarchy-pkg-add` (or `nomarchy-pkg-aur-add` for AUR-only packages)
5. **Is it a package install?** Use `nomarchy-pkg-add` (adds to `user-packages.json`; rebuild applies it). The AUR does not exist on NixOS — search nixpkgs with `nix search nixpkgs <name>`.
6. **Unsure if command exists?** Search with `compgen -c | grep nomarchy`
## Out of Scope

View File

@@ -51,9 +51,6 @@ bindd = SUPER CTRL, B, Bluetooth controls, exec, nomarchy-launch-bluetooth
bindd = SUPER CTRL, W, Wifi controls, exec, nomarchy-launch-wifi
bindd = SUPER CTRL, T, Activity, exec, nomarchy-launch-tui btop
# Dictation
bindd = SUPER CTRL, X, Toggle dictation, exec, voxtype record toggle
# Zoom
bindd = SUPER CTRL, Z, Zoom in, exec, hyprctl keyword cursor:zoom_factor $(hyprctl getoption cursor:zoom_factor -j | jq '.float + 1')
bindd = SUPER CTRL ALT, Z, Reset zoom, exec, hyprctl keyword cursor:zoom_factor 1

View File

@@ -1,97 +0,0 @@
# Voxtype Configuration
#
# Location: ~/.config/voxtype/config.toml
# All settings can be overridden via CLI flags
#
# State file for external integrations (Waybar, polybar, etc.)
# Use "auto" for default location ($XDG_RUNTIME_DIR/voxtype/state),
# a custom path, or "disabled" to turn off. The daemon writes state
# ("idle", "recording", "transcribing") to this file whenever it changes.
# Required for `voxtype record toggle` and `voxtype status` commands.
state_file = "auto"
[hotkey]
# Hotkey is configured in Hyprland. Default is Super + Ctrl + X
enabled = false
[audio]
# Audio input device ("default" uses system default)
# List devices with: pactl list sources short
device = "default"
# Sample rate in Hz (whisper expects 16000)
sample_rate = 16000
# Maximum recording duration in seconds (safety limit)
max_duration_secs = 60
# [audio.feedback]
# Enable audio feedback sounds (beeps when recording starts/stops)
# enabled = true
#
# Sound theme: "default", "subtle", "mechanical", or path to custom theme directory
# theme = "default"
#
# Volume level (0.0 to 1.0)
# volume = 0.7
[whisper]
# Model to use for transcription
# Options: tiny, tiny.en, base, base.en, small, small.en, medium, medium.en, large-v3, large-v3-turbo
# .en models are English-only but faster and more accurate for English
# large-v3-turbo is faster than large-v3 with minimal accuracy loss (recommended for GPU)
# Or provide absolute path to a custom .bin model file
model = "base.en"
# Language for transcription
# Use "en" for English, "auto" for auto-detection
# See: https://github.com/openai/whisper#available-models-and-languages
language = "en"
# Translate non-English speech to English
translate = false
# Number of CPU threads for inference (omit for auto-detection)
# threads = 4
[output]
# Primary output mode: "type" or "clipboard"
# - type: Simulates keyboard input at cursor position (requires ydotool)
# - clipboard: Copies text to clipboard (requires wl-copy)
mode = "type"
# Fall back to clipboard if typing fails
fallback_to_clipboard = true
# Delay between typed characters in milliseconds
# 0 = fastest possible, increase if characters are dropped
type_delay_ms = 1
# Post-processing command (optional)
# Pipe transcribed text through an external command for cleanup before output.
# The command receives text on stdin and outputs processed text on stdout.
# Useful for LLM-based text cleanup, grammar correction, filler word removal.
# On any failure (timeout, error), falls back to original transcription.
#
# [output.post_process]
# command = "ollama run llama3.2:1b 'Clean up this dictation. Fix grammar, remove filler words. Output only the cleaned text:'"
# timeout_ms = 30000 # 30 second timeout (generous for LLM)
[output.notification]
# Show notification when recording starts (hotkey pressed)
on_recording_start = false
# Show notification when recording stops (transcription beginning)
on_recording_stop = false
# Show notification with transcribed text after transcription completes
on_transcription = false
# [text]
# Text processing options (word replacements, spoken punctuation)
#
# Enable spoken punctuation conversion (e.g., say "period" to get ".")
# spoken_punctuation = false
#
# Custom word replacements (case-insensitive)
# replacements = { "hyperwhisper" = "hyprwhspr" }

View File

@@ -87,6 +87,17 @@ in
'';
};
# The impermanence module asserts that every filesystem it touches is
# available in early boot: the persistent-storage volume (/persist) and
# any volume it bind-mounts *into* — the user-persistence dirs land under
# /home, so the @home subvolume counts too. disko and
# nixos-generate-config leave neededForBoot at its default (false) on
# these subvolumes, which trips the assertion ("Please fix the following
# filesystems: /persist /home"). Declare it here, where the requirement
# originates.
fileSystems."/persist".neededForBoot = true;
fileSystems."/home".neededForBoot = true;
# 2. Persistence Configuration: What survives the wipe
environment.persistence."/persist" = {
hideMounts = true;

View File

@@ -206,14 +206,5 @@ in
most users want this off.
'';
};
voxtype = {
enable = lib.mkEnableOption ''
voxtype voice-typing integration. NOTE: voxtype is not packaged in
nixpkgs when enabled, install voxtype yourself (e.g. via
`home.packages = [ (pkgs.callPackage {}) ]`). With this off the
SUPER+CTRL+X keybinding and waybar widget are no-ops.
'';
};
};
}

View File

@@ -1,41 +0,0 @@
#!/usr/bin/env bash
# Nomarchy Update Script
# 1. Updates the flake inputs in the repository
# 2. Applies system-wide NixOS changes
# 3. Applies user-level Home Manager changes (Standalone)
set -e
# Detect the repository location
if [ -f "/etc/nixos/flake.nix" ]; then
REPO_DIR="/etc/nixos"
elif [ -f "/etc/nomarchy/flake.nix" ]; then
REPO_DIR="/etc/nomarchy"
else
echo "Error: Nomarchy flake repository not found in /etc/nixos or /etc/nomarchy."
exit 1
fi
echo "--- Starting Nomarchy Update from $REPO_DIR ---"
# 1. Update Flake Lock
echo "Updating flake inputs..."
sudo nix flake update --flake "$REPO_DIR"
# 2. Rebuild System
echo "Applying system-level updates..."
sudo nixos-rebuild switch --flake "$REPO_DIR#default" --impure
# 3. Rebuild Home Environment (Standalone)
echo "Applying user-level updates..."
home-manager switch --flake "$REPO_DIR#$USER" --impure
# 4. Commit changes if it's a git repo
if [ -d "$REPO_DIR/.git" ]; then
echo "Committing update to local history..."
sudo git -C "$REPO_DIR" add flake.lock
sudo git -C "$REPO_DIR" commit -m "chore: update system (flake.lock)" || echo "No lockfile changes to commit."
fi
echo "--- Nomarchy Update Complete ---"

View File

@@ -52,7 +52,6 @@ _Source: `core/home/config/nomarchy/default/hypr/bindings/utilities.conf`_
| SUPER CTRL | B | Bluetooth controls |
| SUPER CTRL | W | Wifi controls |
| SUPER CTRL | T | Activity |
| SUPER CTRL | X | Toggle dictation |
| SUPER CTRL | Z | Zoom in |
| SUPER CTRL ALT | Z | Reset zoom |
| SUPER CTRL | L | Lock system |

View File

@@ -129,10 +129,6 @@ Without prime config, supergfxd still switches modes but render-offload via `nvi
`bool`, default `false`. fcitx5 input method for CJK / IME. Wires NixOS's `i18n.inputMethod` and autostarts `fcitx5-daemon`.
### `nomarchy.system.voxtype.enable`
`bool`, default `false`. voxtype voice-typing integration. voxtype isn't packaged in nixpkgs — when you enable this, install voxtype yourself (e.g. `home.packages = [ (pkgs.callPackage … {}) ]`). With this off the `SUPER+CTRL+X` keybinding and waybar widget are no-ops.
### `nomarchy.hardware.isXPS`
`bool`, default `false`. Dell XPS fixes — haptic touchpad service and PCI/I²C power-control udev rules.

View File

@@ -24,7 +24,7 @@ Phase B (per-batch PRs) refines those into `port-from-omarchy`,
- `delete-dead` — Phase B verdict: remove and update callers.
- `stub-with-notify` — Phase B verdict: temporary `notify-send` stub.
## Scripts (159)
## Scripts (151)
| Script | Location | Callers | Status | Notes |
| --- | --- | --- | --- | --- |
@@ -40,7 +40,7 @@ Phase B (per-batch PRs) refines those into `port-from-omarchy`,
| `nomarchy-build-iso` | `features/scripts/utils` | README.md | `kept` | |
| `nomarchy-build-live-iso` | `features/scripts/utils` | README.md | `kept` | |
| `nomarchy-cmd-audio-switch` | `features/scripts/utils` | core/home/config/nomarchy/default/hypr/bindings/media.conf | `kept` | |
| `nomarchy-cmd-present` | `features/scripts/utils` | core/home/config/nomarchy/hooks/battery-low.sample,features/scripts/utils/nomarchy-launch-editor, +4 more | `kept` | |
| `nomarchy-cmd-present` | `features/scripts/utils` | core/home/config/nomarchy/hooks/battery-low.sample,features/scripts/utils/nomarchy-launch-editor, +2 more | `kept` | |
| `nomarchy-cmd-screenrecord` | `features/scripts/utils` | features/desktop/waybar/config/config.jsonc,features/desktop/waybar/themes/summer-night/config.jsonc, +1 more | `kept` | |
| `nomarchy-cmd-screensaver` | `features/scripts/utils` | features/scripts/utils/nomarchy-launch-screensaver | `kept` | |
| `nomarchy-cmd-screenshot` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md,core/home/config/nomarchy/default/hypr/bindings/utilities.conf, +1 more | `kept` | |
@@ -62,7 +62,7 @@ Phase B (per-batch PRs) refines those into `port-from-omarchy`,
| `nomarchy-hook` | `features/scripts/utils` | core/system/scripts/nomarchy-battery-monitor,features/scripts/utils/nomarchy-env-update, +3 more | `kept` | |
| `nomarchy-hw-asus-rog` | `core/system/scripts` | features/scripts/utils/nomarchy-on-boot | `kept` | |
| `nomarchy-hw-match` | `core/system/scripts` | features/scripts/utils/nomarchy-on-boot | `kept` | |
| `nomarchy-hw-vulkan` | `core/system/scripts` | features/scripts/utils/nomarchy-voxtype-install | `kept` | |
| `nomarchy-hw-vulkan` | `core/system/scripts` | — | `unused?` | |
| `nomarchy-hyprland-active-window-transparency-toggle` | `features/scripts/utils` | core/home/config/nomarchy/default/hypr/bindings/utilities.conf | `kept` | |
| `nomarchy-hyprland-monitor-scaling-cycle` | `features/scripts/utils` | core/home/config/nomarchy/default/hypr/bindings/tiling-v2.conf,features/scripts/utils/nomarchy-menu, +1 more | `kept` | |
| `nomarchy-hyprland-window-close-all` | `features/scripts/utils` | core/home/config/nomarchy/default/hypr/bindings/tiling-v2.conf,core/system/scripts/nomarchy-system-logout, +2 more | `kept` | |
@@ -77,8 +77,8 @@ Phase B (per-batch PRs) refines those into `port-from-omarchy`,
| `nomarchy-launch-audio` | `features/scripts/utils` | core/home/config/nomarchy/default/hypr/bindings/utilities.conf,features/desktop/waybar/config/config.jsonc, +3 more | `kept` | |
| `nomarchy-launch-bluetooth` | `features/scripts/utils` | core/home/config/nomarchy/default/hypr/bindings/utilities.conf,features/desktop/waybar/config/config.jsonc, +1 more | `kept` | |
| `nomarchy-launch-browser` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md,features/desktop/hyprland/config/bindings.conf | `kept` | |
| `nomarchy-launch-editor` | `features/scripts/utils` | features/desktop/hyprland/config/bindings.conf,features/scripts/utils/nomarchy-menu, +1 more | `kept` | |
| `nomarchy-launch-floating-terminal-with-presentation` | `features/scripts/utils` | core/home/config/nomarchy/default/mako/core.ini,features/desktop/waybar/config/config.jsonc, +4 more | `kept` | |
| `nomarchy-launch-editor` | `features/scripts/utils` | features/desktop/hyprland/config/bindings.conf,features/scripts/utils/nomarchy-menu | `kept` | |
| `nomarchy-launch-floating-terminal-with-presentation` | `features/scripts/utils` | core/home/config/nomarchy/default/mako/core.ini,features/desktop/waybar/config/config.jsonc, +3 more | `kept` | |
| `nomarchy-launch-or-focus` | `features/scripts/utils` | core/home/config/nomarchy/extensions/menu.sh,features/desktop/hyprland/config/bindings.conf, +8 more | `kept` | |
| `nomarchy-launch-or-focus-tui` | `features/scripts/utils` | core/home/config/nomarchy/extensions/menu.sh,features/desktop/waybar/config/config.jsonc, +5 more | `kept` | |
| `nomarchy-launch-or-focus-webapp` | `features/scripts/utils` | features/desktop/hyprland/config/bindings.conf | `kept` | |
@@ -93,11 +93,8 @@ Phase B (per-batch PRs) refines those into `port-from-omarchy`,
| `nomarchy-menu-keybindings` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md,core/home/config/nomarchy/default/hypr/bindings/utilities.conf, +2 more | `kept` | |
| `nomarchy-notification-dismiss` | `features/scripts/utils` | core/home/config/nomarchy/default/mako/core.ini | `kept` | |
| `nomarchy-on-boot` | `features/scripts/utils` | core/home/config/nomarchy/default/hypr/autostart.conf | `kept` | |
| `nomarchy-pkg-add` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md,features/scripts/utils/nomarchy-pkg-install, +2 more | `kept` | |
| `nomarchy-pkg-aur-add` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md | `kept` | |
| `nomarchy-pkg-drop` | `features/scripts/utils` | features/scripts/utils/nomarchy-voxtype-remove | `kept` | |
| `nomarchy-pkg-install` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md | `kept` | |
| `nomarchy-pkg-remove` | `features/scripts/utils` | features/scripts/utils/nomarchy-pkg-drop | `kept` | |
| `nomarchy-pkg-add` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md,features/scripts/utils/nomarchy-windows-vm | `kept` | |
| `nomarchy-pkg-remove` | `features/scripts/utils` | — | `unused?` | |
| `nomarchy-powerprofiles-list` | `core/system/scripts` | features/scripts/utils/nomarchy-menu | `kept` | |
| `nomarchy-preflight-migration` | `features/scripts/utils` | features/scripts/utils/nomarchy-env-update | `kept` | |
| `nomarchy-refresh-config` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md,core/home/configs.nix, +1 more | `kept` | |
@@ -116,7 +113,7 @@ Phase B (per-batch PRs) refines those into `port-from-omarchy`,
| `nomarchy-restart-terminal` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md | `kept` | |
| `nomarchy-restart-trackpad` | `core/system/scripts` | core/home/config/nomarchy-skill/SKILL.md | `kept` | |
| `nomarchy-restart-walker` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md,features/scripts/utils/nomarchy-menu, +1 more | `kept` | |
| `nomarchy-restart-waybar` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md,features/scripts/utils/nomarchy-menu, +4 more | `kept` | |
| `nomarchy-restart-waybar` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md,features/scripts/utils/nomarchy-menu, +2 more | `kept` | |
| `nomarchy-restart-wifi` | `core/system/scripts` | features/scripts/utils/nomarchy-menu | `kept` | |
| `nomarchy-restart-xcompose` | `core/system/scripts` | — | `unused?` | |
| `nomarchy-setup-dns` | `core/system/scripts` | features/scripts/utils/nomarchy-menu | `kept` | |
@@ -169,17 +166,12 @@ Phase B (per-batch PRs) refines those into `port-from-omarchy`,
| `nomarchy-tui-remove` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md | `kept` | |
| `nomarchy-tui-remove-all` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md | `kept` | |
| `nomarchy-tz-select` | `core/system/scripts` | features/desktop/waybar/config/config.jsonc,features/scripts/utils/nomarchy-menu, +2 more | `kept` | |
| `nomarchy-update` | `core/system/scripts` | core/home/config/nomarchy-skill/SKILL.md,core/home/config/nomarchy/default/mako/core.ini, +5 more | `kept` | |
| `nomarchy-update` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md,core/home/config/nomarchy/default/mako/core.ini, +5 more | `kept` | |
| `nomarchy-update-available` | `features/scripts/utils` | features/desktop/waybar/config/config.jsonc,features/desktop/waybar/themes/summer-day/config.jsonc, +1 more | `kept` | |
| `nomarchy-update-firmware` | `features/scripts/utils` | features/scripts/utils/nomarchy-menu | `kept` | |
| `nomarchy-update-time` | `core/system/scripts` | features/scripts/utils/nomarchy-menu | `kept` | |
| `nomarchy-upload-log` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md,features/scripts/utils/nomarchy-debug | `kept` | |
| `nomarchy-version` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md,features/scripts/utils/nomarchy-debug, +1 more | `kept` | |
| `nomarchy-voxtype-config` | `features/scripts/utils` | features/desktop/waybar/config/config.jsonc,features/desktop/waybar/themes/summer-night/config.jsonc | `kept` | |
| `nomarchy-voxtype-install` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md | `kept` | |
| `nomarchy-voxtype-model` | `features/scripts/utils` | features/desktop/waybar/config/config.jsonc,features/desktop/waybar/themes/summer-night/config.jsonc | `kept` | |
| `nomarchy-voxtype-remove` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md | `kept` | |
| `nomarchy-voxtype-status` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md,features/desktop/waybar/config/config.jsonc, +1 more | `kept` | |
| `nomarchy-wallpaper` | `features/scripts/utils` | bin/utils/nomarchy-docs-scripts,core/home/config/nomarchy/default/hypr/autostart.conf, +3 more | `kept` | |
| `nomarchy-webapp-install` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md,features/scripts/utils/nomarchy-webapp-remove-all | `kept` | |
| `nomarchy-webapp-remove` | `features/scripts/utils` | core/home/config/nomarchy-skill/SKILL.md | `kept` | |

210
docs/WORKING-ON-NOMARCHY.md Normal file
View File

@@ -0,0 +1,210 @@
# Working on Nomarchy — a practical orientation
This is the "I just want to change something without getting lost" guide. It is
deliberately short. For the full architecture, see [STRUCTURE.md](STRUCTURE.md);
for every option, [OPTIONS.md](OPTIONS.md).
---
## 1. The 60-second mental model
Nomarchy is a NixOS flake. Three layers, top to bottom:
```
core/ foundation → the OS + base user env that must always exist
features/ the desktop → apps, Hyprland/waybar, user scripts (opt-in modules)
themes/ the look → palettes (data) + engine (logic) + templates (.tpl)
```
Everything else is plumbing: `lib/` (shared Nix helpers), `installer/` + `hosts/`
(how it gets onto a disk), `bin/` (repo tooling, **not** shipped to users),
`docs/`.
The flake wires it up as two NixOS/HM modules:
- `nixosModules.system``core/system/` (the OS)
- `nixosModules.home``features/` (which itself imports `core/home/` + the theme engine)
### The two things that confuse everyone
There are **two** places that look like "app config," and they are *different
concepts*:
| Path | What it is |
|------|-----------|
| `features/apps/<app>/` | The **module** for an app — turns it on, sets its config. This is *code*. |
| `core/home/config/nomarchy/default/<app>/` | A **payload** of files copied verbatim to `~/.config/nomarchy/default/<app>/` at rebuild. This is *data* that scripts + the theme engine read at runtime. |
So when you saw `alacritty` in both trees: `features/apps/alacritty/` is the app
module; `core/home/config/nomarchy/default/alacritty/screensaver.toml` is just a
screensaver file that happens to be named after alacritty. Not a duplicate.
**Rule of thumb:** changing how an app *behaves*`features/apps/`. Changing a
file that lands in the user's home and gets read at runtime → `core/home/config/`.
---
## 2. "I want to change X" → go here
| I want to… | Go to |
|------------|-------|
| Tweak an app's settings (kitty, btop, tmux…) | `features/apps/<app>/default.nix` (+ its `config/`) |
| Change Hyprland behaviour / keybinds | `features/desktop/hyprland/` and `core/home/config/nomarchy/default/hypr/` |
| Change the status bar | `features/desktop/waybar/` |
| Add/remove a theme | `themes/palettes/<name>/` |
| Change how theming is applied | `themes/engine/loader.nix` |
| Add a **user** command (`nomarchy-foo`) | `features/scripts/utils/` |
| Add a **system/root** command | `core/system/scripts/` |
| Add a NixOS option (`nomarchy.system.*`) | `core/system/options.nix` |
| Add a HM option (`nomarchy.*`) | `core/home/options.nix` |
| Change what the installer writes | `installer/install.sh` |
When in doubt, grep for an existing example of the thing you're changing and copy
its shape — the repo is very consistent *within* each of these buckets.
---
## 3. The build/test loop
You almost never need a full install to test a change. From the repo root:
```bash
# Evaluate + build the whole system WITHOUT activating it (safe, no sudo):
nixos-rebuild build --flake .#default --impure
# → prints "Done. The new configuration is /nix/store/…" if it builds.
# (drops a ./result symlink you can delete)
```
On a real install, the user-facing commands are:
```bash
sys-update # sudo nixos-rebuild switch --flake .#default --impure (system)
env-update # home-manager switch --flake .#default --impure (user env)
```
`bin/utils/` holds repo tooling that regenerates the auto-docs
(`SCRIPTS.md`, `KEYBINDINGS.md`). A pre-commit hook runs them; you rarely call
them by hand.
---
## 4. Where scripts live (the one rule)
There are **four** script homes, by **execution context**, not by topic:
| Dir | Context | Example |
|-----|---------|---------|
| `bin/utils/` | Repo tooling, never shipped | `nomarchy-docs-scripts` |
| `core/system/scripts/` | System / root / hardware | `nomarchy-setup-dns`, `nomarchy-toggle-hybrid-gpu` |
| `features/scripts/utils/` | User / desktop | `nomarchy-menu`, `nomarchy-launch-walker` |
| `themes/engine/scripts/` | Theme engine | **`nomarchy-theme-set`**, `nomarchy-theme-bg-set`, `nomarchy-theme-next` |
> **Heads-up:** the `nomarchy-theme-*` family lives in `themes/engine/scripts/`, **not**
> `features/scripts/utils/`. All four dirs are built onto the user's `$PATH`, so at
> runtime `nomarchy-theme-set "Tokyo Night"` just works regardless of which dir it's in —
> the split only matters when you're hunting for the *source*. Find any script's source
> fast with `grep -rl nomarchy-theme-set .` rather than guessing the directory.
New script? Ask: *does it need root or system packages?*`core/system/scripts/`.
*Is it user-facing desktop glue?*`features/scripts/utils/`. *Only useful inside
this repo?* → `bin/utils/`. Scripts are found by name on `$PATH`, so moving one
between the first two means changing the Nix derivation it's built into, not the
call sites.
---
## 5. How theming works (the short version)
1. The active theme name lives in **state**: `~/.config/nomarchy/state.json`
(runtime) → mirrored into `/etc/nixos/nomarchy-state.nix` for reproducibility.
2. `themes/engine/loader.nix` reads that name and deploys the matching themed
files (btop theme, kitty colors, waybar css…) into `~/.config/`.
3. `themes/templates/*.tpl` are filled with the palette's colors to produce
dynamic configs.
4. Switching a theme runs scripts that rewrite those files and then *reload* the
affected apps (this is what the `nomarchy-restart-*` family is for — each app
reloads differently: SIGUSR2, a full restart, etc.).
---
## 6. Walker + elephant (so you can decide on the menus later)
This is the bit you wanted to understand before changing anything. There are
**two separate programs**:
- **Walker** — the *front-end*. A Rust/GTK4 window that shows a list and a
search box. It's what you see. Started as a user service
(`programs.walker`, `runAsService = true`).
- **elephant** — the *back-end*. A Go daemon that actually produces the data
(apps, calculator, clipboard, emoji, and **custom menus**). Walker talks to it
over a Unix socket. Config lives in `features/apps/elephant/config/`, deployed
to `~/.config/elephant/`.
Think: **Walker draws, elephant supplies.**
### How a menu reaches the screen
There are two completely different paths, and only one of them touches Lua:
**Path A — `--dmenu` (no elephant data providers, no Lua).**
Used by `nomarchy-menu`, `nomarchy-font`, the keybindings viewer, etc.
You pipe plain text lines into `walker --dmenu`; Walker shows them and prints the
chosen line back. **Text only** — Walker's dmenu mode literally cannot show icons
or an image preview pane (verified in its source: each line becomes `item.text`
and the preview box is hidden). This is the simple, dependency-free path.
```
echo -e "Option A\nOption B" | walker --dmenu -p "Pick…"
```
**Path B — elephant custom menu providers (`-m menus:<name>`).**
Used by the theme picker and wallpaper picker. Here elephant loads a *menu
provider* from `~/.config/elephant/menus/`. A menu provider can be:
- a **TOML** file with a *static* list of entries — each entry can have an
`icon`, a `preview`/`preview_type`, and `actions`; or
- a **Lua** file (`run = "lua:…"`) whose `GetEntries()` returns a *dynamic*
list built at runtime.
The theme/wallpaper menus need a *variable* list (one entry per theme/wallpaper,
discovered on disk) **and** an image preview. In elephant, the only built-in way
to generate a variable-length list is Lua's `GetEntries()`. That's the entire
reason `nomarchy_themes.lua` and `nomarchy_background_selector.lua` exist — and
they're the *only* Lua in the whole repo.
### The decision space (for later)
If you want to drop Lua but keep Walker, the trade is purely about previews:
- **Keep previews** → replace the two `.lua` files with a small **bash generator**
that writes *static* elephant TOML menus (one `[[entries]]` per theme/wallpaper,
each with `preview = "…/preview.png"`), regenerated at rebuild + on theme
switch. No Lua, keeps the preview pane, adds one generator script.
- **Drop previews** → route the theme/wallpaper pickers through `walker --dmenu`
like the other menus. Deletes both `.lua` files, the elephant menu config for
them, and the `pkgs.lua` dependency. Simplest possible; theme/wallpaper become
plain text lists.
Nothing here is decided yet — this section is just the map.
### Key files for the menu system
| File | Role |
|------|------|
| `features/scripts/utils/nomarchy-launch-walker` | Wrapper: starts elephant + walker services, routes `--dmenu` vs provider calls |
| `features/scripts/utils/nomarchy-menu` | The big interactive menu (all Path A / dmenu) |
| `features/apps/walker.nix` | Walker module + config (prefixes, providers, theme) |
| `features/apps/elephant/config/` | elephant providers (calc, symbols, **menus/**) |
| `features/apps/elephant/config/menus/*.lua` | The two dynamic preview menus (the only Lua) |
---
## 7. Gotchas worth knowing
- **`--impure` is required** on rebuilds — the config reads runtime state
(`state.json`) outside the flake.
- **`docs/SCRIPTS.md` and `docs/KEYBINDINGS.md` are auto-generated.** Don't edit by
hand; the pre-commit hook (and CI) regenerate and verify them.
- **The deep `core/home/config/nomarchy/default/…` tree is a payload**, deployed
wholesale to `~/.config/nomarchy/default/`. Moving files out of it will break the
scripts/loader that read those exact runtime paths.
- **Two parallel module systems**: `core/system` = NixOS (root), `features` +
`core/home` = Home Manager (user). A setting only works if it's in the right one.

View File

@@ -5,7 +5,7 @@
"spacing": 0,
"height": 26,
"modules-left": ["custom/nomarchy", "hyprland/workspaces"],
"modules-center": ["clock", "custom/update", "custom/voxtype", "custom/screenrecording-indicator", "custom/idle-indicator", "custom/notification-silencing-indicator"],
"modules-center": ["clock", "custom/update", "custom/screenrecording-indicator", "custom/idle-indicator", "custom/notification-silencing-indicator"],
"modules-right": [
"tray",
"bluetooth",
@@ -142,19 +142,6 @@
"signal": 10,
"return-type": "json"
},
"custom/voxtype": {
"exec": "nomarchy-voxtype-status",
"return-type": "json",
"format": "{icon}",
"format-icons": {
"idle": "",
"recording": "󰍬",
"transcribing": "󰔟"
},
"tooltip": true,
"on-click-right": "nomarchy-voxtype-config",
"on-click": "nomarchy-voxtype-model"
},
"tray": {
"icon-size": 12,
"spacing": 17

View File

@@ -97,12 +97,3 @@ tooltip {
#custom-notification-silencing-indicator.active {
color: #a55555;
}
#custom-voxtype {
min-width: 12px;
margin: 0 0 0 7.5px;
}
#custom-voxtype.recording {
color: #a55555;
}

View File

@@ -73,20 +73,6 @@
"return-type": "json"
},
"custom/voxtype": {
"exec": "nomarchy-voxtype-status",
"return-type": "json",
"format": "{icon}",
"format-icons": {
"idle": "",
"recording": "󰍬",
"transcribing": "󰔟"
},
"tooltip": true,
"on-click-right": "nomarchy-voxtype-config",
"on-click": "nomarchy-voxtype-model"
},
"backlight": {
"max-length": "4",
"format": "{icon} {percent}%",

View File

@@ -8,12 +8,20 @@ if command -v walker >/dev/null 2>&1; then
# /dev/null. If they inherit stdout from a $(...) caller (e.g. nomarchy-menu
# doing `$(menu ...)`), bash waits for those fds to close on every return,
# which hangs the terminal after each menu selection.
if ! pgrep -x elephant > /dev/null; then
# Prefer the Home Manager systemd user services (programs.walker.runAsService).
# The manual fallbacks below MUST check the services first: the service runs
# the wrapped binary `.elephant-wrapped`, which `pgrep -x elephant` never
# matches — so the old check spawned a *second*, competing elephant on every
# menu invocation, racing the service for the socket. Only hand-start when no
# service and no process exists (e.g. walker used outside the HM service).
if ! systemctl --user is-active --quiet elephant.service 2>/dev/null \
&& ! pgrep -x elephant >/dev/null && ! pgrep -f elephant-wrapped >/dev/null; then
setsid uwsm-app -- elephant </dev/null >/dev/null 2>&1 &
disown
fi
if ! pgrep -f "walker --gapplication-service" > /dev/null; then
if ! systemctl --user is-active --quiet walker.service 2>/dev/null \
&& ! pgrep -f "walker --gapplication-service" >/dev/null; then
setsid uwsm-app -- walker --gapplication-service </dev/null >/dev/null 2>&1 &
disown
fi

View File

@@ -1,9 +0,0 @@
#!/usr/bin/env bash
set -e
# Nomarchy AUR Stub
# Informs the user that AUR is not applicable to NixOS.
notify-send -u critical "Nomarchy" "The AUR is an Arch Linux feature and is not available on NixOS. Try searching for the package in nixpkgs using 'nix search nixpkgs <name>'."
echo "Error: AUR is not available on NixOS."
exit 1

View File

@@ -1,7 +0,0 @@
#!/usr/bin/env bash
set -e
# Nomarchy Package Drop Script
# Alias for nomarchy-pkg-remove.
nomarchy-pkg-remove "$@"

View File

@@ -1,7 +0,0 @@
#!/usr/bin/env bash
set -e
# Nomarchy Package Install Script
# Alias for nomarchy-pkg-add for users coming from other distros.
nomarchy-pkg-add "$@"

View File

@@ -1,6 +0,0 @@
#!/bin/bash
set -e
# Used by Voxtype waybar module to open config on right click
exec nomarchy-launch-editor ~/.config/voxtype/config.toml

View File

@@ -1,21 +0,0 @@
#!/bin/bash
set -e
# Install voxtype and configure it for use.
if gum confirm "Install Voxtype + AI model (~150MB) to enable dictation?"; then
nomarchy-pkg-add wtype voxtype-bin
# Setup voxtype
mkdir -p ~/.config/voxtype
cp ~/.config/nomarchy/default/voxtype/config.toml ~/.config/voxtype/
voxtype setup --download --no-post-install
if nomarchy-hw-vulkan; then
voxtype setup gpu --enable || true
fi
voxtype setup systemd
nomarchy-restart-waybar
notify-send " Voxtype Dictation Ready" "Press Super + Ctrl + X to toggle dictation.\nEdit ~/.config/voxtype/config.toml for options." -t 10000
fi

View File

@@ -1,5 +0,0 @@
#!/bin/bash
set -e
nomarchy-launch-floating-terminal-with-presentation "voxtype setup model"
nomarchy-restart-waybar

View File

@@ -1,20 +0,0 @@
#!/bin/bash
set -e
# Remove voxtype and its configurations.
if nomarchy-cmd-present voxtype; then
echo "Uninstall Voxtype to remove dictation."
# Remove services
systemctl --user stop voxtype.service 2>/dev/null || true
rm -f ~/.config/systemd/user/voxtype*
systemctl --user daemon-reload
# Remove packages and configs
nomarchy-pkg-drop wtype voxtype-bin
rm -rf ~/.config/voxtype
rm -rf ~/.local/share/voxtype
else
echo "Voxtype was not installed."
fi

View File

@@ -1,10 +0,0 @@
#!/bin/bash
set -e
if nomarchy-cmd-present voxtype; then
voxtype status --follow --extended --format json | while read -r line; do
echo "$line" | jq -c '. + {alt: .class}'
done
else
echo '{"alt": "", "tooltip": ""}'
fi

View File

@@ -49,6 +49,14 @@
];
services.xserver.videoDrivers = [ "amdgpu" "radeon" "nouveau" "modesetting" "fbdev" "virtio" ];
# VM guest agents. Without these the virtio-gpu connector only advertises
# its 1024x768 fallback mode, so Hyprland's `monitor = , highres, …` rule
# picks that as the highest available resolution and the live session boots
# tiny. The agents let the SPICE/QEMU host negotiate a real resolution.
# (The installed system gets the same wiring via core/system/vm-guest.nix.)
services.spice-vdagentd.enable = true;
services.qemuGuest.enable = true;
environment.etc."install.sh" = {
source = ../installer/install.sh;
mode = "0755";
@@ -81,6 +89,13 @@
# Allow passwordless sudo for the live user
security.sudo.wheelNeedsPassword = false;
# The live accounts have empty passwords, but pam_unix rejects an empty
# password by default — which leaves hyprlock unsolvable if the idle
# timer locks the session (nothing you can type unlocks it). Allow null
# passwords for the locker so it can be dismissed with a bare Enter.
# Live-ISO only: installed systems must never accept empty unlocks.
security.pam.services.hyprlock.allowNullPassword = true;
# Override the upstream installer helpLine (says "NixOS", points nowhere
# useful for us). Shown on every TTY before login and again as the MOTD.
services.getty.helpLine = lib.mkForce ''

View File

@@ -1740,9 +1740,6 @@ $xkb_variant_line
# fcitx5 input method (CJK / IME).
# nomarchy.system.inputMethod.enable = true;
# voxtype voice-typing wiring (you must install voxtype yourself).
# nomarchy.system.voxtype.enable = true;
system.stateVersion = "25.11";
}
EOF