Compare commits
206 Commits
legacy
...
8fded63b10
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fded63b10 | ||
|
|
edd0bd38ce | ||
|
|
096440a7d7 | ||
|
|
7d5f091c29 | ||
|
|
90a5104f94 | ||
|
|
39cfe0fb12 | ||
|
|
01ee847490 | ||
|
|
808a3febdd | ||
|
|
4ad564bd80 | ||
|
|
3e49481d46 | ||
|
|
8d54eecd67 | ||
|
|
4e3acbe89c | ||
|
|
8f2e047f4a | ||
|
|
8874a22a37 | ||
|
|
310614bdd2 | ||
|
|
fb75c3dedf | ||
|
|
44d5516191 | ||
|
|
47c8b6f997 | ||
|
|
abc953ea84 | ||
|
|
d1d6a09d9d | ||
|
|
a360bc87ca | ||
|
|
1921839e0e | ||
|
|
9df18261f9 | ||
|
|
e02b4d8200 | ||
|
|
5eadf0cff6 | ||
|
|
26e393b65d | ||
|
|
fb78c814cc | ||
|
|
821032e81c | ||
|
|
b7b51e9354 | ||
|
|
0fe46221ea | ||
|
|
bfb80cb60d | ||
|
|
352c681f48 | ||
|
|
d2ac131b75 | ||
|
|
2a23e82169 | ||
|
|
1b8eccbdca | ||
|
|
3f5e414341 | ||
|
|
774bdad6e4 | ||
|
|
e05e3647e6 | ||
|
|
472d7502b4 | ||
|
|
b0b8a9a09b | ||
|
|
56f1cc3fa9 | ||
|
|
9cd6f5e30c | ||
|
|
a83edb0d36 | ||
|
|
fd6e5f60e9 | ||
|
|
a643391d3d | ||
|
|
63136a8cb1 | ||
|
|
0d80ab272f | ||
|
|
397dd5991a | ||
|
|
274ffc25e1 | ||
|
|
0e6c678835 | ||
|
|
18b854563b | ||
|
|
f70838c5b5 | ||
|
|
1e4427f6af | ||
|
|
a47aa3aff5 | ||
|
|
baab2d3b88 | ||
|
|
5ea4f0c9ac | ||
|
|
938753273d | ||
|
|
46af2f0632 | ||
|
|
bc4e8e1410 | ||
|
|
4c2ad38656 | ||
|
|
6d70bba8e6 | ||
|
|
9726ba3b2f | ||
|
|
4024da791f | ||
|
|
aac678335c | ||
|
|
7d6d74fd7f | ||
|
|
cdd1897b14 | ||
|
|
9976ea06f5 | ||
|
|
cdfe92a089 | ||
|
|
431af618cc | ||
|
|
47526ae6e2 | ||
|
|
86802f244e | ||
|
|
f3325385c1 | ||
|
|
aed41793f8 | ||
|
|
685126ab47 | ||
|
|
c8d0b09044 | ||
|
|
c2f90c7d0a | ||
|
|
5747dc9839 | ||
|
|
d1344712b8 | ||
|
|
37204f5f45 | ||
| 97b5944dc1 | |||
| 0c483f9512 | |||
| dfb57c2e34 | |||
| 995810927d | |||
| e1cf190dd2 | |||
|
|
70334e68bb | ||
|
|
6a4af69b0f | ||
|
|
d9466d6555 | ||
|
|
0e42763aea | ||
|
|
a6d6860054 | ||
|
|
5c43a93285 | ||
|
|
09c308b93c | ||
|
|
bdf20f2d8e | ||
|
|
c57d26864e | ||
|
|
019fdfc8bb | ||
|
|
c2281dbc61 | ||
|
|
b4fe52261b | ||
|
|
82659566ac | ||
|
|
994025f0c8 | ||
|
|
b0b2a4d732 | ||
|
|
964a5c98b7 | ||
|
|
c45fb80b79 | ||
|
|
0c668c2eb1 | ||
|
|
1f4bd3d5fa | ||
|
|
017bb1aa41 | ||
|
|
b856bb93e8 | ||
|
|
e0ee5b9e7e | ||
|
|
f68b245d92 | ||
|
|
fb748c217c | ||
|
|
8d3911de1a | ||
|
|
6ad80c045e | ||
|
|
54c6e100fb | ||
|
|
eb76bd61b4 | ||
|
|
71f37bfc30 | ||
|
|
69f959365e | ||
|
|
aef45b3c8d | ||
|
|
0897391cfb | ||
|
|
5c83b52727 | ||
|
|
0751102915 | ||
|
|
5c59da73e7 | ||
|
|
42801548b7 | ||
|
|
1b0eeeaf6c | ||
| a606c0d498 | |||
| cd495d1720 | |||
| dbcb8efd1e | |||
| 07e467027b | |||
| 9a5473e179 | |||
| db6a0ba455 | |||
| 8c47716f9a | |||
| f60f3655f9 | |||
| afdb928ed7 | |||
| 882ba6646b | |||
| db202f90e4 | |||
| 51c11e1df3 | |||
| 6a22eba0c4 | |||
| c47eb5f688 | |||
| 00f5311499 | |||
|
|
8853f6ae49 | ||
|
|
e0182ae7dd | ||
|
|
58096c09ed | ||
|
|
7da6bb979e | ||
|
|
3f36183021 | ||
|
|
d9301ad954 | ||
|
|
66f58fa228 | ||
|
|
2c8e0b47f9 | ||
|
|
69f7ae9051 | ||
|
|
4017b6cff6 | ||
|
|
cde279af0b | ||
|
|
6513908067 | ||
|
|
fdb0685eec | ||
|
|
e411d35544 | ||
|
|
3757e7d66f | ||
|
|
05d995f8e0 | ||
|
|
f6c4a2a591 | ||
|
|
7c34eed2ca | ||
|
|
d252f01f17 | ||
|
|
28a2f5d5ae | ||
|
|
f06d7f361c | ||
|
|
58d79aad17 | ||
|
|
60138e20d0 | ||
|
|
df7c0ef7ae | ||
|
|
f97054c804 | ||
|
|
520c878bb3 | ||
|
|
084b2a0500 | ||
|
|
20df0d8a60 | ||
|
|
abfe872109 | ||
|
|
961314ea86 | ||
|
|
76582c1ee9 | ||
|
|
d06373b155 | ||
|
|
bd42462291 | ||
|
|
583708d78c | ||
|
|
6763bef73e | ||
|
|
465f013155 | ||
|
|
eda8461304 | ||
|
|
1ba1eeed64 | ||
|
|
c1781f45ca | ||
|
|
ed7be0206d | ||
|
|
009bdbad8f | ||
|
|
a33127cd3c | ||
|
|
dccceb4c48 | ||
| bc5faec6b8 | |||
|
|
77a0e70146 | ||
|
|
37819bb50f | ||
|
|
a50e9793ea | ||
|
|
7b5a22c800 | ||
|
|
134695806c | ||
|
|
727f21005d | ||
|
|
1403ea82b2 | ||
|
|
29818d2fb6 | ||
|
|
77dba7ca5d | ||
|
|
dba349a539 | ||
|
|
3b0b2872aa | ||
|
|
804d708f87 | ||
|
|
8da429d611 | ||
|
|
996fdc28c9 | ||
|
|
609bb7e7dc | ||
|
|
ecf94e84ab | ||
|
|
c813055578 | ||
|
|
8881ad3bae | ||
|
|
7aba5fa0a8 | ||
|
|
479193b10b | ||
|
|
71614fa6ca | ||
|
|
f3707357a6 | ||
|
|
8ded92ea63 | ||
|
|
1f22e996dc | ||
|
|
8a0ec763e0 | ||
|
|
f211ef0d09 |
90
.gitea/workflows/bump.yml
Normal file
90
.gitea/workflows/bump.yml
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
# Nomarchy scheduled lock bump — the automated half of "rock-stable
|
||||||
|
# without rotting": once a week, update flake.lock (inputs track pinned
|
||||||
|
# release branches, so this never jumps a NixOS release — that's a
|
||||||
|
# deliberate hand-edited v2, see agent/GOALS.md), gate it, and land it
|
||||||
|
# on main only on green. `v1` promotion stays human, always.
|
||||||
|
#
|
||||||
|
# Fast lane: workflow_dispatch. For a security fix upstream, run this
|
||||||
|
# workflow manually from the Actions tab instead of waiting for Monday.
|
||||||
|
#
|
||||||
|
# Gate scope: `nix flake check --no-build` — the same eval tier as
|
||||||
|
# check.yml (this runner has no KVM; see item 20 for the VM-suite
|
||||||
|
# upgrade path). The py_compile/bash -n steps are skipped on purpose:
|
||||||
|
# they don't read flake.lock, so a lock bump cannot break them. The
|
||||||
|
# bump commit's own push then triggers check.yml as a second net.
|
||||||
|
# A green bump therefore guards evaluation, not VM behaviour — the
|
||||||
|
# checks.* suite still runs locally / at promotion time.
|
||||||
|
#
|
||||||
|
# Failure mode: a red gate fails this run visibly and pushes nothing;
|
||||||
|
# next schedule retries. A push race (someone landed on main mid-run)
|
||||||
|
# also just fails the final push — rerun or wait a week.
|
||||||
|
#
|
||||||
|
# Container recipe (nixbld users, sandbox=false, pinned Nix, plain-shell
|
||||||
|
# install) inherited from check.yml — the gotchas are documented there.
|
||||||
|
|
||||||
|
name: Lock bump
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '17 5 * * 1' # Mondays 05:17 UTC
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
bump:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 90
|
||||||
|
env:
|
||||||
|
NIX_CONFIG: |
|
||||||
|
experimental-features = nix-command flakes
|
||||||
|
sandbox = false
|
||||||
|
NIX_SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Nix
|
||||||
|
run: |
|
||||||
|
NIX_VERSION=2.31.5
|
||||||
|
groupadd -r nixbld 2>/dev/null || true
|
||||||
|
for i in $(seq 1 10); do
|
||||||
|
useradd -r -g nixbld -G nixbld -d /var/empty \
|
||||||
|
-s /usr/sbin/nologin -c "Nix build user $i" "nixbld$i" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
curl -L "https://releases.nixos.org/nix/nix-${NIX_VERSION}/install" | sh -s -- --no-daemon
|
||||||
|
echo "$HOME/.nix-profile/bin" >> "$GITHUB_PATH"
|
||||||
|
|
||||||
|
- name: Update flake.lock
|
||||||
|
# Inputs track release branches (nixos-26.05, release-26.05), so
|
||||||
|
# the update stays within them by construction. The human-readable
|
||||||
|
# change list goes into the commit body below.
|
||||||
|
run: |
|
||||||
|
nix flake update 2>&1 | tee /tmp/bump-log
|
||||||
|
if git diff --quiet flake.lock; then
|
||||||
|
echo "Lock already up to date — nothing to do."
|
||||||
|
echo "changed=0" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "changed=1" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
id: update
|
||||||
|
|
||||||
|
- name: Gate — nix flake check (eval only)
|
||||||
|
if: steps.update.outputs.changed == '1'
|
||||||
|
run: nix flake check --no-build
|
||||||
|
|
||||||
|
- name: Commit + push on green
|
||||||
|
if: steps.update.outputs.changed == '1'
|
||||||
|
# The checkout step persists the Actions token, so this push
|
||||||
|
# authenticates as the workflow; its push triggers check.yml as
|
||||||
|
# the second net. Only flake.lock is committed — pathspec-limited,
|
||||||
|
# nothing else can ride along.
|
||||||
|
run: |
|
||||||
|
{
|
||||||
|
echo "chore(lock): scheduled upstream bump"
|
||||||
|
echo
|
||||||
|
grep -E '^(• | )' /tmp/bump-log || true
|
||||||
|
echo
|
||||||
|
echo "Gate: nix flake check --no-build (eval tier — see bump.yml header)."
|
||||||
|
} > /tmp/bump-msg
|
||||||
|
git -c user.name="nomarchy-bump" -c user.email="actions@git.bemagri.xyz" \
|
||||||
|
commit --only flake.lock -F /tmp/bump-msg
|
||||||
|
git push origin HEAD:main
|
||||||
@@ -1,42 +1,40 @@
|
|||||||
# Nomarchy CI — eval + lint.
|
# Nomarchy CI — the always-on net under direct-to-main pushes.
|
||||||
#
|
#
|
||||||
# Catches the regressions that hurt today:
|
# Scope (deliberate): the EVAL tier only. The runner behind this Gitea
|
||||||
# 1. Flake stops evaluating (broken option ref, missing import, etc.).
|
# instance is act_runner + docker containers (the legacy repo's check.yml
|
||||||
# Checked per-output rather than via `nix flake check` so we can skip
|
# ran 57 times on it) — no systemd, no /dev/kvm — so the checks.* VM
|
||||||
# packages.allThemeVariants — the 22-generation linkFarm that OOMs the
|
# tests and full toplevel builds can't run here. `nix flake check
|
||||||
# runner; every palette is validated one-at-a-time by the matrix (4).
|
# --no-build` still catches most breakage (type errors, missing options,
|
||||||
# 2. A `nomarchy-*` shell script has a syntax error or a shellcheck
|
# bad merges, template/mkFlake drift — see docs/TESTING.md §1); the VM
|
||||||
# error-severity issue.
|
# suite stays a local/promotion gate until a KVM-capable NixOS runner
|
||||||
# 3. `docs/SCRIPTS.md` drifts from the repo state because somebody
|
# exists (see the commented vm-checks job at the bottom).
|
||||||
# added / removed / renamed a script and didn't run the generator
|
|
||||||
# (the pre-commit hook handles this, but only when enabled per-clone).
|
|
||||||
# 4. An opt-in nomarchy.* toggle stops evaluating. `nix flake check`
|
|
||||||
# only evaluates the four default configs, so a bug that only fires
|
|
||||||
# when a toggle is flipped sails through (e.g. the impermanence
|
|
||||||
# systemd-stage-1 assertion). nomarchy-eval-matrix layers each toggle
|
|
||||||
# onto the default config and forces system.build.toplevel.
|
|
||||||
#
|
#
|
||||||
# Doesn't build ISOs — that needs a binary cache. Add a separate job
|
# Inherited-from-legacy gotchas (learned over 57 runs, kept verbatim):
|
||||||
# once Cachix/Attic is in place.
|
# - Single-user Nix (--no-daemon): no systemd in the container. The
|
||||||
|
# installer runs as root and honours build-users-group=nixbld from
|
||||||
|
# its bundled nix.conf, aborting unless the group exists AND has
|
||||||
|
# members — create nixbld + users first.
|
||||||
|
# - sandbox=false: Stylix/base16.nix do import-from-derivation; the
|
||||||
|
# single-user Nix in this container can't set up the build sandbox
|
||||||
|
# (no user namespaces), which otherwise surfaces as
|
||||||
|
# "path '…-source' is not valid".
|
||||||
|
# - Pin the Nix version: 2.34's lazy-trees git cache doesn't
|
||||||
|
# materialise flake-input `-source` paths into the store, breaking
|
||||||
|
# the same IFD reads. 2.31.5 matches what wrote flake.lock.
|
||||||
|
# - Plain-shell Nix install, not a JS action: act_runner's bundled act
|
||||||
|
# tops out at node20; a `run:` step has no node-runtime coupling.
|
||||||
|
|
||||||
name: Check
|
name: Check
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [main, v1]
|
||||||
pull_request:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
eval-and-lint:
|
eval:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
# Flakes for every `nix` invocation in the job (the bare `nix flake
|
timeout-minutes: 60
|
||||||
# check` below relies on this; the scripts pass the flag themselves).
|
|
||||||
# sandbox=false because Stylix/base16.nix do import-from-derivation —
|
|
||||||
# eval realizes fetched `-source` paths mid-check, and the single-user
|
|
||||||
# Nix in this container can't set up the build sandbox (no user
|
|
||||||
# namespaces), which otherwise surfaces as "path '…-source' is not
|
|
||||||
# valid". NIX_SSL_CERT_FILE because we add nix to PATH without sourcing
|
|
||||||
# the installer's profile (which is what normally exports it).
|
|
||||||
env:
|
env:
|
||||||
NIX_CONFIG: |
|
NIX_CONFIG: |
|
||||||
experimental-features = nix-command flakes
|
experimental-features = nix-command flakes
|
||||||
@@ -47,22 +45,6 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
# Plain shell install rather than a JS action: act_runner's bundled
|
|
||||||
# `act` only supports up to node20, and nix-installer-action@main
|
|
||||||
# moved to node24 ("runs.using ... got node24"). A run step has no
|
|
||||||
# node-runtime coupling. Single-user (--no-daemon) needs no systemd,
|
|
||||||
# which the catthehacker container doesn't run as PID 1.
|
|
||||||
#
|
|
||||||
# The installer runs as root here and honours build-users-group=
|
|
||||||
# nixbld from its bundled nix.conf, aborting unless that group exists
|
|
||||||
# AND has members. Create the nixbld group + build users (what a
|
|
||||||
# multi-user install does) before running it.
|
|
||||||
#
|
|
||||||
# Pin the Nix version: the latest (2.34) uses lazy-trees / a git
|
|
||||||
# cache that doesn't materialise flake-input `-source` paths into
|
|
||||||
# the store, so Stylix's import-from-derivation reads fail with
|
|
||||||
# "path '…-source' is not valid". 2.31.5 matches the Nix that wrote
|
|
||||||
# flake.lock locally and evaluates the flake cleanly.
|
|
||||||
run: |
|
run: |
|
||||||
NIX_VERSION=2.31.5
|
NIX_VERSION=2.31.5
|
||||||
groupadd -r nixbld 2>/dev/null || true
|
groupadd -r nixbld 2>/dev/null || true
|
||||||
@@ -73,118 +55,47 @@ jobs:
|
|||||||
curl -L "https://releases.nixos.org/nix/nix-${NIX_VERSION}/install" | sh -s -- --no-daemon
|
curl -L "https://releases.nixos.org/nix/nix-${NIX_VERSION}/install" | sh -s -- --no-daemon
|
||||||
echo "$HOME/.nix-profile/bin" >> "$GITHUB_PATH"
|
echo "$HOME/.nix-profile/bin" >> "$GITHUB_PATH"
|
||||||
|
|
||||||
- name: Materialize flake-input sources for eval
|
- name: nix flake check (eval only)
|
||||||
# Walker's flake reads its own source tree during evaluation:
|
# Full module-system evaluation of every output — both nixos
|
||||||
# importTOML resources/config.toml in its home-manager module and
|
# configs, the home config, the checks.* derivations (instantiated,
|
||||||
# lib.fileset.toSource for the package src (cargoLock.lockFile =
|
# not run) and the downstream template through lib.mkFlake.
|
||||||
# "${src}/Cargo.lock"). On a cold store the input source isn't
|
run: nix flake check --no-build
|
||||||
# materialised, so flake check / eval die with "path '…-source' is
|
|
||||||
# not valid" (works locally only because prior builds materialised
|
|
||||||
# it; `nix flake archive` reports the input but doesn't make the
|
|
||||||
# fileset-derived src readable). `nix build` of walker's src
|
|
||||||
# eagerly realises it — and the input it reads from — priming the
|
|
||||||
# store so the later eval steps find every path valid.
|
|
||||||
run: |
|
|
||||||
nix build --no-link --impure --expr 'let f = builtins.getFlake (toString ./.); in f.inputs.walker.packages.${builtins.currentSystem}.default.src'
|
|
||||||
|
|
||||||
- name: Check flake outputs (except the 22-variant pre-cache package)
|
- name: Python syntax (nomarchy-theme-sync)
|
||||||
# Stand-in for `nix flake check --no-build`. That also evaluates
|
# Via nix shell so the step doesn't depend on the runner image
|
||||||
# packages.allThemeVariants — a linkFarm whose drvPath forces all 22
|
# preinstalling python3.
|
||||||
# home generations into memory at once, OOM-killing the runner. The
|
|
||||||
# eval matrix below already validates every palette one-at-a-time, so
|
|
||||||
# that package's CI value is near-zero. Here we force every other
|
|
||||||
# output (all 4 system closures incl. assertions, both standalone
|
|
||||||
# home generations, the installer VM package, the overlay, the app)
|
|
||||||
# and skip only allThemeVariants/default. Each tryEval is GC'd before
|
|
||||||
# the next, so peak memory is one config, not twenty-two.
|
|
||||||
run: |
|
run: |
|
||||||
nix eval --impure --raw --expr 'let
|
nix shell nixpkgs#python3 --command \
|
||||||
f = builtins.getFlake (toString ./.);
|
python3 -m py_compile pkgs/nomarchy-theme-sync/nomarchy-theme-sync.py
|
||||||
lib = f.inputs.nixpkgs.lib;
|
|
||||||
sys = "x86_64-linux";
|
|
||||||
ok = x: (builtins.tryEval (builtins.seq x true)).success;
|
|
||||||
checks = {
|
|
||||||
"nixos.default" = ok f.nixosConfigurations.default.config.system.build.toplevel.drvPath;
|
|
||||||
"nixos.nomarchy-installer" = ok f.nixosConfigurations.nomarchy-installer.config.system.build.toplevel.drvPath;
|
|
||||||
"nixos.installerVm" = ok f.nixosConfigurations.installerVm.config.system.build.toplevel.drvPath;
|
|
||||||
"nixos.nomarchy-live" = ok f.nixosConfigurations.nomarchy-live.config.system.build.toplevel.drvPath;
|
|
||||||
"home.nomarchy" = ok f.homeConfigurations.nomarchy.activationPackage.drvPath;
|
|
||||||
"home.nixos" = ok f.homeConfigurations.nixos.activationPackage.drvPath;
|
|
||||||
"packages.installerVm" = ok f.packages.${sys}.installerVm.drvPath;
|
|
||||||
"overlays.default" = ok (builtins.isFunction f.overlays.default);
|
|
||||||
"apps.installerVm" = ok f.apps.${sys}.installerVm.program;
|
|
||||||
};
|
|
||||||
failed = builtins.attrNames (lib.filterAttrs (_: v: !v) checks);
|
|
||||||
in if failed == [] then "ALL OK"
|
|
||||||
else throw ("flake-output checks failed: " + builtins.concatStringsSep ", " failed)'
|
|
||||||
|
|
||||||
- name: Evaluate opt-in toggle / palette / home matrix
|
- name: Shell syntax (tracked scripts)
|
||||||
# flake check never flips a nomarchy.* toggle; this does. jq is
|
# The distro's user-facing scripts are generated by Nix (their
|
||||||
# provided via nix shell so the step doesn't depend on the runner
|
# syntax is exercised by the eval + local builds); this covers the
|
||||||
# image preinstalling it.
|
# hand-written .sh files: installer helpers and maintainer tools.
|
||||||
run: nix shell nixpkgs#jq --command ./bin/utils/nomarchy-eval-matrix
|
|
||||||
|
|
||||||
- name: Lint nomarchy-* scripts (bash -n + shellcheck)
|
|
||||||
run: |
|
run: |
|
||||||
# Mirror what .githooks/pre-commit runs locally, but across the
|
|
||||||
# whole tree instead of just changed files. Pre-commit gates
|
|
||||||
# individual commits; CI gates branches (including --no-verify
|
|
||||||
# bypasses).
|
|
||||||
set -e
|
set -e
|
||||||
fail=0
|
fail=0
|
||||||
while IFS= read -r script; do
|
while IFS= read -r script; do
|
||||||
[[ -f "$script" ]] || continue
|
head -1 "$script" | grep -qE '^#!.*\b(bash|sh)\b' || continue
|
||||||
# Python helpers ship under the same nomarchy- prefix
|
|
||||||
# (e.g. nomarchy-haptic-touchpad). Skip non-bash.
|
|
||||||
head -1 "$script" | grep -qE '^#!.*\bbash\b' || continue
|
|
||||||
if ! bash -n "$script"; then
|
if ! bash -n "$script"; then
|
||||||
echo "::error file=$script::bash syntax error"
|
echo "::error file=$script::bash syntax error"
|
||||||
fail=1
|
fail=1
|
||||||
fi
|
fi
|
||||||
if ! nix shell nixpkgs#shellcheck --command shellcheck \
|
done < <(git ls-files '*.sh')
|
||||||
--severity=error --shell=bash "$script"; then
|
|
||||||
echo "::error file=$script::shellcheck error-severity issue"
|
|
||||||
fail=1
|
|
||||||
fi
|
|
||||||
done < <(find features/scripts/utils core/system/scripts \
|
|
||||||
themes/engine/scripts \
|
|
||||||
-maxdepth 1 -type f -name 'nomarchy-*')
|
|
||||||
exit "$fail"
|
exit "$fail"
|
||||||
|
|
||||||
- name: docs/SCRIPTS.md is up to date
|
# ── vm-checks (DISABLED until a KVM runner exists) ────────────────────
|
||||||
run: |
|
# The real prize: running the checks.* VM suite + a toplevel build in
|
||||||
# Regenerate to a temp file and compare. If different, the
|
# CI. Needs a runner on a NixOS (or at least nix + /dev/kvm) host —
|
||||||
# contributor forgot to run the generator (or skipped the
|
# register one with a dedicated label, then uncomment and set runs-on
|
||||||
# pre-commit hook). Fail loudly and tell them the fix.
|
# to that label. Do NOT enable this against a label that doesn't
|
||||||
./bin/utils/nomarchy-docs-scripts --out /tmp/SCRIPTS.regen.md
|
# exist: Gitea queues such jobs forever instead of failing.
|
||||||
if ! diff -q docs/SCRIPTS.md /tmp/SCRIPTS.regen.md >/dev/null; then
|
#
|
||||||
echo "::error::docs/SCRIPTS.md is stale."
|
# vm-checks:
|
||||||
echo "Run: ./bin/utils/nomarchy-docs-scripts --out docs/SCRIPTS.md"
|
# runs-on: nix-kvm
|
||||||
echo "Then commit the regenerated file."
|
# timeout-minutes: 120
|
||||||
echo "--- diff ---"
|
# steps:
|
||||||
diff -u docs/SCRIPTS.md /tmp/SCRIPTS.regen.md || true
|
# - uses: actions/checkout@v4
|
||||||
exit 1
|
# - run: nix flake check # builds + runs the VM tests
|
||||||
fi
|
# - run: nix build .#nixosConfigurations.nomarchy.config.system.build.toplevel --no-link
|
||||||
|
# - run: nix build .#homeConfigurations.nomarchy.activationPackage --no-link
|
||||||
- name: installer/hardware-db.sh references real nixos-hardware modules
|
|
||||||
run: |
|
|
||||||
# Every 4th-pipe-field in HARDWARE_DB is a nixos-hardware module
|
|
||||||
# name. Half the DB used to point at modules that don't exist
|
|
||||||
# (e.g. microsoft-surface-pro-8 — there's only -pro-intel and
|
|
||||||
# -pro-9), which made the install fail at eval time with
|
|
||||||
# cryptic "attribute not found" errors on real laptops. This
|
|
||||||
# step catches that regression class.
|
|
||||||
awk -F'|' '/^ "/ { gsub(/"/,"",$4); gsub(/^[[:space:]]+|[[:space:]]+$/,"",$4); if ($4) print $4 }' \
|
|
||||||
installer/hardware-db.sh | sort -u > /tmp/db-refs.txt
|
|
||||||
nix eval --impure --json --expr '
|
|
||||||
let
|
|
||||||
nh = (builtins.getFlake (toString ./.)).inputs.nixos-hardware.nixosModules;
|
|
||||||
in builtins.attrNames nh' \
|
|
||||||
| nix shell nixpkgs#jq --command jq -r '.[]' | sort -u > /tmp/db-real.txt
|
|
||||||
missing=$(comm -23 /tmp/db-refs.txt /tmp/db-real.txt)
|
|
||||||
if [[ -n "$missing" ]]; then
|
|
||||||
echo "::error::hardware-db.sh references nixos-hardware modules that don't exist:"
|
|
||||||
printf ' - %s\n' $missing
|
|
||||||
echo "Either fix the name (check the actual attr in nixos-hardware) or drop the row."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Nomarchy pre-commit hook.
|
|
||||||
#
|
|
||||||
# Enable per-clone with:
|
|
||||||
# git config core.hooksPath .githooks
|
|
||||||
#
|
|
||||||
# Two responsibilities:
|
|
||||||
# 1. Lint changed nomarchy-* scripts (bash -n + shellcheck if available)
|
|
||||||
# so syntax errors and unquoted-var bugs don't ship.
|
|
||||||
# 2. Regenerate docs/SCRIPTS.md when any nomarchy-* script under the three
|
|
||||||
# script directories is added, modified, or deleted in this commit, and
|
|
||||||
# stage the refreshed file so it lands with the change.
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
repo_root="$(git rev-parse --show-toplevel)"
|
|
||||||
cd "$repo_root"
|
|
||||||
|
|
||||||
script_dirs_re='^(features/scripts/utils|core/system/scripts|themes/engine/scripts)/nomarchy-'
|
|
||||||
|
|
||||||
# 1. Lint changed scripts. bash -n catches syntax errors (always fatal).
|
|
||||||
# shellcheck catches unquoted-var, use-before-define, missing-shebang, etc.
|
|
||||||
# We only fail on severity=error so the long tail of pre-existing warnings
|
|
||||||
# (info / style / warning) doesn't block commits — those can be cleaned up
|
|
||||||
# incrementally without a flag day.
|
|
||||||
changed_scripts=$(git diff --cached --name-only --diff-filter=ACMR \
|
|
||||||
| grep -E "$script_dirs_re" || true)
|
|
||||||
if [[ -n "$changed_scripts" ]]; then
|
|
||||||
while IFS= read -r script; do
|
|
||||||
[[ -f "$script" ]] || continue
|
|
||||||
# Only lint scripts with a bash shebang. nomarchy-* is a name
|
|
||||||
# convention, not a language guarantee — at least one Python helper
|
|
||||||
# ships under the same prefix (nomarchy-haptic-touchpad).
|
|
||||||
head -1 "$script" | grep -qE '^#!.*\bbash\b' || continue
|
|
||||||
if ! bash -n "$script"; then
|
|
||||||
echo "pre-commit: bash syntax error in $script — aborting commit." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if command -v shellcheck >/dev/null 2>&1; then
|
|
||||||
if ! shellcheck --severity=error --shell=bash "$script"; then
|
|
||||||
echo "pre-commit: shellcheck found error-level issues in $script — aborting commit." >&2
|
|
||||||
echo "pre-commit: fix the reported issues, or rerun with --no-verify after a deliberate decision to ship." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done <<< "$changed_scripts"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 2. Regenerate the script audit doc.
|
|
||||||
if git diff --cached --name-only --diff-filter=ACMRD | grep -qE "$script_dirs_re"; then
|
|
||||||
echo "pre-commit: regenerating docs/SCRIPTS.md (script change detected)…"
|
|
||||||
./bin/utils/nomarchy-docs-scripts --out docs/SCRIPTS.md
|
|
||||||
git add docs/SCRIPTS.md
|
|
||||||
fi
|
|
||||||
21
.gitignore
vendored
21
.gitignore
vendored
@@ -1,15 +1,14 @@
|
|||||||
# ---> Nix
|
# Study material from the previous iteration — not part of the flake.
|
||||||
# Ignore build outputs from performing a nix-build or `nix build` command
|
# Delete the directory once everything worth porting has been ported.
|
||||||
|
old_distro/
|
||||||
|
|
||||||
|
# Nix build artifacts
|
||||||
result
|
result
|
||||||
result-*
|
result-*
|
||||||
|
|
||||||
# Ignore automatically generated direnv output
|
__pycache__/
|
||||||
.direnv
|
.DS_Store
|
||||||
|
|
||||||
# Local IDE settings
|
# Claude Code machine-local settings (permissions etc.)
|
||||||
.claude/
|
.claude/settings.local.json
|
||||||
|
.claude/skills/
|
||||||
# VM and ISO artifacts
|
|
||||||
*.qcow2
|
|
||||||
*.qcow
|
|
||||||
*.iso
|
|
||||||
|
|||||||
42
CLAUDE.md
Normal file
42
CLAUDE.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Nomarchy — agent entry point
|
||||||
|
|
||||||
|
Nomarchy is a NixOS-based distro: rock-stable, fully reproducible, themed
|
||||||
|
from one JSON, configured through a menu that writes into the user's own
|
||||||
|
flake checkout. Read the README for the architecture.
|
||||||
|
|
||||||
|
## If you're here to work autonomously (the loop)
|
||||||
|
Follow **`agent/LOOP.md`** — it defines one iteration: orient
|
||||||
|
(GOALS/BACKLOG/JOURNAL/MEMORY), take the top actionable BACKLOG item,
|
||||||
|
verify up the V0–V3 ladder, commit+push on `main`, record. All loop state
|
||||||
|
is git-tracked in `agent/`.
|
||||||
|
|
||||||
|
## Rules that apply to every session, loop or not
|
||||||
|
- **Honesty rule** (docs/TESTING.md): for visual/interactive changes,
|
||||||
|
evaluation is not rendering — state exactly what you verified and at
|
||||||
|
which tier. Cheap check first, always: `nix flake check --no-build`.
|
||||||
|
- **Conventions** (`agent/CONVENTIONS.md`): in-flake state, menu
|
||||||
|
placement, Waybar parity with the summer whole-swaps, toggle-vs-package
|
||||||
|
discipline, commented template examples for opt-ins.
|
||||||
|
- **Git:** direct commits on `main`, pushed; `v1` is the human-only
|
||||||
|
release pointer — never touch it. Never run `nix flake update` unless
|
||||||
|
the task is a lock bump. No formatter — match the aligned
|
||||||
|
hand-formatting.
|
||||||
|
- Machine-specifics live in `hosts/`, the distro in `modules/`, data in
|
||||||
|
`themes/`, code in `pkgs/`, maintainer tools in `tools/`.
|
||||||
|
|
||||||
|
## Delegation
|
||||||
|
|
||||||
|
The higher your tier, the more you delegate. Push the work down, keep your own context for judgment. Brief every child: the context, the why, what done looks like. It starts blank and inherits nothing.
|
||||||
|
|
||||||
|
| Model | Best for | Delegate? | Effort |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Haiku | bulk mechanical | never | low |
|
||||||
|
| Sonnet | scoped research | when it helps | medium |
|
||||||
|
| Opus 4.8 | multi-step reasoning | on clear benefit | xhigh |
|
||||||
|
| Fable 5 | judgment, taste | by default | medium |
|
||||||
|
|
||||||
|
Fable goes xhigh only for the hardest calls. Skip high.
|
||||||
|
|
||||||
|
## Escalation
|
||||||
|
|
||||||
|
The parent doesn't have to be the top model. An Opus parent spawns a Fable child for the one hard call. The child answers and returns. Work above your tier? Return it, don't burn tokens on it.
|
||||||
508
README.md
508
README.md
@@ -1,118 +1,442 @@
|
|||||||
# 👑 Nomarchy
|
# Nomarchy
|
||||||
|
|
||||||
**Nomarchy** is a professional-grade NixOS distribution that ships a highly curated Hyprland desktop on a strictly declarative, flake-based foundation. It provides a highly polished, "it just works" experience for power users who want a beautiful Wayland environment without sacrificing the reliability of NixOS.
|
**The rock-solid reproducibility of NixOS 26.05. The out-of-the-box polish of
|
||||||
|
Omarchy/Omakub.** One JSON file rules the look of the entire desktop; every
|
||||||
|
theme change is a Home Manager generation — atomic, rollbackable, never
|
||||||
|
partial.
|
||||||
|
|
||||||
## ✨ Key Features
|
|
||||||
|
|
||||||
- **Purely Declarative:** Your entire desktop—themes, fonts, wallpapers, and toolchains—is defined in code.
|
|
||||||
- **Modular Merging Architecture:** Distro code and user code are strictly separated. You can update the distro core without ever touching or breaking your personal configurations.
|
|
||||||
- **Interactive "Smart" Installer:** Detects hardware, sets up networking, localizes timezones/keymaps, and offers multi-select software profiles.
|
|
||||||
- **Erase Your Darlings (Optional):** Optional BTRFS root-wipe on boot ensures your system stays pristine and 100% declarative.
|
|
||||||
- **Dynamic Theming Engine:** 20+ built-in themes with instant UI feedback via IPC (swww, waybar, and stylix).
|
|
||||||
- **Portable State (`nomarchy-sync`):** Easily backup and sync your declarative config and dynamic state (theme/wallpaper choices) to a private Git repo.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📂 Component-Based Architecture
|
|
||||||
|
|
||||||
Nomarchy uses a **Feature-Centric Directory Structure**. For a comprehensive breakdown of the system architecture, folder roles, and module logic, see the [Detailed Architecture Documentation](docs/STRUCTURE.md).
|
|
||||||
|
|
||||||
Configuration, modules, and utilities are strictly organized to maintain sanity as the system grows.
|
|
||||||
|
|
||||||
- **`core/`**: Foundational OS & User defaults (Bootloader, Audio, Bluetooth, core system features).
|
|
||||||
- **`features/`**: Isolated modules containing Nix logic and raw dotfiles.
|
|
||||||
- **`features/apps/`**: App-specific configs (e.g., `features/apps/btop/`, `features/apps/kitty/`), each containing their own `default.nix` and standalone `config/` directory mapped via Home Manager.
|
|
||||||
- **`features/desktop/`**: Desktop environment components (e.g., Hyprland, Waybar).
|
|
||||||
- **`features/scripts/utils/`**: Consolidated repository for all custom Nomarchy bash scripts, centrally packaged and injected into the user's `PATH` with correct dependencies.
|
|
||||||
- **`themes/`**: The global theming engine. It holds pure color data and logic. *Theme-specific app layouts* (like a custom Waybar layout) are stored directly inside the app's feature folder, solving the matrix problem of theming.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📥 Installation
|
|
||||||
|
|
||||||
### 1. Try it in a VM (Recommended)
|
|
||||||
Verify the experience without touching your hardware:
|
|
||||||
```bash
|
|
||||||
./bin/utils/nomarchy-test-installer
|
|
||||||
```
|
```
|
||||||
This builds a full graphical VM of the installer environment. Once inside, click the **Install Nomarchy** icon or run `nomarchy-install`.
|
┌──────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ theme-state.json (single source of truth) │
|
||||||
### 2. Build the Installer ISO
|
│ lives INSIDE your flake checkout, git-tracked │
|
||||||
To install on physical hardware, generate your own bootable image:
|
└───────────────────────────────────┬──────────────────────────────────────┘
|
||||||
```bash
|
│
|
||||||
./features/scripts/utils/nomarchy-build-iso # Minimal TTY installer
|
nomarchy-theme-sync apply gruvbox
|
||||||
./features/scripts/utils/nomarchy-build-live-iso # Graphical try-before-install
|
1. merges the preset into the JSON (atomic write)
|
||||||
|
2. runs `home-manager switch` (no sudo, no system rebuild)
|
||||||
|
│
|
||||||
|
▼ pure read (nomarchy.stateFile)
|
||||||
|
┌──────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ Home Manager bakes EVERYTHING into one read-only generation: │
|
||||||
|
│ Hyprland (colors/gaps/borders) Waybar (palette or whole-swap) │
|
||||||
|
│ Ghostty (full ANSI palette) btop (asset or generated) │
|
||||||
|
│ Stylix → GTK, Qt, cursors, fonts │
|
||||||
|
└───────────────────────────────────┬──────────────────────────────────────┘
|
||||||
|
▼
|
||||||
|
wallpaper via awww (the one runtime piece:
|
||||||
|
applied post-switch + at session start, `bg next` cycles)
|
||||||
```
|
```
|
||||||
The ISO will be located at `./result/iso/nixos-*.iso`. Flash it to a USB drive and boot.
|
|
||||||
|
|
||||||
### 3. Run the Installer
|
## 1. Layout
|
||||||
Once booted into the Live environment, launch the installer:
|
|
||||||
```bash
|
Flat on purpose. Two module trees, one options file each, no hidden layers.
|
||||||
nomarchy-install
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── flake.nix # inputs + the downstream API (exports below)
|
||||||
|
├── lib.nix # nomarchy.lib.mkFlake — one-call downstream wrapper
|
||||||
|
├── theme-state.json # ★ THE single source of truth (git-tracked!)
|
||||||
|
├── themes/ # 21 presets: <slug>.json + optional <slug>/ assets
|
||||||
|
│ ├── nord.json # palette (required, works alone)
|
||||||
|
│ └── nord/ # assets (optional, fixed filenames)
|
||||||
|
│ ├── backgrounds/ # wallpapers (auto-picked, SUPER+SHIFT+T cycles)
|
||||||
|
│ ├── btop.theme # hand-made config drop (else generated)
|
||||||
|
│ └── waybar.css # whole-swap: replaces the generated bar style
|
||||||
|
├── modules/
|
||||||
|
│ ├── nixos/ # the distro, system side
|
||||||
|
│ │ ├── default.nix # Hyprland session, Pipewire, greetd, fonts
|
||||||
|
│ │ ├── options.nix # nomarchy.system.* toggles
|
||||||
|
│ │ ├── plymouth.nix # boot splash, tinted from the JSON
|
||||||
|
│ │ ├── file-manager.nix # Thunar GUI + gvfs/tumbler/udisks2
|
||||||
|
│ │ └── power.nix # power-profiles-daemon/TLP, thermald, charge limit
|
||||||
|
│ └── home/ # the distro, user side
|
||||||
|
│ ├── default.nix # entry point
|
||||||
|
│ ├── options.nix # nomarchy.* option surface
|
||||||
|
│ ├── theme.nix # JSON ingestion + wallpaper hook
|
||||||
|
│ ├── stylix.nix # GTK/Qt/cursors/fonts from the same JSON
|
||||||
|
│ ├── hyprland.nix # all JSON-driven
|
||||||
|
│ ├── waybar.nix
|
||||||
|
│ ├── ghostty.nix
|
||||||
|
│ ├── btop.nix
|
||||||
|
│ ├── rofi.nix # launcher + nomarchy-menu (calc, emoji, clip…)
|
||||||
|
│ ├── keybinds.nix # single source: Hyprland binds + SUPER+? sheet
|
||||||
|
│ ├── swaync.nix # notifications, same JSON
|
||||||
|
│ ├── idle.nix # hyprlock + hypridle, same JSON
|
||||||
|
│ ├── yazi.nix # flagship TUI file manager + plugins
|
||||||
|
│ ├── osd.nix # swayosd volume/brightness OSD
|
||||||
|
│ ├── shell.nix # zsh + starship + bat/eza/zoxide
|
||||||
|
│ ├── keys.nix # gpg-agent fronting SSH, pinentry-qt
|
||||||
|
│ └── fastfetch.nix # themed Nomarchy logo + system info
|
||||||
|
├── hosts/
|
||||||
|
│ ├── default/ # reference machine (thin: boot, user, hostname)
|
||||||
|
│ └── live.nix # bootable live ISO (try the distro, no install)
|
||||||
|
├── pkgs/
|
||||||
|
│ ├── nomarchy-theme-sync/ # state writer + rebuild dispatcher (Python)
|
||||||
|
│ └── nomarchy-install/ # live-ISO installer (gum + disko + mkFlake)
|
||||||
|
├── templates/downstream/ # `nix flake init -t` starter for users
|
||||||
|
├── docs/TESTING.md # how to verify changes (incl. AI-agent rules)
|
||||||
|
├── docs/OVERRIDES.md # how downstream users override defaults
|
||||||
|
├── docs/RECOVERY.md # runbook: broken theme/desktop/boot → undo it
|
||||||
|
├── docs/ROADMAP.md # design/decision records + shipped-fixes log
|
||||||
|
├── agent/ # autonomous-agent loop: protocol (LOOP.md),
|
||||||
|
│ # prioritized BACKLOG, journal, memory
|
||||||
|
└── tools/ # maintainer-only
|
||||||
|
├── import-palettes.py # converts old-distro themes → JSON + assets
|
||||||
|
├── test-live-iso.sh # build the ISO + boot it in QEMU
|
||||||
|
├── test-install.sh # full offline-install regression in QEMU
|
||||||
|
└── vm/ # headless-VM helpers (QMP keys, VNC shots,
|
||||||
|
# offline-pin gap analysis)
|
||||||
```
|
```
|
||||||
The wizard will guide you through:
|
|
||||||
- **Networking:** An interactive wizard to connect to Wi-Fi if needed.
|
|
||||||
- **Hardware:** Optimized profiles for Dell XPS, Framework, Apple T2, and more.
|
|
||||||
- **Storage:** Choice between Standard Ext4 or Encrypted BTRFS with optional **Impermanence**.
|
|
||||||
- **Localization:** Searchable timezones and keyboard layout selection.
|
|
||||||
|
|
||||||
### Already on NixOS?
|
**Rule of thumb:** `modules/` is the distro (reusable, no machine specifics),
|
||||||
Layer Nomarchy onto an existing 25.11 install without reformatting — see the [Migration Guide](docs/MIGRATION.md).
|
`hosts/` is a machine, `themes/` is data, `pkgs/` is code, `tools/` is
|
||||||
|
maintainer-only. If a new file doesn't obviously belong to one of those, it
|
||||||
|
probably shouldn't exist.
|
||||||
|
|
||||||
---
|
## 2. Try it first (live ISO)
|
||||||
|
|
||||||
## 🛠️ Configuration & Usage
|
Boot the full desktop from a USB stick or VM without installing anything:
|
||||||
|
|
||||||
Nomarchy uses a "Downstream" model. After installation, your configuration lives in `/etc/nixos/` and is split into three main parts:
|
```sh
|
||||||
|
nix build .#nixosConfigurations.nomarchy-live.config.system.build.isoImage
|
||||||
|
# → result/iso/*.iso — dd to a stick, or boot it in QEMU:
|
||||||
|
tools/test-live-iso.sh
|
||||||
|
```
|
||||||
|
|
||||||
### 1. Distro Core (Upstream)
|
The live session auto-logs-in, seeds the flake at `~/.nomarchy`, and pins
|
||||||
Managed via the public Git repository. This is the engine. You should generally not modify files here.
|
the locked inputs into the ISO store — so theme switching (including the
|
||||||
|
`home-manager switch` it triggers) works **offline**, exactly like on an
|
||||||
|
installed system. Verification checklist: [docs/TESTING.md](docs/TESTING.md).
|
||||||
|
|
||||||
|
Like what you see? **`nomarchy-install`** (in a terminal) walks you through
|
||||||
|
installing to disk: pick a disk, LUKS2 full-disk encryption **by default**
|
||||||
|
(in exchange the desktop logs in passwordless — the passphrase already
|
||||||
|
gates the machine), user + hostname + timezone, hardware autodetection
|
||||||
|
(DMI → nixos-hardware profile), a hibernation-ready swapfile sized to RAM,
|
||||||
|
then disko partitions (GPT + ESP + BTRFS subvolumes incl. `@snapshots` —
|
||||||
|
snapper timeline snapshots are on) and `nixos-install` runs — **without a
|
||||||
|
network** when the ISO was built from a clean tree (the target's
|
||||||
|
`flake.lock` is composed from the rev the ISO carries). The installed
|
||||||
|
machine gets the standard downstream layout: the flake at `~/.nomarchy`
|
||||||
|
(`/etc/nixos` symlinks to it), one `mkFlake` call, your
|
||||||
|
`system.nix`/`home.nix`. First boot lands in the fully themed desktop —
|
||||||
|
the installer pre-activates the Home Manager generation. UEFI only for now.
|
||||||
|
|
||||||
|
## 3. Using Nomarchy on your machine (downstream)
|
||||||
|
|
||||||
|
Nomarchy is consumed as a flake input — you never fork or edit this repo:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mkdir my-machine && cd my-machine
|
||||||
|
nix flake init -t "git+https://git.bemagri.xyz/bernardo/nomarchy.git?ref=v1"
|
||||||
|
```
|
||||||
|
|
||||||
|
The template's own README then walks the first-run steps: a real
|
||||||
|
`hardware-configuration.nix`, `git init` (flakes only see tracked
|
||||||
|
files), the two first rebuilds, and landing the checkout at
|
||||||
|
`~/.nomarchy` so the theme CLI finds it. (The installer does all of
|
||||||
|
this for you.)
|
||||||
|
|
||||||
|
You own two files day-to-day: `system.nix` and `home.nix` (plus
|
||||||
|
`theme-state.json`, written by the CLI). Your `flake.nix` is set up once —
|
||||||
|
later by the installer — and never hand-edited; it's a single call:
|
||||||
|
|
||||||
### 2. Your System (`system.nix`)
|
|
||||||
Add system-wide packages, services, and hardware tweaks here.
|
|
||||||
*Example: Adding a persistent directory for Docker if using Impermanence:*
|
|
||||||
```nix
|
```nix
|
||||||
environment.persistence."/persist" = {
|
outputs = { nomarchy, ... }:
|
||||||
directories = [ "/var/lib/docker" ];
|
nomarchy.lib.mkFlake {
|
||||||
|
src = ./.;
|
||||||
|
username = "me";
|
||||||
|
hardwareProfile = "framework-13-7040-amd"; # optional, nixos-hardware name
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Your User Environment (`home.nix`)
|
| `mkFlake` arg | Default | Purpose |
|
||||||
Add user-level packages, aliases, and dotfiles here.
|
|---|---|---|
|
||||||
*Example: Overriding the default terminal:*
|
| `src` | — (required) | Your flake directory (`./.`) |
|
||||||
```nix
|
| `username` | — (required) | Login name; flows into `system.nix` and names the HM config |
|
||||||
nomarchy.home.terminal = "kitty";
|
| `hardwareProfile` | `null` | One [nixos-hardware](https://github.com/NixOS/nixos-hardware) module name, or a list of them (pinned + tested by Nomarchy; unknown names fail with suggestions) |
|
||||||
|
| `system` | `"x86_64-linux"` | Platform |
|
||||||
|
|
||||||
|
(Power users can skip `mkFlake` and wire `nixosModules.nomarchy` /
|
||||||
|
`homeModules.nomarchy` / `overlays.default` by hand — the wrapper is sugar.)
|
||||||
|
|
||||||
|
Two deliberately separate rebuild paths:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo nixos-rebuild switch --flake .#default # system: rare
|
||||||
|
home-manager switch --flake .#me # desktop: every theme change, no sudo
|
||||||
```
|
```
|
||||||
|
|
||||||
For the full list of `nomarchy.*` options you can set in `system.nix` and `home.nix`, see the [Options Reference](docs/OPTIONS.md). For custom automation, see [Runtime Hooks](docs/HOOKS.md). Hit a rebuild error? Check [Troubleshooting](docs/TROUBLESHOOTING.md). For where the project is heading next, see the [Roadmap](docs/ROADMAP.md).
|
Day-to-day you'll use the shipped shortcuts instead:
|
||||||
|
|
||||||
### Applying Changes
|
```sh
|
||||||
After editing your files, apply them instantly. **IMPORTANT:** Nomarchy requires the `--impure` flag for evaluation. You **MUST** use the following aliases rather than standard NixOS commands:
|
sys-update # nix flake update + system rebuild (BTRFS snapshot first when available)
|
||||||
|
sys-rebuild # system rebuild against the CURRENT lock (config changes only, no update)
|
||||||
```bash
|
# …both end with a package-level diff of what the rebuild changed (nvd)
|
||||||
sys-update # Rebuilds the NixOS system (Runs: sudo nixos-rebuild switch --flake .#default --impure)
|
home-update # home-manager switch (no flake update, no sudo)
|
||||||
env-update # Reloads your Home Manager environment (Runs: home-manager switch --flake .#default --impure)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
**Order matters when pulling distro updates.** `home-update` does *not*
|
||||||
|
touch the lock — it rebuilds the desktop against the **current**
|
||||||
|
`flake.lock`. A new Nomarchy revision (new keybinds, theming, modules)
|
||||||
|
arrives only when the lock is updated, which `sys-update` does
|
||||||
|
(`nix flake update`). So to pull an update that affects the desktop layer:
|
||||||
|
run `sys-update` **first** (updates the lock + rebuilds the system), **then**
|
||||||
|
`home-update` (re-applies the desktop against the new lock). Doing them in
|
||||||
|
the other order rebuilds the desktop against the *old* inputs and silently
|
||||||
|
skips the new home-side changes. After a home-side keybind/config change,
|
||||||
|
also `hyprctl reload` (or relogin) so the running session re-reads it.
|
||||||
|
|
||||||
## 🚀 Commands & Keybindings
|
Override anything via the `nomarchy.*` surface or plain NixOS/HM options:
|
||||||
|
appearance (gaps/colors/fonts) changes through `nomarchy-theme-sync`,
|
||||||
|
behaviour (input/misc/monitor/chrome) is `mkDefault` so a plain `home.nix`
|
||||||
|
assignment wins, and bind/exec-once lists concatenate. Full guide with
|
||||||
|
examples: **[docs/OVERRIDES.md](docs/OVERRIDES.md)**.
|
||||||
|
|
||||||
The full list lives in [`docs/KEYBINDINGS.md`](docs/KEYBINDINGS.md) (auto-generated from the Hyprland configs). A few highlights:
|
**Where each option goes.** `nomarchy.system.*`, `nomarchy.hardware.*`, and
|
||||||
|
`nomarchy.services.*` are NixOS options — set them in `system.nix`. Everything
|
||||||
|
else under `nomarchy.*` is a Home Manager option — set it in `home.nix`. The
|
||||||
|
two tables below are split along exactly that line.
|
||||||
|
|
||||||
| Keybinding | Action |
|
**`home.nix`** (Home Manager — the desktop):
|
||||||
| :--- | :--- |
|
|
||||||
| `Super + Space` | **App Launcher** (Walker) |
|
|
||||||
| `Super + Shift + Space` | **Nomarchy Menu** (Walker) |
|
|
||||||
| `Super + Alt + Space` | **Toggle Top Bar** (Waybar) |
|
|
||||||
| `Super + Return` | Open Terminal |
|
|
||||||
| `Super + Q` | Close Window |
|
|
||||||
|
|
||||||
### Utility Scripts
|
| Option | Default | Purpose |
|
||||||
Nomarchy includes dozens of productivity scripts available in your PATH. Some highlights:
|
|---|---|---|
|
||||||
- `nomarchy-sync push <repo>`: Backup your setup to Git.
|
| `nomarchy.stateFile` | — (required) | Path to your theme-state.json |
|
||||||
- `nomarchy-theme-bg-next`: Cycle to the next wallpaper in the current theme.
|
| `nomarchy.terminal` | `"ghostty"` | Terminal for keybinds and `$TERMINAL` |
|
||||||
- `nomarchy-menu`: The central hub for all utilities and pickers.
|
| `nomarchy.keyboard.layout` | `"us"` | XKB layout for the Hyprland session (installer writes the matching `services.xserver.xkb` in system.nix; the console + LUKS prompt follow via the distro default) |
|
||||||
|
| `nomarchy.keyboard.variant` | `""` | XKB variant for the session |
|
||||||
|
| `nomarchy.keyboard.devices` | `{}` | Per-device layout overrides (Hyprland `device` blocks keyed by `hyprctl devices` name) — e.g. an external keyboard with its own layout/variant |
|
||||||
|
| `nomarchy.keyboard.layouts` | `[]` | Extra candidate layouts; when set, a watcher prompts (rofi) for a layout on a newly-connected keyboard and remembers it per-device |
|
||||||
|
| `nomarchy.nightlight.enable` | `false` | Scheduled blue-light filter (hyprsunset) — warm at night (`.temperature`, default 4000K) between `.sunset`/`.sunrise`, no shift by day; off by default — enable it from the menu (System › Night light; the first enable rebuilds), then toggle on/off instantly from the menu or the Waybar moon indicator (writes `settings.nightlight.on` in your flake, no rebuild) and it survives reboot, so it stays reproducible |
|
||||||
|
| `nomarchy.updates.enable` | `false` | Passive update awareness: a background check (`.interval`, default daily) that flags when flake inputs (nixpkgs, the Nomarchy input, …) are behind upstream — and, with Flatpak on, when apps have updates (`.flatpak`) — via a Waybar indicator + notification. Never changes anything; click the indicator to run the upgrade flow |
|
||||||
|
| `nomarchy.hyprland.enable` | `true` | Nomarchy's Hyprland config |
|
||||||
|
| `nomarchy.waybar.enable` | `true` | Nomarchy's Waybar |
|
||||||
|
| `nomarchy.rofi.enable` | `true` | Themed rofi launcher + `nomarchy-menu` dispatcher |
|
||||||
|
| `nomarchy.swaync.enable` | `true` | swaync notifications, themed |
|
||||||
|
| `nomarchy.batteryNotify.enable` | `true` | Low-battery toasts at the bar's thresholds — 25% low, 10% critical (stays up until dismissed); silent no-op on machines without a battery |
|
||||||
|
| `nomarchy.idle.enable` | `true` | hyprlock + hypridle (idle lock 5 min, display off 10, suspend 30) |
|
||||||
|
| `nomarchy.yazi.enable` | `true` | yazi TUI file manager, themed + curated plugins |
|
||||||
|
| `nomarchy.osd.enable` | `true` | swayosd on-screen display for volume/brightness/mute |
|
||||||
|
| `nomarchy.shell.enable` | `true` | zsh + starship prompt + bat/eza/zoxide (zsh is the default login shell) |
|
||||||
|
| `nomarchy.ghostty.enable` | `true` | Nomarchy's Ghostty |
|
||||||
|
| `nomarchy.btop.enable` | `true` | btop with per-theme colors |
|
||||||
|
| `nomarchy.stylix.enable` | `true` | GTK/Qt/cursor theming |
|
||||||
|
| `nomarchy.fastfetch.enable` | `true` | fastfetch fronted by the themed Nomarchy logo |
|
||||||
|
| `nomarchy.keys.enable` | `true` | gpg-agent fronting SSH + pinentry-qt |
|
||||||
|
| `nomarchy.displays.enable` | `true` | nwg-displays interactive monitor arranger (helper for `nomarchy.monitors`) |
|
||||||
|
| `nomarchy.viewers.enable` | `true` | Document/image viewers: zathura (Stylix-themed PDF) + imv |
|
||||||
|
| `nomarchy.mime.enable` | `true` | Default "open with" associations (PDF/image/video/text/browser/directory); entries for apps you removed are skipped, so it degrades with the suite |
|
||||||
|
| `nomarchy.monitors` | `[]` | Declarative per-output layout → Hyprland `monitor` rules (applied on hotplug); `,preferred,auto,1` wildcard kept as fallback |
|
||||||
|
| `nomarchy.displayProfiles` | `{}` | Named layouts for the same outputs (docked/undocked/…), switched from System › Display › Profiles: instant via hyprctl, persisted in-flake (`settings.displayProfile`), baked over `nomarchy.monitors` at the next rebuild. The menu's Auto-switch row (`settings.displayProfileAuto`) makes plugging/unplugging outputs apply the matching profile automatically. A profile can also pin workspaces to outputs (`workspaces = { "1" = "DP-3"; }`) — moved instantly on switch, baked as Hyprland `workspace` rules |
|
||||||
|
| `nomarchy.launchOrFocus` | `[]` | Launch-or-focus binds: `SUPER+<key>` focuses the app's window (case-insensitive class match) or launches it; entries land in the SUPER+? cheatsheet, and a bind whose app was removed notifies instead of failing silently |
|
||||||
|
| `nomarchy.themesDir` | Nomarchy's `themes/` | Where per-theme app overrides are probed |
|
||||||
|
| `nomarchy.package` | overlay's `nomarchy-theme-sync` | The theme/state tool package, overridable if you fork it |
|
||||||
|
|
||||||
---
|
**`system.nix`** (NixOS — the machine):
|
||||||
*Built with ❤️ using NixOS, Hyprland, Stylix, and the Nomarchy Community.*
|
|
||||||
|
| Option | Default | Purpose |
|
||||||
|
|---|---|---|
|
||||||
|
| `nomarchy.system.plymouth.enable` | `true` | Branded boot splash, background from the theme JSON (recolors on system rebuilds) |
|
||||||
|
| `nomarchy.system.stateFile` | `null` | theme-state.json for the system-side consumers (the Plymouth tint); `lib.mkFlake` wires it for you — set it only when composing the modules by hand |
|
||||||
|
| `nomarchy.system.fileManager.enable` | `true` | Thunar GUI + gvfs/tumbler/udisks2 (the "open folder" handler) |
|
||||||
|
| `nomarchy.system.greeter.enable` | `true` | greetd/tuigreet |
|
||||||
|
| `nomarchy.system.greeter.autoLogin` | `null` | Auto-login this user into Hyprland (installer sets it on LUKS machines) |
|
||||||
|
| `nomarchy.system.audio.enable` | `true` | Pipewire stack |
|
||||||
|
| `nomarchy.system.bluetooth.enable` | `true` | Bluetooth + blueman |
|
||||||
|
| `nomarchy.system.autoTimezone.enable` | `false` | Automatic timezone (geoclue + automatic-timezoned) — the clock follows your location; toggle from System › Auto timezone (a menu enable rebuilds: it has to unset the static `time.timeZone`) |
|
||||||
|
| `nomarchy.system.snapper.enable` | `false` | Hourly/daily BTRFS timeline snapshots + `nixos-rebuild-snap` (installer enables it; no-op unless root is BTRFS) |
|
||||||
|
| `nomarchy.system.power.enable` | `true` | Active power management (see below) |
|
||||||
|
| `nomarchy.system.power.backend` | `"ppd"` | `"ppd"` (power-profiles-daemon + menu/Waybar switcher) or `"tlp"` (deeper battery tuning, no switcher) — mutually exclusive |
|
||||||
|
| `nomarchy.system.power.laptop` | `false` | Marks a laptop, gating battery-only features; the installer sets it when a battery is present |
|
||||||
|
| `nomarchy.system.power.thermal.enable` | `false` | thermald (Intel-only); the installer enables it on a GenuineIntel CPU |
|
||||||
|
| `nomarchy.system.power.batteryChargeLimit` | `null` | Stop charging at this % (e.g. `80`) where the hardware supports it; needs `power.laptop` |
|
||||||
|
| `nomarchy.hardware.intel.enable` | `false` | Intel enablement above nixos-hardware (GuC/HuC firmware via `i915.enable_guc=3` — `.guc` toggles just that; the installer unsets it on `xe`-driver GPUs); the installer sets it on an Intel CPU/GPU |
|
||||||
|
| `nomarchy.hardware.intel.computeRuntime` | `false` | Opt-in: Intel GPU compute — OpenCL/Level-Zero (`intel-compute-runtime`) + oneVPL (`vpl-gpu-rt`) |
|
||||||
|
| `nomarchy.hardware.amd.enable` | `false` | AMD enablement above nixos-hardware (amd-pstate EPP + radeonsi VA-API, each toggleable via `.pstate` / `.vaapi`); installer-set on an AMD CPU/GPU |
|
||||||
|
| `nomarchy.hardware.amd.rocm.enable` | `false` | Opt-in: ROCm HIP/OpenCL GPU compute (multi-GB); pair with `.gfxOverride` (e.g. `"11.0.0"`) for an unlisted iGPU |
|
||||||
|
| `nomarchy.hardware.fingerprint.enable` | `false` | fprintd for a detected fingerprint reader (installer-set); enroll with `fprintd-enroll` |
|
||||||
|
| `nomarchy.hardware.fingerprint.pam` | `false` | Opt-in: use the fingerprint for login + sudo (PAM) |
|
||||||
|
| `nomarchy.hardware.npu.enable` | `false` | Opt-in/experimental: load the on-die NPU driver (`amdxdna`/`intel_vpu`); userspace runtime is BYO |
|
||||||
|
| `nomarchy.hardware.latestKernel` | `false` | Opt-in: ship `linuxPackages_latest` instead of the default kernel — for very new hardware whose drivers landed recently |
|
||||||
|
| `nomarchy.hardware.camera.hideIrSensor` | `false` | Hide a dual-sensor webcam's IR node from PipeWire so apps only ever see the colour camera (the "second, dark Integrated Camera"); installer-set on a paired RGB+IR webcam. `/dev/video*` stays open, so Howdy-style face unlock still works; `.irMatch` overrides the IR-name regex |
|
||||||
|
| `nomarchy.services.tailscale.enable` | `false` | Opt-in: Tailscale mesh VPN (then `sudo tailscale up`) |
|
||||||
|
| `nomarchy.services.syncthing.enable` | `false` | Opt-in: Syncthing file sync as the login user (GUI at `127.0.0.1:8384`) |
|
||||||
|
| `nomarchy.services.podman.enable` | `false` | Opt-in: rootless Podman (`docker` aliased to it) |
|
||||||
|
| `nomarchy.services.flatpak.enable` | `false` | Opt-in: Flatpak + the Flathub remote |
|
||||||
|
| `nomarchy.services.pika.enable` | `false` | Opt-in: Pika Backup (GUI Borg backups) |
|
||||||
|
| `nomarchy.services.steam.enable` | `false` | Opt-in: Steam via `programs.steam` (32-bit libs, controller udev, Remote-Play ports) |
|
||||||
|
| `nomarchy.services.libvirt.enable` | `false` | Opt-in: libvirt/KVM + virt-manager GUI (login user added to `libvirtd`) |
|
||||||
|
| `nomarchy.services.obs.enable` | `false` | Opt-in: OBS Studio + a v4l2loopback virtual camera (selectable as a webcam in Zoom/Teams) |
|
||||||
|
| `nomarchy.services.docker.enable` | `false` | Opt-in: rootful Docker (user in `docker` group); don't enable alongside podman |
|
||||||
|
| `nomarchy.services.kdeconnect.enable` | `false` | Opt-in: KDE Connect phone integration (opens its firewall ports) |
|
||||||
|
| `nomarchy.services.gamemode.enable` | `false` | Opt-in: Feral GameMode performance daemon (`gamemoderun`) |
|
||||||
|
| `nomarchy.services.adb.enable` | `false` | Opt-in: Android adb/fastboot tools (systemd handles device udev rules) |
|
||||||
|
| `nomarchy.services.wireshark.enable` | `false` | Opt-in: Wireshark Qt GUI (user in `wireshark` group, capture without root) |
|
||||||
|
| `nomarchy.services.ollama.enable` | `false` | Opt-in: Ollama local LLM runtime on `127.0.0.1:11434` (CPU; GPU via `services.ollama.acceleration`) |
|
||||||
|
| `nomarchy.services.printing.enable` | `false` | Opt-in: CUPS + Avahi/mDNS network printer discovery |
|
||||||
|
| `nomarchy.services.openrgb.enable` | `false` | Opt-in: OpenRGB daemon for RGB peripheral/motherboard lighting |
|
||||||
|
| `nomarchy.services.restic.enable` | `false` | Opt-in: scheduled daily restic backup (set `.repository` + `.passwordFile`; backs up `.paths`, default `/home`; 7/4/6 retention; list/restore via the `restic-nomarchy` wrapper) |
|
||||||
|
|
||||||
|
Beyond the `nomarchy.*` surface, the system layer turns on the usual
|
||||||
|
desktop services with `lib.mkDefault` (override natively). Two worth
|
||||||
|
calling out: **`services.fwupd.enable`** is on by default for firmware
|
||||||
|
updates via LVFS — it only refreshes metadata, never flashes on its own,
|
||||||
|
so run `fwupdmgr update` to apply; disable with `services.fwupd.enable =
|
||||||
|
false;` on machines without real firmware (VMs/headless). And
|
||||||
|
**`services.earlyoom`** is on by default so running out of memory kills
|
||||||
|
the offending process (with a desktop notification) instead of freezing
|
||||||
|
the desktop — process-level on purpose, since a Hyprland session is one
|
||||||
|
cgroup and systemd-oomd would kill all of it (oomd is disabled
|
||||||
|
accordingly). Opt out with `services.earlyoom.enable = false;`.
|
||||||
|
|
||||||
|
## 4. How theming works
|
||||||
|
|
||||||
|
### Pure JSON ingestion
|
||||||
|
|
||||||
|
The trap with "read a mutable file from Nix" is pure evaluation: flakes
|
||||||
|
cannot read arbitrary `$HOME` paths without `--impure` (the old prototype
|
||||||
|
required it — never again). Nomarchy's convention: **the state file lives
|
||||||
|
inside the consuming flake** and is wired via
|
||||||
|
`nomarchy.stateFile = ./theme-state.json;`. Reading it is pure — it's flake
|
||||||
|
source. It must be git-tracked (`nomarchy-theme-sync` runs
|
||||||
|
`git add --intent-to-add` after every write as a safety net).
|
||||||
|
|
||||||
|
### One change = one generation
|
||||||
|
|
||||||
|
`nomarchy-theme-sync apply <theme>` merges the preset into the JSON and runs
|
||||||
|
`home-manager switch` (override the command with `$NOMARCHY_REBUILD`, or pass
|
||||||
|
`--no-switch` to only write). Everything is baked: Hyprland, Waybar, Ghostty,
|
||||||
|
btop, and — via Stylix, mapped onto base16 roles — GTK, Qt, cursors and
|
||||||
|
fonts. No runtime patching means no partial states, and `home-manager
|
||||||
|
generations` is also your theme history. Waybar even restyles in place: it
|
||||||
|
re-reads `style.css` when the symlink flips.
|
||||||
|
|
||||||
|
The **wallpaper** is the one runtime piece (awww — nixpkgs' swww — is
|
||||||
|
imperative; nothing in Nix consumes the path): applied at session start and
|
||||||
|
after every switch via a tiny activation hook, cycled instantly with
|
||||||
|
`bg next`.
|
||||||
|
|
||||||
|
### Config the menu writes (not just themes)
|
||||||
|
|
||||||
|
The in-flake-state model isn't only for appearance. **Feature toggles you flip
|
||||||
|
from the menu are written into a `settings.*` section of the *same* state file**
|
||||||
|
— git-tracked, reproducible, never stashed in `~/.local/state`. The menu is just
|
||||||
|
an ergonomic writer for your flake, so version-controlling your downstream
|
||||||
|
reproduces the machine, settings and all. Where a toggle can take effect without
|
||||||
|
a rebuild it does: the menu writes the key (`--no-switch`) and flips the running
|
||||||
|
service, which reads the *live* flake state at session start, so the choice is
|
||||||
|
both instant and survives reboot.
|
||||||
|
|
||||||
|
**Night light** is the first to use this — enable it from the menu (System ›
|
||||||
|
Night light; the first enable rebuilds to install hyprsunset), then on/off is
|
||||||
|
instant. Internally it's two keys: `settings.nightlight.installed` (sticky —
|
||||||
|
gates the unit, the first enable rebuilds) and `settings.nightlight.on` (the
|
||||||
|
instant on/off). Expect more `nomarchy.*` toggles to migrate to this pattern.
|
||||||
|
|
||||||
|
**Auto-commit (opt-in):** System › Auto-commit makes every `apply`/`set`
|
||||||
|
mutation also `git commit` theme-state.json in your flake — *only* that
|
||||||
|
file, so unrelated dirty work is never swept up — turning your settings
|
||||||
|
history into `git log`. Off by default; the toggle is instant (nothing in
|
||||||
|
Nix consumes the flag), the off-write is itself committed so history stays
|
||||||
|
consistent, and wallpaper cycling (`bg next`) is deliberately excluded —
|
||||||
|
the current wallpaper rides along with the next real commit.
|
||||||
|
|
||||||
|
### Per-theme app assets (`themes/<slug>/`)
|
||||||
|
|
||||||
|
Recoloring covers 95% of theming; the rest is one optional assets directory
|
||||||
|
per theme — a single place to look, unlike the old distro's split:
|
||||||
|
|
||||||
|
| Asset | Mechanism |
|
||||||
|
|---|---|
|
||||||
|
| `backgrounds/` | wallpapers; empty `wallpaper` in the state means "first one"; `bg next` cycles |
|
||||||
|
| `btop.theme` | baked into the generation (generated from the palette when absent) |
|
||||||
|
| `waybar.css` | **whole-swap**: replaces the generated bar style entirely (probed at eval time, self-contained) |
|
||||||
|
| `waybar.jsonc` | whole-swap for the bar *layout* (must be plain JSON) |
|
||||||
|
| `rofi.rasi` | **whole-swap**: replaces the generated launcher/menu theme entirely |
|
||||||
|
|
||||||
|
Six ported themes ship a `waybar.css` identity (catppuccin, lumon, nord,
|
||||||
|
retro-82, summer-day, summer-night). Custom user themes can live in
|
||||||
|
`$NOMARCHY_PATH/themes/` (preset lookup) and `nomarchy.themesDir` (eval-time
|
||||||
|
asset probe).
|
||||||
|
|
||||||
|
## 5. Day-to-day
|
||||||
|
|
||||||
|
```sh
|
||||||
|
nomarchy-theme-sync list # 21 presets (nord, gruvbox, rose-pine, …)
|
||||||
|
nomarchy-theme-sync apply kanagawa # whole desktop, one generation (~a switch)
|
||||||
|
nomarchy-theme-sync set ui.gapsOut 16 # tweak one knob (also a switch)
|
||||||
|
nomarchy-theme-sync bg next # cycle wallpapers — instant, no rebuild
|
||||||
|
nomarchy-theme-sync bg auto # back to the theme's default wallpaper
|
||||||
|
nomarchy-theme-sync get colors.accent
|
||||||
|
sys-update # update inputs + rebuild the system (snapshots first)
|
||||||
|
sys-rebuild # rebuild the system, current lock (no update)
|
||||||
|
home-update # rebuild just the desktop layer
|
||||||
|
nomarchy-doctor # read-only health sheet (also: menu › System › Doctor)
|
||||||
|
```
|
||||||
|
|
||||||
|
Something broke anyway? Every rebuild is a generation and (on BTRFS)
|
||||||
|
every hour is a snapshot — the undo story, from a bad theme to a
|
||||||
|
machine that won't boot, is **[docs/RECOVERY.md](docs/RECOVERY.md)**.
|
||||||
|
|
||||||
|
Keybinds: `SUPER+Return` terminal · `SUPER+D` launcher · `SUPER+T` theme
|
||||||
|
picker · `SUPER+SHIFT+T` next wallpaper · `SUPER+X` power menu ·
|
||||||
|
`SUPER+E` file manager (yazi) · `SUPER+N` notifications · `SUPER+CTRL+V`
|
||||||
|
clipboard history · `SUPER+Q`
|
||||||
|
close · `SUPER+1..9` workspaces · `Print` region screenshot.
|
||||||
|
|
||||||
|
Shell aliases (zsh, gated on `nomarchy.shell.enable`) — `alias` lists them
|
||||||
|
all; the curated set:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# navigation
|
||||||
|
.. ... .... # cd up 1 / 2 / 3 levels
|
||||||
|
|
||||||
|
# git
|
||||||
|
g gst # git · git status -sb
|
||||||
|
ga gaa # git add · git add -A
|
||||||
|
gc gcm # git commit · git commit -m
|
||||||
|
gco gsw gb # checkout · switch · branch
|
||||||
|
gd gds # diff · diff --staged
|
||||||
|
gl glg # log graph (last 20 · all branches)
|
||||||
|
gp gpl gf # push · pull · fetch --all --prune
|
||||||
|
|
||||||
|
# nix (system/home rebuilds keep their full sys-update / home-update names)
|
||||||
|
ns nr # nix shell · nix run (e.g. ns nixpkgs#ripgrep)
|
||||||
|
nfu nfc # nix flake update · check
|
||||||
|
nsearch ngc # nix search nixpkgs · nix-collect-garbage -d
|
||||||
|
|
||||||
|
# misc
|
||||||
|
path # print $PATH, one entry per line
|
||||||
|
reload # exec zsh (reload the shell)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. Extending
|
||||||
|
|
||||||
|
- **New theme:** drop a JSON into `themes/` (schema = any existing preset),
|
||||||
|
plus an optional `themes/<slug>/` assets directory.
|
||||||
|
- **New themed value:** add the key to `theme-state.json` and consume it in
|
||||||
|
the Nix modules. One place — there is no second renderer to keep in sync.
|
||||||
|
- **Importing more old-distro palettes:**
|
||||||
|
`tools/import-palettes.py <palettes-dir> themes/`.
|
||||||
|
- **New opt-in feature (convention):** when a feature is off by default and
|
||||||
|
needs the user to set `nomarchy.*` options (e.g. night light, per-device
|
||||||
|
keyboard layouts, monitor layout, power management), ship a **commented**
|
||||||
|
example of it in `templates/downstream/home.nix` or `system.nix`. New
|
||||||
|
installs then enable it by uncommenting + tweaking, rather than hunting the
|
||||||
|
docs for the option name.
|
||||||
|
- **Applications:** the starter complete-workstation set (LibreOffice, VS
|
||||||
|
Code, GIMP, Inkscape) lives in the `home.packages` list in your
|
||||||
|
`home.nix` — it's a plain package list, so curate it directly: delete a
|
||||||
|
line to slim the machine, uncomment an extra (a browser, email, full TeX
|
||||||
|
Live), or add your own. No `nomarchy.apps.*` toggles — a package list is
|
||||||
|
already its own opt-out, so the distro doesn't impose these or wrap them.
|
||||||
|
|
||||||
|
## Roadmap & known issues
|
||||||
|
|
||||||
|
The prioritized queue of what's next lives in
|
||||||
|
**[agent/BACKLOG.md](agent/BACKLOG.md)**; the detailed design/decision
|
||||||
|
records and the log of shipped fixes stay in
|
||||||
|
**[docs/ROADMAP.md](docs/ROADMAP.md)**. Development runs on an
|
||||||
|
agent-driven loop — see **[agent/LOOP.md](agent/LOOP.md)**. Kept out of
|
||||||
|
the README so this stays a focused entry point.
|
||||||
|
|||||||
286
agent/BACKLOG.md
Normal file
286
agent/BACKLOG.md
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
# Backlog — the prioritized task queue
|
||||||
|
|
||||||
|
The forward-looking half of the old docs/ROADMAP.md, reworked as a queue
|
||||||
|
agents can execute. Detailed design notes and decision records stay in
|
||||||
|
`docs/ROADMAP.md` (referenced as "ROADMAP § <item>"); this file is *what's
|
||||||
|
next, in what order*.
|
||||||
|
|
||||||
|
**Rules:**
|
||||||
|
- Agents take the topmost actionable item (see LOOP.md). Finished items
|
||||||
|
are **deleted** here — the journal + git log are the record; durable
|
||||||
|
design notes get a ✓-entry in docs/ROADMAP.md if worth keeping.
|
||||||
|
- Item numbers are **stable IDs** — never renumbered or reused. A gap in
|
||||||
|
the sequence means shipped (or dropped) work; new items take the next
|
||||||
|
free number regardless of tier.
|
||||||
|
- Tags: `[blocked:hw]` needs real hardware (see HARDWARE-QUEUE.md) ·
|
||||||
|
`[human]` needs Bernardo · `[stuck]` two failed attempts, needs help ·
|
||||||
|
`[big]` must be split before starting.
|
||||||
|
- Agents may append to **PROPOSED** and **Decisions** freely; only
|
||||||
|
Bernardo moves items *out* of PROPOSED into the tiers.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## NOW
|
||||||
|
|
||||||
|
*(empty — NEXT's top item is the queue head)*
|
||||||
|
|
||||||
|
## NEXT
|
||||||
|
|
||||||
|
### 28. Theme UI review — make every surface stunning `[big]`
|
||||||
|
(Raised by Bernardo, 2026-07-05 — placed at the head of NEXT; reorder
|
||||||
|
freely.) A thorough visual pass over the whole themed UI — Waybar (the
|
||||||
|
generated bar AND the summer whole-swaps), rofi menus, swaync,
|
||||||
|
hyprlock, the cheatsheet, ghostty/btop, GTK/Qt, boot splash, greeter —
|
||||||
|
with the bar set at *stunning*, not merely consistent (pillar 4).
|
||||||
|
Grounded in design theory, not taste alone:
|
||||||
|
- **Color:** palette-role relationships that demonstrably work
|
||||||
|
together — harmony models (analogous/complementary accents),
|
||||||
|
perceptual lightness ordering of base→surface→overlay→text (check in
|
||||||
|
OKLCH, not raw hex), accent/warn/bad distinguishable for color-blind
|
||||||
|
users; extend tools/check-theme-contrast.py to encode the adopted
|
||||||
|
rules (it currently guards legibility pairs only).
|
||||||
|
- **Typography & rhythm:** a consistent type scale across bar/menus/
|
||||||
|
OSD, spacing on the ui.gapsIn/gapsOut grid, aligned paddings (the
|
||||||
|
bar's per-module padding vs rofi rows vs swaync toasts).
|
||||||
|
- **Hierarchy:** what reads first — bar module ordering/weights, menu
|
||||||
|
title vs rows, toast title vs body; icon weights consistent with the
|
||||||
|
adjacent text.
|
||||||
|
Bernardo has offered image-expert models for designed graphics
|
||||||
|
(wallpapers, logos, glyphs, preview/branding art): an agent slice that
|
||||||
|
needs artwork must STOP and ask ("say the word") instead of shipping
|
||||||
|
programmer-art.
|
||||||
|
Slices: (a) ✓ the audit (2026-07-05, iteration #31 — findings below);
|
||||||
|
(b) palette-level fixes + the extended contrast/harmony checker —
|
||||||
|
P1s ✓ shipped 2026-07-05 (iteration #32): summer-day + flexoki-light
|
||||||
|
subtext/surface/overlay/muted retuned (flexoki to its canonical
|
||||||
|
upstream tones), miasma + kanagawa surfaces raised (kanagawa to
|
||||||
|
sumiInk4); `subtext/base ≥ 3` now GATED in check-theme-contrast.py
|
||||||
|
(all 21 pass). P2s ✓ shipped 2026-07-05 (iteration #33): 18 hex
|
||||||
|
retunes across 9 themes (OKLCH hue-preserving minimal raises;
|
||||||
|
canonical where upstream defines one — gruvbox bg4, nord #616e88,
|
||||||
|
latte overlay1, flexoki 600-series statuses for light mode) and the
|
||||||
|
four floors GATED: muted ≥ 2, text/surface ≥ 4.5, accentAlt ≥ 3,
|
||||||
|
warn ≥ 2.5 (21×7 pairings green; audit contrast findings 20 → 1 —
|
||||||
|
miasma's earthy `bad` stays as identity, good/bad floors stay
|
||||||
|
audit-only so no exemption list was needed). Remaining (b): nothing —
|
||||||
|
further palette work graduates from slices (c)/(d) findings;
|
||||||
|
(c) per-surface polish slices — capture harness ✓ shipped 2026-07-05
|
||||||
|
(iteration #34): `tools/theme-shot.nix` boots the themed desktop
|
||||||
|
headlessly at 1080p and screenshots desktop + open root menu (proven
|
||||||
|
on tokyo-night); per-surface punch items from the first full-res
|
||||||
|
review:
|
||||||
|
- ✓ **rofi keybind hints** (shipped iteration #37): dimmed pango
|
||||||
|
hints on root/Tools/System rows, generated from keybinds.nix via
|
||||||
|
the cheatsheet's prettyKeys (single source, can't drift) —
|
||||||
|
capture-verified on tokyo-night.
|
||||||
|
- **Icon weight mix `[human]`:** full-color Papirus icons in the
|
||||||
|
menus vs all-monochrome bar glyphs — pick: symbolic/monochrome
|
||||||
|
menu icons for one system, or color as the menu's identity.
|
||||||
|
A/B captured on lumon (iteration #46, side-by-side:
|
||||||
|
https://claude.ai/code/artifact/1ccd10fe-4b6f-454a-888d-e7fdf2362b03):
|
||||||
|
B (symbolic) matches the bar's weight but Papirus symbolic
|
||||||
|
coverage has holes (preferences-desktop-theme-symbolic missing —
|
||||||
|
Look & Feel lost its icon) and rofi tints symbolics a fixed dim
|
||||||
|
gray, not the theme text color — going B needs an icon audit +
|
||||||
|
recolor slice. A costs nothing. Awaiting the call; A stays until
|
||||||
|
then.
|
||||||
|
- ✓ **Bar right-cluster rhythm** (shipped iteration #36): group
|
||||||
|
margins before pulseaudio/powerprofile/battery — heads that
|
||||||
|
self-hide degrade to the uniform spacing.
|
||||||
|
- ✓ **Semantic dim** (shipped iteration #36): workspaces + dnd +
|
||||||
|
muted-volume now use `@muted` (floor-guaranteed by 28b) instead
|
||||||
|
of `alpha(@text, 0.5)` tints; the CSS comment now documents the
|
||||||
|
new invariant.
|
||||||
|
- ✓ **compositor backdrop** (shipped iteration #35): Hyprland
|
||||||
|
`misc:background_color` now the theme's base — no more black flash
|
||||||
|
behind a missing/slow wallpaper (glaring on light themes in the
|
||||||
|
summer-day capture).
|
||||||
|
- summer-day whole-swap capture reviewed (iteration #35): the
|
||||||
|
authored slate menu + island-pill bar survive the 28b retunes and
|
||||||
|
read as one coherent identity — keep. ✓ placeholder-dim nit fixed
|
||||||
|
(iteration #38: both summer rasi, bg0 at 60% alpha).
|
||||||
|
- latte capture reviewed (iteration #38): the generated menu is
|
||||||
|
fully coherent on light themes (zebra rows, retuned surface, blue
|
||||||
|
selected, dimmed hints) — the audit's "dark terminal on latte"
|
||||||
|
preview concern was a stale preview, not a defect. Backdrop
|
||||||
|
probe: misc:background_color IS applied (hyprctl getoption =
|
||||||
|
0xFFEFF1F5); captures show dark because awww's empty-state layer
|
||||||
|
paints over it in the wallpaper-less VM — on hardware the fix
|
||||||
|
covers its intended window (the pre-awww startup gap).
|
||||||
|
- ✓ Harness gap fixed (iteration #44): guest `~/.nomarchy` seeded
|
||||||
|
via tmpfiles BEFORE greetd starts the session, so the session's
|
||||||
|
own exec-once wallpaper paint runs (a post-boot testScript seed
|
||||||
|
was too late for exec-once, and a manual re-run fails without
|
||||||
|
WAYLAND_DISPLAY — awww's client socket is display-named).
|
||||||
|
Wallpaper-complete summer-night capture reviewed: lakeside night
|
||||||
|
scene + cream inverted bar + menu-over-scene all cohere; the
|
||||||
|
placeholder dim (#2d353b99) renders. Note: summer-night's cream
|
||||||
|
bar/menu on dark backdrop is the authored inverted design (fg as
|
||||||
|
surface), not a rendering bug.
|
||||||
|
- ✓ Identity-theme capture + stub purge (iteration #45): the lumon
|
||||||
|
capture exposed that catppuccin/lumon/nord/retro-82 shipped stub
|
||||||
|
waybar.css files (2–14 lines, from the f211ef0 rewrite import) —
|
||||||
|
and a theme waybar.css whole-swaps the ENTIRE generated
|
||||||
|
stylesheet, so those four ran an unstyled default bar. Stubs
|
||||||
|
deleted; re-capture confirms lumon falls back to the generated
|
||||||
|
styled bar (workspace pill, padded right cluster). Their full
|
||||||
|
~110-line rofi.rasi designs kept. Real whole-swaps remain only
|
||||||
|
summer-day/night (+ nord/retro-82 lost nothing: the stubs had no
|
||||||
|
design).
|
||||||
|
(d) the whole-swap themes brought to the same bar (module parity
|
||||||
|
verified textually 2026-07-05: whole-swaps carry every functional
|
||||||
|
module; omitting cpu/memory is identity). Visual work is
|
||||||
|
V3-bound by nature — screenshots are the review artifact, hardware
|
||||||
|
confirms.
|
||||||
|
|
||||||
|
**Audit findings (slice a — `tools/audit-theme-design.py` over all 21
|
||||||
|
palettes + visual pass over previews; identity-aware curation):**
|
||||||
|
- ~~P1 · invisible-secondary-text palettes~~ ✓ fixed iteration #32
|
||||||
|
(summer-day subtext #6e828a, surface #efe7d0; flexoki-light to
|
||||||
|
canonical Flexoki: surface #E6E4D9, overlay #B7B5AC, subtext
|
||||||
|
#6F6E69, muted #878580). Gate added.
|
||||||
|
- ~~P1 · inverted bg stacks~~ ✓ fixed iteration #32 (miasma surface
|
||||||
|
#2e2e2e; kanagawa surface #2a2a37 = upstream sumiInk4). Note
|
||||||
|
learned: in this palette model `overlay` is a MID-TONE
|
||||||
|
(borders/dim, catppuccin semantics), not a third bg tier — the
|
||||||
|
dark-theme overlay==muted pattern is intentional.
|
||||||
|
- **P2 · muted floor:** muted-on-base < 2.0 on gruvbox (1.27),
|
||||||
|
everforest (1.55), lumon (1.68), nord (1.69), white (1.82), latte
|
||||||
|
(1.91), retro-82 (1.93) — dimmed workspaces/inactive items barely
|
||||||
|
render (visible on the lumon preview). Adopt ≥ 2.0 and retune.
|
||||||
|
- **P2 · warn barely reads:** warn-on-base ≈ 2.0–2.3 on rose-pine,
|
||||||
|
summer-day, latte, flexoki-light — this is the bar's 25%-battery
|
||||||
|
color. Floor 2.5 (or see the color-only rule below).
|
||||||
|
- **P2 · text-on-surface < 4.5:** ristretto 3.88, latte 4.39 (menus
|
||||||
|
and chips draw text on surface).
|
||||||
|
- **P3 · accentAlt-on-base < 3:** latte 2.34, summer-day 2.83.
|
||||||
|
- **Design rule (systemic, beats palette surgery): status is never
|
||||||
|
color-only.** good/warn collapse under protanopia on ~half the
|
||||||
|
themes and good/bad under deuteranopia (59 pair-findings) — that's
|
||||||
|
inherent to red/green/yellow, not fixable per-palette. Battery and
|
||||||
|
recording already carry glyph changes; sweep the remaining
|
||||||
|
color-only indicators (updates count, notification dot, VPN shield
|
||||||
|
states) for shape/glyph redundancy.
|
||||||
|
- **Identity exemptions, made explicit:** vantablack + white
|
||||||
|
(deliberately hueless statuses), lumon (all-blue), hackerman
|
||||||
|
(matrix green statuses), matte-black/retro-82 (off-family hues) are
|
||||||
|
identity, not defects — slice (b)'s checker gets a per-theme
|
||||||
|
exemption list instead of silently lowered floors.
|
||||||
|
- **ANSI / greeter notes:** latte, rose-pine and white ship
|
||||||
|
`ansi[0]` LIGHTER than `ansi[15]` — decide the light-theme ANSI
|
||||||
|
convention (terminals conventionally keep black dark) before the
|
||||||
|
greeter/tty theming ships to them. tokyo-night/summer-night
|
||||||
|
`ansi[7]-on-ansi[0]` ≈ 2.8–3.0 = the greeter's muted text; fine as
|
||||||
|
muted, watch on hardware.
|
||||||
|
- **Visual pass (480×270 previews — too small for type/spacing; the
|
||||||
|
deep per-surface pass needs 1080p captures):** the generated bar's
|
||||||
|
right cluster runs ~9 modules with uniform spacing — no grouping
|
||||||
|
rhythm (consider micro-gaps between tray/net · stats · toggles ·
|
||||||
|
battery/notify groups); latte's preview shows a DARK terminal on
|
||||||
|
the light desktop — verify ghostty consumes the latte palette (or
|
||||||
|
the preview is stale); summer-day's island-pill whole-swap bar and
|
||||||
|
lumon's globe identity are strong — preserve through any polish.
|
||||||
|
|
||||||
|
### 14. Automated lock bumps — confirm the first real run
|
||||||
|
Slices b+c shipped 2026-07-05 (`.gitea/workflows/bump.yml`): weekly
|
||||||
|
schedule (Mon 05:17 UTC) + `workflow_dispatch` as the security
|
||||||
|
fast-lane; `nix flake update` → eval gate → pathspec-limited lock
|
||||||
|
commit pushed to `main` on green (that push triggers check.yml as the
|
||||||
|
second net). Update/commit/push logic simulated locally end-to-end in
|
||||||
|
a scratch clone, incl. a real update; today's bumped lock evals green.
|
||||||
|
Remaining (not confirmable from a session): the first scheduled or
|
||||||
|
dispatched run must land — watch that the runner picks up the cron and
|
||||||
|
that the Actions token can push. Then delete this item. Item 20's KVM
|
||||||
|
runner later upgrades the gate from eval-only to the VM suite.
|
||||||
|
|
||||||
|
### 20. KVM runner → VM suite in CI `[human]`
|
||||||
|
The remaining stretch of the CI item — checks-on-push is live and
|
||||||
|
**green** (run #58; runner = gitea/act_runner docker, eval tier).
|
||||||
|
Register a second runner on a host with `/dev/kvm` + nix (host-mode
|
||||||
|
label `nix-kvm`), then an agent uncomments the workflow's `vm-checks`
|
||||||
|
job: the `checks.*` VM suite + real toplevel/HM builds on every push
|
||||||
|
(also upgrades item 14's bump gate from eval-only to the full suite).
|
||||||
|
|
||||||
|
### 18. "nomarchy" control center + first-boot welcome `[big]`
|
||||||
|
ROADMAP § control center. A single front-end over the common toggles on
|
||||||
|
the same `nomarchy-theme-sync` surface, + a first-boot guided
|
||||||
|
"pick your theme / essentials" flow. Needs a design pass (TUI vs GUI)
|
||||||
|
→ write options into Decisions before implementing. Note: items 9–11
|
||||||
|
(rollback menu, doctor, validation) are natural panels of it — design
|
||||||
|
them as composable commands, not dead ends.
|
||||||
|
|
||||||
|
## LATER
|
||||||
|
|
||||||
|
- **Wallpapers artifact split** (ROADMAP § Faster switches — decided,
|
||||||
|
deferred): pinned `Nomarchy-wallpapers` input so a state write stops
|
||||||
|
re-copying 86 MB. Follow-on: pre-built theme variants if switches are
|
||||||
|
still slow after.
|
||||||
|
- **Installer round 2** (ROADMAP § Installer): multi-disk BTRFS RAID,
|
||||||
|
impermanence, BIOS/legacy boot.
|
||||||
|
- **Boot-from-snapshot**: a systemd-boot equivalent of grub-btrfs.
|
||||||
|
- **Night-light geo mode**: lat/long auto sunset/sunrise (means wlsunset).
|
||||||
|
- **Per-theme icon overrides** / more icon packs (ROADMAP § Icon themes).
|
||||||
|
- **MIPI/IPU software-ISP camera** support (no-UVC machines).
|
||||||
|
- **VPN exit-node richer display** (country/city) (optional).
|
||||||
|
- **NixOS release bump → v2** `[human]`: deliberate, hand-edited, never
|
||||||
|
automated; the previous attempt was discarded (2026-06-22) over a
|
||||||
|
Hyprland OOM blocker — see MEMORY.md before retrying (NOW#3 should
|
||||||
|
also soften that blocker class).
|
||||||
|
|
||||||
|
## PROPOSED (agent suggestions — await human triage)
|
||||||
|
|
||||||
|
*Agents: append here with a one-paragraph pitch (what/why/cost). Do not
|
||||||
|
implement. Bernardo moves accepted items into a tier.*
|
||||||
|
|
||||||
|
- **Menu parity for downstream-flake options** (raised by Bernardo,
|
||||||
|
2026-07-04, from the hardware sweep): anything the docs or the
|
||||||
|
hardware queue ask a user to *hand-edit into the downstream flake*
|
||||||
|
(`keyboard.layout` multi-layout, `power.batteryChargeLimit`,
|
||||||
|
`updates.enable`, `services.printing`, …) should have a menu toggle
|
||||||
|
instead — the in-flake-state philosophy already gives the menu a
|
||||||
|
write-into-the-flake path, and night-light / auto-timezone /
|
||||||
|
auto-commit prove the pattern (incl. rebuild-on-first-enable).
|
||||||
|
Pitch: (a) an audit listing every user-facing `nomarchy.*` option vs
|
||||||
|
its menu surface; (b) menu writers for the gaps, respecting the
|
||||||
|
toggle-vs-package discipline (bare template packages stay hand-edits)
|
||||||
|
and menu-placement convention (right submenu, root stays short).
|
||||||
|
Values beyond booleans (layout lists, charge thresholds) need a small
|
||||||
|
input UI per option. Cost: audit is one iteration; the writers a few
|
||||||
|
more, sliceable per option.
|
||||||
|
|
||||||
|
- **Portal/Flatpak camera picker still lists the internal IR sensor**
|
||||||
|
(ROADMAP § Webcam follow-up). The shipped IR-hide is a *WirePlumber
|
||||||
|
v4l2* rule, but Flatpak/portal apps consume cameras via the
|
||||||
|
**libcamera** path, where both sensors remain visible — a Flatpak
|
||||||
|
Zoom user can still pick the black IR "camera". Options, roughly
|
||||||
|
ascending cost: (a) do nothing — document it (portal camera support
|
||||||
|
is still rare in practice); (b) a WirePlumber *libcamera* monitor
|
||||||
|
rule disabling GREY-only nodes — needs verifying that libcamera
|
||||||
|
monitor rules can match early enough (the v4l2 investigation found
|
||||||
|
only `device.api` binds pre-rule, which is why surgical scoping
|
||||||
|
failed before — same wall likely applies); (c) a libcamera
|
||||||
|
configuration/udev quirk hiding the IR sensor at the libcamera layer
|
||||||
|
itself. Cost: (b)/(c) need a T14s-style RGB+IR machine to verify →
|
||||||
|
pairs with a hardware-queue session. Recommend (a) now, (b)
|
||||||
|
investigated when the T14s is next available.
|
||||||
|
|
||||||
|
## Decisions `[human]`
|
||||||
|
|
||||||
|
Open calls only Bernardo can make; agents add options/evidence but never
|
||||||
|
decide.
|
||||||
|
|
||||||
|
- **Formatter adoption:** repo deliberately has none; `nixfmt-rfc-style`
|
||||||
|
would flatten the aligned hand-formatting of ~33 files. Adopt or
|
||||||
|
declare never?
|
||||||
|
- **Docs site vs Markdown-in-repo** (from the docs-review item).
|
||||||
|
- **Control center form factor:** TUI (gum/ratatui-style) vs GUI vs
|
||||||
|
"the rofi menu *is* the control center, just add a first-boot flow".
|
||||||
|
- **zram swap:** faster under pressure and pairs with NOW#3, but it
|
||||||
|
interacts with the hibernation-swapfile story (resume device/priority
|
||||||
|
ordering) — adopt, adopt-with-hibernation-guard, or skip?
|
||||||
|
- **Default browser:** the template comments Firefox out. The shipped
|
||||||
|
mime defaults (item 8, done) point `text/html`/http(s) at
|
||||||
|
`firefox.desktop` as *inert* entries — they activate the moment
|
||||||
|
Firefox is installed and are skipped otherwise, so the remaining call
|
||||||
|
is only: ship a browser active in the suite, or stay
|
||||||
|
browserless-by-default?
|
||||||
70
agent/CONVENTIONS.md
Normal file
70
agent/CONVENTIONS.md
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
# Conventions — how Nomarchy code is written
|
||||||
|
|
||||||
|
The standing rules an agent must follow while coding. GOALS.md says what
|
||||||
|
we're building; this says how. Details/rationale live in docs/ROADMAP.md's
|
||||||
|
decision records and the README.
|
||||||
|
|
||||||
|
## Repo layout (the rule of thumb)
|
||||||
|
`modules/` is the distro (reusable, no machine specifics) · `hosts/` is a
|
||||||
|
machine · `themes/` is data · `pkgs/` is code · `tools/` is maintainer-only
|
||||||
|
· `agent/` is loop state. If a new file doesn't obviously belong to one of
|
||||||
|
those, it probably shouldn't exist.
|
||||||
|
|
||||||
|
## Nix style
|
||||||
|
- **No formatter.** Files use deliberate aligned hand-formatting — match
|
||||||
|
the surrounding style exactly; never reflow a file you're only touching
|
||||||
|
a line of.
|
||||||
|
- Distro defaults use `lib.mkDefault` so a plain downstream assignment
|
||||||
|
wins; bind/exec lists concatenate. Behaviour options overridable,
|
||||||
|
appearance flows from the state JSON.
|
||||||
|
- Options live in the existing surfaces: `nomarchy.system.*` /
|
||||||
|
`nomarchy.hardware.*` / `nomarchy.services.*` (NixOS, `system.nix`),
|
||||||
|
everything else `nomarchy.*` (HM, `home.nix`). Update the README tables
|
||||||
|
when the surface changes.
|
||||||
|
|
||||||
|
## Feature design
|
||||||
|
- **In-flake state:** any user-settable config gets a menu writer that
|
||||||
|
lands it in `theme-state.json` (`settings.*`), git-tracked. No
|
||||||
|
`~/.local/state`, no side files. Instant-effect where possible
|
||||||
|
(`--no-switch` + flip the service; the service reads the *live* working
|
||||||
|
tree at start — the night-light `ExecCondition` pattern). Rebuild-baked
|
||||||
|
values graduate via `mkDefault` reads of the settings key.
|
||||||
|
- **Toggle vs package:** a `nomarchy.*` toggle only when there's real
|
||||||
|
config behind it (units, groups, udev, firewall). A bare package goes
|
||||||
|
in the downstream template's `home.packages` — opt-out is deleting the
|
||||||
|
line.
|
||||||
|
- **Opt-in features** ship a commented example in
|
||||||
|
`templates/downstream/home.nix` or `system.nix`.
|
||||||
|
- **Menu:** new entries go in the right submenu (Tools › / System ›; root
|
||||||
|
stays six entries), end lists with the shared `↩ Back`, self-gate on
|
||||||
|
the feature's availability, and add the direct
|
||||||
|
`SUPER+CTRL+<mnemonic>` bind in `keybinds.nix` (single source — it
|
||||||
|
feeds both Hyprland and the SUPER+? cheatsheet).
|
||||||
|
- **Waybar:** new indicators self-gate (hidden when irrelevant), use
|
||||||
|
named `writeShellScriptBin`s on PATH (so static configs can exec them
|
||||||
|
by bare name), and are added to **both** the generated `waybar.nix`
|
||||||
|
config **and** the summer-day/night `waybar.jsonc` whole-swaps (the
|
||||||
|
parity rule).
|
||||||
|
- **Theming:** every new visual surface consumes the palette from the
|
||||||
|
state JSON. There is no second renderer to keep in sync — add the key
|
||||||
|
to the JSON, consume it in the module.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
- docs/TESTING.md is canonical; LOOP.md's ladder (V0–V3) sets the
|
||||||
|
required tier. Cheap first: `nix flake check --no-build`, `bash -n`,
|
||||||
|
`py_compile`.
|
||||||
|
- Prefer a permanent `checks.*` runNixOSTest over a one-off manual poke;
|
||||||
|
reusable recipes (headless Hyprland with software GL, QMP screenshots,
|
||||||
|
udev-event fakes) are indexed in MEMORY.md and demonstrated by the
|
||||||
|
existing checks (`distro-id`, `hardware-toggles`,
|
||||||
|
`battery-charge-limit`).
|
||||||
|
- The honesty rule: report exactly what you verified and at which tier.
|
||||||
|
|
||||||
|
## Git
|
||||||
|
- `main` is development (direct commits, pushed); `v1` is the release
|
||||||
|
pointer — **human-only, fast-forward-only, never touched by agents**.
|
||||||
|
- Commit style: `feat|fix|test|docs|chore(scope): summary`, body with
|
||||||
|
what/why + verification tier + what remains. Bookkeeping (`agent/`
|
||||||
|
updates) rides in the same commit as the change.
|
||||||
|
- `flake.lock` moves only when the task *is* a lock bump, and only within
|
||||||
|
the pinned release branches.
|
||||||
58
agent/GOALS.md
Normal file
58
agent/GOALS.md
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# Goals — what "done" looks like for Nomarchy
|
||||||
|
|
||||||
|
The north star every loop iteration serves. When two options conflict,
|
||||||
|
the earlier pillar wins.
|
||||||
|
|
||||||
|
## The four pillars (in priority order)
|
||||||
|
|
||||||
|
1. **Rock-stable.** A workstation you never fight. Everything is a NixOS/HM
|
||||||
|
generation — atomic, rollbackable, never partial. `nix flake check` is
|
||||||
|
green at every commit on `main`. Regressions are caught by the VM-test
|
||||||
|
suite (`checks.*`), not by users. `v1` only ever advances after human
|
||||||
|
on-hardware QA.
|
||||||
|
2. **Reproducible, with zero hidden state.** The downstream flake checkout
|
||||||
|
*is* the machine. All user-settable config is menu-writable into the
|
||||||
|
git-tracked state file (`theme-state.json` `settings.*`) — never
|
||||||
|
`~/.local/state`, never `~/.config` side files. Re-cloning your flake
|
||||||
|
reproduces the machine, settings and all.
|
||||||
|
3. **Effortless to configure.** The user never has to learn Nix. Every
|
||||||
|
common knob is reachable from `nomarchy-menu` (SUPER+M); the menu is an
|
||||||
|
ergonomic writer for the flake. Where a toggle can take effect without a
|
||||||
|
rebuild, it must (`--no-switch` + flip the running service).
|
||||||
|
4. **Beautiful.** One JSON themes the entire desktop coherently — Hyprland,
|
||||||
|
Waybar, Ghostty, btop, rofi, GTK/Qt, boot splash, greeter. Every new
|
||||||
|
surface follows the palette. Informative, self-gating Waybar modules
|
||||||
|
(they hide when irrelevant). No unthemed corner survives contact with
|
||||||
|
the theme switcher.
|
||||||
|
|
||||||
|
## Quality bars (non-negotiable)
|
||||||
|
|
||||||
|
- **The honesty rule** (docs/TESTING.md): for anything visual, "the Nix
|
||||||
|
evaluates" is not "it renders". Verify at the highest tier you can reach
|
||||||
|
(see LOOP.md's verification ladder) and *state the tier you reached*.
|
||||||
|
Never claim a check you didn't run.
|
||||||
|
- **Parity rule:** any module added to the generated Waybar config must
|
||||||
|
also be added to the summer-day/night `waybar.jsonc` whole-swaps.
|
||||||
|
- **Menu placement:** new menu entries go in the right category submenu
|
||||||
|
(Tools › / System ›), with a direct `SUPER+CTRL+<mnemonic>` bind and
|
||||||
|
self-gating where applicable. The root picker stays six entries.
|
||||||
|
- **Opt-in features** ship a commented example in
|
||||||
|
`templates/downstream/{home,system}.nix`.
|
||||||
|
- **Option surface discipline:** a toggle exists only when there is real
|
||||||
|
config behind it. Bare package installs go in the template's
|
||||||
|
`home.packages` (opt-out = delete the line), never a `nomarchy.apps.*`.
|
||||||
|
|
||||||
|
## Non-goals (do not drift into these)
|
||||||
|
|
||||||
|
- **No binary cache.** Compile-from-source is a deliberate values call;
|
||||||
|
automation targets the config/lock channel, not artifact distribution.
|
||||||
|
- **No second theming pipeline.** The dispatcher owns menu structure; the
|
||||||
|
renderer (rofi) stays swappable. No GTK4 launcher.
|
||||||
|
- **No nixpkgs major bump on `main`.** Lock updates stay within the pinned
|
||||||
|
release branch; a release jump is a deliberate `v2`, hand-edited by the
|
||||||
|
maintainer (the last attempt was discarded over a Hyprland OOM — see
|
||||||
|
agent/MEMORY.md).
|
||||||
|
- **No repo-wide reformat.** The `.nix` files use deliberate aligned
|
||||||
|
hand-formatting; adopting a formatter is an open maintainer decision
|
||||||
|
(BACKLOG.md § Decisions), not a cleanup.
|
||||||
|
- **No multi-DE.** Hyprland is the desktop.
|
||||||
249
agent/HARDWARE-QUEUE.md
Normal file
249
agent/HARDWARE-QUEUE.md
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
# Hardware queue — V3 checks only a human can run
|
||||||
|
|
||||||
|
Everything shipped at V1/V2 whose final verification needs real hardware.
|
||||||
|
Agents **append** (newest at the bottom of a section) with exact steps;
|
||||||
|
Bernardo runs them and either checks off (`[x]` + date + verdict) or files
|
||||||
|
the failure as a NOW bug in BACKLOG.md. Machines: the **AMD dev box**
|
||||||
|
(Ryzen AI laptop: AMD + fingerprint + NPU), the **Latitude 5410** (Intel
|
||||||
|
QA machine), the **T14s** (webcam case).
|
||||||
|
|
||||||
|
## Any machine (dev box is fine)
|
||||||
|
- [ ] **Battery charge limit re-apply on unplug** — `sudo nixos-rebuild
|
||||||
|
switch` with `power.batteryChargeLimit = 80`, physically unplug/replug
|
||||||
|
AC, confirm `charge_control_end_threshold` re-reads 80. (udev trigger
|
||||||
|
already VM-verified.)
|
||||||
|
- [ ] **SSH_AUTH_SOCK for GUI clients** — after relogin, launch a GUI git
|
||||||
|
client (or `rofi`-launched terminal-less app) and confirm it reaches
|
||||||
|
gpg-agent's SSH socket without an interactive shell parent.
|
||||||
|
- [x] **Night-light full cycle** — first menu enable rebuilds + hyprsunset
|
||||||
|
starts; later toggles are instant (no rebuild); an *off* survives
|
||||||
|
reboot (ExecCondition); stopping hyprsunset restores gamma.
|
||||||
|
— 2026-07-04 Bernardo: PASS enable/disable on hardware
|
||||||
|
(off-survives-reboot + gamma-restore not explicitly checked).
|
||||||
|
- [x] **Auto-timezone** — enable from the menu; confirm geoclue finds the
|
||||||
|
zone, `/etc/localtime` updates, and the Waybar clock refreshes
|
||||||
|
(SIGUSR2 watcher) — also after a manual `timedatectl set-timezone`.
|
||||||
|
— 2026-07-04 Bernardo: PASS — enabled from the menu, `timedatectl`
|
||||||
|
shows Europe/London (the manual set-timezone re-trigger wasn't
|
||||||
|
exercised).
|
||||||
|
- [ ] **Keyboard layout cycle bind** — with a comma layout (e.g.
|
||||||
|
`nomarchy.keyboard.layout = "us,de"`), SUPER+SHIFT+K cycles the
|
||||||
|
focused keyboard's layout, the Waybar `` indicator follows, and
|
||||||
|
the row shows in the SUPER+? cheatsheet. — 2026-07-04 attempt:
|
||||||
|
no comma layout was configured, so the bind wasn't rendered (the
|
||||||
|
gate working as designed, not a failure) — retest after setting a
|
||||||
|
comma layout + rebuild + relogin. The SUPER+? no-op found en
|
||||||
|
route IS a real bug → BACKLOG item 26 (fix shipped — see the
|
||||||
|
dedicated SUPER+? entry below).
|
||||||
|
- [ ] **SUPER+? opens the cheatsheet** (item 26 fix) — after
|
||||||
|
`home-update` + relogin (or `hyprctl reload`), SUPER+? must open
|
||||||
|
the keybindings cheatsheet, whose row still reads `SUPER + ?`
|
||||||
|
(not `SUPER + SHIFT + ?`).
|
||||||
|
- [ ] **swaync readable on summer-day** (item 25 fix) — on summer-day
|
||||||
|
after `home-update`: `notify-send "title" "body text"` shows
|
||||||
|
readable body text; open the control centre (SUPER+N), hover a
|
||||||
|
notification row and check the Clear button — all text legible
|
||||||
|
(body/buttons now @text on tinted chips, not subtext/surface).
|
||||||
|
- [ ] **Bar + rofi legible on flexoki-light** (item 27 fix) — switch to
|
||||||
|
flexoki-light: every Waybar module readable (window title, tray
|
||||||
|
row, dimmed inactive workspaces / muted volume visible-but-dim),
|
||||||
|
rofi inputbar/alternate rows show text. Spot-check one dark theme
|
||||||
|
(e.g. tokyo-night) for no visual regression in the same spots.
|
||||||
|
- [ ] **Stub-bar themes got the generated bar** (item 28, 90a5104) —
|
||||||
|
switch to catppuccin, lumon, nord and retro-82: each now shows
|
||||||
|
the generated styled bar in its own palette (workspace pill,
|
||||||
|
padded right cluster) instead of the old raw default Waybar.
|
||||||
|
Their rofi menus should look unchanged.
|
||||||
|
- [ ] **Back-audit spot-check** (item 24) — the keybinds cheatsheet
|
||||||
|
(SUPER+? / root menu › Keybindings) now ends in ↩ Back and
|
||||||
|
returns to the root picker; spot a couple of submenus (Display,
|
||||||
|
VPN › Tailscale) still Back correctly after the audit pass.
|
||||||
|
- [ ] **Network menu has no blank rows** (item 22 fix, needs Wi-Fi) —
|
||||||
|
after `home-update`, open Tools › Network: no empty separator
|
||||||
|
rows between the ethernet/wifi/VPN sections (compact = True).
|
||||||
|
KNOWN RESIDUAL: if exactly one nameless wifi row remains showing
|
||||||
|
only security+bars, that's a hidden-SSID AP — config can't filter
|
||||||
|
it; report it and the follow-up is a small source patch skipping
|
||||||
|
empty-name APs in create_ap_list.
|
||||||
|
- [ ] **Keyboard hotplug picker (re-verify after in-flake graduation)** —
|
||||||
|
plug an external keyboard post-login, pick a layout in rofi, confirm
|
||||||
|
it applies per-device only, persists in `settings.keyboard.devices`,
|
||||||
|
and graduates into a `device{}` block on the next rebuild.
|
||||||
|
- [x] **Snapshots restore/rollback** — ⚠ PRECONDITION: update to main ≥
|
||||||
|
a47aa3a and RELOGIN first (the polkit agent starts with the session).
|
||||||
|
Bernardo's 2026-07-04 Latitude findings 5/6 ("btrfs-assistant still
|
||||||
|
crashes", "menu snapshots shows nothing") match the PRE-fix behavior
|
||||||
|
exactly: no agent → pkexec fails silently (= menu does nothing), and
|
||||||
|
a direct unprivileged run crashes (= the libbtrfsutil bug). If either
|
||||||
|
still reproduces ON THE FIXED BUILD after relogin, reopen BACKLOG
|
||||||
|
item 4 as [stuck]. Then: `nomarchy-menu snapshot` now opens
|
||||||
|
the **btrfs-assistant GUI**: a *themed* polkit prompt must appear
|
||||||
|
(hyprpolkitagent — first on-hardware outing) and the GUI must open
|
||||||
|
as root. Also exercise the fzf fallback in a terminal
|
||||||
|
(`sudo nomarchy-snapshots`): browse/diff, restore a file
|
||||||
|
(`undochange`), and a root-config rollback behind the typed-`yes`
|
||||||
|
gate. Bonus check: any other pkexec flow now prompts instead of
|
||||||
|
silently failing. — 2026-07-04 Bernardo: PASS on the fixed build —
|
||||||
|
polkit prompt appears, GUI opens as root, fzf fallback works.
|
||||||
|
Restore/rollback not exercised → residual item below.
|
||||||
|
- [ ] **Snapshots restore + rollback exercise** (residual from the item
|
||||||
|
above — the GUI/polkit half passed 2026-07-04): in
|
||||||
|
`sudo nomarchy-snapshots`, restore a single file (`undochange`)
|
||||||
|
and walk a root-config rollback up to (or through) the
|
||||||
|
typed-`yes` gate.
|
||||||
|
- [ ] **Caffeine toggle (item 13 slice)** — click in the bar → turns
|
||||||
|
(warm tint on the generated bar) and hypridle must NOT lock /
|
||||||
|
blank while it's on (wait past the 5-min lock); click again
|
||||||
|
releases. Also present on both summer bars now.
|
||||||
|
- [ ] **Screen recording (item 12)** — Tools › Capture: Record region
|
||||||
|
(slurp) and Record screen produce a playable .mp4 in
|
||||||
|
~/Videos/Recordings; the red ⏺ REC appears in the bar instantly
|
||||||
|
and CLICKING IT stops + notifies the path; the + audio variants
|
||||||
|
carry sound. While recording, the Capture menu offers only
|
||||||
|
"■ Stop recording". On the AMD box wl-screenrec (VAAPI) should
|
||||||
|
do the work; if it dies at start the wf-recorder fallback kicks
|
||||||
|
in silently — check the notification says which. Summer bars
|
||||||
|
have the same ⏺ (parity).
|
||||||
|
- [ ] **Doctor (item 10)** — menu › System › Doctor opens the sheet in
|
||||||
|
a terminal; `nomarchy-doctor` over SSH shows the same minus user
|
||||||
|
units. On a healthy machine everything is ✔/– (dev-box run
|
||||||
|
2026-07-04 correctly flagged a genuinely failed user unit).
|
||||||
|
- [ ] **Rollback menu (item 9b)** — after a couple of theme changes,
|
||||||
|
menu › System › Rollback: recent desktop generations listed
|
||||||
|
(newest marked current); picking an older one opens a terminal,
|
||||||
|
activates it, and the theme visibly reverts; picking the newer one
|
||||||
|
again rolls forward. The two System rows: Snapshots opens the
|
||||||
|
snapshot flow, "boot an older generation (how)" fires an
|
||||||
|
instruction notification.
|
||||||
|
- [ ] **Open-a-file smoke (viewers + mime defaults, item 8)** — after
|
||||||
|
`home-update`: from yazi/Thunar, open a PDF (→ zathura, themed to
|
||||||
|
the palette), an image (→ imv, NOT GIMP), a video (→ mpv);
|
||||||
|
`xdg-open .` on a directory → Thunar. With no browser installed,
|
||||||
|
clicking a link must still fall through to *something sane* (the
|
||||||
|
firefox.desktop entries are inert); if you've uncommented a
|
||||||
|
browser, links go there.
|
||||||
|
- [ ] **Update awareness** — with `nomarchy.updates.enable`, let the timer
|
||||||
|
fire (or start the unit): indicator appears only when inputs are
|
||||||
|
behind, notification only on count growth, click opens the upgrade
|
||||||
|
flow.
|
||||||
|
- [ ] **VPN menu live paths** — import a real WireGuard `.conf` and an
|
||||||
|
`.ovpn` via System → VPN, toggle up/down (● / ○ state), and the
|
||||||
|
Tailscale block: up/down + exit-node without sudo (operator grant).
|
||||||
|
- [ ] **Printer menu** — with `nomarchy.services.printing`, System →
|
||||||
|
Printers opens system-config-printer; add a printer, test page.
|
||||||
|
- [ ] **GRUB UEFI ISO theme render** — boot the ISO on UEFI hardware:
|
||||||
|
composed splash background, palette menu in the lower third, accent
|
||||||
|
timeout bar.
|
||||||
|
- [ ] **Visual theme pass** — live ISO: all six identity themes (bars) +
|
||||||
|
the four authored rofi `.rasi` (nord/retro-82/lumon/kanagawa) look
|
||||||
|
right, not just parse.
|
||||||
|
- [x] **Auto-commit on a real machine** — System › Auto-commit toggles on
|
||||||
|
(row shows state, notification fires); a theme apply from SUPER+T then
|
||||||
|
shows a `nomarchy: apply theme …` commit in `~/.nomarchy` (`git log`);
|
||||||
|
unrelated dirty files in the checkout stay uncommitted; toggle off is
|
||||||
|
itself the last commit. Also: the "Auto timezone (on/off)" row label
|
||||||
|
now reflects the real state (the `= true` comparison fix).
|
||||||
|
— 2026-07-04 Bernardo: PASS — theme changes committed and the
|
||||||
|
toggle self-committed.
|
||||||
|
- [ ] **Display profiles, slice a (item 15)** — declare two
|
||||||
|
`nomarchy.displayProfiles` (e.g. docked disables eDP-1 + arranges
|
||||||
|
the externals; undocked re-enables it), `home-update`, then:
|
||||||
|
System › Display › Profiles lists them (● marks active); applying
|
||||||
|
is instant (no rebuild) and survives a relogin (the baked
|
||||||
|
overlay); "Base layout" restores; a menu resolution pick made
|
||||||
|
earlier must NOT re-enable a profile-disabled panel after the
|
||||||
|
next rebuild.
|
||||||
|
- [ ] **Display profiles workspace pins, slice c (item 15)** — give the
|
||||||
|
docked profile `workspaces = { "1" = "<ext>"; "9" = "eDP-1"; }`:
|
||||||
|
applying the profile moves open workspaces 1/9 to those outputs
|
||||||
|
immediately, new visits land there too, and the pins survive a
|
||||||
|
relogin (baked `workspace` rules). Switching to a profile without
|
||||||
|
pins leaves workspaces where they are (stale session pins are
|
||||||
|
expected until reload/rebuild — noted in the applier).
|
||||||
|
- [ ] **Display profiles auto-switch, slice b (item 15)** — same setup,
|
||||||
|
then menu › Profiles › Auto-switch on: plugging the dock/monitor
|
||||||
|
applies the matching profile within ~3s (toast names it);
|
||||||
|
unplugging switches back; Auto-switch off stops that; with two
|
||||||
|
profiles naming the same outputs, no flapping (ties do nothing).
|
||||||
|
- [ ] **P2 retunes eyeball (item 28b)** — spot-check on top of the P1
|
||||||
|
entry below: gruvbox/nord/lumon/everforest/retro-82/white dimmed
|
||||||
|
text (inactive workspaces, muted volume) now visible-but-dim;
|
||||||
|
latte + rose-pine(dawn) + summer-day warn/battery tint reads on
|
||||||
|
the light bases; flexoki-light statuses are the deeper canonical
|
||||||
|
600s; latte selected-row/alt-accent pink darker. Anything that
|
||||||
|
lost its "dim" feel → reopen 28b.
|
||||||
|
- [ ] **Retuned palettes eyeball (item 28b P1)** — switch through
|
||||||
|
summer-day, flexoki-light, kanagawa, miasma: chips/menus/toasts
|
||||||
|
now draw on a *raised* surface (summer-day's was slate-on-cream,
|
||||||
|
kanagawa's near-black, miasma's pure black), secondary text
|
||||||
|
(tooltips, fastfetch labels) is visible on summer-day +
|
||||||
|
flexoki-light, kanagawa floats are lighter than the bg (upstream
|
||||||
|
sumiInk4). Anything that reads worse than before → reopen 28b.
|
||||||
|
- [ ] **Clock zone tooltip (LATER item)** — hover the bar clock: the
|
||||||
|
tooltip's first line shows the zone ("BST (UTC+0100)") above the
|
||||||
|
calendar, on the generated AND summer bars; with auto-timezone
|
||||||
|
on, a zone change updates it (the SIGUSR2 reload).
|
||||||
|
- [ ] **Doctor bar tripwire (LATER item)** — with everything healthy
|
||||||
|
the bar shows nothing; `systemctl --user start doomed`-style
|
||||||
|
induced failure → within ~5 min a red appears (tooltip lists
|
||||||
|
the ✖ lines), clicking opens the sheet in a terminal;
|
||||||
|
reset-failed → it disappears on the next poll. Also visible on
|
||||||
|
both summer bars.
|
||||||
|
- [ ] **OCR region (LATER item)** — Tools › Capture › "OCR region →
|
||||||
|
clipboard": select a region with visible text → toast reports
|
||||||
|
the word count and `wl-paste` yields the text; Esc in slurp
|
||||||
|
cancels silently; a text-free region toasts "No text recognized"
|
||||||
|
without clobbering the clipboard.
|
||||||
|
- [ ] **Look & Feel submenu (item 19)** — root menu: "Look & Feel"
|
||||||
|
(replacing Theme, root still six rows) → Theme grid opens, Next
|
||||||
|
wallpaper cycles instantly, Night light toggles (and is GONE
|
||||||
|
from System). SUPER+T / SUPER+SHIFT+T direct binds unchanged.
|
||||||
|
- [ ] **Launch-or-focus (item 17)** — uncomment the template's
|
||||||
|
`nomarchy.launchOrFocus` firefox example (with firefox
|
||||||
|
installed), `home-update` + reload: SUPER+B launches firefox
|
||||||
|
when closed, FOCUSES the existing window when open (also from
|
||||||
|
another workspace); with firefox removed the bind fires a
|
||||||
|
"not installed" toast; the row shows under SUPER+?.
|
||||||
|
- [ ] **Themed greeter + console (item 16)** — after `sys-rebuild` +
|
||||||
|
logout: tuigreet renders in theme colors (dark container, accent
|
||||||
|
border, themed prompt/time) and a raw tty (CTRL+ALT+F2) shows the
|
||||||
|
theme's ANSI palette; on a LUKS machine the passphrase prompt
|
||||||
|
follows too. Then switch theme + `sys-rebuild` + logout → the
|
||||||
|
greeter follows the new palette. (tuigreet can't run under the
|
||||||
|
VM harness — see MEMORY.md — so rendering is hardware-tier.)
|
||||||
|
- [ ] **Color picker (item 13, final slice)** — SUPER+CTRL+P (or Tools ›
|
||||||
|
Color picker): hyprpicker's zoom loupe appears; click a pixel →
|
||||||
|
toast shows the hex and `wl-paste` yields it; Esc cancels with no
|
||||||
|
toast. Row present in the SUPER+? cheatsheet.
|
||||||
|
- [ ] **Low-battery toasts (item 13 slice)** — on battery, drain past
|
||||||
|
25%: one "Battery low" toast; past 10%: a critical "Battery
|
||||||
|
critical" toast that stays up until dismissed (swaync); plug in,
|
||||||
|
drain again → it re-notifies; no repeat toasts while it just keeps
|
||||||
|
draining. (Crossing logic VM-verified — this checks the real
|
||||||
|
swaync rendering in a session.)
|
||||||
|
|
||||||
|
## AMD dev box only
|
||||||
|
- [ ] **AMD runtime bits** — VA-API (`vainfo` → radeonsi), amd-pstate EPP
|
||||||
|
active and PPD switching governors; opt-ins: ROCm (`rocminfo`, a GPU
|
||||||
|
PyTorch/Ollama smoke) and the XDNA NPU driver loading.
|
||||||
|
- [ ] **Fingerprint** — `fprintd-enroll` + (opt-in PAM) login/sudo.
|
||||||
|
|
||||||
|
## Latitude 5410 only
|
||||||
|
- [x] **Waybar theme-switch resilience** (finding #1 re-test, needs main ≥
|
||||||
|
the supervisor commit + relogin) — switch themes repeatedly (incl.
|
||||||
|
summer-day/night whole-swaps): the bar restarts cleanly each time;
|
||||||
|
if anything kills it, it's back within ~a second. `pgrep -f
|
||||||
|
nomarchy-waybar` shows the supervisor. — 2026-07-04 Bernardo:
|
||||||
|
PASS — theme switches clean; pkill respawn so fast the bar never
|
||||||
|
visibly disappears.
|
||||||
|
- [x] **Media keys + gestures** (from dccceb4) — volume/brightness keys
|
||||||
|
drive the OSD; touchpad gestures work. — 2026-07-04 Bernardo:
|
||||||
|
PASS, volume/brightness keys and touchpad gestures all working.
|
||||||
|
- [ ] **v1 QA batch on-hardware pass** (583708d batch was QEMU-verified) —
|
||||||
|
general smoke before the next `main → v1` promotion.
|
||||||
|
|
||||||
|
## T14s only
|
||||||
|
- [ ] **Webcam IR-hide end-to-end on Nomarchy** — installer detects the
|
||||||
|
RGB+IR pair, bakes `hardware.camera.hideIrSensor`; `wpctl status`
|
||||||
|
shows one colour source; an app picker lists one camera; Howdy-style
|
||||||
|
direct `/dev/video2` reads still work.
|
||||||
981
agent/JOURNAL.md
Normal file
981
agent/JOURNAL.md
Normal file
@@ -0,0 +1,981 @@
|
|||||||
|
# Journal — append-only iteration log
|
||||||
|
|
||||||
|
One entry per iteration, **newest first**. This is the loop's short-term
|
||||||
|
memory: the next session reads the last 3–5 entries to orient. Keep an
|
||||||
|
entry under ~15 lines; durable lessons go to MEMORY.md, not here.
|
||||||
|
|
||||||
|
Template:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## YYYY-MM-DD — <task title> (<commit sha, or "no commit">)
|
||||||
|
- **Task:** which BACKLOG item (or QA sweep / bootstrap / escalation)
|
||||||
|
- **Did:** what changed, in 2–4 lines
|
||||||
|
- **Verified:** tier reached (V0/V1/V2) + the actual commands/checks run
|
||||||
|
- **Pending:** V3 queued? follow-ups filed? anything [stuck]?
|
||||||
|
- **Next suggestion:** what the following iteration should probably take
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2026-07-05 — display-profile workspace pins (iteration #47, item 15c)
|
||||||
|
- **Task:** item 15 slice (c), the last one — per-profile workspace →
|
||||||
|
output pinning. Item 15 deleted (a/b/c all shipped; V3s queued).
|
||||||
|
- **Did:** a profile is now `{ monitors; workspaces = { "1" = "DP-3"; }; }`
|
||||||
|
(bare list still accepted — either-type + normalization in
|
||||||
|
hyprland.nix; coercedTo refuses list-of-submodule sources). Pins bake
|
||||||
|
as Hyprland `workspace` rules and apply instantly on profile switch
|
||||||
|
(`hyprctl keyword workspace` + `dispatch moveworkspacetomonitor`).
|
||||||
|
monitor-rules.nix gained pure `workspaceRule`; template + README
|
||||||
|
updated.
|
||||||
|
- **Verified:** V1 flake check green (incl. the extended
|
||||||
|
checks.display-profiles assert) + scratch-downstream eval: baked
|
||||||
|
settings render both rule sets, the generated applier carries the
|
||||||
|
keyword+dispatch pairs (bash -n OK), match/list still correct with
|
||||||
|
mixed profile shapes.
|
||||||
|
- **Pending:** V3 queued (workspace-pins entry in HARDWARE-QUEUE, rides
|
||||||
|
the slice-a dock test). Stale-pin note documented in the applier.
|
||||||
|
- **Next suggestion:** backlog is now human/event-gated (28 taste
|
||||||
|
calls, 14 Monday, 18 Decision, 20 KVM) — idle the loop or triage
|
||||||
|
PROPOSED.
|
||||||
|
|
||||||
|
## 2026-07-05 — icon-weight A/B for the human call (iteration #46, item 28)
|
||||||
|
- **Task:** item 28's last `[human]` blocker — make the color-vs-
|
||||||
|
symbolic menu-icon decision cheap.
|
||||||
|
- **Did:** captured the lumon root menu with `-symbolic` icon names
|
||||||
|
(temporary uncommitted rofi.nix edit, reverted after) and published
|
||||||
|
a side-by-side artifact (link in the BACKLOG bullet). Findings:
|
||||||
|
symbolic matches the bar's weight, but Papirus symbolic coverage
|
||||||
|
has holes and rofi tints symbolics fixed gray — B needs an
|
||||||
|
audit+recolor slice; A (color) is the free default.
|
||||||
|
- **Verified:** V2 for the experiment itself (both variants VM-
|
||||||
|
captured); no repo code changed — tree is clean apart from agent/.
|
||||||
|
- **Pending:** Bernardo's call on the artifact. Item 28 is now fully
|
||||||
|
agent-side done: all remaining bullets are `[human]`/hardware.
|
||||||
|
- **Next suggestion:** general loop — item 15 slice (c) (per-profile
|
||||||
|
workspaces) is the topmost actionable code item; 14 fires Monday.
|
||||||
|
|
||||||
|
## 2026-07-05 — purge stub waybar.css whole-swaps (iteration #45, item 28c/d)
|
||||||
|
- **Task:** item 28 — lumon vibe capture exposed four themes shipping
|
||||||
|
an unstyled default bar.
|
||||||
|
- **Did:** deleted the stub waybar.css in catppuccin/lumon/nord/
|
||||||
|
retro-82 (2–14 lines of color defines from the f211ef0 rewrite
|
||||||
|
import; a theme waybar.css replaces the WHOLE generated stylesheet,
|
||||||
|
so the stubs nuked all bar styling). The four themes now get the
|
||||||
|
generated bar in their own palette; their full rofi.rasi designs
|
||||||
|
kept. Whole-swap bars are now only summer-day/night, both authored.
|
||||||
|
- **Verified:** V2 — lumon re-capture shows the generated styling
|
||||||
|
(workspace pill, padded right cluster, no edge clipping); V1 flake
|
||||||
|
check green. catppuccin/nord/retro-82 share the mechanism, not
|
||||||
|
individually captured.
|
||||||
|
- **Pending:** HARDWARE-QUEUE eyeballs; the `[human]` icon-weight call.
|
||||||
|
- **Next suggestion:** item 28 is agent-side done pending Bernardo's
|
||||||
|
taste calls — park it; take the next actionable BACKLOG item.
|
||||||
|
|
||||||
|
## 2026-07-05 — capture harness paints wallpapers (iteration #44, item 28c)
|
||||||
|
- **Task:** item 28c harness gap — captures rendered a bare base-color
|
||||||
|
backdrop because the guest had no `~/.nomarchy` runtime state.
|
||||||
|
- **Did:** tools/theme-shot.nix now seeds theme-state.json via tmpfiles
|
||||||
|
at boot (before greetd), so the session's exec-once
|
||||||
|
`nomarchy-theme-sync wallpaper` paints naturally; dropped the
|
||||||
|
testScript seed+manual-repaint (too late for exec-once; manual runs
|
||||||
|
also lack WAYLAND_DISPLAY, which awww's client needs to find its
|
||||||
|
socket).
|
||||||
|
- **Verified:** V2 — summer-night capture shows wallpaper + cream
|
||||||
|
inverted bar + menu + placeholder dim, all coherent. V1 flake check
|
||||||
|
green.
|
||||||
|
- **Pending:** identity-theme vibe capture (lumon/retro-82); the
|
||||||
|
`[human]` icon-weight call; HARDWARE-QUEUE eyeballs.
|
||||||
|
- **Next suggestion:** item 28c identity capture, or park 28 for
|
||||||
|
Bernardo's taste calls.
|
||||||
|
|
||||||
|
## 2026-07-05 — clock zone tooltip (iteration #43, LATER item)
|
||||||
|
- **Task:** LATER › auto-timezone Waybar tooltip. Bullet deleted.
|
||||||
|
- **Did:** the clock tooltip's first line is now the zone —
|
||||||
|
`{:%Z (UTC%z)}` above the calendar — in the generated bar AND both
|
||||||
|
summer whole-swaps (parity). Under auto-timezone the existing
|
||||||
|
tz-watch SIGUSR2 reload keeps it current, so it shows the detected
|
||||||
|
zone live. (%Z abbreviation, not the IANA name — strftime has no
|
||||||
|
code for that; good enough for an "(optional)" nicety.)
|
||||||
|
- **Verified:** V0; V1 — rendered generated config carries the new
|
||||||
|
tooltip-format; both summer jsonc parse (jq) with %Z present.
|
||||||
|
Hover render → V3 queued.
|
||||||
|
- **Pending:** V3. LATER now holds only deferred/big/hw/human items.
|
||||||
|
- **Next suggestion:** a QA sweep, or stop-and-wait — the queue is
|
||||||
|
effectively drained for unattended work; meaty LATER items
|
||||||
|
(wallpapers split is *deferred by decision*, installer round 2
|
||||||
|
[big]) deserve Bernardo's go-ahead or a fresh session.
|
||||||
|
|
||||||
|
## 2026-07-05 — doctor bar tripwire (iteration #42, LATER item)
|
||||||
|
- **Task:** LATER › doctor Waybar warning. Bullet deleted.
|
||||||
|
- **Did:** nomarchy-doctor-status (named bin, PATH): silent exit 0
|
||||||
|
while the doctor is healthy or absent (self-gate), else JSON with
|
||||||
|
the first ✖ lines jq-escaped into the tooltip, in @bad; click =
|
||||||
|
nomarchy-menu doctor (the sheet). custom/doctor added to the
|
||||||
|
generated bar (after battery, interval 300 — the check is real
|
||||||
|
work, this is a tripwire not a monitor) + CSS, AND both summer
|
||||||
|
whole-swaps (module list, jsonc block, CSS membership + @red rule)
|
||||||
|
per the parity rule.
|
||||||
|
- **Verified:** V0; V1 — template-home builds, status bash -n, config
|
||||||
|
+ CSS each carry the module, both summer jsonc still parse (jq)
|
||||||
|
with the block; FUNCTIONAL — self-gate silent, and a shimmed
|
||||||
|
failing doctor produces valid JSON (jq-verified: class bad, ✖
|
||||||
|
lines in tooltip). Live render → V3 queued.
|
||||||
|
- **Pending:** V3. LATER remaining: wallpapers-artifact split
|
||||||
|
(deferred by decision), installer round 2 [big], boot-from-
|
||||||
|
snapshot, night-light geo, icon overrides, MIPI camera [hw],
|
||||||
|
auto-timezone tooltip, VPN richer display, release bump [human].
|
||||||
|
- **Next suggestion:** auto-timezone Waybar tooltip (small) — or a
|
||||||
|
QA sweep; the meatier LATER items deserve a fresh session.
|
||||||
|
|
||||||
|
## 2026-07-05 — OCR screenshot-to-text (iteration #41, LATER item)
|
||||||
|
- **Task:** LATER › OCR (NEXT is fully human/event-gated, so LATER is
|
||||||
|
in play per LOOP.md). Bullet deleted.
|
||||||
|
- **Did:** Capture › "OCR region → clipboard" (self-gated on
|
||||||
|
tesseract): slurp (Esc = silent cancel, the recording pattern) →
|
||||||
|
grim → tesseract stdin/stdout → wl-copy, whitespace-only results
|
||||||
|
toast instead of clobbering the clipboard; success toasts the word
|
||||||
|
count. tesseract ships eng-only via rofi.nix home.packages
|
||||||
|
(override documented — unscoped it drags every language's
|
||||||
|
traineddata, real cost on a compile-from-source distro).
|
||||||
|
- **Verified:** V0; V1 — template-home builds, menu bash -n, gated
|
||||||
|
row + case present; FUNCTIONAL — the profile's own tesseract read a
|
||||||
|
rendered test image back verbatim ("Nomarchy OCR smoke test 42"),
|
||||||
|
so the OCR half of the pipe is proven; grim/slurp half needs a
|
||||||
|
session → V3 queued.
|
||||||
|
- **Pending:** V3.
|
||||||
|
- **Next suggestion:** LATER: doctor Waybar warning (self-gating bar
|
||||||
|
indicator fed by nomarchy-doctor) or auto-timezone tooltip; both
|
||||||
|
small.
|
||||||
|
|
||||||
|
## 2026-07-05 — Look & Feel menu category (iteration #40, item 19)
|
||||||
|
- **Task:** BACKLOG NEXT#19 — its ≥3-entries gate is met (Theme, Next
|
||||||
|
wallpaper, Night light). Item deleted.
|
||||||
|
- **Did:** root's Theme row → "Look & Feel" (pango-escaped —
|
||||||
|
-markup-rows menus treat & as an entity; matched on *Look*); new
|
||||||
|
lookfeel mode: Theme (SUPER+T hint), Next wallpaper (SUPER+SHIFT+T
|
||||||
|
hint via the new generalized hintForAction), Night light row moved
|
||||||
|
from System (System thins by one). Root stays six. menuHint is now
|
||||||
|
sugar over hintForAction.
|
||||||
|
- **Verified:** V0; V1 — menu bash -n, lookfeel mode + escaped label
|
||||||
|
+ night light relocated (4 occurrences, all in lookfeel/nightlight
|
||||||
|
paths); VISUAL — tokyo-night capture: root renders "Look & Feel"
|
||||||
|
correctly with six rows and intact hints. Submenu flow → V3
|
||||||
|
queued.
|
||||||
|
- **Pending:** V3. NEXT now: 28 (Bernardo-gated) · 14 (Monday watch)
|
||||||
|
· 18 [big, Decision-gated] · 20 [human] — the LATER tier or QA
|
||||||
|
sweeps are next for the loop.
|
||||||
|
- **Next suggestion:** LATER's OCR screenshot-to-text (two-row
|
||||||
|
Capture addition, self-contained) — or a QA sweep.
|
||||||
|
|
||||||
|
## 2026-07-05 — launch-or-focus binds (iteration #39, item 17)
|
||||||
|
- **Task:** BACKLOG NEXT#17 (the UI review is Bernardo-gated; back to
|
||||||
|
the queue head). Item deleted.
|
||||||
|
- **Did:** nomarchy.launchOrFocus (listOf submodule: key/mods/class/
|
||||||
|
command/desc; opt-in, template example) → hyprland.nix generates
|
||||||
|
binds through a shared nomarchy-focus-or-launch script (jq
|
||||||
|
case-insensitive class match → focuswindow "(?i)" regex, else
|
||||||
|
launch; uninstalled command → toast, so binds survive suite edits);
|
||||||
|
rofi.nix renders the same entries into the SUPER+? cheatsheet via
|
||||||
|
prettyKeys (single source). README row.
|
||||||
|
- **Verified:** V0; V1 — scratch downstream with 2 entries: both
|
||||||
|
binds rendered (default command = lowercased class; custom
|
||||||
|
mods/command/desc honored), tool bash -n + usage exit 64,
|
||||||
|
cheatsheet rows present. Focus behaviour needs a session → V3
|
||||||
|
queued.
|
||||||
|
- **Pending:** V3. Queue after this: #18 control center [big, needs
|
||||||
|
the form-factor Decision], #19 Look&Feel menu (gated on ≥3
|
||||||
|
entries), #20 [human], LATER tier.
|
||||||
|
- **Next suggestion:** a QA sweep (#18/#19/#20 are blocked-ish) — or
|
||||||
|
item 19's precondition check (does Look & Feel earn 3 entries
|
||||||
|
yet?).
|
||||||
|
|
||||||
|
## 2026-07-05 — placeholder dim + latte review + backdrop probe (iteration #38, item 28c)
|
||||||
|
- **Task:** item 28 slice (c) — the summer-rasi quickie + the light-
|
||||||
|
theme capture.
|
||||||
|
- **Did:** both summer rasi: placeholder-color @bg0 → bg0 at 60%
|
||||||
|
alpha (#…99), so prompt and placeholder no longer read as one
|
||||||
|
phrase. Captured catppuccin-latte at 1080p: the generated menu is
|
||||||
|
COHERENT on light themes (zebra rows on the 28b-retuned surface,
|
||||||
|
hints dimmed) — closes the audit's "dark terminal on latte"
|
||||||
|
concern as a stale preview. Backdrop suspicion probed with a
|
||||||
|
dedicated VM (hyprctl getoption): misc:background_color IS set
|
||||||
|
(0xFFEFF1F5) — awww's empty-state layer occludes it in the
|
||||||
|
wallpaper-less VM; on hardware the fix covers the startup gap as
|
||||||
|
intended.
|
||||||
|
- **Verified:** rasi edits grep-verified (rasi parses at rofi
|
||||||
|
runtime; visual rides the next summer capture / V3); latte menu
|
||||||
|
capture reviewed; probe output above.
|
||||||
|
- **Pending:** item 28 remaining: icon-weight `[human]`, hardware
|
||||||
|
eyeballs (queued), identity-theme capture (optional), slice (d)
|
||||||
|
needs nothing (parity verified).
|
||||||
|
- **Next suggestion:** item 28 is now Bernardo-gated (taste calls +
|
||||||
|
V3); the loop should return to the general BACKLOG head (item 14
|
||||||
|
watch / item 17 launch-or-focus).
|
||||||
|
|
||||||
|
## 2026-07-05 — rofi keybind hints (iteration #37, item 28c)
|
||||||
|
- **Task:** item 28 slice (c) — the hint column, the audit's biggest
|
||||||
|
remaining UX item.
|
||||||
|
- **Did:** rofi.nix: menuHint builds a dimmed pango span
|
||||||
|
(size small, alpha 55%) from keybinds.nix via the cheatsheet's
|
||||||
|
prettyKeys — single source, hints can't drift from the live binds;
|
||||||
|
applied to root (Apps/Theme/Power/Keybindings; Apps special-cased,
|
||||||
|
it's rofi drun not a menu module), Tools (all eight leaves), System
|
||||||
|
(Network/Bluetooth/DND); those three menus now pass -markup-rows.
|
||||||
|
Contains-glob matching and the exact "↩ Back" match are unaffected
|
||||||
|
(labels keep their prefix; Back stays markup-free).
|
||||||
|
- **Verified:** V0; V1 rendered menu bash -n + hint spans present +
|
||||||
|
3× -markup-rows; VISUAL — tokyo-night capture: hints render dimmed
|
||||||
|
and subordinate on normal AND selected (accent) rows; Tools/System
|
||||||
|
rows correctly bare.
|
||||||
|
- **Pending:** slice-c remainder: summer-rasi placeholder dim,
|
||||||
|
latte/identity captures, icon-weight `[human]`.
|
||||||
|
- **Next suggestion:** the placeholder-dim quickie + a latte capture
|
||||||
|
in one tick; then item 28 pauses for Bernardo's icon-weight call
|
||||||
|
and the hardware eyeballs.
|
||||||
|
|
||||||
|
## 2026-07-05 — bar group rhythm + @muted adoption (iteration #36, item 28c)
|
||||||
|
- **Task:** item 28 slice (c) — the two queued bar polish items.
|
||||||
|
- **Did:** waybar.nix generated CSS: margin-left 14px on the three
|
||||||
|
right-cluster group heads (pulseaudio/powerprofile/battery — media
|
||||||
|
· toggles · status; hidden heads degrade to uniform spacing);
|
||||||
|
workspaces buttons, dnd bell, and muted volume moved from
|
||||||
|
alpha(@text,.5) tints to the semantic @muted role — safe since 28b
|
||||||
|
floor-gates muted/base ≥ 2.0 (the old comment warning against
|
||||||
|
@muted documented the pre-28b world; rewritten to state the new
|
||||||
|
invariant). Whole-swap bars untouched (authored identity).
|
||||||
|
- **Verified:** V0; V1 rendered CSS has 4 @muted uses + the margin
|
||||||
|
rule; VISUAL — tokyo-night re-capture: themed backdrop confirmed
|
||||||
|
(navy base, not black), group gap visible before the volume group,
|
||||||
|
workspace pill legible. Cross-theme minima are guaranteed by the
|
||||||
|
gated checker rather than per-theme eyeballs.
|
||||||
|
- **Pending:** slice-c remainder: rofi hint column, summer-rasi
|
||||||
|
placeholder dim, icon-weight `[human]`, latte/identity captures.
|
||||||
|
- **Next suggestion:** rofi keybind-hint column (the biggest
|
||||||
|
remaining UX win), or the two-line placeholder nit as a quickie.
|
||||||
|
|
||||||
|
## 2026-07-05 — summer-day capture review + themed backdrop (iteration #35, item 28c)
|
||||||
|
- **Task:** item 28 slice (c) — whole-swap capture review + the first
|
||||||
|
cheap polish fix.
|
||||||
|
- **Did:** captured summer-day at 1080p (harness, VM): the authored
|
||||||
|
slate menu + island-pill bar hold up with the 28b retunes —
|
||||||
|
initially misread as polarity soup, but the rasi whole-swap
|
||||||
|
deliberately mirrors the bar's slate strip: identity, keep (nit
|
||||||
|
filed: undimmed entry placeholder). The surviving cross-theme fix:
|
||||||
|
Hyprland `misc:background_color` = theme base (was compositor
|
||||||
|
black — a glitch-looking flash behind missing/slow wallpaper,
|
||||||
|
glaring on light themes). Punch list updated.
|
||||||
|
- **Verified:** V0; V1 — template-home rebuilt, rendered hyprland.conf
|
||||||
|
carries `background_color=rgb(1a1b26)` (theme base). Backdrop
|
||||||
|
visible confirmation rides the next capture run / V3.
|
||||||
|
- **Pending:** captures for latte + one identity theme; polish items
|
||||||
|
queued: bar group margins, @muted adoption, rofi hint column, icon
|
||||||
|
weight `[human]`.
|
||||||
|
- **Next suggestion:** bar polish slice (group margins + @muted) —
|
||||||
|
code-level, verifiable by build + re-capture.
|
||||||
|
|
||||||
|
## 2026-07-05 — 1080p capture harness + first slice-c review (iteration #34, item 28c)
|
||||||
|
- **Task:** item 28 slice (c) prep — full-res captures for the
|
||||||
|
per-surface polish pass.
|
||||||
|
- **Did:** tools/theme-shot.nix (maintainer tool, THEME env-driven):
|
||||||
|
full themed desktop headless at 1920x1080 via the memory recipe +
|
||||||
|
two fixes over the spike — home-manager.useGlobalPkgs (HM submodule
|
||||||
|
otherwise misses the overlay → 'nomarchy-theme-sync missing') and a
|
||||||
|
menu.png shot (hyprctl dispatch exec nomarchy-menu). Proven on
|
||||||
|
tokyo-night; both shots read. Findings → item 28 punch list: rofi
|
||||||
|
root width vs empty space (→ keybind-hint column idea), icon-weight
|
||||||
|
mix (color Papirus vs mono bar) `[human]`, bar group margins
|
||||||
|
confirmed, alpha-tint dim vs @muted role. Whole-swap module parity
|
||||||
|
verified textually (no drift; cpu/memory omission is identity).
|
||||||
|
- **Verified:** harness runs end-to-end (exit 0, screenshots read);
|
||||||
|
eval from tools/ with relative flake path OK. Wallpaper still
|
||||||
|
doesn't paint (theme-sync needs ~/.nomarchy in the guest — fix
|
||||||
|
noted in the header for the next run).
|
||||||
|
- **Pending:** capture summer-day/night (whole-swaps) + latte;
|
||||||
|
then the polish slices; icon-weight call is Bernardo's.
|
||||||
|
- **Next suggestion:** run the retuned-theme captures + start the
|
||||||
|
cheap polish items (group margins, @muted adoption).
|
||||||
|
|
||||||
|
## 2026-07-05 — P2 floors retuned + gated (iteration #33, item 28b done)
|
||||||
|
- **Task:** item 28 slice (b) remainder — the P2 contrast floors.
|
||||||
|
- **Did:** 18 hex retunes across 9 themes: muted raised on lumon/
|
||||||
|
white/retro-82/everforest (OKLCH hue-preserving minimal solve to
|
||||||
|
≥2.05) + gruvbox→bg4 #7c6f64, nord→#616e88 (community standard),
|
||||||
|
latte→overlay1 #8c8fa1; text-on-surface via surface nudges
|
||||||
|
(ristretto darker, latte lighter); accentAlt darkened (latte,
|
||||||
|
summer-day); warn darkened on the light themes (latte, summer-day,
|
||||||
|
rose-pine-dawn) and flexoki-light's four statuses moved to the
|
||||||
|
canonical 600 series. check-theme-contrast.py gates all four
|
||||||
|
adopted floors (muted ≥2, text/surface ≥4.5, accentAlt ≥3, warn
|
||||||
|
≥2.5 — warn is the battery tint); good/bad stay audit-only
|
||||||
|
(identity), so no exemption mechanism was needed. Slice (b) done.
|
||||||
|
- **Verified:** V0 + checks.theme-contrast GREEN (21×7); re-audit:
|
||||||
|
contrast findings 20→1 (miasma bad = identity); flake check green.
|
||||||
|
Rendering is V3 → queued (P2 eyeball entry).
|
||||||
|
- **Pending:** slices (c) per-surface polish (needs 1080p captures)
|
||||||
|
and (d) whole-swap bar parity; ansi[] conventions decision still
|
||||||
|
open (audit notes).
|
||||||
|
- **Next suggestion:** slice (c) prep — 1080p captures via the VM
|
||||||
|
recipe, or hardware captures if Bernardo prefers eyeballing first.
|
||||||
|
|
||||||
|
## 2026-07-05 — P1 palette retunes + gated subtext floor (iteration #32, item 28b)
|
||||||
|
- **Task:** item 28 slice (b), P1s from the #31 audit.
|
||||||
|
- **Did:** summer-day: surface #5c6a72(=text!)→#efe7d0 raised cream,
|
||||||
|
subtext #fdf6e3(=base!)→#6e828a slate; flexoki-light to canonical
|
||||||
|
Flexoki tones: surface #E6E4D9(ui), overlay #B7B5AC, subtext
|
||||||
|
#6F6E69(tx-2), muted #878580(base-500); miasma surface #000→#2e2e2e;
|
||||||
|
kanagawa surface #090618→#2a2a37 (upstream sumiInk4 — old value was
|
||||||
|
sumiInk0, darker than bg). check-theme-contrast.py gains the adopted
|
||||||
|
`subtext/base ≥ 3` pairing (the item-25/27 trap, now impossible).
|
||||||
|
Model note recorded: `overlay` is a mid-tone role, not a bg tier.
|
||||||
|
- **Verified:** V0 + checks.theme-contrast GREEN (21×3 pairings);
|
||||||
|
re-audit: all four P1 findings gone (kanagawa now CVD-only findings);
|
||||||
|
V1 — scratch downstream with summer-day ACTIVE builds, new surface
|
||||||
|
hex present in rendered ghostty config. Looks are V3 → queued
|
||||||
|
(four-theme eyeball).
|
||||||
|
- **Pending:** 28b remainder: P2 floors (muted ≥2, warn ≥2.5,
|
||||||
|
text-on-surface ≥4.5, accentAlt ≥3) + exemption-list mechanism.
|
||||||
|
- **Next suggestion:** 28b P2s (7 muted retunes + 4 warn + 2
|
||||||
|
text-on-surface + 2 accentAlt, then gate with exemptions).
|
||||||
|
|
||||||
|
## 2026-07-05 — theme design audit (iteration #31, item 28 slice a)
|
||||||
|
- **Task:** BACKLOG NEXT#28 slice (a) — the design-theory audit
|
||||||
|
(human-requested; Bernardo asked to run it now).
|
||||||
|
- **Did:** tools/audit-theme-design.py (new, report-only): OKLCH
|
||||||
|
lightness architecture, extended WCAG pairs, status-hue families,
|
||||||
|
accent harmony, Machado protan/deutan simulation, ANSI slot
|
||||||
|
semantics — over all 21 palettes; plus a visual pass over 4
|
||||||
|
representative preview.png captures. Findings curated
|
||||||
|
identity-aware into a P1–P3 punch list appended to item 28: 2
|
||||||
|
invisible-subtext palettes (summer-day, flexoki-light), 2 inverted
|
||||||
|
bg stacks (miasma, kanagawa), 7 muted-floor misses, warn-barely-
|
||||||
|
reads ×4, a systemic "status is never color-only" rule (CVD
|
||||||
|
collapse is inherent, glyph redundancy is the fix), explicit
|
||||||
|
identity exemptions, light-theme ANSI convention decision, bar
|
||||||
|
right-cluster grouping rhythm, latte dark-terminal verify.
|
||||||
|
- **Verified:** V0 (py_compile; report tool, not wired into checks).
|
||||||
|
Analysis is palette-math + thumbnail previews; per-surface
|
||||||
|
spacing/type audit needs 1080p captures (slice c prep).
|
||||||
|
- **Pending:** slice (b) — palette retunes + checker extension w/
|
||||||
|
exemption list; needs Bernardo's eye on the P1 retunes (visual
|
||||||
|
taste calls). Artwork needs none so far — no image-model ask yet.
|
||||||
|
- **Next suggestion:** slice (b) P1s (summer-day/flexoki subtext+
|
||||||
|
surface, miasma/kanagawa stacks) — small hex edits, big payoff.
|
||||||
|
|
||||||
|
## 2026-07-05 — greeter theming from the JSON (iteration #30, item 16)
|
||||||
|
- **Task:** BACKLOG NEXT#16 — tuigreet themed from theme-state.json at
|
||||||
|
system rebuild (the Plymouth model). Item deleted.
|
||||||
|
- **Did:** new modules/nixos/greeter.nix owns the greetd block (moved
|
||||||
|
out of default.nix, one concern one file) + the theming: (1)
|
||||||
|
console.colors = the theme's ansi[] (mkDefault; lands as
|
||||||
|
vt.default_* kernel params — also themes raw ttys + LUKS prompt);
|
||||||
|
(2) tuigreet --theme on NAMED slots (its parser is ratatui
|
||||||
|
Color::from_str, verified in source; names hit the standard indexes
|
||||||
|
the retinted VT palette now serves). Sparse state w/o ansi → skips
|
||||||
|
cleanly.
|
||||||
|
- **Verified:** V0; V1 — template-system toplevel: baked greetd.toml
|
||||||
|
carries the full --theme spec, kernel-params carry all three
|
||||||
|
vt.default_{red,grn,blu}. A checks.greeter VM test was attempted and
|
||||||
|
DROPPED: tuigreet dies under runNixOSTest even bare (harness limit,
|
||||||
|
not our flag — bisected; nixpkgs tests use agreety) → MEMORY.md.
|
||||||
|
- **Pending:** V3 queued (rendering + theme-follows-rebuild).
|
||||||
|
- **Next suggestion:** #17 launch-or-focus, or the new #28 UI-review
|
||||||
|
audit slice once Bernardo confirms its placement.
|
||||||
|
|
||||||
|
## 2026-07-05 — display profiles auto-switch (iteration #29, item 15b)
|
||||||
|
- **Task:** BACKLOG NEXT#15 slice b — opt-in hotplug auto-switch.
|
||||||
|
- **Did:** nomarchy-display-profile gains `match <outputs>` (exact set
|
||||||
|
→ else unambiguous largest subset → ties/none = exit 1);
|
||||||
|
nomarchy-display-profile-watch polls `hyprctl monitors all` every 3s
|
||||||
|
(exec-once, the keyboard-watcher pattern — session units race
|
||||||
|
Hyprland IPC), reacts only to CHANGES, reads settings.displayProfileAuto
|
||||||
|
LIVE each change (instant menu toggle, no rebuild) and applies via
|
||||||
|
the tool, so auto-picks persist concrete profiles that rebuilds
|
||||||
|
bake. Chose a separate boolean over an "auto" pseudo-profile for
|
||||||
|
exactly that bake semantics. Menu: Auto-switch (on/off) row in
|
||||||
|
Profiles. Template + README notes.
|
||||||
|
- **Verified:** V0; V1 — scratch 4-profile downstream builds; both
|
||||||
|
scripts bash -n; match matrix exercised: exact ×3, unambiguous
|
||||||
|
subset, tie → none, no-fit → none; watcher exec-once present; menu
|
||||||
|
renders with the row. Real hotplug needs a session+dock → V3 (rides
|
||||||
|
the slice-a queue entry).
|
||||||
|
- **Pending:** V3. Slice c (workspace binding) remains, tagged
|
||||||
|
optional.
|
||||||
|
- **Next suggestion:** #16 greeter theming — item 15's remaining
|
||||||
|
slice c is optional; a fresh item keeps variety.
|
||||||
|
|
||||||
|
## 2026-07-05 — display profiles slice a (iteration #28, item 15a)
|
||||||
|
- **Task:** BACKLOG NEXT#15 slice a, per the #27 design: option +
|
||||||
|
overlay + applier + menu + template example.
|
||||||
|
- **Did:** nomarchy.displayProfiles (attrsOf (listOf monitorType));
|
||||||
|
monitor logic extracted to pure modules/home/monitor-rules.nix
|
||||||
|
(rule renderer + 3-layer resolve: profile replaces whole-by-name →
|
||||||
|
resolution picks field-level with the disable-guard → wildcard),
|
||||||
|
hyprland.nix consumes it and gains nomarchy-display-profile
|
||||||
|
(list/active/apply/base; apply = baked hyprctl rules + state write
|
||||||
|
--no-switch, base = clear + hyprctl reload) on PATH only when
|
||||||
|
profiles exist; menu: Display gains a gated "Profiles ›" row + new
|
||||||
|
display-profile mode (●/○ active mark, Base layout row); template
|
||||||
|
example + README row. checks.display-profiles unit-tests resolve
|
||||||
|
(incl. junk-state degradation) — the first HM-eval fixture attempt
|
||||||
|
hit "path not valid" (eval store won't realise writeText/toFile
|
||||||
|
under flake check), hence the pure-function extraction.
|
||||||
|
- **Verified:** V0 (check's asserts force at eval); V1 — scratch
|
||||||
|
downstream through lib.mkFlake builds: tool bash -n + correct baked
|
||||||
|
rules (disable, vrr, floats), hyprland.conf shows the exact overlay
|
||||||
|
(wildcard + kept base + disabled panel + profile output), menu bash
|
||||||
|
-n, list/usage smoke. Live switching needs a session+dock → V3.
|
||||||
|
- **Pending:** V3 queued. Slices b (hotplug auto-switch) and c
|
||||||
|
(workspace binding) remain in the item.
|
||||||
|
- **Next suggestion:** #16 greeter theming, or 15b if momentum on
|
||||||
|
displays is preferred.
|
||||||
|
|
||||||
|
## 2026-07-05 — display-profiles design pass (iteration #27, item 15, no code)
|
||||||
|
- **Task:** BACKLOG NEXT#15 — the entry itself demands "design first,
|
||||||
|
write the plan into this entry before coding". Backlog-only iteration.
|
||||||
|
- **Did:** wrote the plan into item 15: `nomarchy.displayProfiles =
|
||||||
|
attrsOf (listOf monitorType)` (reuse the existing submodule),
|
||||||
|
`settings.displayProfile` state via the night-light pattern (instant
|
||||||
|
hyprctl apply + bake on rebuild), whole-entry-by-name overlay with a
|
||||||
|
disable-guard against stale resolution picks, self-gated menu row,
|
||||||
|
three slices (option+overlay+menu / opt-in hotplug auto-switch /
|
||||||
|
per-profile workspace binding), kanshi stays a non-goal.
|
||||||
|
- **Verified:** V0 (docs-only; flake untouched).
|
||||||
|
- **Pending:** nothing — 15a is now directly codeable.
|
||||||
|
- **Next suggestion:** 15a (option + overlay + menu picker), or #16
|
||||||
|
greeter theming if a fresh session prefers a self-contained item.
|
||||||
|
|
||||||
|
## 2026-07-05 — scheduled lock-bump workflow (iteration #26, item 14 b+c)
|
||||||
|
- **Task:** BACKLOG NEXT#14 `[big]` — split: (a) checks-on-push shipped
|
||||||
|
earlier; this ships (b) the weekly bump + (c) the fast-lane as
|
||||||
|
workflow_dispatch on the same job.
|
||||||
|
- **Did:** .gitea/workflows/bump.yml — Mon 05:17 UTC cron + dispatch:
|
||||||
|
nix flake update (pinned branches by construction) → gate `nix flake
|
||||||
|
check --no-build` (py_compile/bash -n skipped: they don't read the
|
||||||
|
lock) → commit --only flake.lock with the update's change list as
|
||||||
|
body → push main (triggers check.yml as second net). Red gate/push
|
||||||
|
race = failed run, nothing lands. Container recipe from check.yml.
|
||||||
|
- **Verified:** V0 (yq parse + bash -n each run block); logic simulated
|
||||||
|
end-to-end in a scratch clone with a REAL nix flake update + bare
|
||||||
|
remote: changed/unchanged branches, bystander file stays uncommitted,
|
||||||
|
push lands; today's bumped lock evals green (Monday's baseline).
|
||||||
|
Gitea 1.25.4 confirmed (schedule supported). The real cron pickup +
|
||||||
|
token push are NOT confirmable from here → item 14 slimmed to
|
||||||
|
"confirm first run".
|
||||||
|
- **Pending:** watch the first scheduled/dispatched bump run.
|
||||||
|
- **Next suggestion:** #16 greeter theming (next codeable item; #15
|
||||||
|
needs its design pass written first).
|
||||||
|
|
||||||
|
## 2026-07-05 — color picker (iteration #25, item 13 final slice → item done)
|
||||||
|
- **Task:** BACKLOG NEXT#13 last slice — hyprpicker → clipboard from
|
||||||
|
the menu + a direct bind. Item 13 complete; deleted from BACKLOG.
|
||||||
|
- **Did:** hyprpicker into systemPackages (next to grim/slurp); rofi.nix
|
||||||
|
`colorpicker` mode (hyprpicker → wl-copy → hex-in-toast, Esc = silent
|
||||||
|
cancel) + self-gated Tools › "Color picker" row + usage line;
|
||||||
|
keybinds.nix SUPER+CTRL+P row (feeds bind + cheatsheet).
|
||||||
|
- **Verified:** V0; V1 — template-home AND template-system build;
|
||||||
|
rendered nomarchy-menu bash -n OK with mode + gated row; cheatsheet
|
||||||
|
txt has the SUPER+CTRL+P row; hyprland conf has the bind; system
|
||||||
|
toplevel ships sw/bin/hyprpicker. Picking needs a compositor → V3.
|
||||||
|
- **Pending:** V3 queued (loupe → click → wl-paste round-trip).
|
||||||
|
- **Next suggestion:** #15 (display profiles) needs a design pass
|
||||||
|
written into the entry first; #16 (greeter theming) is the next
|
||||||
|
directly codeable item — or #14's bump workflow (eval-tier gate).
|
||||||
|
|
||||||
|
## 2026-07-05 — low-battery notifications (iteration #24, item 13 slice)
|
||||||
|
- **Task:** BACKLOG NEXT#13 second slice — the bar colors the battery
|
||||||
|
at 25/10% but nothing *notified*.
|
||||||
|
- **Did:** pkgs/nomarchy-battery-notify (shellcheck-gated watcher:
|
||||||
|
polls the same sysfs the bar reads — type=Battery, scope≠Device —
|
||||||
|
one toast per downward crossing: normal@25, critical@10; re-armed by
|
||||||
|
charging; self-gates on battery presence → desktop no-op) + overlay.
|
||||||
|
HM unit in modules/home/battery-notify.nix behind
|
||||||
|
nomarchy.batteryNotify.enable (default on), graphical-session-bound,
|
||||||
|
libnotify on the unit PATH (notify-send resolved from PATH so the
|
||||||
|
check can shim it). README row. Chose the tiny watcher over
|
||||||
|
poweralertd: its UPower thresholds (20/5) wouldn't match the bar,
|
||||||
|
and it toasts every plug/unplug.
|
||||||
|
- **Verified:** V0; V1 — template-home builds, unit present; V2 GREEN —
|
||||||
|
new checks.battery-notify (test_power fake battery): self-gate exits
|
||||||
|
0 without a battery, silence at 80%, exactly one low toast crossing
|
||||||
|
25, one critical-urgency toast crossing 10, charging re-arms → a
|
||||||
|
second drain toasts again.
|
||||||
|
- **Pending:** V3 queued (real toast through swaync while draining).
|
||||||
|
- **Next suggestion:** item 13 final slice — hyprpicker color picker
|
||||||
|
(Tools › entry + SUPER+CTRL bind).
|
||||||
|
|
||||||
|
## 2026-07-04 — caffeine/idle-inhibit toggle (iteration #23, item 13 slice)
|
||||||
|
- **Task:** BACKLOG NEXT#13 first slice — idle_inhibitor in the
|
||||||
|
generated bar (summer-night had it; reverse parity gap).
|
||||||
|
- **Did:** waybar.nix: idle_inhibitor module (/, tooltips, placed
|
||||||
|
after the ⏺), CSS membership + `.activated { color: @warn; }`.
|
||||||
|
summer-day: module + CSS mirrored from summer-night (same glyphs,
|
||||||
|
no tint — glyph change is the state signal there). keybinds.nix
|
||||||
|
extra row → cheatsheet mentions the bar click.
|
||||||
|
- **Verified:** V0; V1 — template-home built; rendered config has the
|
||||||
|
module second in modules-right with correct glyphs; CSS rules
|
||||||
|
present; cheatsheet row renders. Inhibit behaviour needs a session
|
||||||
|
→ V3 queued (hold past the lock timeout).
|
||||||
|
- **Pending:** V3. Item 13 remaining slices: low-battery
|
||||||
|
notifications, color picker.
|
||||||
|
- **Next suggestion:** item 13 next slice (low-battery notifications,
|
||||||
|
gate on power.laptop) — or #14 lock-bump CI if variety is better.
|
||||||
|
|
||||||
|
## 2026-07-04 — screen recording in Capture (iteration #22, item 12)
|
||||||
|
- **Task:** BACKLOG NEXT#12 — record region/screen from the menu, stop
|
||||||
|
from the bar.
|
||||||
|
- **Did:** modules/home/recording.nix: `nomarchy-record`
|
||||||
|
start/stop/active/status — wl-screenrec first, wf-recorder fallback
|
||||||
|
if it dies at startup (no-VAAPI case), SIGINT-finalized stop,
|
||||||
|
runtime pidfile, signal-8 bar pokes. Capture menu: 4 record rows that
|
||||||
|
self-swap to "■ Stop recording" while one runs. Waybar: self-gating
|
||||||
|
custom/recording (⏺ REC, @bad red), click = stop — the one stop
|
||||||
|
surface. Parity: both summer whole-swap bars got the module + CSS
|
||||||
|
(@red). DEVIATIONS: saves to ~/Videos/Recordings (an .mp4 in
|
||||||
|
Pictures/Screenshots felt wrong — same timestamp naming though);
|
||||||
|
audio = two extra explicit rows, not a toggle state.
|
||||||
|
- **Verified:** V0; V1 — template-home builds; rendered bar config has
|
||||||
|
the module (first in modules-right) + CSS rule; summer jsonc still
|
||||||
|
parse; nomarchy-record dry-run: status empty+exit 0 idle, active
|
||||||
|
exit 1, usage exit 2; both recorders in home-path. Real capture
|
||||||
|
needs a session → V3 (headless GL recipe can't confirm an encoder).
|
||||||
|
- **Pending:** V3 recording exercise (incl. VAAPI-vs-fallback check).
|
||||||
|
- **Next suggestion:** NEXT#13 niceties, one slice: idle-inhibit
|
||||||
|
(caffeine) toggle — reverse-parity gap already noted in the item.
|
||||||
|
|
||||||
|
## 2026-07-04 — state-file validation & friendly errors (iteration #21, item 11)
|
||||||
|
- **Task:** BACKLOG NEXT#11 — hand-edited state must fail with field +
|
||||||
|
problem + fix, never a Nix stack.
|
||||||
|
- **Did:** (a) tool: validate_state() (appearance schema = hard errors;
|
||||||
|
settings.*/unknown keys = warnings), `validate` subcommand,
|
||||||
|
validate-BEFORE-write in write_state (invalid set/apply never touches
|
||||||
|
disk), JSON syntax errors now say line/column/fix. (b) theme.nix:
|
||||||
|
same schema at eval time on `parsed` (post-defaults, so sparse files
|
||||||
|
stay fine); throws a multi-line message naming each field, the got-
|
||||||
|
value, and the three fix paths. Doctor's JSON fix-text now points at
|
||||||
|
`validate`.
|
||||||
|
- **Verified:** V0; V1 — new checks.theme-sync-validate GREEN: good
|
||||||
|
template passes, trailing comma → line/col message, bad hex/type →
|
||||||
|
field named, unknown key → warning only, invalid `set` refused with
|
||||||
|
the file byte-identical (cmp). Negative eval of a broken scratch
|
||||||
|
downstream through mkFlake shows the friendly throw (both fields);
|
||||||
|
good-path template-home still builds.
|
||||||
|
- **Pending:** nothing — no hardware dependency.
|
||||||
|
- **Next suggestion:** NEXT#12 (screen recording) or #13 niceties
|
||||||
|
slice; #12 first (it reshapes the Capture submenu the OCR LATER item
|
||||||
|
waits on).
|
||||||
|
|
||||||
|
## 2026-07-04 — nomarchy-doctor (iteration #20, item 10)
|
||||||
|
- **Task:** BACKLOG NEXT#10 — one-shot read-only health check.
|
||||||
|
- **Did:** pkgs/nomarchy-doctor (writeShellApplication → shellcheck-
|
||||||
|
gated; a package so the VM check runs on a minimal node): failed
|
||||||
|
system+user units (user bus self-skips), disk space on real
|
||||||
|
filesystems only (fstype allowlist skips tmpfs/9p → VM-safe; device
|
||||||
|
dedupe), state-file parses + git-tracked, flake dirty/behind
|
||||||
|
(warn-level), generation age via the profile SYMLINK mtime (store
|
||||||
|
paths are epoch-1), snapper timer when enabled. Every ✖ prints its
|
||||||
|
fix; exit 1 on any ✖. Wired: overlay, systemPackages, System ›
|
||||||
|
Doctor menu row (terminal), README §5.
|
||||||
|
- **Verified:** V0; V1 package build (shellcheck) + real-hardware
|
||||||
|
smoke: correctly flagged a genuinely failed user unit on the dev box;
|
||||||
|
V2 GREEN — VM test: induced failed unit → exit 1 + names it + prints
|
||||||
|
fix; reset-failed → healthy exit 0. Menu rebuild bash -n ok.
|
||||||
|
- **Pending:** V3 menu-row check queued. Waybar-warning follow-up →
|
||||||
|
LATER.
|
||||||
|
- **Next suggestion:** NEXT#11 (state-file validation) — doctor's
|
||||||
|
"parses" check is its little sibling; 11 adds validate-before-write
|
||||||
|
+ eval-time schema messages.
|
||||||
|
|
||||||
|
## 2026-07-04 — System › Rollback menu (iteration #19, item 9b → item 9 done)
|
||||||
|
- **Task:** BACKLOG NEXT#9 half (b) — undo one menu away.
|
||||||
|
- **Did:** new `rollback` case in nomarchy-menu (System submenu row):
|
||||||
|
lists the last 10 `home-manager generations` (newest marked current),
|
||||||
|
picking one activates it in a terminal — HM's supported rollback,
|
||||||
|
reversible, so no typed-yes. System-level undo LINKS OUT by design:
|
||||||
|
Snapshots row → existing flow; "boot an older generation (how)" →
|
||||||
|
instruction notification pointing at docs/RECOVERY.md §3 (no
|
||||||
|
destructive reimplementation in rofi). RECOVERY §1 cross-references
|
||||||
|
the menu path. Item 9 complete → deleted.
|
||||||
|
- **Verified:** V0; V1 — template-home built, generated nomarchy-menu
|
||||||
|
bash -n clean, row-render + pick-parse logic run against a fixture
|
||||||
|
`generations` output (id/path extraction correct). V2 skipped
|
||||||
|
deliberately: the only novel logic is the parsing (fixture-covered);
|
||||||
|
the activate step is HM's own mechanism. V3 queued.
|
||||||
|
- **Pending:** V3 rollback-menu exercise on hardware.
|
||||||
|
- **Next suggestion:** NEXT#10 `nomarchy-doctor` (V2-able in a VM).
|
||||||
|
|
||||||
|
## 2026-07-04 — sys-update/-rebuild what-changed diff (iteration #18, item 9a)
|
||||||
|
- **Task:** BACKLOG NEXT#9 half (a) — a human diff after system rebuilds.
|
||||||
|
- **Did:** both sys-update and sys-rebuild (twins stay twins) capture
|
||||||
|
/run/current-system before, and after the switch print
|
||||||
|
`nvd diff before after` (store-path-pinned ${"$"}{pkgs.nvd}, `|| true`
|
||||||
|
so it can't fail a succeeded rebuild; identical-path fast-path says
|
||||||
|
"no changes"). README §3 shortcut block notes it.
|
||||||
|
- **Verified:** V0; V1 — template-system toplevel rebuilt, generated
|
||||||
|
scripts extracted + bash -n, nvd smoke-run against the real closure
|
||||||
|
(correct output format). Runtime behaviour is a trivial shell path —
|
||||||
|
no VM needed.
|
||||||
|
- **Pending:** half (b) — the System → Rollback menu flow (desktop
|
||||||
|
generations picker; system → boot menu + snapshots pointer).
|
||||||
|
- **Next suggestion:** item 9b — it completes the item; V2 the
|
||||||
|
generation-activate path.
|
||||||
|
|
||||||
|
## 2026-07-04 — viewers + mime defaults (iteration #17, item 8)
|
||||||
|
- **Task:** BACKLOG NEXT#8 — PDF/image viewers + xdg-mime defaults.
|
||||||
|
- **Did:** modules/home/viewers.nix (`nomarchy.viewers.enable`, default
|
||||||
|
on): programs.zathura (Stylix themes it — target added to stylix.nix's
|
||||||
|
explicit list, autoEnable=false bit us first try) + imv.
|
||||||
|
modules/home/mime.nix (`nomarchy.mime.enable`): mkDefault
|
||||||
|
xdg.mimeApps for pdf→zathura, image/*→imv, av→mpv, text→code,
|
||||||
|
dir→thunar, html/http(s)→firefox as INERT entries (browser Decision
|
||||||
|
untouched — absent .desktop entries are skipped by GIO). README rows
|
||||||
|
added (option-docs enforces them now). DEVIATION from the item text:
|
||||||
|
viewers are a module toggle, not template packages — zathura's
|
||||||
|
theming needs its HM module, which is exactly the "real config"
|
||||||
|
boundary of the toggle discipline.
|
||||||
|
- **Verified:** V0; V1 — template-home generation builds; asserted
|
||||||
|
rendered mimeapps.list (all associations), themed zathurarc
|
||||||
|
(Tokyo Night rgb), imv/zathura in home-path. V3 smoke queued.
|
||||||
|
- **Pending:** V3 open-a-file smoke; browser Decision now smaller
|
||||||
|
(inert entries ship; only "active in suite?" remains).
|
||||||
|
- **Next suggestion:** NEXT#9 (update & rollback UX) — or #10 doctor.
|
||||||
|
|
||||||
|
## 2026-07-04 — docs slice (c): install story — item 6 COMPLETE (iteration #16)
|
||||||
|
- **Task:** BACKLOG NOW#6 slice (c), the last one — install/first-run
|
||||||
|
narrative end to end.
|
||||||
|
- **Did:** read README §2 (ISO/installer) → §3 (downstream) → template
|
||||||
|
README as one story; checked the facts en route: mkFlake's arg
|
||||||
|
surface == the §3 table (src/username/hardwareProfile/system, lib.nix),
|
||||||
|
disko really makes @snapshots + the hibernation swapfile, .#default /
|
||||||
|
.#me names consistent. One seam fixed: §3 showed `nix flake init -t`
|
||||||
|
but never handed off to the template README's six first-run steps —
|
||||||
|
connective paragraph added (+ "the installer does all of this").
|
||||||
|
Item 6 done → deleted from BACKLOG (NOW now empty); ROADMAP § Full
|
||||||
|
docs review flipped to ✓ with the slice summary.
|
||||||
|
- **Verified:** V0 (docs-only) — flake check clean pre-commit.
|
||||||
|
- **Pending:** docs-site-vs-Markdown stays a Decision.
|
||||||
|
- **Next suggestion:** NEXT#8 (viewers + mime defaults) is the new queue
|
||||||
|
head; note its "Default browser" Decision dependency — the mime module
|
||||||
|
half can proceed with mkDefault degradation regardless.
|
||||||
|
|
||||||
|
## 2026-07-04 — docs slice (d): recovery runbook (iteration #15, item 6d)
|
||||||
|
- **Task:** BACKLOG NOW#6 slice (d) — write the undo story.
|
||||||
|
- **Did:** docs/RECOVERY.md, symptom-ordered: (1) bad theme/HM change →
|
||||||
|
generations / apply-known-good / git-revert ~/.nomarchy; (2) desktop
|
||||||
|
won't start → Ctrl+Alt+F2, greetd + user journals, VM-GL and
|
||||||
|
preactivate-log pointers; (3) system change → systemd-boot older
|
||||||
|
generation (kept: 10) + make-it-stick via sys-rebuild; (4) files →
|
||||||
|
btrfs-assistant / sudo nomarchy-snapshots (undochange, root rollback,
|
||||||
|
typed-yes); (5) ISO + nixos-enter. Every command checked against the
|
||||||
|
tree (greetd cfg, configurationLimit, snapshots script actions,
|
||||||
|
helper names). Linked from README tree + §5.
|
||||||
|
- **Verified:** V0 (docs-only) — flake check clean pre-commit.
|
||||||
|
- **Pending:** slice (c) install-story read-through — the last of item 6.
|
||||||
|
- **Next suggestion:** finish item 6 with slice (c).
|
||||||
|
|
||||||
|
## 2026-07-04 — docs slice (b): drift pass (iteration #14, item 6b)
|
||||||
|
- **Task:** BACKLOG NOW#6 slice (b) — OVERRIDES.md / TESTING.md /
|
||||||
|
templates/downstream/README.md vs the live tree.
|
||||||
|
- **Did:** spot-checked every factual claim: mkDefault sites (hyprland
|
||||||
|
behaviour knobs, ghostty paddings, waybar mainBar/style), bind-list
|
||||||
|
normal priority, `set ui.gapsOut` CLI key, awww(-daemon) naming,
|
||||||
|
21 presets, tokyo-night's 4 wallpapers, summer-night's light @fg bar,
|
||||||
|
live `,highres` mkForce, .gitea/workflows/check.yml, QEMU gl flags,
|
||||||
|
template `.#me` + ~/.nomarchy/NOMARCHY_PATH. All accurate. Fixed the
|
||||||
|
two real gaps: OVERRIDES §2 predated `nomarchy.monitors` (now routes
|
||||||
|
there + quick-ref row); TESTING §1 lacked the shell-syntax check §1b
|
||||||
|
claims CI runs (added `bash -n`).
|
||||||
|
- **Verified:** V0 (docs-only; flake untouched — check run pre-commit).
|
||||||
|
- **Pending:** slices (c) install story, (d) recovery runbook.
|
||||||
|
- **Next suggestion:** item 6 slice (c) or (d) — (d) is self-contained
|
||||||
|
and ships user value (the runbook).
|
||||||
|
|
||||||
|
## 2026-07-04 — docs slice (a): option-surface reconcile (iteration #13, item 6a)
|
||||||
|
- **Task:** BACKLOG NOW#6, first slice — README tables vs live options.
|
||||||
|
- **Did:** split item 6 into slices (a–d) in BACKLOG. Reconciled: 9
|
||||||
|
undocumented options (autoTimezone.enable!, camera.hideIrSensor +
|
||||||
|
irMatch!, intel.guc, amd.pstate/vaapi, package, system.stateFile,
|
||||||
|
restic.paths) — rows/inline mentions added, no stale rows found.
|
||||||
|
Made it permanent: `checks.option-docs` — flake.nix eval-walks option
|
||||||
|
names from the 4 option files (config halves stay lazy; dummy args)
|
||||||
|
→ tools/check-option-docs.py enforces row-or-`.leaf`-mention + flags
|
||||||
|
stale rows.
|
||||||
|
- **Verified:** V0; V1 — check builds green (78 options); negative test:
|
||||||
|
same script vs the pre-fix README reports exactly the 9 gaps.
|
||||||
|
- **Pending:** slices (b) doc drift pass, (c) install story, (d)
|
||||||
|
recovery runbook.
|
||||||
|
- **Next suggestion:** item 6 slice (b) — or NEXT#8 (viewers+mime) for
|
||||||
|
variety; both fine.
|
||||||
|
|
||||||
|
## 2026-07-04 — Back audit (iteration #12, item 24)
|
||||||
|
- **Task:** BACKLOG NOW#24 — every list menu ends in ↩ Back.
|
||||||
|
- **Did:** audited every `rofi -dmenu` call site in the generated
|
||||||
|
nomarchy-menu + nomarchy-vpn. Already compliant: power, power-profile,
|
||||||
|
theme, clipboard, files, audio, display (both stages), capture,
|
||||||
|
tools, system, VPN main/import/exit-node/tailscale. Fixed: keybinds
|
||||||
|
cheatsheet (Enter was a silent exit) now ends in ↩ Back → root
|
||||||
|
picker. Documented the exceptions in rofi.nix: external modi
|
||||||
|
(calc/emoji/networkmanager_dmenu/rofi-pulse-select) can't take an
|
||||||
|
injected row (Esc = back); free-text prompts (web/ask) have no list.
|
||||||
|
- **Verified:** V0; V1 — built nomarchy-menu, bash -n OK; awk audit
|
||||||
|
over the generated script: only rows lacking back are the root
|
||||||
|
picker (by design) and the free-text prompt. V3 spot-check queued.
|
||||||
|
- **Pending:** V3 spot-check. NOW now holds only item 6 (docs, [big]).
|
||||||
|
- **Next suggestion:** item 6 first slice, or NEXT#8 (viewers+mime).
|
||||||
|
|
||||||
|
## 2026-07-04 — network menu blank rows (iteration #11, item 22)
|
||||||
|
- **Task:** BACKLOG NOW#22 — nameless entries in the network picker.
|
||||||
|
- **Did:** read the pinned networkmanager_dmenu 2.6.2 source: with
|
||||||
|
`compact = False` (our config!) it inserts literal empty rows as
|
||||||
|
section separators (eth/wifi/vpn) — the systematic blank entries.
|
||||||
|
Flipped config.ini to `compact = True` (also unpadded row format,
|
||||||
|
better in rofi's proportional font). Hidden-SSID APs additionally
|
||||||
|
render ONE nameless sec+bars row (dedup keeps one; not config-
|
||||||
|
filterable) — documented, V3-gated, source-patch follow-up if seen.
|
||||||
|
- **Verified:** V0; V1 — rendered config.ini shows compact = True.
|
||||||
|
Behavior needs Wi-Fi hardware → V3 queued.
|
||||||
|
- **Pending:** V3 on the Latitude (no separators; hidden-AP residual?).
|
||||||
|
- **Next suggestion:** item 24 (Back audit) — grep-the-generated-script.
|
||||||
|
|
||||||
|
## 2026-07-04 — waybar/rofi palette-safe pairings (iteration #10, item 27)
|
||||||
|
- **Task:** BACKLOG NOW#27 — generated waybar/rofi CSS invisible on
|
||||||
|
on-surface palettes (flexoki-light runs it; summers whole-swap).
|
||||||
|
- **Did:** waybar.nix generated CSS: module row + #window →
|
||||||
|
alpha(@text, 0.85); inactive workspaces / dnd / pulseaudio.muted →
|
||||||
|
alpha(@text, 0.5) (gruvbox's muted/base was 1.27). rofi.nix: @dim →
|
||||||
|
text+80, @surface → text+1a (#RRGGBBAA fg tints). Contrast check
|
||||||
|
docstring/pairings now cover all three generated surfaces. Status
|
||||||
|
glyphs (good/warn/bad on base, worst 2.05) left as-is — palette
|
||||||
|
design, human call. Generated bar only; whole-swaps untouched.
|
||||||
|
- **Verified:** V0; V1 — checks.theme-contrast green (21 themes),
|
||||||
|
downstream-template-home builds, rendered waybar style has zero
|
||||||
|
@subtext/@muted/@surface, rendered custom.rasi shows fg-derived
|
||||||
|
tints. NOT visually verified — V3 queued (flexoki-light eyeball).
|
||||||
|
- **Pending:** V3 flexoki-light + dark-theme regression spot-check.
|
||||||
|
- **Next suggestion:** item 22 (network menu rows) — V1-actionable.
|
||||||
|
|
||||||
|
## 2026-07-04 — swaync contrast fix + theme-contrast check (iteration #9, item 25)
|
||||||
|
- **Task:** BACKLOG NOW#25 — swaync text invisible on summer-day.
|
||||||
|
- **Did:** swaync.nix now uses only palette-safe pairings: body/summary
|
||||||
|
= @text on @base (worst ratio 5.18 across all 21 themes; subtext/base
|
||||||
|
was 1.00 on summer-day + flexoki-light), hover rows + widget buttons
|
||||||
|
= alpha(@text, 0.1) tints (contrast by construction); dropped the
|
||||||
|
subtext/surface defines. NEW permanent check `checks.theme-contrast`
|
||||||
|
(tools/check-theme-contrast.py) asserts the hex-on-hex text pairings
|
||||||
|
across every theme JSON. Audit found the same mispairing in generated
|
||||||
|
waybar/rofi CSS, live on flexoki-light (no whole-swap) → NOW item 27.
|
||||||
|
- **Verified:** V0; V1 — checks.theme-contrast builds green (21 themes),
|
||||||
|
rendered services.swaync.style contains zero @subtext/@surface.
|
||||||
|
NOT V2/V3-verified visually — queued (Bernardo is at the Latitude).
|
||||||
|
- **Pending:** V3 notify-send readability check on summer-day; item 27.
|
||||||
|
- **Next suggestion:** item 27 (same bug class, waybar/rofi surfaces).
|
||||||
|
|
||||||
|
## 2026-07-04 — SUPER+? bind fix (iteration #8, item 26)
|
||||||
|
- **Task:** BACKLOG NOW#26 — cheatsheet bind never fires on hardware.
|
||||||
|
- **Did:** keybinds.nix: `$mod, question` → `$mod SHIFT, question`
|
||||||
|
(? is Shift+/, Hyprland matches the exact modmask); rofi.nix
|
||||||
|
prettyKeys collapses "SHIFT + ?" → "?" so the row stays SUPER + ?.
|
||||||
|
Gotcha added to MEMORY.md (shifted keysyms need SHIFT in mods).
|
||||||
|
- **Verified:** V0 (flake check --no-build); V1 both surfaces — eval'd
|
||||||
|
hyprland settings.bind renders `$mod SHIFT, question, exec,
|
||||||
|
nomarchy-menu keybinds`, and built nomarchy-menu's cheatsheet file
|
||||||
|
renders `SUPER + ?`. No other shifted keysyms in the bind list.
|
||||||
|
- **Pending:** V3 queued (SUPER+? on the Latitude after home-update +
|
||||||
|
relogin).
|
||||||
|
- **Next suggestion:** item 25 (swaync contrast on summer-day).
|
||||||
|
|
||||||
|
## 2026-07-04 — Latitude hardware sweep #2 (Bernardo; results booked, no code)
|
||||||
|
- **Task:** V3 sweep on the Latitude after pulling ≥18b8545 + reboot.
|
||||||
|
- **PASS:** waybar supervisor (theme switches clean; `pkill -x waybar`
|
||||||
|
respawns instantly); snapshots — themed polkit prompt → GUI as root,
|
||||||
|
fzf fallback works (restore/rollback gate not exercised → residual
|
||||||
|
queued); `sys-rebuild`; night-light enable/disable; auto-commit
|
||||||
|
(theme commits + the toggle self-commit); hibernate single-unlock +
|
||||||
|
suspend-still-locks (1b0eeea CONFIRMED).
|
||||||
|
- **PASS (late confirm):** auto-timezone — `timedatectl` shows
|
||||||
|
Europe/London.
|
||||||
|
- **Bug:** SUPER+? never fires — `$mod, question` misses because a real
|
||||||
|
? carries SHIFT in the modmask → BACKLOG 26 (bind-only: the menu
|
||||||
|
itself opens fine from a terminal). SUPER+SHIFT+K no-op was the
|
||||||
|
comma-layout gate working (none configured) — retest queued.
|
||||||
|
- **Next suggestion:** item 25 (swaync contrast) or 26 (cheatsheet bind).
|
||||||
|
|
||||||
|
## 2026-07-04 — Waybar resilience + sys-rebuild (iteration #7, items 21+23)
|
||||||
|
- **Task:** the two top Latitude findings.
|
||||||
|
- **Did:** (21) `nomarchy-waybar` supervisor (waybar.nix, exec-once'd
|
||||||
|
from hyprland.nix): ANY waybar exit respawns, crash-loop guard (5
|
||||||
|
fast exits → critical notify + stop), TERM trap for a real stop.
|
||||||
|
theme-sync now prefers a clean `pkill -x waybar` when the supervisor
|
||||||
|
is running (restart with fresh config+style — avoids waybar's
|
||||||
|
in-place SIGUSR2 reload entirely, the suspected double-reload race
|
||||||
|
with reload_style_on_change during symlink flips); SIGUSR2 stays as
|
||||||
|
the unsupervised fallback; reload_style_on_change kept for manual
|
||||||
|
home-update restyles. (23) `sys-rebuild` — snapshot-first rebuild
|
||||||
|
against the current lock, no `nix flake update`; README §3/§5 + motd.
|
||||||
|
- **Verified:** V0; V1 (HM renders `exec-once=nomarchy-waybar`,
|
||||||
|
supervisor bash -n; `sys-rebuild` in systemPackages). V2: headless
|
||||||
|
software-GL desktop VM (recipe from memory — gotchas hit: node needs
|
||||||
|
the overlay, users.users.<u>, useGlobalPkgs) — SIGKILL→new pid, clean
|
||||||
|
kill→respawn, SIGUSR2→alive. Result recorded below once green.
|
||||||
|
- **Pending:** V3 on the Latitude: theme switch survives / bar returns.
|
||||||
|
- **Next suggestion:** item 22 (network menu rows) or 24 (Back audit).
|
||||||
|
|
||||||
|
## 2026-07-04 — Keyboard cycle bind + parity (iteration #6) + Latitude triage
|
||||||
|
- **Task:** BACKLOG NOW#5; mid-iteration Bernardo delivered Latitude
|
||||||
|
5410 hardware-QA findings (the machine got a real session!).
|
||||||
|
- **Did:** `multiLayoutBinds` in keybinds.nix (SUPER+SHIFT+K →
|
||||||
|
`switchxkblayout current next`), gated in hyprland.nix AND the rofi
|
||||||
|
cheatsheet on the same comma-in-layout condition; `hyprland/language`
|
||||||
|
+ `#language` CSS added to both summer whole-swaps (shows even
|
||||||
|
single-layout there — static JSON can't gate; deliberate). Reverse
|
||||||
|
parity gap found (summer-night has idle_inhibitor, generated bar
|
||||||
|
doesn't) → folded into item 13. **Triage:** four new NOW items from
|
||||||
|
hardware: #21 Waybar crash on theme switch + no respawn (top),
|
||||||
|
#22 nameless network-menu entries, #23 `sys-rebuild` (no-update
|
||||||
|
rebuild), #24 Back-everywhere audit.
|
||||||
|
- **Verified:** V0 (JSON + flake check) + V1 both directions
|
||||||
|
(single-layout build: no bind; `us,de` via extendModules: bind + the
|
||||||
|
cheatsheet row render; summer JSONs parse).
|
||||||
|
- **Pending:** V3 cycle-bind check queued; items 21/22/24 carry V3
|
||||||
|
re-checks on the Latitude.
|
||||||
|
- **Next suggestion:** #21 (waybar crash — stability pillar, user-hit).
|
||||||
|
|
||||||
|
## 2026-07-04 — Webcam follow-ups (loop iteration #5, quick item)
|
||||||
|
- **Task:** BACKLOG NOW#7 (Bernardo asked for "a quick item").
|
||||||
|
- **Did:** template `home.packages` gains a commented "Webcam tuning"
|
||||||
|
pair (cameractrls GUI, v4l-utils CLI — bare packages, so template not
|
||||||
|
toggle, per the option-surface rule); the portal/Flatpak libcamera IR
|
||||||
|
gap is written up as a PROPOSED item with three options (recommend:
|
||||||
|
document-only now, libcamera-rule investigation when the T14s is
|
||||||
|
available). CI runs #60/#61 confirmed green (earlyoom + snapshot fix).
|
||||||
|
- **Verified:** V0 (flake check — template evals through mkFlake;
|
||||||
|
changes are comments + agent docs).
|
||||||
|
- **Next suggestion:** NOW#5 (keyboard cycle bind + summer parity) —
|
||||||
|
the last code item in NOW besides the docs pass.
|
||||||
|
|
||||||
|
## 2026-07-04 — Snapshot GUI un-broken + polkit agent (loop iteration #4)
|
||||||
|
- **Task:** BACKLOG NOW#4 — btrfs-assistant segfault.
|
||||||
|
- **Did:** re-diagnosed instead of overriding. gdb: crash is in
|
||||||
|
libbtrfsutil's *unprivileged* subvolume iteration (btrfs-progs 6.17.1;
|
||||||
|
upstream fix `886571653` post-6.17.1; symbol versions verified — not
|
||||||
|
ABI drift). VM A/B: root works (exit 0), user crashes (139). The
|
||||||
|
launcher runs it as root → GUI fine *if* pkexec can prompt — and the
|
||||||
|
distro shipped **no polkit agent** (all pkexec silently failed; the
|
||||||
|
actual root cause of "GUI is dead"). Shipped: hyprpolkitagent
|
||||||
|
(exec-once, Stylix-themed Qt), menu re-pointed to the launcher with
|
||||||
|
the fzf flow as fallback, `checks.snapshot-gui` canary (root path +
|
||||||
|
offscreen event loop on real btrfs). No btrfs-progs patch — root-side
|
||||||
|
flows don't hit the bug; the fix arrives with a lock bump.
|
||||||
|
- **Verified:** V0 + V2 (snapshot-gui check, run for real) + V1 (HM
|
||||||
|
generation renders the agent exec-once; menu bash -n).
|
||||||
|
- **Pending:** V3 queued — first on-hardware themed polkit prompt.
|
||||||
|
- **Next suggestion:** NOW#5 (keyboard cycle bind + summer parity).
|
||||||
|
|
||||||
|
## 2026-07-04 — CI is green (run #58) — item 20 main half closed
|
||||||
|
- **Task:** monitor follow-up, no code. Run #58 (the .gitea path fix)
|
||||||
|
**succeeded** — first green CI: the container recipe works on the
|
||||||
|
live runner, eval tier confirmed end to end.
|
||||||
|
- **Did:** BACKLOG item 20 reduced to its stretch (KVM runner → enable
|
||||||
|
vm-checks), moved to NEXT. Run #59 (earlyoom push) monitored.
|
||||||
|
- **Next suggestion:** NOW#4 (btrfs-assistant override attempt).
|
||||||
|
|
||||||
|
## 2026-07-04 — Memory-pressure protection shipped (loop iteration #3)
|
||||||
|
- **Task:** BACKLOG NOW#3 — default-on userspace OOM killer.
|
||||||
|
- **Did:** `modules/nixos/oom.nix`: earlyoom (mkDefault on, desktop
|
||||||
|
notifications, session-plumbing `--avoid` list, no `--prefer`) +
|
||||||
|
`systemd.oomd.enable = false`. Choice rationale: Hyprland session is
|
||||||
|
one cgroup scope → oomd's cgroup-level kill would nuke the desktop;
|
||||||
|
earlyoom is process-level. Found en route: nixpkgs default-enables
|
||||||
|
oomd *inert* (enable=true, all slice toggles false). README "beyond
|
||||||
|
the surface" note added.
|
||||||
|
- **Verified:** V0 (flake check) + **V2** — new `checks.oom-protection`
|
||||||
|
runNixOSTest, run for real: hog (chunked allocator, 686 MB peak in a
|
||||||
|
1 GB VM) SIGTERM'd by earlyoom in 0.1 s, bystander unit survived,
|
||||||
|
oomd asserted inactive. 25 s test, cheap enough for the suite.
|
||||||
|
- **Pending:** nothing hardware-specific (behavior fully VM-provable).
|
||||||
|
- **Next suggestion:** NOW#4 (btrfs-assistant override attempt). Also:
|
||||||
|
CI run #58 (the .gitea fix) was *running* at commit time — check its
|
||||||
|
outcome next tick; this push triggers #59.
|
||||||
|
|
||||||
|
## 2026-07-04 — CI fix: wrong workflow dir (correction to iteration #2)
|
||||||
|
- **Task:** Bernardo reported no run despite an active runner + shared
|
||||||
|
his compose file: the server is **Gitea** (gitea/act_runner), not
|
||||||
|
Forgejo — I'd shipped the workflow to `.forgejo/workflows/`, which
|
||||||
|
Gitea never reads. The legacy repo's `.gitea/workflows/` path was the
|
||||||
|
clue I under-weighted.
|
||||||
|
- **Did:** `git mv` → `.gitea/workflows/check.yml`; corrected the
|
||||||
|
Forgejo references in the workflow header, TESTING.md §1b, BACKLOG
|
||||||
|
item 20 (now: watch the first run; runner was never the problem);
|
||||||
|
MEMORY.md gains the Gitea-not-Forgejo line.
|
||||||
|
- **Verified:** the push of this commit is itself the test — the run
|
||||||
|
must appear; monitoring.
|
||||||
|
- **Pending:** first green run (item 20); runner-container memory
|
||||||
|
headroom is the watch-out.
|
||||||
|
|
||||||
|
## 2026-07-04 — CI checks-on-push shipped (loop iteration #2)
|
||||||
|
- **Task:** BACKLOG NOW#2 — Forgejo Actions workflow.
|
||||||
|
- **Did:** `.forgejo/workflows/check.yml` (push to main/v1 + dispatch):
|
||||||
|
flake check --no-build, theme-sync py_compile, bash -n over tracked
|
||||||
|
.sh. Scoped to the **eval tier** deliberately — API probing +
|
||||||
|
archaeology of the legacy `.gitea/workflows/check.yml` (57 runs on
|
||||||
|
this instance) showed the runner is an act_runner docker container
|
||||||
|
(no KVM/systemd), so the VM suite can't run there; a commented
|
||||||
|
`vm-checks` job documents the KVM-runner upgrade path. Legacy's
|
||||||
|
hard-won container gotchas (nixbld setup, sandbox=false for Stylix
|
||||||
|
IFD, Nix 2.31.5 pin) carried over verbatim. TESTING.md §1b added.
|
||||||
|
- **Verified:** V0 locally (same commands the workflow runs, minus the
|
||||||
|
container Nix install) + yq YAML parse. The real green run needs the
|
||||||
|
runner to be alive — **not confirmable from here** (runners API is
|
||||||
|
401 unauthenticated); watching the run after push.
|
||||||
|
- **Pending:** new `[human]` item 20 — confirm/re-register the runner;
|
||||||
|
stretch: a KVM runner unlocks the vm-checks job.
|
||||||
|
- **Next suggestion:** NOW#3 (memory-pressure protection).
|
||||||
|
|
||||||
|
## 2026-07-04 — Opt-in auto-commit shipped (loop iteration #1)
|
||||||
|
- **Task:** BACKLOG NOW#1 — auto-commit of state mutations (in-flake
|
||||||
|
state Phase 4). First autonomous /loop iteration.
|
||||||
|
- **Did:** `settings.autoCommit` live-read by nomarchy-theme-sync;
|
||||||
|
pathspec-limited commit of theme-state.json on apply/set (fires if flag
|
||||||
|
on before OR after the write → the off-toggle commits too); identity
|
||||||
|
fallback; same-value no-op; `bg` excluded. Menu: System › Auto-commit
|
||||||
|
(instant, self-gated on `.git`). Rider: `get` prints booleans as JSON
|
||||||
|
`true`/`false`, fixing the stuck "Auto timezone (on/off)" menu label.
|
||||||
|
BACKLOG numbering switched to stable IDs (no renumbering).
|
||||||
|
- **Verified:** V0 (py_compile, flake check) + V1 (HM generation builds;
|
||||||
|
generated menu `bash -n`) + a 7-assertion sandbox git-repo round-trip
|
||||||
|
(enable/set/same-value/disable/post-disable/apply/identity-fallback).
|
||||||
|
- **Pending:** V3 queued in HARDWARE-QUEUE (on-machine toggle + apply).
|
||||||
|
- **Next suggestion:** NOW#2 (CI checks-on-push) — but its runner half
|
||||||
|
may need Bernardo to register a Forgejo runner; deliver the workflow
|
||||||
|
regardless.
|
||||||
|
|
||||||
|
## 2026-07-04 — Backlog revision pass (human-requested)
|
||||||
|
- **Task:** Bernardo asked for a philosophy-aligned revision of BACKLOG.md
|
||||||
|
("I'm sure I'm forgetting important items").
|
||||||
|
- **Did:** verified guessed gaps against the tree first (GC/optimise/boot
|
||||||
|
limit + all 21 previews already ship — dropped those ideas). Added the
|
||||||
|
confirmed gaps: CI-on-push promoted to NOW#2 (agents push to main now),
|
||||||
|
memory-pressure protection NOW#3 (nothing mitigates OOM; the release
|
||||||
|
bump died to one), viewers+mime defaults #8, update/rollback UX #9,
|
||||||
|
nomarchy-doctor #10, state-file validation #11, screen recording #12,
|
||||||
|
niceties batch #13 (idle-inhibit, low-battery notify, hyprpicker), OCR
|
||||||
|
in LATER; recovery runbook folded into the docs item; zram + default
|
||||||
|
browser added to Decisions.
|
||||||
|
- **Verified:** V0 (docs-only).
|
||||||
|
- **Pending:** Bernardo to sanity-check the new NOW ordering, esp. CI at
|
||||||
|
#2 and the two new Decisions.
|
||||||
|
- **Next suggestion:** unchanged — NOW#1 (opt-in auto-commit).
|
||||||
|
|
||||||
|
## 2026-07-04 — Bootstrap the loop infrastructure (this commit)
|
||||||
|
- **Task:** create `agent/` (human-requested): LOOP/GOALS/BACKLOG/
|
||||||
|
CONVENTIONS/MEMORY/HARDWARE-QUEUE/JOURNAL, root CLAUDE.md, README +
|
||||||
|
ROADMAP pointers.
|
||||||
|
- **Did:** reworked the forward half of docs/ROADMAP.md into the tiered
|
||||||
|
BACKLOG (5 NOW / 6 NEXT / LATER / Decisions); collected every pending
|
||||||
|
on-hardware check into HARDWARE-QUEUE.md; seeded MEMORY.md from the
|
||||||
|
ROADMAP's decision records.
|
||||||
|
- **Verified:** V0 (docs-only change; `nix flake check --no-build` run to
|
||||||
|
confirm the tree still evaluates).
|
||||||
|
- **Pending:** Bernardo to sanity-read GOALS.md pillars + BACKLOG tiering
|
||||||
|
— reorder freely, the order *is* the instruction.
|
||||||
|
- **Next suggestion:** BACKLOG NOW#1 (opt-in auto-commit — Phase 4 of
|
||||||
|
in-flake state, already the agreed next step).
|
||||||
147
agent/LOOP.md
Normal file
147
agent/LOOP.md
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
# The loop — autonomous iteration protocol
|
||||||
|
|
||||||
|
How an AI agent works on Nomarchy unattended. One **iteration** = pick one
|
||||||
|
task, do it, verify it, commit it, record it. The protocol is
|
||||||
|
runner-agnostic; the same iteration works under any of:
|
||||||
|
|
||||||
|
- **Interactive `/loop`** in a Claude Code session in this repo — the agent
|
||||||
|
self-paces iterations until stopped.
|
||||||
|
- **Headless** (`claude -p`, cron/systemd-timer) — one invocation runs one
|
||||||
|
iteration (or a small fixed number) and exits.
|
||||||
|
- **A fresh manual session** — a human says "do a loop iteration"; the
|
||||||
|
files below carry all the state, so any session can pick up where the
|
||||||
|
last left off.
|
||||||
|
|
||||||
|
All loop state lives in this directory, git-tracked. There is no state
|
||||||
|
outside the checkout (the distro's own philosophy, applied to its agents).
|
||||||
|
|
||||||
|
## The files
|
||||||
|
|
||||||
|
| File | Role | Who writes it |
|
||||||
|
|---|---|---|
|
||||||
|
| `GOALS.md` | North star + quality bars + non-goals | Human (agents propose edits) |
|
||||||
|
| `BACKLOG.md` | Prioritized task queue (NOW/NEXT/LATER/PROPOSED/DECISIONS) | Both — see its header rules |
|
||||||
|
| `JOURNAL.md` | Append-only iteration log | Agents |
|
||||||
|
| `MEMORY.md` | Curated durable lessons/gotchas | Agents (curated, not append-only) |
|
||||||
|
| `HARDWARE-QUEUE.md` | Pending on-hardware checks only Bernardo can run | Agents append, human checks off |
|
||||||
|
| `CONVENTIONS.md` | Repo/design conventions to follow while coding | Human (agents propose edits) |
|
||||||
|
|
||||||
|
## Model & token economy
|
||||||
|
|
||||||
|
Spend expensive tokens on judgment, not mechanics.
|
||||||
|
|
||||||
|
- **Plan and reason on the strong model.** Orientation, task selection,
|
||||||
|
design, debugging, Nix eval semantics, verification judgment, and
|
||||||
|
anything that would land in a commit unreviewed stay with the
|
||||||
|
top-tier model running the loop (Fable 5).
|
||||||
|
- **Delegate mechanical subtasks to cheaper models.** When a subtask is
|
||||||
|
fully specified and needs no design judgment — grep/audit sweeps,
|
||||||
|
README-option-table reconciliation, a repeated edit applied across
|
||||||
|
files, summarizing long logs or check output — hand it to a subagent
|
||||||
|
with a `model` override: `haiku` for search/summarize/audit, `sonnet`
|
||||||
|
for routine well-specified edits. The strong model writes the spec,
|
||||||
|
reviews the result, and owns the commit. Only delegate when writing
|
||||||
|
the spec is cheaper than doing the work — a spawned agent starts cold
|
||||||
|
and must re-derive context.
|
||||||
|
- **Read narrowly.** Step 0's list is the whole orientation read (the
|
||||||
|
*last 3–5 entries* of the journal, never the full file). Read large
|
||||||
|
files by section, don't re-read what's already in context, and tail
|
||||||
|
build/check logs instead of dumping them.
|
||||||
|
- **Write tersely.** Journal entries follow the template and no more;
|
||||||
|
commit bodies state what/why/tier, not a narrative.
|
||||||
|
- **Headless runners** may run whole low-stakes iterations (QA sweeps,
|
||||||
|
docs-drift passes) on a cheaper `--model`; iterations touching
|
||||||
|
`modules/` or `pkgs/` behavior keep the strong model.
|
||||||
|
|
||||||
|
## One iteration, step by step
|
||||||
|
|
||||||
|
### 0. Orient
|
||||||
|
1. Read `GOALS.md`, `CONVENTIONS.md`, `MEMORY.md`, the **last 3–5 entries**
|
||||||
|
of `JOURNAL.md`, and `BACKLOG.md`.
|
||||||
|
2. `git pull --ff-only` (skip silently if offline). Confirm you are on
|
||||||
|
`main` with a clean tree. **A dirty tree you didn't create → stop and
|
||||||
|
report; never stash or discard someone else's work.**
|
||||||
|
3. Sanity baseline: if the last journal entry reports a red
|
||||||
|
`nix flake check`, or you have any reason to suspect breakage, run
|
||||||
|
`nix flake check --no-build` first. **A red baseline preempts the
|
||||||
|
backlog — fixing it *is* this iteration's task.**
|
||||||
|
|
||||||
|
### 1. Pick exactly one task
|
||||||
|
- Take the **topmost actionable** item: NOW before NEXT; never LATER
|
||||||
|
unless NOW and NEXT are empty or all blocked.
|
||||||
|
- *Actionable* means: not `[blocked:hw]` (those wait in
|
||||||
|
`HARDWARE-QUEUE.md`), not `[human]` (decisions), and small enough to
|
||||||
|
finish + verify in one iteration. If the top item is too big, **split
|
||||||
|
it in BACKLOG.md** (that edit is part of the iteration) and take the
|
||||||
|
first slice.
|
||||||
|
- Never implement anything from **PROPOSED** — those await human triage.
|
||||||
|
- If nothing is actionable, do a **QA sweep** instead: run the full check
|
||||||
|
suite, hunt drift (README option tables vs the live `nomarchy.*`
|
||||||
|
surface, template drift, dead code), deepen a VM test, or research and
|
||||||
|
write up a PROPOSED item. An iteration that only improves the backlog
|
||||||
|
is a valid iteration. If even that yields nothing, journal it and stop
|
||||||
|
— do not manufacture churn.
|
||||||
|
|
||||||
|
### 2. Work
|
||||||
|
- Keep the diff focused on the task. Unrelated fixes you trip over become
|
||||||
|
PROPOSED/NOW entries, not scope creep.
|
||||||
|
- Mechanical, fully-specified sub-steps go to a cheaper model
|
||||||
|
(see *Model & token economy* above); design and review stay here.
|
||||||
|
- Follow `CONVENTIONS.md`. Match the surrounding hand-formatting; never
|
||||||
|
run a formatter.
|
||||||
|
- New gotcha discovered the hard way → one line in `MEMORY.md` now, while
|
||||||
|
it's fresh.
|
||||||
|
|
||||||
|
### 3. Verify — the ladder
|
||||||
|
Climb as high as the change warrants and your environment allows; **record
|
||||||
|
the tier reached** in the commit body and journal entry.
|
||||||
|
|
||||||
|
| Tier | What | When required |
|
||||||
|
|---|---|---|
|
||||||
|
| **V0** | `nix flake check --no-build` (+ `bash -n` / `py_compile` for scripts) | Every change, no exceptions |
|
||||||
|
| **V1** | Build the touched output: `system.build.toplevel`, the HM generation, the ISO, or the package | Anything beyond docs/comments |
|
||||||
|
| **V2** | VM: a `checks.*` runNixOSTest (add one if the change is guardable), or boot `tools/test-live-iso.sh` / `tools/test-install.sh` | Behavioral changes — services, boot, installer, session |
|
||||||
|
| **V3** | Real hardware | Cannot be done by the agent → append to `HARDWARE-QUEUE.md` with exact test steps |
|
||||||
|
|
||||||
|
The honesty rule governs: a visual/interactive change verified only to V1
|
||||||
|
is **not done** — it ships as "V1-verified, V2/V3 pending" with the pending
|
||||||
|
check queued. Prefer *adding a permanent `checks.*` test* over a one-off
|
||||||
|
manual VM poke when the behavior is testable headlessly (see MEMORY.md for
|
||||||
|
the reusable recipes).
|
||||||
|
|
||||||
|
### 4. Commit + push
|
||||||
|
- Style: match the log — `feat(scope): …`, `fix(scope): …`,
|
||||||
|
`test(scope): …`, `docs(scope): …`. Body explains what/why + the
|
||||||
|
verification tier reached and what remains.
|
||||||
|
- Include the `agent/` bookkeeping updates (backlog/journal/memory/queue)
|
||||||
|
**in the same commit** as the change they describe.
|
||||||
|
- Commit directly on `main` and `git push` (Bernardo's standing workflow).
|
||||||
|
- **Never:** force-push; touch the `v1` branch or any branch/tag you
|
||||||
|
didn't create; commit secrets or binaries; run `nix flake update`
|
||||||
|
unless the task is explicitly a lock bump; delete themes, wallpapers,
|
||||||
|
or user-facing assets without the backlog saying so.
|
||||||
|
|
||||||
|
### 5. Record
|
||||||
|
1. Mark the task in `BACKLOG.md` (move to its ✓ line or delete, per that
|
||||||
|
file's rules).
|
||||||
|
2. Append a `JOURNAL.md` entry (template in that file).
|
||||||
|
3. Queue any V3 checks in `HARDWARE-QUEUE.md`.
|
||||||
|
|
||||||
|
### 6. Pace (self-paced runners only)
|
||||||
|
Under `/loop`, continue to the next iteration while tasks remain
|
||||||
|
actionable and checks stay green. Stop the loop when: nothing is
|
||||||
|
actionable, the same task has failed twice (journal the failure analysis
|
||||||
|
and mark the item `[stuck]`), or a `[human]` decision blocks everything
|
||||||
|
remaining.
|
||||||
|
|
||||||
|
## Stop-and-escalate conditions (any runner)
|
||||||
|
|
||||||
|
Write a journal entry + a BACKLOG note, then stop, when:
|
||||||
|
- A fix would require touching `v1`, force-pushing, or a nixpkgs release
|
||||||
|
jump.
|
||||||
|
- The working tree contains uncommitted work you didn't create.
|
||||||
|
- A task turns out to need a design decision Bernardo hasn't made → move
|
||||||
|
it to **Decisions** in BACKLOG.md with the options laid out.
|
||||||
|
- Two consecutive iterations failed on the same task (`[stuck]`).
|
||||||
|
- Anything would delete or rewrite user data, git history, or the state
|
||||||
|
file schema in a non-backward-compatible way.
|
||||||
97
agent/MEMORY.md
Normal file
97
agent/MEMORY.md
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
# Memory — durable lessons, learned the hard way
|
||||||
|
|
||||||
|
Curated, not append-only: one line per fact, newest at the top of its
|
||||||
|
section; delete entries that stop being true. Details usually live in a
|
||||||
|
docs/ROADMAP.md decision record — pointer given as (§ item). Add a fact
|
||||||
|
here the moment a debugging session teaches you something a future
|
||||||
|
iteration would otherwise rediscover.
|
||||||
|
|
||||||
|
## Testing & VM recipes
|
||||||
|
- **tuigreet dies silently under runNixOSTest** (even bare, no theme
|
||||||
|
flag: greetd sits as "(greetd)" with no child, nothing in the
|
||||||
|
journal — its stderr goes to the VT) — nixpkgs' own greetd test uses
|
||||||
|
agreety instead. Greeter *rendering* is interactive-ISO/hardware
|
||||||
|
tier; don't burn another session on a checks.greeter VM test.
|
||||||
|
- In VM tests `pgrep -f PATTERN` can match the test backdoor's own
|
||||||
|
`bash -c` wrapper (the pattern is in its cmdline) — use `pgrep -x`
|
||||||
|
or a `[t]uigreet`-style bracket pattern.
|
||||||
|
- A checks.* fixture CANNOT be a writeText/toFile state file read at
|
||||||
|
eval time ("path … is not valid" — flake check's eval store won't
|
||||||
|
realise it): extract the logic into a pure importable file and
|
||||||
|
unit-test THAT (monitor-rules.nix / checks.display-profiles is the
|
||||||
|
pattern).
|
||||||
|
- CI (`.gitea/workflows/check.yml`) is **eval-tier only**: the act_runner
|
||||||
|
is a docker container (no systemd, no /dev/kvm). Container gotchas are
|
||||||
|
documented in the workflow header (single-user Nix + nixbld users,
|
||||||
|
`sandbox=false` for Stylix IFD, Nix pinned 2.31.5 vs lazy-trees, no JS
|
||||||
|
actions past node20) — learned over the legacy repo's 57 runs; read
|
||||||
|
them before touching the workflow.
|
||||||
|
- The Gitea instance is **1.25.4** — `on: schedule` workflows are
|
||||||
|
supported; bump.yml assumes the Actions token can push to `main`
|
||||||
|
(standard Gitea behaviour, but unconfirmed until the first run lands).
|
||||||
|
- The git server is **Gitea** (gitea/act_runner via docker-compose), NOT
|
||||||
|
Forgejo — workflows are read from `.gitea/workflows/` (or `.github/`),
|
||||||
|
never `.forgejo/workflows/` (a whole push cycle was lost to that).
|
||||||
|
- Reusable headless VM harness: `checks.*` via runNixOSTest — existing
|
||||||
|
examples to crib from: `distro-id` (boots + `switch-to-configuration
|
||||||
|
dry-activate`), `hardware-toggles` (kernel cmdline/PAM assertions),
|
||||||
|
`battery-charge-limit` (fake Mains adapter via `test_power`, real udev
|
||||||
|
uevent, `InvocationID` change proves the restart).
|
||||||
|
- Themed-desktop screenshots work headlessly: software-GL Hyprland
|
||||||
|
(`LIBGL_ALWAYS_SOFTWARE` on virtio-gpu) + `machine.screenshot()` QMP
|
||||||
|
dump — prototyped 2026-06-19, kept as the fallback for theme previews
|
||||||
|
(§ Visual theme picker).
|
||||||
|
- Hyprland/Ghostty need guest GL (`virtio-vga-gl`, `gl=on`) in
|
||||||
|
interactive QEMU or the session won't start; black screen ≈ missing GL
|
||||||
|
(docs/TESTING.md § gotchas).
|
||||||
|
- No KVM = slow, not broken; don't read slowness as failure.
|
||||||
|
|
||||||
|
## Known-broken / watchlist
|
||||||
|
- **btrfs-assistant "segfault" was unprivileged-only** (re-diagnosed
|
||||||
|
2026-07-04): libbtrfsutil's unprivileged subvolume iteration crashes on
|
||||||
|
btrfs-progs 6.17.1 (upstream-fixed after); **as root it works**, and the
|
||||||
|
pkexec launcher runs it as root. The real distro bug was **no polkit
|
||||||
|
agent in the session** (every pkexec failed silently) — hyprpolkitagent
|
||||||
|
now ships (hyprland.nix exec-once). `checks.snapshot-gui` guards the
|
||||||
|
root path. Lesson: before "app X is broken", check WHO it runs as — and
|
||||||
|
whether polkit prompts can render at all (§ Snapshot browse/restore).
|
||||||
|
- **NixOS release bump is a trap:** the discarded attempt
|
||||||
|
(branch deleted 2026-06-22) hit a Hyprland OOM blocker; a redo is a
|
||||||
|
deliberate `v2`, never part of routine lock bumps.
|
||||||
|
- `theme-state.json` is git-tracked inside an 86 MB flake tree, so every
|
||||||
|
state write re-copies the source before eval — the wallpapers-artifact
|
||||||
|
split (BACKLOG LATER) is the decided fix (§ Faster switches).
|
||||||
|
|
||||||
|
## Gotchas (cost a debugging session once)
|
||||||
|
- Hyprland binds match the exact modmask: a shifted keysym (`question`)
|
||||||
|
needs SHIFT in `mods` or the bind never fires — the keypress falls
|
||||||
|
through to the focused window (§ item 26; caught on hardware, invisible
|
||||||
|
to eval-tier tests).
|
||||||
|
- Never kill a Wayland session-lock client (hyprlock): its crash
|
||||||
|
failsafe drops to a tty instead of unlocking (§ Hibernate
|
||||||
|
double-unlock).
|
||||||
|
- rofi `element-icon size` is one value = a square cell; `WxH` silently
|
||||||
|
collapses and non-square icons letterbox — pre-crop images square at
|
||||||
|
build (§ Visual theme picker).
|
||||||
|
- WirePlumber 0.5 monitor rules can only early-match `device.api`;
|
||||||
|
`device.product.name` etc. bind *after* the rule runs — surgical
|
||||||
|
libcamera scoping is impossible (§ Webcam).
|
||||||
|
- `hyprctl switchxkblayout` is a *global* layout flip; per-device isolation
|
||||||
|
needs `device[<name>]:kb_layout` keywords (§ Keyboard layouts).
|
||||||
|
- Waybar's clock captures the timezone at construction — a zone change
|
||||||
|
needs SIGUSR2 (watcher in `timezone.nix`) (§ Automatic timezone).
|
||||||
|
- Waybar `persistent_workspaces` (underscore) is dead syntax silently
|
||||||
|
ignored; the hyphen form is honoured and renders phantom workspaces
|
||||||
|
(§ Waybar shows non-existent workspaces).
|
||||||
|
- GTK4/libadwaita/Qt6 read light/dark from the portal's
|
||||||
|
`org.freedesktop.appearance color-scheme` (dconf), not Stylix polarity
|
||||||
|
(§ GTK/Qt ignore the theme's mode).
|
||||||
|
- Update order matters downstream: `sys-update` (lock) before
|
||||||
|
`home-update`, or desktop changes are silently skipped against the old
|
||||||
|
lock (README § 3).
|
||||||
|
- grub `loadfont`s every `.pf2` in a theme dir — reuse a bundled DejaVu
|
||||||
|
rather than shipping fonts (§ Distro branding).
|
||||||
|
- The Claude Code harness drops machine-local files into the repo
|
||||||
|
(`.claude/skills/…`) mid-session — never `git add -A` blindly; check
|
||||||
|
`git status --short` for strangers first (they're gitignored now, but
|
||||||
|
the next surprise won't be) (§ loop hygiene).
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# nomarchy-docs-keybindings
|
|
||||||
#
|
|
||||||
# Regenerates docs/KEYBINDINGS.md from the Hyprland binding files. Run from the
|
|
||||||
# repo root or anywhere — paths are resolved relative to this script.
|
|
||||||
#
|
|
||||||
# nomarchy-docs-keybindings # write to stdout
|
|
||||||
# nomarchy-docs-keybindings --out docs/KEYBINDINGS.md
|
|
||||||
#
|
|
||||||
# Source files in render order. Each entry is "<repo-relative path>|<title>".
|
|
||||||
|
|
||||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
||||||
|
|
||||||
sources=(
|
|
||||||
"core/home/config/nomarchy/default/hypr/bindings/utilities.conf|Utilities"
|
|
||||||
"core/home/config/nomarchy/default/hypr/bindings/tiling-v2.conf|Tiling"
|
|
||||||
"core/home/config/nomarchy/default/hypr/bindings/clipboard.conf|Clipboard"
|
|
||||||
"core/home/config/nomarchy/default/hypr/bindings/media.conf|Media keys"
|
|
||||||
"features/desktop/hyprland/config/bindings.conf|Apps & web shortcuts"
|
|
||||||
)
|
|
||||||
|
|
||||||
prettify_key() {
|
|
||||||
case "$1" in
|
|
||||||
code:10) echo "1" ;; code:11) echo "2" ;; code:12) echo "3" ;;
|
|
||||||
code:13) echo "4" ;; code:14) echo "5" ;; code:15) echo "6" ;;
|
|
||||||
code:16) echo "7" ;; code:17) echo "8" ;; code:18) echo "9" ;;
|
|
||||||
code:19) echo "0" ;;
|
|
||||||
XF86AudioRaiseVolume) echo "Volume Up" ;;
|
|
||||||
XF86AudioLowerVolume) echo "Volume Down" ;;
|
|
||||||
XF86AudioMute) echo "Mute" ;;
|
|
||||||
XF86AudioMicMute) echo "Mic Mute" ;;
|
|
||||||
XF86AudioPlay) echo "Play/Pause" ;;
|
|
||||||
XF86AudioStop) echo "Stop" ;;
|
|
||||||
XF86AudioNext) echo "Next Track" ;;
|
|
||||||
XF86AudioPrev) echo "Previous Track" ;;
|
|
||||||
XF86MonBrightnessUp) echo "Brightness Up" ;;
|
|
||||||
XF86MonBrightnessDown) echo "Brightness Down" ;;
|
|
||||||
XF86KbdBrightnessUp) echo "Kbd Brightness Up" ;;
|
|
||||||
XF86KbdBrightnessDown) echo "Kbd Brightness Down" ;;
|
|
||||||
XF86KbdLightOnOff) echo "Kbd Backlight" ;;
|
|
||||||
*) echo "$1" ;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
trim() { sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//'; }
|
|
||||||
|
|
||||||
render_section() {
|
|
||||||
local file="$1" title="$2"
|
|
||||||
[[ ! -f "$repo_root/$file" ]] && return
|
|
||||||
local rows
|
|
||||||
rows=$(grep -E '^[[:space:]]*bind[a-z]*[[:space:]]*=' "$repo_root/$file" || true)
|
|
||||||
[[ -z "$rows" ]] && return
|
|
||||||
|
|
||||||
local body=""
|
|
||||||
while IFS= read -r line; do
|
|
||||||
# Strip the "bindXXX =" prefix.
|
|
||||||
local rhs="${line#*=}"
|
|
||||||
local mods key desc
|
|
||||||
IFS=',' read -r mods key desc _ <<<"$rhs"
|
|
||||||
mods=$(printf '%s' "${mods:-}" | trim)
|
|
||||||
key=$(printf '%s' "${key:-}" | trim)
|
|
||||||
desc=$(printf '%s' "${desc:-}" | trim)
|
|
||||||
[[ -z "$desc" ]] && continue # skip non-descriptive bindings
|
|
||||||
[[ -z "$mods" ]] && mods="—"
|
|
||||||
key=$(prettify_key "$key")
|
|
||||||
body+=$(printf '| %s | %s | %s |\n' "$mods" "$key" "$desc")
|
|
||||||
body+=$'\n'
|
|
||||||
done <<<"$rows"
|
|
||||||
|
|
||||||
[[ -z "$body" ]] && return
|
|
||||||
|
|
||||||
printf '\n## %s\n\n' "$title"
|
|
||||||
printf '_Source: `%s`_\n\n' "$file"
|
|
||||||
printf '| Modifiers | Key | Action |\n'
|
|
||||||
printf '| --- | --- | --- |\n'
|
|
||||||
printf '%s' "$body"
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
cat <<'HEADER'
|
|
||||||
# Nomarchy Keybindings
|
|
||||||
|
|
||||||
Auto-generated from the Hyprland binding files. **Do not edit by hand.**
|
|
||||||
Re-run the generator after changing any `bindings/*.conf`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./bin/utils/nomarchy-docs-keybindings --out docs/KEYBINDINGS.md
|
|
||||||
```
|
|
||||||
|
|
||||||
`SUPER` is the Meta / Win key. `code:NN` keys (X11 digit keycodes) are
|
|
||||||
shown as the digit they correspond to. Media keys (`XF86Audio*`,
|
|
||||||
`XF86MonBrightness*`, …) are prettified.
|
|
||||||
HEADER
|
|
||||||
for entry in "${sources[@]}"; do
|
|
||||||
render_section "${entry%|*}" "${entry#*|}"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
out=""
|
|
||||||
if [[ "${1:-}" == "--out" ]]; then
|
|
||||||
out="${2:?--out needs a path}"; shift 2
|
|
||||||
fi
|
|
||||||
if [[ -n "$out" ]]; then
|
|
||||||
main >"$out"
|
|
||||||
else
|
|
||||||
main
|
|
||||||
fi
|
|
||||||
@@ -1,288 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# Generator tolerates "no matches" exit codes from grep | sort.
|
|
||||||
# pipefail and -e off; -u stays.
|
|
||||||
set -u
|
|
||||||
|
|
||||||
# Deterministic collation regardless of the caller's locale. Without this
|
|
||||||
# `sort` orders rows and caller lists by the ambient LC_COLLATE (UTF-8 on a
|
|
||||||
# dev box, C in the CI container), so the committed doc and CI's regenerated
|
|
||||||
# copy disagree on ordering and the drift check fails on pure noise.
|
|
||||||
export LC_ALL=C
|
|
||||||
|
|
||||||
# nomarchy-docs-scripts
|
|
||||||
#
|
|
||||||
# Regenerates docs/SCRIPTS.md from the repo state. Produces:
|
|
||||||
# 1. Header + status legend + regen instructions.
|
|
||||||
# 2. Table of every nomarchy-* script (location, callers, status).
|
|
||||||
# 3. Table of every menu entry in features/scripts/utils/nomarchy-menu
|
|
||||||
# (submenu, label, target command, status).
|
|
||||||
# 4. Snapshot list of orphaned references (called somewhere, no script).
|
|
||||||
#
|
|
||||||
# Status heuristic in Phase A:
|
|
||||||
# kept — file exists AND is called from at least one *.nix / *.conf /
|
|
||||||
# shell file outside its own directory.
|
|
||||||
# unused? — file exists but no caller found. Phase B decides delete-dead
|
|
||||||
# vs intentional public API.
|
|
||||||
# missing — referenced but no file. Phase B decides port-from-omarchy
|
|
||||||
# vs delete-dead vs stub-with-notify.
|
|
||||||
#
|
|
||||||
# nomarchy-docs-scripts # write to stdout
|
|
||||||
# nomarchy-docs-scripts --out docs/SCRIPTS.md
|
|
||||||
|
|
||||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
||||||
cd "$repo_root"
|
|
||||||
|
|
||||||
# --- Inventory -------------------------------------------------------------
|
|
||||||
|
|
||||||
# Where scripts live, in render order.
|
|
||||||
declare -A loc_label=(
|
|
||||||
["features/scripts/utils"]="features/scripts/utils"
|
|
||||||
["core/system/scripts"]="core/system/scripts"
|
|
||||||
["themes/engine/scripts"]="themes/engine/scripts"
|
|
||||||
)
|
|
||||||
script_dirs=(features/scripts/utils core/system/scripts themes/engine/scripts)
|
|
||||||
|
|
||||||
# Build name → location map (associative array of basename → repo-relative dir).
|
|
||||||
declare -A script_loc
|
|
||||||
for dir in "${script_dirs[@]}"; do
|
|
||||||
[[ -d "$dir" ]] || continue
|
|
||||||
while IFS= read -r f; do
|
|
||||||
script_loc["$(basename "$f")"]="$dir"
|
|
||||||
done < <(find "$dir" -maxdepth 1 -type f -name 'nomarchy-*')
|
|
||||||
done
|
|
||||||
|
|
||||||
# Find every nomarchy-* token referenced anywhere outside the script dirs.
|
|
||||||
# (We exclude the script files themselves so they don't list themselves as
|
|
||||||
# their own caller.)
|
|
||||||
# File types we search for references. *.md catches docs and README;
|
|
||||||
# branding/hook/extension files have varied or no extensions.
|
|
||||||
# *.lua catches elephant providers; *.ini catches mako on-button-* hooks;
|
|
||||||
# *.desktop catches MimeType-registered URL handlers.
|
|
||||||
grep_includes=(
|
|
||||||
--include='*.nix' --include='*.conf' --include='*.sh' --include='*.md'
|
|
||||||
--include='nomarchy-*' --include='*.jsonc' --include='*.json'
|
|
||||||
--include='*.toml' --include='*.ini' --include='*.lua'
|
|
||||||
--include='*.desktop' --include='*.txt' --include='*.sample'
|
|
||||||
)
|
|
||||||
search_dirs=(core features themes installer hosts bin lib README.md)
|
|
||||||
|
|
||||||
# Files whose mentions of nomarchy-* are documentation about the scripts,
|
|
||||||
# not real callers. Excluded from caller discovery so they don't promote
|
|
||||||
# every script to `kept`.
|
|
||||||
self_refs=(docs/SCRIPTS.md docs/ROADMAP.md docs/AGENT.md)
|
|
||||||
|
|
||||||
ref_files_per_cmd() {
|
|
||||||
local cmd="$1"
|
|
||||||
local self_pattern
|
|
||||||
self_pattern=$(IFS='|'; echo "${self_refs[*]}")
|
|
||||||
grep -rlE "\\b${cmd}\\b" \
|
|
||||||
"${grep_includes[@]}" \
|
|
||||||
"${search_dirs[@]}" 2>/dev/null \
|
|
||||||
| grep -vE "^(features/scripts/utils|core/system/scripts|themes/engine/scripts)/${cmd}$" \
|
|
||||||
| grep -vE "^(${self_pattern})$" \
|
|
||||||
| sort -u
|
|
||||||
}
|
|
||||||
|
|
||||||
# All distinct nomarchy-* tokens we see anywhere in the repo.
|
|
||||||
# Final char must be alphanumeric — dropping trailing-dash matches like
|
|
||||||
# `nomarchy-pkg-` that come from glob references (`for c in nomarchy-pkg-*`).
|
|
||||||
# Restrict to grep_includes so binaries / tmpfiles don't pollute the set.
|
|
||||||
# The first `grep -vE` drops lines where `nomarchy-*` is a derivation /
|
|
||||||
# tmp file / sudoers basename / systemd unit / flake output / docker
|
|
||||||
# container identifier rather than a shell invocation.
|
|
||||||
# The second `grep -vE` is a token-level safety net for prefix-only
|
|
||||||
# tokens left over from wildcards/expansions (e.g. `nomarchy-pkg-*`).
|
|
||||||
all_refs=$(grep -rhE 'nomarchy-[a-z0-9]([a-z0-9-]*[a-z0-9])?' \
|
|
||||||
"${grep_includes[@]}" \
|
|
||||||
"${search_dirs[@]}" 2>/dev/null \
|
|
||||||
| grep -vE \
|
|
||||||
-e '(pname|name)[[:space:]]*=[[:space:]]*"nomarchy-' \
|
|
||||||
-e '/tmp/nomarchy-' \
|
|
||||||
-e '/etc/sudoers\.d/[^"[:space:]]*nomarchy-' \
|
|
||||||
-e 'nixosConfigurations\.nomarchy-' \
|
|
||||||
-e 'packages\.[^.]+\.nomarchy-' \
|
|
||||||
-e '\./result/bin/run-nomarchy-' \
|
|
||||||
-e 'mktemp[[:space:]]+[^|]*-t[[:space:]]+nomarchy-' \
|
|
||||||
-e '(TIMER_NAME|NOPASSWD_FILE|UNIT_NAME)=.*nomarchy-' \
|
|
||||||
-e '\.services\.nomarchy-' \
|
|
||||||
-e 'docker[[:space:]]+[^|]*nomarchy-' \
|
|
||||||
| grep -oE 'nomarchy-[a-z0-9]([a-z0-9-]*[a-z0-9])?' \
|
|
||||||
| grep -vE '^(nomarchy-launch|nomarchy-brightness|nomarchy-cmd|nomarchy-pkg|nomarchy-restart|nomarchy-toggle|nomarchy-theme|nomarchy-webapp-handler|nomarchy-font-selector|nomarchy-theme-selector|nomarchy-wallpaper-selector|nomarchy-setup|nomarchy-refresh|nomarchy-scripts|nomarchy-system-scripts|nomarchy-theme-engine-scripts)$' \
|
|
||||||
| grep -vE '^(nomarchy-plymouth|nomarchy-sddm-theme|nomarchy-live|nomarchy-rev|nomarchy-windows)$' \
|
|
||||||
| grep -vE '^(nomarchy-eval-matrix|nomarchy-docs-scripts|nomarchy-docs-keybindings)$' \
|
|
||||||
| sort -u)
|
|
||||||
# The second denylist covers identifiers whose ambiguity survives the line
|
|
||||||
# filter: `nomarchy-plymouth` / `nomarchy-sddm-theme` are Nix derivation
|
|
||||||
# names referenced as bare idents in `[...]` lists, `nomarchy-live` is an
|
|
||||||
# ISO label that shows up in comments, `nomarchy-rev` is `/etc/nomarchy-rev`
|
|
||||||
# (written by the ISO), and `nomarchy-windows` is a docker container name
|
|
||||||
# in compose heredocs.
|
|
||||||
# The third denylist: `nomarchy-eval-matrix`, `nomarchy-docs-scripts` (this
|
|
||||||
# generator), and `nomarchy-docs-keybindings` are bin/utils repo tools that
|
|
||||||
# name themselves in their own headers / AGENT.md — not user-facing scripts
|
|
||||||
# that ship in nomarchy-system-scripts.
|
|
||||||
|
|
||||||
# --- Render: header --------------------------------------------------------
|
|
||||||
|
|
||||||
main() {
|
|
||||||
cat <<'HEADER'
|
|
||||||
# Nomarchy Script & Menu Audit
|
|
||||||
|
|
||||||
Auto-generated table for [Pillar 3 of the roadmap](ROADMAP.md#3-pillar-script--menu-audit).
|
|
||||||
**Do not edit by hand.** Regenerate after script or menu changes:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./bin/utils/nomarchy-docs-scripts --out docs/SCRIPTS.md
|
|
||||||
```
|
|
||||||
|
|
||||||
The status column uses a Phase A heuristic — `kept` / `unused?` / `missing`.
|
|
||||||
Phase B (per-batch PRs) refines those into `port-from-omarchy`,
|
|
||||||
`delete-dead`, or `stub-with-notify` and updates the rows.
|
|
||||||
|
|
||||||
## Status legend
|
|
||||||
|
|
||||||
- `kept` — script exists and is called from somewhere outside its own directory.
|
|
||||||
- `unused?` — script exists but no caller was found. Could be dead, could be
|
|
||||||
intentional public API. Phase B triage decides.
|
|
||||||
- `missing` — referenced from code but no script file exists. Phase B triage
|
|
||||||
decides whether to port from Omarchy upstream, delete the caller, or stub
|
|
||||||
with `notify-send`.
|
|
||||||
- `port-from-omarchy` — Phase B verdict: lift the upstream Omarchy script,
|
|
||||||
rewrite for NixOS paths.
|
|
||||||
- `delete-dead` — Phase B verdict: remove and update callers.
|
|
||||||
- `stub-with-notify` — Phase B verdict: temporary `notify-send` stub.
|
|
||||||
|
|
||||||
HEADER
|
|
||||||
|
|
||||||
# --- Render: scripts table ----------------------------------------------
|
|
||||||
printf '## Scripts (%d)\n\n' "${#script_loc[@]}"
|
|
||||||
printf '| Script | Location | Callers | Status | Notes |\n'
|
|
||||||
printf '| --- | --- | --- | --- | --- |\n'
|
|
||||||
|
|
||||||
# Sort scripts by name.
|
|
||||||
for name in $(printf '%s\n' "${!script_loc[@]}" | sort); do
|
|
||||||
local dir="${script_loc[$name]}"
|
|
||||||
local callers status callers_str
|
|
||||||
callers=$(ref_files_per_cmd "$name")
|
|
||||||
if [[ -z "$callers" ]]; then
|
|
||||||
status='`unused?`'
|
|
||||||
callers_str='—'
|
|
||||||
else
|
|
||||||
status='`kept`'
|
|
||||||
# Trim caller list to 2 entries + count.
|
|
||||||
local count
|
|
||||||
count=$(printf '%s\n' "$callers" | wc -l)
|
|
||||||
if (( count > 2 )); then
|
|
||||||
callers_str=$(printf '%s\n' "$callers" | head -2 | paste -sd, -)
|
|
||||||
callers_str="$callers_str, +$((count - 2)) more"
|
|
||||||
else
|
|
||||||
callers_str=$(printf '%s\n' "$callers" | paste -sd, -)
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
printf '| `%s` | `%s` | %s | %s | |\n' \
|
|
||||||
"$name" "$dir" "$callers_str" "$status"
|
|
||||||
done
|
|
||||||
echo
|
|
||||||
|
|
||||||
# --- Render: missing references -----------------------------------------
|
|
||||||
printf '## Missing references\n\n'
|
|
||||||
printf 'Tokens grepped from `core/`, `features/`, `themes/`, `installer/`, `hosts/`, `bin/`, `lib/` that have no matching script file.\n\n'
|
|
||||||
printf '| Token | Referenced in | Status |\n'
|
|
||||||
printf '| --- | --- | --- |\n'
|
|
||||||
while IFS= read -r token; do
|
|
||||||
[[ -z "$token" ]] && continue
|
|
||||||
[[ -n "${script_loc[$token]:-}" ]] && continue
|
|
||||||
local refs
|
|
||||||
self_pattern=$(IFS='|'; echo "${self_refs[*]}")
|
|
||||||
refs=$(grep -rlE "\\b${token}\\b" \
|
|
||||||
"${grep_includes[@]}" \
|
|
||||||
"${search_dirs[@]}" 2>/dev/null \
|
|
||||||
| grep -vE "^(${self_pattern})$" \
|
|
||||||
| sort -u)
|
|
||||||
[[ -z "$refs" ]] && continue
|
|
||||||
local count refs_str
|
|
||||||
count=$(printf '%s\n' "$refs" | wc -l)
|
|
||||||
if (( count > 2 )); then
|
|
||||||
refs_str=$(printf '%s\n' "$refs" | head -2 | paste -sd, -)
|
|
||||||
refs_str="$refs_str, +$((count - 2)) more"
|
|
||||||
else
|
|
||||||
refs_str=$(printf '%s\n' "$refs" | paste -sd, -)
|
|
||||||
fi
|
|
||||||
printf '| `%s` | %s | `missing` |\n' "$token" "$refs_str"
|
|
||||||
done <<<"$all_refs"
|
|
||||||
echo
|
|
||||||
|
|
||||||
# --- Render: menu items -------------------------------------------------
|
|
||||||
printf '## Menu items\n\n'
|
|
||||||
printf 'Walked from `features/scripts/utils/nomarchy-menu`. Each `case` arm in a `show_*_menu` function becomes one row.\n\n'
|
|
||||||
printf '| Submenu | Entry | Calls | Status |\n'
|
|
||||||
printf '| --- | --- | --- | --- |\n'
|
|
||||||
|
|
||||||
awk '
|
|
||||||
/^show_[a-z_]+_menu\(\) {/ { sub(/\(\) {/, ""); current=$1; in_func=1; next }
|
|
||||||
/^[a-z_]+\(\) {/ && !/^show_/ { current=""; in_func=0; next }
|
|
||||||
/^}$/ { current=""; in_func=0; next }
|
|
||||||
!in_func { next }
|
|
||||||
/^ case \$\(menu / {
|
|
||||||
# extract the menu title between the first pair of double quotes
|
|
||||||
match($0, /menu "[^"]+" "[^"]+"/);
|
|
||||||
if (RSTART == 0) next;
|
|
||||||
title=substr($0, RSTART, RLENGTH);
|
|
||||||
# second quoted string is the option list
|
|
||||||
n=split(title, parts, "\"");
|
|
||||||
title=parts[2];
|
|
||||||
options=parts[4];
|
|
||||||
# split options on \n
|
|
||||||
split(options, opts, "\\\\n");
|
|
||||||
pending_submenu=current;
|
|
||||||
pending_title=title;
|
|
||||||
for (i=1;i<=length(opts);i++) pending_opts[i]=opts[i];
|
|
||||||
pending_count=length(opts);
|
|
||||||
next
|
|
||||||
}
|
|
||||||
/^ \*[A-Za-z]/ {
|
|
||||||
# case arm — extract pattern between the first * and the closing )
|
|
||||||
match($0, /\*[^)]*\)/);
|
|
||||||
if (RSTART == 0) next;
|
|
||||||
arm=substr($0, RSTART, RLENGTH);
|
|
||||||
gsub(/[*)]/, "", arm);
|
|
||||||
gsub(/^[[:space:]]+|[[:space:]]+$/, "", arm);
|
|
||||||
# action follows the )
|
|
||||||
rest=substr($0, RSTART+RLENGTH);
|
|
||||||
sub(/^[[:space:]]+/, "", rest);
|
|
||||||
sub(/[[:space:]]*;;[[:space:]]*$/, "", rest);
|
|
||||||
# match the first nomarchy-* token in the action
|
|
||||||
cmd=""
|
|
||||||
if (match(rest, /nomarchy-[a-z0-9-]+/)) {
|
|
||||||
cmd=substr(rest, RSTART, RLENGTH);
|
|
||||||
}
|
|
||||||
printf "%s|%s|%s\n", pending_submenu, arm, cmd;
|
|
||||||
}
|
|
||||||
' features/scripts/utils/nomarchy-menu > /tmp/nomarchy-menu-rows.$$
|
|
||||||
|
|
||||||
while IFS='|' read -r submenu entry cmd; do
|
|
||||||
[[ -z "$entry" ]] && continue
|
|
||||||
[[ "$entry" =~ ^\) ]] && continue
|
|
||||||
status='`kept`'
|
|
||||||
if [[ -n "$cmd" ]]; then
|
|
||||||
if [[ -z "${script_loc[$cmd]:-}" ]]; then
|
|
||||||
status='`missing`'
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
cmd='_(inline)_'
|
|
||||||
fi
|
|
||||||
printf '| `%s` | %s | `%s` | %s |\n' "$submenu" "$entry" "$cmd" "$status"
|
|
||||||
done < /tmp/nomarchy-menu-rows.$$
|
|
||||||
rm -f /tmp/nomarchy-menu-rows.$$
|
|
||||||
echo
|
|
||||||
}
|
|
||||||
|
|
||||||
out=""
|
|
||||||
if [[ "${1:-}" == "--out" ]]; then
|
|
||||||
out="${2:?--out needs a path}"; shift 2
|
|
||||||
fi
|
|
||||||
if [[ -n "$out" ]]; then
|
|
||||||
main >"$out"
|
|
||||||
else
|
|
||||||
main
|
|
||||||
fi
|
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# nomarchy-eval-matrix
|
|
||||||
#
|
|
||||||
# Evaluates the opt-in nomarchy.* surface that the per-output flake check
|
|
||||||
# never touches. flake check only evaluates the default configs, so a bug
|
|
||||||
# that only fires when a toggle is flipped — a renamed option, a failed
|
|
||||||
# assertion, a stale reference — sails straight through. Two such bugs
|
|
||||||
# shipped to main before this existed (the vscode option rename and the
|
|
||||||
# impermanence systemd-stage-1 assertion); both would have been caught
|
|
||||||
# here.
|
|
||||||
#
|
|
||||||
# Cost matters: this runs in CI on a small self-hosted runner, and the
|
|
||||||
# first cut (one full `extendModules` eval per individual toggle, plus one
|
|
||||||
# per palette) did ~39 whole-system evaluations and ran ~3h. So:
|
|
||||||
#
|
|
||||||
# * Compatible toggles are COMBINED into a few configs (a failure means
|
|
||||||
# re-run the offending toggle alone to pinpoint it — see the trace hint
|
|
||||||
# at the end). laptop vs desktop formFactor conflict, so they split;
|
|
||||||
# impermanence's multi-disk variant gets its own config for the alt
|
|
||||||
# mainLuksName.
|
|
||||||
# * Palettes are checked DIRECTLY via the lib — the per-palette risk is
|
|
||||||
# the system-side Plymouth base00 → RGB math (fromHexString of 2-char
|
|
||||||
# slices in themes/engine/plymouth.nix), which is pure and needs no
|
|
||||||
# module-system instantiation. Forcing the whole palette attrset also
|
|
||||||
# catches a missing/garbled palette.
|
|
||||||
# * The standalone homeConfigurations aren't re-checked here — the
|
|
||||||
# per-output flake-check step already forces both.
|
|
||||||
#
|
|
||||||
# Net: a handful of full evals instead of ~39. Results come from
|
|
||||||
# builtins.tryEval so one failure doesn't mask the rest.
|
|
||||||
#
|
|
||||||
# nomarchy-eval-matrix # run the matrix, table + exit code
|
|
||||||
#
|
|
||||||
# Add a new opt-in option's coverage by dropping it into the relevant
|
|
||||||
# combined scenario in the `scenarios` attrset below.
|
|
||||||
|
|
||||||
set -u
|
|
||||||
|
|
||||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
||||||
cd "$repo_root"
|
|
||||||
|
|
||||||
NIX=(nix --extra-experimental-features 'nix-command flakes')
|
|
||||||
|
|
||||||
read -r -d '' EXPR <<'NIXEOF' || true
|
|
||||||
let
|
|
||||||
f = builtins.getFlake (toString ./.);
|
|
||||||
lib = f.inputs.nixpkgs.lib;
|
|
||||||
nl = import ./lib { inherit lib; };
|
|
||||||
default = f.nixosConfigurations.default;
|
|
||||||
|
|
||||||
forced = x: (builtins.tryEval (builtins.seq x true)).success;
|
|
||||||
|
|
||||||
# Combined opt-in scenarios. Each enables as many compatible toggles as
|
|
||||||
# possible so CI does ~3 full-system evals, not one per toggle. Home-side
|
|
||||||
# options go under home-manager.users.nomarchy.nomarchy.*.
|
|
||||||
scenarios = {
|
|
||||||
# laptop formFactor + every compatible system/home toggle + impermanence.
|
|
||||||
"laptop-stack" = {
|
|
||||||
nomarchy.system = {
|
|
||||||
formFactor = "laptop";
|
|
||||||
laptop.enable = true;
|
|
||||||
accessibility.enable = true;
|
|
||||||
gaming.enable = true;
|
|
||||||
features.hybridGPU = true;
|
|
||||||
hibernation.enable = true;
|
|
||||||
virtualization.docker.enable = true;
|
|
||||||
impermanence.enable = true;
|
|
||||||
};
|
|
||||||
nomarchy.hardware.fwupd = true;
|
|
||||||
home-manager.users.nomarchy.nomarchy = {
|
|
||||||
accessibility.enable = true;
|
|
||||||
gaming.enable = true;
|
|
||||||
overrides.enable = true;
|
|
||||||
panelPosition = "bottom";
|
|
||||||
keymap = { layout = "de"; variant = "nodeadkeys"; };
|
|
||||||
toggles = { waybar = false; idle = false; nightlight = false; };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# desktop preset — conflicts with the laptop formFactor, so its own eval.
|
|
||||||
"desktop-stack" = {
|
|
||||||
nomarchy.system = { formFactor = "desktop"; desktop.enable = true; };
|
|
||||||
};
|
|
||||||
|
|
||||||
# impermanence multi-disk variant (alternate mainLuksName).
|
|
||||||
"impermanence-multi" = {
|
|
||||||
nomarchy.system.impermanence = { enable = true; mainLuksName = "crypted_main"; };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
evalToplevel = mod:
|
|
||||||
forced (default.extendModules { modules = [ mod ]; }).config.system.build.toplevel.drvPath;
|
|
||||||
|
|
||||||
# base00 → the three byte values the Plymouth template substitutes; plus
|
|
||||||
# the whole palette attrset, so a missing/garbled palette is caught.
|
|
||||||
paletteOk = name:
|
|
||||||
let
|
|
||||||
p = nl.getPalette name;
|
|
||||||
b = p.base00;
|
|
||||||
bytes = [
|
|
||||||
(lib.fromHexString (lib.substring 0 2 b))
|
|
||||||
(lib.fromHexString (lib.substring 2 2 b))
|
|
||||||
(lib.fromHexString (lib.substring 4 2 b))
|
|
||||||
];
|
|
||||||
in forced (builtins.deepSeq [ p bytes ] true);
|
|
||||||
in {
|
|
||||||
scenarios = builtins.mapAttrs (_: evalToplevel) scenarios;
|
|
||||||
palettes = builtins.listToAttrs (map (n: { name = n; value = paletteOk n; }) nl.themeNames);
|
|
||||||
}
|
|
||||||
NIXEOF
|
|
||||||
|
|
||||||
echo "Evaluating combined toggle scenarios + per-palette colour math..."
|
|
||||||
json="$("${NIX[@]}" eval --impure --json --expr "$EXPR" 2>/tmp/eval-matrix.err)"
|
|
||||||
status=$?
|
|
||||||
if [[ $status -ne 0 || -z "$json" ]]; then
|
|
||||||
echo "ERROR: the matrix evaluation aborted before producing results." >&2
|
|
||||||
echo "This usually means an uncatchable error (abort/infinite recursion) in one" >&2
|
|
||||||
echo "scenario, or a syntax error in the expression. Full output:" >&2
|
|
||||||
cat /tmp/eval-matrix.err >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Render each section and tally failures.
|
|
||||||
fails=0
|
|
||||||
render() {
|
|
||||||
local section="$1"
|
|
||||||
echo
|
|
||||||
echo "=== $section ==="
|
|
||||||
while IFS=$'\t' read -r name ok; do
|
|
||||||
if [[ "$ok" == "true" ]]; then
|
|
||||||
printf ' ok %s\n' "$name"
|
|
||||||
else
|
|
||||||
printf ' FAIL %s\n' "$name"
|
|
||||||
fails=$((fails + 1))
|
|
||||||
fi
|
|
||||||
done < <(echo "$json" | jq -r --arg s "$section" '.[$s] | to_entries[] | "\(.key)\t\(.value)"' | sort)
|
|
||||||
}
|
|
||||||
|
|
||||||
render scenarios
|
|
||||||
render palettes
|
|
||||||
|
|
||||||
echo
|
|
||||||
if [[ $fails -gt 0 ]]; then
|
|
||||||
echo "$fails scenario(s) failed to evaluate. A combined scenario bundles several"
|
|
||||||
echo "toggles — re-run the suspects individually for the trace, e.g.:"
|
|
||||||
echo " nix eval --impure --show-trace --expr 'let f = builtins.getFlake (toString ./.); in (f.nixosConfigurations.default.extendModules { modules = [ { <the toggle> } ]; }).config.system.build.toplevel.drvPath'"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "All scenarios evaluated cleanly."
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
# About Nomarchy
|
|
||||||
|
|
||||||
Nomarchy is a highly curated, NixOS-based distribution designed for power users.
|
|
||||||
It features a customized Hyprland desktop environment with a declarative
|
|
||||||
theming engine and a suite of integrated utility scripts.
|
|
||||||
|
|
||||||
Built on a foundation of:
|
|
||||||
- NixOS (Linux)
|
|
||||||
- Hyprland (Window Manager)
|
|
||||||
- Waybar (Status Bar)
|
|
||||||
- Walker (Application Launcher & Menu)
|
|
||||||
- Stylix (Theming Engine)
|
|
||||||
|
|
||||||
Version: 2026.05.04
|
|
||||||
Docs: https://github.com/nomarchy/nomarchy/docs
|
|
||||||
Manual: nomarchy-manual (Command)
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 23 KiB |
@@ -1,56 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
width="210mm"
|
|
||||||
height="297mm"
|
|
||||||
viewBox="0 0 210 297"
|
|
||||||
version="1.1"
|
|
||||||
id="svg1"
|
|
||||||
xml:space="preserve"
|
|
||||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
|
||||||
sodipodi:docname="icon.svg"
|
|
||||||
inkscape:export-filename="logo.svg"
|
|
||||||
inkscape:export-xdpi="96"
|
|
||||||
inkscape:export-ydpi="96"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
|
||||||
id="namedview1"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#000000"
|
|
||||||
borderopacity="0.25"
|
|
||||||
inkscape:showpageshadow="2"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pagecheckerboard="0"
|
|
||||||
inkscape:deskcolor="#d1d1d1"
|
|
||||||
inkscape:document-units="mm"
|
|
||||||
inkscape:zoom="0.82803284"
|
|
||||||
inkscape:cx="215.57116"
|
|
||||||
inkscape:cy="452.27675"
|
|
||||||
inkscape:window-width="1025"
|
|
||||||
inkscape:window-height="1012"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="0"
|
|
||||||
inkscape:window-maximized="0"
|
|
||||||
inkscape:current-layer="layer1" /><defs
|
|
||||||
id="defs1" /><g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"><g
|
|
||||||
id="g4"
|
|
||||||
transform="translate(3.1953242,-22.686801)"
|
|
||||||
style="fill:#000088;fill-opacity:1"><path
|
|
||||||
style="fill:#000088;stroke-width:0.264583;fill-opacity:1"
|
|
||||||
d="M 25.136891,85.823024 25.557592,210.77125 88.452409,174.38061 67.417351,160.49747 57.110174,166.38729 V 105.80633 Z"
|
|
||||||
id="path1" /><path
|
|
||||||
style="fill:#000088;stroke-width:0.264583;fill-opacity:1"
|
|
||||||
d="M 67.728991,112.41131 182.54178,185.60757 153.16137,202.85259 67.830432,148.17947 Z"
|
|
||||||
id="path2" /><path
|
|
||||||
style="fill:#000088;stroke-width:0.264583;fill-opacity:1"
|
|
||||||
d="M 139.74857,145.88014 140.00405,110.4959 54.800856,56.333749 25.675926,73.32329 Z"
|
|
||||||
id="path3" /><path
|
|
||||||
style="fill:#000088;stroke-width:0.264583;fill-opacity:1"
|
|
||||||
d="M 182.2863,172.70573 V 48.286069 l -62.59305,36.406166 20.82177,13.668277 10.21927,-5.74834 0.12774,60.165978 z"
|
|
||||||
id="path4" /></g></g></svg>
|
|
||||||
|
Before Width: | Height: | Size: 2.2 KiB |
@@ -1,34 +0,0 @@
|
|||||||
${2},,,
|
|
||||||
${1},, ${2},,,,,,
|
|
||||||
${1},,,,,,,, ${2},,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,,, ${2}.,,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,,,,,,,,,,,,. ${2},,,,,,,,,,,,,,,,,,,
|
|
||||||
${1}.,,,,,,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,,,,,,,,,,,,
|
|
||||||
${1}, ${1},,,,,,,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,,,,,,,,,,,,,
|
|
||||||
${1},,, ${1},,,,,,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,,,,,,,,,,,,,
|
|
||||||
${1},,,,,, ${1}.,,,,,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,. ${1},,,,,,,,,,,,,,,,,,,,,,,,, ${2},,, ${2}.,,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,, ${1}.,,,,,,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,,,,,,,. ${2},,,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,, ${1},, ${1},,,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,, ${1},,,,, ${1},,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,, ${1},,,,,,,, ${1},,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,, ${1},,,,,,,,,, ${1},,,,,,,,,,,,, ${2},,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,, ${1},,,,,,,,,,,,,, ${1},,,,,,,,,, ${2},,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,, ${1},,,,,,, ${2},,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,, ${1},,,, ${2},,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,,,,, ${1},, ${2},,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,, ${1},,, ${1},,,,,,,,,,,,,,,,,,,,,,,,, ${2},,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,,,,,,, ${2}.,,,,,
|
|
||||||
${1},,,,,,,,,,,,,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,,,,,,,, ${2},,,
|
|
||||||
${1},,,,,,,,,,,,,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,,,,,,,, ${1},,,,,,,,,,,,,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,,,,, ${1}.,,,,,,,,,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,,,,, ${1},,,,,,,,,,,,,,
|
|
||||||
${1},,,,,,,,,, ${1},,,,,,,,,.
|
|
||||||
${1},,,,,, ${1},,
|
|
||||||
${1},,,,
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
,,,
|
|
||||||
,, ,,,,,,
|
|
||||||
,,,,,,,, ,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,,, .,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,,,,,,,,,,,,. ,,,,,,,,,,,,,,,,,,,
|
|
||||||
.,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,
|
|
||||||
, ,,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,
|
|
||||||
,,, ,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,
|
|
||||||
,,,,,, .,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,. ,,,,,,,,,,,,,,,,,,,,,,,,, ,,, .,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,, .,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,. ,,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,, ,, ,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,, ,,,,, ,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,, ,,,,,,,, ,,,,,,,,,,,,,,,, ,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,, ,,,,,,,,,, ,,,,,,,,,,,,, ,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,, ,,,,,,,,,,,,,, ,,,,,,,,,, ,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,, ,,,,,,,,,,,,,,,, ,,,,,,, ,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,, ,,,, ,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,, ,, ,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,, ,,, ,,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,, .,,,,,
|
|
||||||
,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,, ,,,
|
|
||||||
,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,,,,, .,,,,,,,,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,,,,, ,,,,,,,,,,,,,,
|
|
||||||
,,,,,,,,,, ,,,,,,,,,.
|
|
||||||
,,,,,, ,,
|
|
||||||
,,,,
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# Nomarchy Screensaver Configuration
|
|
||||||
|
|
||||||
Nomarchy uses hyprlock for locking and hypridle for idle management.
|
|
||||||
To configure the screensaver/lock screen visuals, edit:
|
|
||||||
~/.config/hypr/hyprlock.conf
|
|
||||||
|
|
||||||
To configure idle timeouts and actions, edit:
|
|
||||||
~/.config/hypr/hypridle.conf
|
|
||||||
|
|
||||||
You can also toggle the screensaver/idle management via the Nomarchy Menu:
|
|
||||||
Trigger > Toggle > Idle Lock
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{ ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
imports = [ ./system ];
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
{ config, lib, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
cfg = config.nomarchy.accessibility;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
# Hyprland-side accessibility extras. The system preset
|
|
||||||
# (core/system/accessibility.nix) covers AT-SPI2 + Orca on PATH +
|
|
||||||
# XCURSOR_SIZE; this module adds the bits Hyprland reads directly.
|
|
||||||
#
|
|
||||||
# Loaded via extraConfig (mkAfter) so it merges with — and overrides
|
|
||||||
# — the templated input.conf for the repeat-rate / repeat-delay
|
|
||||||
# fields. The Orca keybinding is additive.
|
|
||||||
wayland.windowManager.hyprland.extraConfig = lib.mkAfter ''
|
|
||||||
# Accessibility — slower key-repeat so holding a key isn't a
|
|
||||||
# runaway machine-gun for users with low-mobility hands.
|
|
||||||
input {
|
|
||||||
repeat_rate = 25
|
|
||||||
repeat_delay = 1000
|
|
||||||
}
|
|
||||||
|
|
||||||
# Launch the Orca screen reader. The system preset puts `orca`
|
|
||||||
# on PATH when nomarchy.system.accessibility.enable = true.
|
|
||||||
bindd = SUPER ALT, S, Launch Orca, exec, orca
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
{ config, lib, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
programs.bash = {
|
|
||||||
enable = true;
|
|
||||||
|
|
||||||
bashrcExtra = ''
|
|
||||||
if [[ -f ~/.config/nomarchy/default/bash/rc ]]; then
|
|
||||||
source ~/.config/nomarchy/default/bash/rc
|
|
||||||
fi
|
|
||||||
'';
|
|
||||||
|
|
||||||
shellAliases = lib.mkDefault {
|
|
||||||
# File system
|
|
||||||
lsa = "ls -a";
|
|
||||||
|
|
||||||
# Directories
|
|
||||||
".." = "cd ..";
|
|
||||||
"..." = "cd ../..";
|
|
||||||
"...." = "cd ../../..";
|
|
||||||
|
|
||||||
# Tools
|
|
||||||
c = "opencode";
|
|
||||||
d = "docker";
|
|
||||||
r = "rails";
|
|
||||||
t = "tmux attach || tmux new -s Work";
|
|
||||||
|
|
||||||
# Git
|
|
||||||
g = "git";
|
|
||||||
gcm = "git commit -m";
|
|
||||||
gcam = "git commit -a -m";
|
|
||||||
gcad = "git commit -a --amend";
|
|
||||||
|
|
||||||
# NixOS commands
|
|
||||||
sys-update = "nomarchy-sys-update";
|
|
||||||
env-update = "nomarchy-env-update";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
--ozone-platform=wayland
|
|
||||||
--ozone-platform-hint=wayland
|
|
||||||
--enable-features=TouchpadOverscrollHistoryNavigation
|
|
||||||
--load-extension=~/.config/nomarchy/default/chromium/extensions/copy-url
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
--ozone-platform=wayland
|
|
||||||
--ozone-platform-hint=wayland
|
|
||||||
--enable-features=TouchpadOverscrollHistoryNavigation
|
|
||||||
--load-extension=~/.config/nomarchy/default/chromium/extensions/copy-url
|
|
||||||
@@ -1,137 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json",
|
|
||||||
"logo": {
|
|
||||||
"type": "file",
|
|
||||||
"source": "~/.config/nomarchy/branding/icon.txt",
|
|
||||||
"color": { "1": "green", "2": "blue" },
|
|
||||||
"padding": {
|
|
||||||
"top": 2,
|
|
||||||
"right": 6,
|
|
||||||
"left": 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"modules": [
|
|
||||||
"break",
|
|
||||||
{
|
|
||||||
"type": "custom",
|
|
||||||
"format": "\u001b[90m┌──────────────────────Hardware──────────────────────┐"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "host",
|
|
||||||
"key": " PC",
|
|
||||||
"keyColor": "green"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "cpu",
|
|
||||||
"key": "│ ├",
|
|
||||||
"showPeCoreCount": true,
|
|
||||||
"keyColor": "green"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "gpu",
|
|
||||||
"key": "│ ├",
|
|
||||||
"detectionMethod": "pci",
|
|
||||||
"keyColor": "green"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "display",
|
|
||||||
"key": "│ ├",
|
|
||||||
"keyColor": "green"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "disk",
|
|
||||||
"key": "│ ├",
|
|
||||||
"keyColor": "green"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "memory",
|
|
||||||
"key": "│ ├",
|
|
||||||
"keyColor": "green"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "swap",
|
|
||||||
"key": "└ └ ",
|
|
||||||
"keyColor": "green"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "custom",
|
|
||||||
"format": "\u001b[90m└────────────────────────────────────────────────────┘"
|
|
||||||
},
|
|
||||||
"break",
|
|
||||||
{
|
|
||||||
"type": "custom",
|
|
||||||
"format": "\u001b[90m┌──────────────────────Software──────────────────────┐"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "os",
|
|
||||||
"key": "\ue900 OS",
|
|
||||||
"keyColor": "blue"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "kernel",
|
|
||||||
"key": "│ ├",
|
|
||||||
"keyColor": "blue"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "wm",
|
|
||||||
"key": "│ ├",
|
|
||||||
"keyColor": "blue"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "de",
|
|
||||||
"key": " DE",
|
|
||||||
"keyColor": "blue"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "terminal",
|
|
||||||
"key": "│ ├",
|
|
||||||
"keyColor": "blue"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "packages",
|
|
||||||
"key": "│ ├",
|
|
||||||
"keyColor": "blue"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "wmtheme",
|
|
||||||
"key": "│ ├",
|
|
||||||
"keyColor": "blue"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"key": "│ ├",
|
|
||||||
"keyColor": "blue",
|
|
||||||
"text": "theme=$(cat ~/.config/nomarchy/current/theme.name); echo -e \"$theme \\e[38m●\\e[37m●\\e[36m●\\e[35m●\\e[34m●\\e[33m●\\e[32m●\\e[31m●\""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "terminalfont",
|
|
||||||
"key": "└ └",
|
|
||||||
"keyColor": "blue"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "custom",
|
|
||||||
"format": "\u001b[90m└────────────────────────────────────────────────────┘"
|
|
||||||
},
|
|
||||||
"break",
|
|
||||||
{
|
|
||||||
"type": "custom",
|
|
||||||
"format": "\u001b[90m┌────────────────Age / Uptime / Update───────────────┐"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "command",
|
|
||||||
"key": " OS Age",
|
|
||||||
"keyColor": "magenta",
|
|
||||||
"text": "echo $(( ($(date +%s) - $(stat -c %W /)) / 86400 )) days"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "uptime",
|
|
||||||
"key": " Uptime",
|
|
||||||
"keyColor": "magenta"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "custom",
|
|
||||||
"format": "\u001b[90m└────────────────────────────────────────────────────┘"
|
|
||||||
},
|
|
||||||
"break"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
TriggerKey=
|
|
||||||
PastePrimaryKey=
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Allow Overriding System XKB Settings=False
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
|
|
||||||
<fontconfig>
|
|
||||||
<match target="pattern">
|
|
||||||
<test name="family" qual="any">
|
|
||||||
<string>sans-serif</string>
|
|
||||||
</test>
|
|
||||||
<edit name="family" mode="assign" binding="strong">
|
|
||||||
<string>Liberation Sans</string>
|
|
||||||
</edit>
|
|
||||||
</match>
|
|
||||||
|
|
||||||
<match target="pattern">
|
|
||||||
<test name="family" qual="any">
|
|
||||||
<string>serif</string>
|
|
||||||
</test>
|
|
||||||
<edit name="family" mode="assign" binding="strong">
|
|
||||||
<string>Liberation Serif</string>
|
|
||||||
</edit>
|
|
||||||
</match>
|
|
||||||
|
|
||||||
<match target="pattern">
|
|
||||||
<test name="family" qual="any">
|
|
||||||
<string>monospace</string>
|
|
||||||
</test>
|
|
||||||
<edit name="family" mode="assign" binding="strong">
|
|
||||||
<string>JetBrainsMono Nerd Font</string>
|
|
||||||
</edit>
|
|
||||||
</match>
|
|
||||||
|
|
||||||
<alias>
|
|
||||||
<family>system-ui</family>
|
|
||||||
<prefer>
|
|
||||||
<family>Liberation Sans</family>
|
|
||||||
</prefer>
|
|
||||||
</alias>
|
|
||||||
|
|
||||||
<alias>
|
|
||||||
<family>ui-monospace</family>
|
|
||||||
<default>
|
|
||||||
<family>monospace</family>
|
|
||||||
</default>
|
|
||||||
</alias>
|
|
||||||
|
|
||||||
<alias>
|
|
||||||
<family>-apple-system</family>
|
|
||||||
<prefer>
|
|
||||||
<family>Liberation Sans</family>
|
|
||||||
</prefer>
|
|
||||||
</alias>
|
|
||||||
|
|
||||||
<alias>
|
|
||||||
<family>BlinkMacSystemFont</family>
|
|
||||||
<prefer>
|
|
||||||
<family>Liberation Sans</family>
|
|
||||||
</prefer>
|
|
||||||
</alias>
|
|
||||||
|
|
||||||
<alias>
|
|
||||||
<family>sans-serif</family>
|
|
||||||
<accept>
|
|
||||||
<family>Noto Color Emoji</family>
|
|
||||||
</accept>
|
|
||||||
</alias>
|
|
||||||
|
|
||||||
<alias>
|
|
||||||
<family>serif</family>
|
|
||||||
<accept>
|
|
||||||
<family>Noto Color Emoji</family>
|
|
||||||
</accept>
|
|
||||||
</alias>
|
|
||||||
|
|
||||||
<alias>
|
|
||||||
<family>monospace</family>
|
|
||||||
<accept>
|
|
||||||
<family>Noto Color Emoji</family>
|
|
||||||
</accept>
|
|
||||||
</alias>
|
|
||||||
</fontconfig>
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
# See https://git-scm.com/docs/git-config
|
|
||||||
|
|
||||||
[alias]
|
|
||||||
co = checkout
|
|
||||||
br = branch
|
|
||||||
ci = commit
|
|
||||||
st = status
|
|
||||||
[init]
|
|
||||||
defaultBranch = master
|
|
||||||
[pull]
|
|
||||||
rebase = true # Rebase (instead of merge) on pull
|
|
||||||
[push]
|
|
||||||
autoSetupRemote = true # Automatically set upstream branch on push
|
|
||||||
[diff]
|
|
||||||
algorithm = histogram # Clearer diffs on moved/edited lines
|
|
||||||
colorMoved = plain # Highlight moved blocks in diffs
|
|
||||||
mnemonicPrefix = true # More intuitive refs in diff output
|
|
||||||
[commit]
|
|
||||||
verbose = true # Include diff comment in commit message template
|
|
||||||
[column]
|
|
||||||
ui = auto # Output in columns when possible
|
|
||||||
[branch]
|
|
||||||
sort = -committerdate # Sort branches by most recent commit first
|
|
||||||
[tag]
|
|
||||||
sort = -version:refname # Sort version numbers as you would expect
|
|
||||||
[rerere]
|
|
||||||
enabled = true # Record and reuse conflict resolutions
|
|
||||||
autoupdate = true # Apply stored conflict resolutions automatically
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
[binds]
|
|
||||||
|
|
||||||
# Print the current image file
|
|
||||||
<Ctrl+p> = exec lp "$imv_current_file"
|
|
||||||
|
|
||||||
# Delete the current image and quit the viewer
|
|
||||||
<Ctrl+x> = exec rm "$imv_current_file"; quit
|
|
||||||
|
|
||||||
# Delete the current image and move to the next one
|
|
||||||
<Ctrl+Shift+X> = exec rm "$imv_current_file"; close
|
|
||||||
|
|
||||||
# Rotate the currently open image by 90 degrees
|
|
||||||
<Ctrl+r> = exec mogrify -rotate 90 "$imv_current_file"
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
import os
|
|
||||||
import shutil
|
|
||||||
|
|
||||||
from gi import require_version
|
|
||||||
|
|
||||||
require_version("Nautilus", "4.1")
|
|
||||||
|
|
||||||
from gi.repository import GObject, Gio, Nautilus
|
|
||||||
|
|
||||||
|
|
||||||
class SendViaLocalSendAction(GObject.GObject, Nautilus.MenuProvider):
|
|
||||||
def _launch_localsend(self, paths):
|
|
||||||
command = self._resolve_command()
|
|
||||||
if not command:
|
|
||||||
return
|
|
||||||
|
|
||||||
if command[-1] == "@@":
|
|
||||||
command = command + paths + ["@@"]
|
|
||||||
else:
|
|
||||||
command = command + paths
|
|
||||||
|
|
||||||
Gio.Subprocess.new(command, Gio.SubprocessFlags.NONE)
|
|
||||||
|
|
||||||
def _resolve_command(self):
|
|
||||||
localsend = shutil.which("localsend")
|
|
||||||
if localsend:
|
|
||||||
return [localsend, "--headless", "send"]
|
|
||||||
|
|
||||||
flatpak = shutil.which("flatpak")
|
|
||||||
if flatpak and self._has_flatpak_app(flatpak, "org.localsend.localsend_app"):
|
|
||||||
return [
|
|
||||||
flatpak,
|
|
||||||
"run",
|
|
||||||
"--file-forwarding",
|
|
||||||
"org.localsend.localsend_app",
|
|
||||||
"@@",
|
|
||||||
]
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _has_flatpak_app(self, flatpak, app_id):
|
|
||||||
process = Gio.Subprocess.new(
|
|
||||||
[flatpak, "info", app_id],
|
|
||||||
Gio.SubprocessFlags.STDOUT_SILENCE | Gio.SubprocessFlags.STDERR_SILENCE,
|
|
||||||
)
|
|
||||||
return process.wait_check()
|
|
||||||
|
|
||||||
def _selected_paths(self, files):
|
|
||||||
paths = []
|
|
||||||
|
|
||||||
for file in files:
|
|
||||||
location = file.get_location()
|
|
||||||
if not location:
|
|
||||||
continue
|
|
||||||
|
|
||||||
path = location.get_path()
|
|
||||||
if path and path not in paths:
|
|
||||||
paths.append(path)
|
|
||||||
|
|
||||||
return paths
|
|
||||||
|
|
||||||
def _make_item(self, paths):
|
|
||||||
label = (
|
|
||||||
"Send via LocalSend" if len(paths) == 1 else "Send selected via LocalSend"
|
|
||||||
)
|
|
||||||
item = Nautilus.MenuItem(
|
|
||||||
name="LocalSendNautilus::send_via_localsend",
|
|
||||||
label=label,
|
|
||||||
icon="localsend",
|
|
||||||
)
|
|
||||||
item.connect("activate", self._on_activate, paths)
|
|
||||||
return item
|
|
||||||
|
|
||||||
def _on_activate(self, _menu, paths):
|
|
||||||
self._launch_localsend(paths)
|
|
||||||
|
|
||||||
def get_file_items(self, *args):
|
|
||||||
files = args[0] if len(args) == 1 else args[1]
|
|
||||||
paths = self._selected_paths(files)
|
|
||||||
|
|
||||||
if not paths or not self._resolve_command():
|
|
||||||
return []
|
|
||||||
|
|
||||||
return [self._make_item(paths)]
|
|
||||||
@@ -1,399 +0,0 @@
|
|||||||
---
|
|
||||||
name: nomarchy
|
|
||||||
description: >
|
|
||||||
REQUIRED for end-user customization of Linux desktop, window manager, or system config.
|
|
||||||
Use when editing ~/.config/hypr/, ~/.config/waybar/, ~/.config/walker/,
|
|
||||||
~/.config/alacritty/, ~/.config/kitty/, ~/.config/ghostty/, ~/.config/mako/,
|
|
||||||
or ~/.config/nomarchy/. Triggers: Hyprland, window rules, animations, keybindings,
|
|
||||||
monitors, gaps, borders, blur, opacity, waybar, walker, terminal config, themes,
|
|
||||||
wallpaper, night light, idle, lock screen, screenshots, layer rules, workspace
|
|
||||||
settings, display config, and user-facing nomarchy commands. Excludes Nomarchy
|
|
||||||
source development in ~/.local/share/nomarchy/ and repo-internal workflows.
|
|
||||||
---
|
|
||||||
|
|
||||||
# Nomarchy Skill
|
|
||||||
|
|
||||||
Manage [Nomarchy](https://nomarchy.org/) Linux systems - a beautiful, modern, opinionated Arch Linux distribution with Hyprland.
|
|
||||||
|
|
||||||
This skill is for end-user customization on installed systems.
|
|
||||||
It is not for contributing to Nomarchy source code.
|
|
||||||
|
|
||||||
## When This Skill MUST Be Used
|
|
||||||
|
|
||||||
**ALWAYS invoke this skill for end-user requests involving ANY of these:**
|
|
||||||
|
|
||||||
- Editing ANY file in `~/.config/hypr/` (window rules, animations, keybindings, monitors, etc.)
|
|
||||||
- Editing ANY file in `~/.config/waybar/`, `~/.config/walker/`, `~/.config/mako/`
|
|
||||||
- Editing terminal configs (alacritty, kitty, ghostty)
|
|
||||||
- Editing ANY file in `~/.config/nomarchy/`
|
|
||||||
- Window behavior, animations, opacity, blur, gaps, borders
|
|
||||||
- Layer rules, workspace settings, display/monitor configuration
|
|
||||||
- Themes, wallpapers, fonts, appearance changes
|
|
||||||
- User-facing `nomarchy-*` commands (`nomarchy-theme-*`, `nomarchy-refresh-*`, `nomarchy-restart-*`, etc.)
|
|
||||||
- Screenshots, screen recording, night light, idle behavior, lock screen
|
|
||||||
|
|
||||||
**If you're about to edit a config file in ~/.config/ on this system, STOP and use this skill first.**
|
|
||||||
|
|
||||||
**Do NOT use this skill for Nomarchy development tasks** — editing files in `~/.local/share/nomarchy/` or modifying repo internals.
|
|
||||||
|
|
||||||
## Critical Safety Rules
|
|
||||||
|
|
||||||
**For end-user customization tasks, NEVER modify anything in `~/.local/share/nomarchy/`** - but READING is safe and encouraged.
|
|
||||||
|
|
||||||
This directory contains Nomarchy's source files managed by git. Any changes will be:
|
|
||||||
- Lost on next `nomarchy-update`
|
|
||||||
- Cause conflicts with upstream
|
|
||||||
- Break the system's update mechanism
|
|
||||||
|
|
||||||
```
|
|
||||||
~/.local/share/nomarchy/ # READ-ONLY - NEVER EDIT (reading is OK)
|
|
||||||
├── bin/ # Source scripts (symlinked to PATH)
|
|
||||||
├── config/ # Default config templates
|
|
||||||
├── themes/ # Stock themes
|
|
||||||
├── default/ # System defaults
|
|
||||||
├── migrations/ # Update migrations
|
|
||||||
└── install/ # Installation scripts
|
|
||||||
```
|
|
||||||
|
|
||||||
**Reading `~/.local/share/nomarchy/` is SAFE and useful** - do it freely to:
|
|
||||||
- Understand how nomarchy commands work: `cat $(which nomarchy-theme-set)`
|
|
||||||
- See default configs before customizing: `cat ~/.local/share/nomarchy/config/fastfetch/config.jsonc`
|
|
||||||
- Check stock theme files to copy for customization
|
|
||||||
- Reference default hyprland settings: `cat ~/.config/nomarchy/default/hypr/*`
|
|
||||||
|
|
||||||
**Always use these safe locations instead:**
|
|
||||||
- `~/.config/` - User configuration (safe to edit)
|
|
||||||
- `~/.config/nomarchy/themes/<custom-name>/` - Custom themes (must be real directories)
|
|
||||||
- `~/.config/nomarchy/hooks/` - Custom automation hooks
|
|
||||||
|
|
||||||
If the request is to develop Nomarchy itself, this skill is out of scope. Follow repository development instructions instead of this skill.
|
|
||||||
|
|
||||||
## System Architecture
|
|
||||||
|
|
||||||
Nomarchy is built on:
|
|
||||||
|
|
||||||
| Component | Purpose | Config Location |
|
|
||||||
|-----------|---------|-----------------|
|
|
||||||
| **Arch Linux** | Base OS | `/etc/`, `~/.config/` |
|
|
||||||
| **Hyprland** | Wayland compositor/WM | `~/.config/hypr/` |
|
|
||||||
| **Waybar** | Status bar | `~/.config/waybar/` |
|
|
||||||
| **Walker** | App launcher | `~/.config/walker/` |
|
|
||||||
| **Alacritty/Kitty/Ghostty** | Terminals | `~/.config/<terminal>/` |
|
|
||||||
| **Mako** | Notifications | `~/.config/mako/` |
|
|
||||||
| **SwayOSD** | On-screen display | `~/.config/swayosd/` |
|
|
||||||
|
|
||||||
## Command Discovery
|
|
||||||
|
|
||||||
Nomarchy provides ~145 commands following `nomarchy-<category>-<action>` pattern.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# List all nomarchy commands
|
|
||||||
compgen -c | grep -E '^nomarchy-' | sort -u
|
|
||||||
|
|
||||||
# Find commands by category
|
|
||||||
compgen -c | grep -E '^nomarchy-theme'
|
|
||||||
compgen -c | grep -E '^nomarchy-restart'
|
|
||||||
|
|
||||||
# Read a command's source to understand it
|
|
||||||
cat $(which nomarchy-theme-set)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Command Categories
|
|
||||||
|
|
||||||
| Prefix | Purpose | Example |
|
|
||||||
|--------|---------|---------|
|
|
||||||
| `nomarchy-refresh-*` | Reset config to defaults (backs up first) | `nomarchy-refresh-waybar` |
|
|
||||||
| `nomarchy-restart-*` | Restart a service/app | `nomarchy-restart-waybar` |
|
|
||||||
| `nomarchy-toggle-*` | Toggle feature on/off | `nomarchy-toggle-nightlight` |
|
|
||||||
| `nomarchy-theme-*` | Theme management | `nomarchy-theme-set <name>` |
|
|
||||||
| `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-add <pkg>` |
|
|
||||||
| `nomarchy-setup-*` | Initial setup tasks | `nomarchy-setup-fingerprint` |
|
|
||||||
| `nomarchy-update-*` | System updates | `nomarchy-update` |
|
|
||||||
|
|
||||||
## Configuration Locations
|
|
||||||
|
|
||||||
### Hyprland (Window Manager)
|
|
||||||
|
|
||||||
```
|
|
||||||
~/.config/hypr/
|
|
||||||
├── hyprland.conf # Main config (sources others)
|
|
||||||
├── bindings.conf # Keybindings
|
|
||||||
├── monitors.conf # Display configuration
|
|
||||||
├── input.conf # Keyboard/mouse settings
|
|
||||||
├── looknfeel.conf # Appearance (gaps, borders, animations)
|
|
||||||
├── envs.conf # Environment variables
|
|
||||||
├── autostart.conf # Startup applications
|
|
||||||
├── hypridle.conf # Idle behavior (screen off, lock, suspend)
|
|
||||||
├── hyprlock.conf # Lock screen appearance
|
|
||||||
└── hyprsunset.conf # Night light / blue light filter
|
|
||||||
```
|
|
||||||
|
|
||||||
**Key behaviors:**
|
|
||||||
- Hyprland auto-reloads on config save (no restart needed for most changes)
|
|
||||||
- Use `hyprctl reload` to force reload
|
|
||||||
- Use `nomarchy-refresh-hyprland` to reset to defaults
|
|
||||||
|
|
||||||
### Waybar (Status Bar)
|
|
||||||
|
|
||||||
```
|
|
||||||
~/.config/waybar/
|
|
||||||
├── config.jsonc # Bar layout and modules (JSONC format)
|
|
||||||
└── style.css # Styling
|
|
||||||
```
|
|
||||||
|
|
||||||
**Waybar does NOT auto-reload.** You MUST run `nomarchy-restart-waybar` after any config changes.
|
|
||||||
|
|
||||||
**Commands:** `nomarchy-restart-waybar`, `nomarchy-refresh-waybar`, `nomarchy-toggle-waybar`
|
|
||||||
|
|
||||||
### Terminals
|
|
||||||
|
|
||||||
```
|
|
||||||
~/.config/alacritty/alacritty.toml
|
|
||||||
~/.config/kitty/kitty.conf
|
|
||||||
~/.config/ghostty/config
|
|
||||||
```
|
|
||||||
|
|
||||||
**Command:** `nomarchy-restart-terminal`
|
|
||||||
|
|
||||||
### Other Configs
|
|
||||||
|
|
||||||
| App | Location |
|
|
||||||
|-----|----------|
|
|
||||||
| btop | `~/.config/btop/btop.conf` |
|
|
||||||
| fastfetch | `~/.config/fastfetch/config.jsonc` |
|
|
||||||
| lazygit | `~/.config/lazygit/config.yml` |
|
|
||||||
| starship | `~/.config/starship.toml` |
|
|
||||||
| git | `~/.config/git/config` |
|
|
||||||
| walker | `~/.config/walker/config.toml` |
|
|
||||||
|
|
||||||
## Safe Customization Patterns
|
|
||||||
|
|
||||||
### Pattern 1: Edit User Config Directly
|
|
||||||
|
|
||||||
For simple changes, edit files in `~/.config/`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. Read current config
|
|
||||||
cat ~/.config/hypr/bindings.conf
|
|
||||||
|
|
||||||
# 2. Backup before changes
|
|
||||||
cp ~/.config/hypr/bindings.conf ~/.config/hypr/bindings.conf.bak.$(date +%s)
|
|
||||||
|
|
||||||
# 3. Make changes with Edit tool
|
|
||||||
|
|
||||||
# 4. Apply changes
|
|
||||||
# - Hyprland: auto-reloads on save (no restart needed)
|
|
||||||
# - Waybar: MUST restart with nomarchy-restart-waybar
|
|
||||||
# - Walker: MUST restart with nomarchy-restart-walker
|
|
||||||
# - Terminals: MUST restart with nomarchy-restart-terminal
|
|
||||||
```
|
|
||||||
|
|
||||||
### Pattern 2: Make a new theme
|
|
||||||
|
|
||||||
1. Create a directory under ~/.config/nomarchy/themes.
|
|
||||||
2. See how an existing theme is done via ~/.local/share/nomarchy/themes/catppuccin.
|
|
||||||
3. Download a matching background (or several) from the internet and put them in ~/.config/nomarchy/themes/[name-of-new-theme]
|
|
||||||
4. When done with the theme, run nomarchy-theme-set "Name of new theme"
|
|
||||||
|
|
||||||
### Pattern 3: Use Hooks for Automation
|
|
||||||
|
|
||||||
Create scripts in `~/.config/nomarchy/hooks/` to run automatically on events:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Available hooks (see samples in ~/.config/nomarchy/hooks/):
|
|
||||||
~/.config/nomarchy/hooks/
|
|
||||||
├── theme-set # Runs after theme change (receives theme name as $1)
|
|
||||||
├── font-set # Runs after font change
|
|
||||||
└── post-update # Runs after nomarchy-update
|
|
||||||
```
|
|
||||||
|
|
||||||
Example hook (`~/.config/nomarchy/hooks/theme-set`):
|
|
||||||
```bash
|
|
||||||
#!/bin/bash
|
|
||||||
THEME_NAME=$1
|
|
||||||
echo "Theme changed to: $THEME_NAME"
|
|
||||||
# Add custom actions here
|
|
||||||
```
|
|
||||||
|
|
||||||
### Pattern 4: Reset to Defaults -- ALWAYS SEEK USER CONFIRMATION BEFORE RUNNING
|
|
||||||
|
|
||||||
When customizations go wrong:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Reset specific config (creates backup automatically)
|
|
||||||
nomarchy-refresh-waybar
|
|
||||||
nomarchy-refresh-hyprland
|
|
||||||
|
|
||||||
# The refresh command:
|
|
||||||
# 1. Backs up current config with timestamp
|
|
||||||
# 2. Copies default from ~/.local/share/nomarchy/config/
|
|
||||||
# 3. Restarts the component
|
|
||||||
```
|
|
||||||
|
|
||||||
## Common Tasks
|
|
||||||
|
|
||||||
### Themes
|
|
||||||
|
|
||||||
```bash
|
|
||||||
nomarchy-theme-list # Show available themes
|
|
||||||
nomarchy-theme-current # Show current theme
|
|
||||||
nomarchy-theme-set <name> # Apply theme (use "Tokyo Night" not "tokyo-night")
|
|
||||||
nomarchy-theme-next # Cycle to next theme
|
|
||||||
nomarchy-theme-bg-next # Cycle wallpaper
|
|
||||||
nomarchy-theme-install <url> # Install from git repo
|
|
||||||
nomarchy-theme-remove <name> # Remove an installed extra theme
|
|
||||||
nomarchy-theme-refresh # Re-apply current theme from templates
|
|
||||||
nomarchy-theme-bg-install # Open backgrounds dir to drop in custom images
|
|
||||||
```
|
|
||||||
|
|
||||||
### Keybindings
|
|
||||||
|
|
||||||
Edit `~/.config/hypr/bindings.conf`. Format:
|
|
||||||
```
|
|
||||||
bind = SUPER, Return, exec, xdg-terminal-exec
|
|
||||||
bind = SUPER, Q, killactive
|
|
||||||
bind = SUPER SHIFT, E, exit
|
|
||||||
```
|
|
||||||
|
|
||||||
View current bindings: `nomarchy-menu-keybindings --print`
|
|
||||||
|
|
||||||
**IMPORTANT: When re-binding an existing key:**
|
|
||||||
|
|
||||||
1. First check existing bindings: `nomarchy-menu-keybindings --print`
|
|
||||||
2. If the key is already bound, you MUST add an `unbind` directive BEFORE your new `bind`
|
|
||||||
3. Inform the user what the key was previously bound to
|
|
||||||
|
|
||||||
Example - rebinding SUPER+F (which is bound to fullscreen by default):
|
|
||||||
```
|
|
||||||
# Unbind existing SUPER+F (was: fullscreen)
|
|
||||||
unbind = SUPER, F
|
|
||||||
# New binding for file manager
|
|
||||||
bind = SUPER, F, exec, nautilus
|
|
||||||
```
|
|
||||||
|
|
||||||
Always tell the user: "Note: SUPER+F was previously bound to fullscreen. I've added an unbind directive to override it."
|
|
||||||
|
|
||||||
### Display/Monitors
|
|
||||||
|
|
||||||
Edit `~/.config/hypr/monitors.conf`. Format:
|
|
||||||
```
|
|
||||||
monitor = eDP-1, 1920x1080@60, 0x0, 1
|
|
||||||
monitor = HDMI-A-1, 2560x1440@144, 1920x0, 1
|
|
||||||
```
|
|
||||||
|
|
||||||
List monitors: `hyprctl monitors`
|
|
||||||
|
|
||||||
### Window Rules
|
|
||||||
|
|
||||||
**CRITICAL: Hyprland window rules syntax changes frequently between versions.**
|
|
||||||
|
|
||||||
Before writing ANY window rules, you MUST fetch the current documentation from the official Hyprland wiki:
|
|
||||||
- https://github.com/hyprwm/hyprland-wiki/blob/main/content/Configuring/Window-Rules.md
|
|
||||||
|
|
||||||
DO NOT rely on cached or memorized window rule syntax. The format has changed multiple times and using outdated syntax will cause errors or unexpected behavior.
|
|
||||||
|
|
||||||
Window rules go in `~/.config/hypr/hyprland.conf` or a sourced file. Always verify the current syntax from the wiki first.
|
|
||||||
|
|
||||||
### Fonts
|
|
||||||
|
|
||||||
```bash
|
|
||||||
nomarchy-font-list # Available fonts
|
|
||||||
nomarchy-font-current # Current font
|
|
||||||
nomarchy-font-set <name> # Change font
|
|
||||||
```
|
|
||||||
|
|
||||||
### System
|
|
||||||
|
|
||||||
```bash
|
|
||||||
nomarchy-update # Full system update
|
|
||||||
nomarchy-version # Show Nomarchy version
|
|
||||||
nomarchy-debug --no-sudo --print # Debug info (ALWAYS use these flags)
|
|
||||||
nomarchy-lock-screen # Lock screen
|
|
||||||
nomarchy-system-shutdown # Shutdown
|
|
||||||
nomarchy-system-reboot # Reboot
|
|
||||||
nomarchy-sudo-passwordless-toggle # Toggle 15-min passwordless sudo
|
|
||||||
nomarchy-sudo-reset # Clear sudo lockout / faillock
|
|
||||||
nomarchy-restart-trackpad # Reload intel_quicki2c (fixes dead THC trackpad)
|
|
||||||
```
|
|
||||||
|
|
||||||
**IMPORTANT:** Always run `nomarchy-debug` with `--no-sudo --print` flags to avoid interactive sudo prompts that will hang the terminal.
|
|
||||||
|
|
||||||
### Custom App Launchers
|
|
||||||
|
|
||||||
```bash
|
|
||||||
nomarchy-webapp-install # Add a web app launcher (interactive)
|
|
||||||
nomarchy-webapp-remove [name...] # Remove web apps (interactive if no name)
|
|
||||||
nomarchy-webapp-remove-all # Bulk-remove every web app
|
|
||||||
nomarchy-tui-install # Add a TUI launcher for a terminal program
|
|
||||||
nomarchy-tui-remove [name...] # Remove TUI launchers
|
|
||||||
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).
|
|
||||||
|
|
||||||
### Virtualization
|
|
||||||
|
|
||||||
```bash
|
|
||||||
nomarchy-windows-vm install # Provision a Windows VM via docker-compose
|
|
||||||
nomarchy-windows-vm launch # Connect to the VM (auto-stop on disconnect)
|
|
||||||
nomarchy-windows-vm launch -k # Connect, keep VM running after disconnect
|
|
||||||
nomarchy-windows-vm stop # Shut the VM down
|
|
||||||
nomarchy-windows-vm status # Show current state
|
|
||||||
```
|
|
||||||
|
|
||||||
Requires KVM (`/dev/kvm`) and Docker (enable via `nomarchy.system.virtualization.docker`).
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Get debug information (ALWAYS use these flags to avoid interactive prompts)
|
|
||||||
nomarchy-debug --no-sudo --print
|
|
||||||
|
|
||||||
# Upload logs for support
|
|
||||||
nomarchy-upload-log
|
|
||||||
|
|
||||||
# Reset specific config to defaults
|
|
||||||
# Examples: nomarchy-refresh-fastfetch, nomarchy-refresh-hyprland, nomarchy-refresh-waybar
|
|
||||||
nomarchy-refresh-<app>
|
|
||||||
|
|
||||||
# Refresh specific config file
|
|
||||||
# config-file path is relative to ~/.config/; the stock copy must exist under
|
|
||||||
# ~/.local/share/nomarchy/config/ (i.e. a core/home/config item).
|
|
||||||
# eg. nomarchy-refresh-config fastfetch/config.jsonc refreshes ~/.config/fastfetch/config.jsonc
|
|
||||||
nomarchy-refresh-config <config-file>
|
|
||||||
|
|
||||||
# Full reinstall of configs (nuclear option)
|
|
||||||
nomarchy-reinstall
|
|
||||||
```
|
|
||||||
|
|
||||||
## Decision Framework
|
|
||||||
|
|
||||||
When user requests system changes:
|
|
||||||
|
|
||||||
1. **Is it a stock nomarchy command?** Use it directly
|
|
||||||
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` (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
|
|
||||||
|
|
||||||
This skill intentionally does not cover Nomarchy source development. Do not use this skill for:
|
|
||||||
- Editing files in `~/.local/share/nomarchy/` (`bin/`, `config/`, `default/`, `themes/`, `migrations/`, etc.)
|
|
||||||
- Creating or editing migrations
|
|
||||||
- Modifying Nomarchy's own source tree
|
|
||||||
|
|
||||||
## Example Requests
|
|
||||||
|
|
||||||
- "Change my theme to catppuccin" -> `nomarchy-theme-set catppuccin`
|
|
||||||
- "Add a keybinding for Super+E to open file manager" -> Check existing bindings first, add `unbind` if needed, then add `bind` in `~/.config/hypr/bindings.conf`
|
|
||||||
- "Configure my external monitor" -> Edit `~/.config/hypr/monitors.conf`
|
|
||||||
- "Make the window gaps smaller" -> Edit `~/.config/hypr/looknfeel.conf`
|
|
||||||
- "Set up night light to turn on at sunset" -> `nomarchy-toggle-nightlight` or edit `~/.config/hypr/hyprsunset.conf`
|
|
||||||
- "Customize the catppuccin theme colors" -> Create `~/.config/nomarchy/themes/catppuccin-custom/` by copying from stock, then edit
|
|
||||||
- "Run a script every time I change themes" -> Create `~/.config/nomarchy/hooks/theme-set`
|
|
||||||
- "Reset waybar to defaults" -> `nomarchy-refresh-waybar`
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
[colors.primary]
|
|
||||||
background = "0x000000"
|
|
||||||
|
|
||||||
[colors.cursor]
|
|
||||||
cursor = "0x000000"
|
|
||||||
|
|
||||||
[font]
|
|
||||||
size = 18.0
|
|
||||||
|
|
||||||
[window]
|
|
||||||
opacity = 1.0
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
# File system
|
|
||||||
if command -v eza &> /dev/null; then
|
|
||||||
alias ls='eza -lh --group-directories-first --icons=auto'
|
|
||||||
alias lsa='ls -a'
|
|
||||||
alias lt='eza --tree --level=2 --long --icons --git'
|
|
||||||
alias lta='lt -a'
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$TERM" == "xterm-kitty" ]]; then
|
|
||||||
alias ff="fzf --preview 'case \$(file --mime-type -b {}) in image/*) kitty icat --clear --transfer-mode=memory --stdin=no --place=\${FZF_PREVIEW_COLUMNS}x\${FZF_PREVIEW_LINES}@0x0 {} ;; *) bat --style=numbers --color=always {} ;; esac'"
|
|
||||||
else
|
|
||||||
alias ff="fzf --preview 'bat --style=numbers --color=always {}'"
|
|
||||||
fi
|
|
||||||
alias eff='$EDITOR "$(ff)"'
|
|
||||||
sff() { if [ $# -eq 0 ]; then echo "Usage: sff <destination> (e.g. sff host:/tmp/)"; return 1; fi; local file; file=$(find . -type f -printf '%T@\t%p\n' | sort -rn | cut -f2- | ff) && [ -n "$file" ] && scp "$file" "$1"; }
|
|
||||||
|
|
||||||
if command -v zoxide &> /dev/null; then
|
|
||||||
alias cd="zd"
|
|
||||||
zd() {
|
|
||||||
if (( $# == 0 )); then
|
|
||||||
builtin cd ~ || return
|
|
||||||
elif [[ -d $1 ]]; then
|
|
||||||
builtin cd "$1" || return
|
|
||||||
else
|
|
||||||
if ! z "$@"; then
|
|
||||||
echo "Error: Directory not found"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
printf "\U000F17A9 "
|
|
||||||
pwd
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
|
|
||||||
open() (
|
|
||||||
xdg-open "$@" >/dev/null 2>&1 &
|
|
||||||
)
|
|
||||||
|
|
||||||
# Directories
|
|
||||||
alias ..='cd ..'
|
|
||||||
alias ...='cd ../..'
|
|
||||||
alias ....='cd ../../..'
|
|
||||||
|
|
||||||
# Tools
|
|
||||||
alias c='opencode'
|
|
||||||
alias cx='printf "\033[2J\033[3J\033[H" && claude --allow-dangerously-skip-permissions'
|
|
||||||
alias d='docker'
|
|
||||||
alias r='rails'
|
|
||||||
alias t='tmux attach || tmux new -s Work'
|
|
||||||
n() { if [ "$#" -eq 0 ]; then command nvim . ; else command nvim "$@"; fi; }
|
|
||||||
|
|
||||||
# Git
|
|
||||||
alias g='git'
|
|
||||||
alias gcm='git commit -m'
|
|
||||||
alias gcam='git commit -a -m'
|
|
||||||
alias gcad='git commit -a --amend'
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
# Editor used by CLI
|
|
||||||
export SUDO_EDITOR="$EDITOR"
|
|
||||||
export BAT_THEME=ansi
|
|
||||||
|
|
||||||
# Duplicated from .config/uwsm/env so SSH works too
|
|
||||||
export PATH=$PATH:$HOME/.local/bin
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
# Compression
|
|
||||||
compress() { tar -czf "${1%/}.tar.gz" "${1%/}"; }
|
|
||||||
alias decompress="tar -xzf"
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
# Write iso file to sd card
|
|
||||||
iso2sd() {
|
|
||||||
if (( $# < 1 )); then
|
|
||||||
echo "Usage: iso2sd <input_file> [output_device]"
|
|
||||||
echo "Example: iso2sd ~/Downloads/ubuntu-25.04-desktop-amd64.iso /dev/sda"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local iso="$1"
|
|
||||||
local drive="$2"
|
|
||||||
|
|
||||||
if [[ -z $drive ]]; then
|
|
||||||
local available_sds=$(lsblk -dpno NAME | grep -E '/dev/sd')
|
|
||||||
|
|
||||||
if [[ -z $available_sds ]]; then
|
|
||||||
echo "No SD drives found and no drive specified"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
drive=$(nomarchy-drive-select "$available_sds")
|
|
||||||
|
|
||||||
if [[ -z $drive ]]; then
|
|
||||||
echo "No drive selected"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
sudo dd bs=4M status=progress oflag=sync if="$iso" of="$drive"
|
|
||||||
sudo eject "$drive"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Format an entire drive for a single partition using exFAT
|
|
||||||
format-drive() {
|
|
||||||
if (( $# != 2 )); then
|
|
||||||
echo "Usage: format-drive <device> <name>"
|
|
||||||
echo "Example: format-drive /dev/sda 'My Stuff'"
|
|
||||||
echo -e "\nAvailable drives:"
|
|
||||||
lsblk -d -o NAME -n | awk '{print "/dev/"$1}'
|
|
||||||
else
|
|
||||||
echo "WARNING: This will completely erase all data on $1 and label it '$2'."
|
|
||||||
read -rp "Are you sure you want to continue? (y/N): " confirm
|
|
||||||
|
|
||||||
if [[ $confirm =~ ^[Yy]$ ]]; then
|
|
||||||
sudo wipefs -a "$1"
|
|
||||||
sudo dd if=/dev/zero of="$1" bs=1M count=100 status=progress
|
|
||||||
sudo parted -s "$1" mklabel gpt
|
|
||||||
sudo parted -s "$1" mkpart primary 1MiB 100%
|
|
||||||
sudo parted -s "$1" set 1 msftdata on
|
|
||||||
|
|
||||||
partition="$([[ $1 == *"nvme"* ]] && echo "${1}p1" || echo "${1}1")"
|
|
||||||
sudo partprobe "$1" || true
|
|
||||||
sudo udevadm settle || true
|
|
||||||
|
|
||||||
sudo mkfs.exfat -n "$2" "$partition"
|
|
||||||
|
|
||||||
echo "Drive $1 formatted as exFAT and labeled '$2'."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
# SSH Port Forwarding Functions
|
|
||||||
fip() {
|
|
||||||
(( $# < 2 )) && echo "Usage: fip <host> <port1> [port2] ..." && return 1
|
|
||||||
local host="$1"
|
|
||||||
shift
|
|
||||||
for port in "$@"; do
|
|
||||||
ssh -f -N -L "$port:localhost:$port" "$host" && echo "Forwarding localhost:$port -> $host:$port"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
dip() {
|
|
||||||
(( $# == 0 )) && echo "Usage: dip <port1> [port2] ..." && return 1
|
|
||||||
for port in "$@"; do
|
|
||||||
pkill -f "ssh.*-L $port:localhost:$port" && echo "Stopped forwarding port $port" || echo "No forwarding on port $port"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
lip() {
|
|
||||||
pgrep -af "ssh.*-L [0-9]+:localhost:[0-9]+" || echo "No active forwards"
|
|
||||||
}
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
# Create a Tmux Dev Layout with editor, ai, and terminal
|
|
||||||
# Usage: tdl <c|cx|codex|other_ai> [<second_ai>]
|
|
||||||
tdl() {
|
|
||||||
[[ -z $1 ]] && { echo "Usage: tdl <c|cx|codex|other_ai> [<second_ai>]"; return 1; }
|
|
||||||
[[ -z $TMUX ]] && { echo "You must start tmux to use tdl."; return 1; }
|
|
||||||
|
|
||||||
local current_dir="${PWD}"
|
|
||||||
local editor_pane ai_pane ai2_pane
|
|
||||||
local ai="$1"
|
|
||||||
local ai2="$2"
|
|
||||||
|
|
||||||
# Use TMUX_PANE for the pane we're running in (stable even if active window changes)
|
|
||||||
editor_pane="$TMUX_PANE"
|
|
||||||
|
|
||||||
# Name the current window after the base directory name
|
|
||||||
tmux rename-window -t "$editor_pane" "$(basename "$current_dir")"
|
|
||||||
|
|
||||||
# Split window vertically - top 85%, bottom 15% (target editor pane explicitly)
|
|
||||||
tmux split-window -v -p 15 -t "$editor_pane" -c "$current_dir"
|
|
||||||
|
|
||||||
# Split editor pane horizontally - AI on right 30% (capture new pane ID directly)
|
|
||||||
ai_pane=$(tmux split-window -h -p 30 -t "$editor_pane" -c "$current_dir" -P -F '#{pane_id}')
|
|
||||||
|
|
||||||
# If second AI provided, split the AI pane vertically
|
|
||||||
if [[ -n $ai2 ]]; then
|
|
||||||
ai2_pane=$(tmux split-window -v -t "$ai_pane" -c "$current_dir" -P -F '#{pane_id}')
|
|
||||||
tmux send-keys -t "$ai2_pane" "$ai2" C-m
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Run ai in the right pane
|
|
||||||
tmux send-keys -t "$ai_pane" "$ai" C-m
|
|
||||||
|
|
||||||
# Run nvim in the left pane
|
|
||||||
tmux send-keys -t "$editor_pane" "$EDITOR ." C-m
|
|
||||||
|
|
||||||
# Select the nvim pane for focus
|
|
||||||
tmux select-pane -t "$editor_pane"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create multiple tdl windows with one per subdirectory in the current directory
|
|
||||||
# Usage: tdlm <c|cx|codex|other_ai> [<second_ai>]
|
|
||||||
tdlm() {
|
|
||||||
[[ -z $1 ]] && { echo "Usage: tdlm <c|cx|codex|other_ai> [<second_ai>]"; return 1; }
|
|
||||||
[[ -z $TMUX ]] && { echo "You must start tmux to use tdlm."; return 1; }
|
|
||||||
|
|
||||||
local ai="$1"
|
|
||||||
local ai2="$2"
|
|
||||||
local base_dir="$PWD"
|
|
||||||
local first=true
|
|
||||||
|
|
||||||
# Rename the session to the current directory name (replace dots/colons which tmux disallows)
|
|
||||||
tmux rename-session "$(basename "$base_dir" | tr '.:' '--')"
|
|
||||||
|
|
||||||
for dir in "$base_dir"/*/; do
|
|
||||||
[[ -d $dir ]] || continue
|
|
||||||
local dirpath="${dir%/}"
|
|
||||||
|
|
||||||
if $first; then
|
|
||||||
# Reuse the current window for the first project
|
|
||||||
tmux send-keys -t "$TMUX_PANE" "cd '$dirpath' && tdl $ai $ai2" C-m
|
|
||||||
first=false
|
|
||||||
else
|
|
||||||
local pane_id=$(tmux new-window -c "$dirpath" -P -F '#{pane_id}')
|
|
||||||
tmux send-keys -t "$pane_id" "tdl $ai $ai2" C-m
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create a multi-pane swarm layout with the same command started in each pane (great for AI)
|
|
||||||
# Usage: tsl <pane_count> <command>
|
|
||||||
tsl() {
|
|
||||||
[[ -z $1 || -z $2 ]] && { echo "Usage: tsl <pane_count> <command>"; return 1; }
|
|
||||||
[[ -z $TMUX ]] && { echo "You must start tmux to use tsl."; return 1; }
|
|
||||||
|
|
||||||
local count="$1"
|
|
||||||
local cmd="$2"
|
|
||||||
local current_dir="${PWD}"
|
|
||||||
local -a panes
|
|
||||||
|
|
||||||
tmux rename-window -t "$TMUX_PANE" "$(basename "$current_dir")"
|
|
||||||
|
|
||||||
panes+=("$TMUX_PANE")
|
|
||||||
|
|
||||||
while (( ${#panes[@]} < count )); do
|
|
||||||
local new_pane
|
|
||||||
local split_target="${panes[-1]}"
|
|
||||||
new_pane=$(tmux split-window -h -t "$split_target" -c "$current_dir" -P -F '#{pane_id}')
|
|
||||||
panes+=("$new_pane")
|
|
||||||
tmux select-layout -t "${panes[0]}" tiled
|
|
||||||
done
|
|
||||||
|
|
||||||
for pane in "${panes[@]}"; do
|
|
||||||
tmux send-keys -t "$pane" "$cmd" C-m
|
|
||||||
done
|
|
||||||
|
|
||||||
tmux select-pane -t "${panes[0]}"
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
# Transcode a video to a good-balance 1080p that's great for sharing online
|
|
||||||
transcode-video-1080p() {
|
|
||||||
ffmpeg -i "$1" -vf scale=1920:1080 -c:v libx264 -preset fast -crf 23 -c:a copy "${1%.*}-1080p.mp4"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Transcode a video to a good-balance 4K that's great for sharing online
|
|
||||||
transcode-video-4K() {
|
|
||||||
ffmpeg -i "$1" -c:v libx265 -preset slow -crf 24 -c:a aac -b:a 192k "${1%.*}-optimized.mp4"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Transcode any image to JPG image that's great for shrinking wallpapers
|
|
||||||
img2jpg() {
|
|
||||||
img="$1"
|
|
||||||
shift
|
|
||||||
|
|
||||||
magick "$img" "$@" -quality 85 -strip "${img%.*}-converted.jpg"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Transcode any image to a small JPG (max 1080px wide)
|
|
||||||
img2jpg-small() {
|
|
||||||
img="$1"
|
|
||||||
shift
|
|
||||||
|
|
||||||
magick "$img" "$@" -resize 1080x\> -quality 85 -strip "${img%.*}-small.jpg"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Transcode any image to a 4K JPG (max 2160px wide)
|
|
||||||
img2jpg-medium() {
|
|
||||||
img="$1"
|
|
||||||
shift
|
|
||||||
|
|
||||||
magick "$img" "$@" -resize 2160x\> -quality 85 -strip "${img%.*}-medium.jpg"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Transcode any image to a 6K JPG (max 3160px wide)
|
|
||||||
img2jpg-large() {
|
|
||||||
img="$1"
|
|
||||||
shift
|
|
||||||
|
|
||||||
magick "$img" "$@" -resize 3160x\> -quality 85 -strip "${img%.*}-large.jpg"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Transcode any image to compressed-but-lossless PNG
|
|
||||||
img2png() {
|
|
||||||
img="$1"
|
|
||||||
shift
|
|
||||||
|
|
||||||
magick "$img" "$@" -strip -define png:compression-filter=5 \
|
|
||||||
-define png:compression-level=9 \
|
|
||||||
-define png:compression-strategy=1 \
|
|
||||||
-define png:exclude-chunk=all \
|
|
||||||
"${img%.*}-optimized.png"
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
# Create a new worktree and branch from within current git directory.
|
|
||||||
ga() {
|
|
||||||
if [[ -z "$1" ]]; then
|
|
||||||
echo "Usage: ga [branch name]"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local branch="$1"
|
|
||||||
local base="$(basename "$PWD")"
|
|
||||||
local wt_path="../${base}--${branch}"
|
|
||||||
|
|
||||||
git worktree add -b "$branch" "$wt_path"
|
|
||||||
mise trust "$wt_path"
|
|
||||||
cd "$wt_path"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Remove worktree and branch from within active worktree directory.
|
|
||||||
gd() {
|
|
||||||
if gum confirm "Remove worktree and branch?"; then
|
|
||||||
local cwd base branch root worktree
|
|
||||||
|
|
||||||
cwd="$(pwd)"
|
|
||||||
worktree="$(basename "$cwd")"
|
|
||||||
|
|
||||||
# split on first `--`
|
|
||||||
root="${worktree%%--*}"
|
|
||||||
branch="${worktree#*--}"
|
|
||||||
|
|
||||||
# Protect against accidentally nuking a non-worktree directory
|
|
||||||
if [[ "$root" != "$worktree" ]]; then
|
|
||||||
cd "../$root"
|
|
||||||
git worktree remove "$cwd" --force || return 1
|
|
||||||
git branch -D "$branch"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
for f in $HOME/.config/nomarchy/default/bash/fns/*; do source "$f"; done
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
if command -v mise &> /dev/null; then
|
|
||||||
eval "$(mise activate bash)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if command -v starship &> /dev/null; then
|
|
||||||
eval "$(starship init bash)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if command -v zoxide &> /dev/null; then
|
|
||||||
eval "$(zoxide init bash)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if command -v try &> /dev/null; then
|
|
||||||
eval "$(SHELL=/bin/bash command try init ~/Work/tries)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if command -v fzf &> /dev/null; then
|
|
||||||
if [[ -f /usr/share/fzf/completion.bash ]]; then
|
|
||||||
source /usr/share/fzf/completion.bash
|
|
||||||
fi
|
|
||||||
if [[ -f /usr/share/fzf/key-bindings.bash ]]; then
|
|
||||||
source /usr/share/fzf/key-bindings.bash
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
set meta-flag on
|
|
||||||
set input-meta on
|
|
||||||
set output-meta on
|
|
||||||
set convert-meta off
|
|
||||||
set completion-ignore-case on
|
|
||||||
set completion-prefix-display-length 2
|
|
||||||
set show-all-if-ambiguous on
|
|
||||||
set show-all-if-unmodified on
|
|
||||||
|
|
||||||
# Arrow keys match what you've typed so far against your command history
|
|
||||||
"\e[A": history-search-backward
|
|
||||||
"\e[B": history-search-forward
|
|
||||||
"\e[C": forward-char
|
|
||||||
"\e[D": backward-char
|
|
||||||
|
|
||||||
# Immediately add a trailing slash when autocompleting symlinks to directories
|
|
||||||
set mark-symlinked-directories on
|
|
||||||
|
|
||||||
# Do not autocomplete hidden files unless the pattern explicitly begins with a dot
|
|
||||||
set match-hidden-files off
|
|
||||||
|
|
||||||
# Show all autocomplete results at once
|
|
||||||
set page-completions off
|
|
||||||
|
|
||||||
# If there are more than 200 possible completions for a word, ask to show them all
|
|
||||||
set completion-query-items 200
|
|
||||||
|
|
||||||
# Show extra file information when completing, like `ls -F` does
|
|
||||||
set visible-stats on
|
|
||||||
|
|
||||||
# Be more intelligent when autocompleting by also looking at the text after
|
|
||||||
# the cursor. For example, when the current line is "cd ~/src/mozil", and
|
|
||||||
# the cursor is on the "z", pressing Tab will not autocomplete it to "cd
|
|
||||||
# ~/src/mozillail", but to "cd ~/src/mozilla". (This is supported by the
|
|
||||||
# Readline used by Bash 4.)
|
|
||||||
set skip-completed-text on
|
|
||||||
|
|
||||||
# Coloring for Bash 4 tab completions.
|
|
||||||
set colored-stats on
|
|
||||||
|
|
||||||
# Cycle forward and backward through completion candidates (tab/shift+tab)
|
|
||||||
# (completion listing and display behavior configured above)
|
|
||||||
TAB: menu-complete
|
|
||||||
"\e[Z": menu-complete-backward
|
|
||||||
|
|
||||||
# On first Tab, complete the common prefix before cycling candidates
|
|
||||||
set menu-complete-display-prefix on
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
source ~/.config/nomarchy/default/bash/envs
|
|
||||||
source ~/.config/nomarchy/default/bash/shell
|
|
||||||
source ~/.config/nomarchy/default/bash/aliases
|
|
||||||
source ~/.config/nomarchy/default/bash/functions
|
|
||||||
source ~/.config/nomarchy/default/bash/init
|
|
||||||
[[ $- == *i* ]] && bind -f ~/.config/nomarchy/default/bash/inputrc
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# History control
|
|
||||||
shopt -s histappend
|
|
||||||
HISTCONTROL=ignoreboth
|
|
||||||
HISTSIZE=32768
|
|
||||||
HISTFILESIZE="${HISTSIZE}"
|
|
||||||
|
|
||||||
# Autocompletion
|
|
||||||
if [[ ! -v BASH_COMPLETION_VERSINFO && -f /usr/share/bash-completion/bash_completion ]]; then
|
|
||||||
source /usr/share/bash-completion/bash_completion
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Ensure command hashing is off for mise
|
|
||||||
set +h
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
chrome.commands.onCommand.addListener((command) => {
|
|
||||||
if (command === 'copy-url') {
|
|
||||||
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
|
|
||||||
const currentTab = tabs[0];
|
|
||||||
|
|
||||||
chrome.scripting.executeScript({
|
|
||||||
target: { tabId: currentTab.id },
|
|
||||||
func: () => {
|
|
||||||
navigator.clipboard.writeText(window.location.href);
|
|
||||||
}
|
|
||||||
}).then(() => {
|
|
||||||
chrome.notifications.create({
|
|
||||||
type: 'basic',
|
|
||||||
iconUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==',
|
|
||||||
title: ' URL copied to clipboard',
|
|
||||||
message: ''
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../../../icon.png
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"manifest_version": 3,
|
|
||||||
"name": "Copy URL",
|
|
||||||
"version": "1.0",
|
|
||||||
"description": "Copy current URL to clipboard, this extension is installed by Nomarchy",
|
|
||||||
"permissions": ["activeTab", "scripting", "notifications"],
|
|
||||||
"icons": {
|
|
||||||
"16": "icon.png",
|
|
||||||
"48": "icon.png",
|
|
||||||
"128": "icon.png"
|
|
||||||
},
|
|
||||||
"commands": {
|
|
||||||
"copy-url": {
|
|
||||||
"suggested_key": {"default": "Alt+Shift+L"},
|
|
||||||
"description": "Copy URL"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"background": {"service_worker": "background.js"}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
window-padding-x = 0
|
|
||||||
window-padding-y = 0
|
|
||||||
window-padding-color = "extend-always"
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
keyserver hkps://keyserver.ubuntu.com
|
|
||||||
keyserver hkps://pgp.surfnet.nl
|
|
||||||
keyserver hkps://keys.mailvelope.com
|
|
||||||
keyserver hkps://keyring.debian.org
|
|
||||||
keyserver hkps://pgp.mit.edu
|
|
||||||
|
|
||||||
connect-quick-timeout 4
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# App-specific tweaks. All rules are class- or title-gated, so sourcing
|
|
||||||
# unconditionally is harmless when the app isn't installed or running.
|
|
||||||
source = ~/.config/nomarchy/default/hypr/apps/1password.conf
|
|
||||||
source = ~/.config/nomarchy/default/hypr/apps/bitwarden.conf
|
|
||||||
source = ~/.config/nomarchy/default/hypr/apps/browser.conf
|
|
||||||
source = ~/.config/nomarchy/default/hypr/apps/davinci-resolve.conf
|
|
||||||
source = ~/.config/nomarchy/default/hypr/apps/geforce.conf
|
|
||||||
source = ~/.config/nomarchy/default/hypr/apps/hyprshot.conf
|
|
||||||
source = ~/.config/nomarchy/default/hypr/apps/localsend.conf
|
|
||||||
source = ~/.config/nomarchy/default/hypr/apps/moonlight.conf
|
|
||||||
source = ~/.config/nomarchy/default/hypr/apps/pip.conf
|
|
||||||
source = ~/.config/nomarchy/default/hypr/apps/qemu.conf
|
|
||||||
source = ~/.config/nomarchy/default/hypr/apps/retroarch.conf
|
|
||||||
source = ~/.config/nomarchy/default/hypr/apps/steam.conf
|
|
||||||
source = ~/.config/nomarchy/default/hypr/apps/system.conf
|
|
||||||
source = ~/.config/nomarchy/default/hypr/apps/telegram.conf
|
|
||||||
source = ~/.config/nomarchy/default/hypr/apps/terminals.conf
|
|
||||||
source = ~/.config/nomarchy/default/hypr/apps/walker.conf
|
|
||||||
source = ~/.config/nomarchy/default/hypr/apps/webcam-overlay.conf
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
windowrulev2 = noscreenshare, class:^(1[p|P]assword)$
|
|
||||||
windowrulev2 = tag +floating-window, class:^(1[p|P]assword)$
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
windowrulev2 = noscreenshare, class:^(Bitwarden)$
|
|
||||||
windowrulev2 = tag +floating-window, class:^(Bitwarden)$
|
|
||||||
|
|
||||||
# Bitwarden Chrome Extension
|
|
||||||
windowrulev2 = noscreenshare, class:chrome-nngceckbapebfimnlniiiahkandclblb-Default
|
|
||||||
windowrulev2 = tag +floating-window, class:chrome-nngceckbapebfimnlniiiahkandclblb-Default
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
# Browser types
|
|
||||||
windowrulev2 = tag +chromium-based-browser, class:((google-)?[cC]hrom(e|ium)|[bB]rave-browser|[mM]icrosoft-edge|Vivaldi-stable|helium)
|
|
||||||
windowrulev2 = tag +firefox-based-browser, class:([fF]irefox|zen|librewolf)
|
|
||||||
windowrulev2 = tag -default-opacity, tag:chromium-based-browser
|
|
||||||
windowrulev2 = tag -default-opacity, tag:firefox-based-browser
|
|
||||||
|
|
||||||
# Video apps: remove chromium browser tag so they don't get opacity applied
|
|
||||||
windowrulev2 = tag -chromium-based-browser, class:(chrome-youtube.com__-Default|chrome-app.zoom.us__wc_home-Default)
|
|
||||||
windowrulev2 = tag -default-opacity, class:(chrome-youtube.com__-Default|chrome-app.zoom.us__wc_home-Default)
|
|
||||||
|
|
||||||
# Force chromium-based browsers into a tile to deal with --app bug
|
|
||||||
windowrulev2 = tile, tag:chromium-based-browser
|
|
||||||
|
|
||||||
# Only a subtle opacity change, but not for video sites
|
|
||||||
windowrulev2 = opacity 1.0 0.97, tag:chromium-based-browser
|
|
||||||
windowrulev2 = opacity 1.0 0.97, tag:firefox-based-browser
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
# Focus floating DaVinci Resolve dialog windows
|
|
||||||
windowrulev2 = stayfocused, class:.*[Rr]esolve.*, float:1
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
windowrulev2 = idleinhibit fullscreen, class:^(GeForceNOW)$
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
# Remove 1px border around hyprshot screenshots
|
|
||||||
layerrule = noanim, namespace:selection
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
# Float LocalSend and fzf file picker
|
|
||||||
windowrulev2 = float, class:(Share|localsend)
|
|
||||||
windowrulev2 = center, class:(Share|localsend)
|
|
||||||
windowrulev2 = size 1100 700, class:localsend
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
windowrulev2 = fullscreen, class:^(com.moonlight_stream.Moonlight)$
|
|
||||||
windowrulev2 = idleinhibit fullscreen, class:^(com.moonlight_stream.Moonlight)$
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
# Picture-in-picture overlays
|
|
||||||
windowrulev2 = tag +pip, title:(Picture.?in.?[Pp]icture)
|
|
||||||
windowrulev2 = tag -default-opacity, tag:pip
|
|
||||||
windowrulev2 = float, tag:pip
|
|
||||||
windowrulev2 = pin, tag:pip
|
|
||||||
windowrulev2 = size 600 338, tag:pip
|
|
||||||
windowrulev2 = keepaspectratio, tag:pip
|
|
||||||
windowrulev2 = bordersize 0, tag:pip
|
|
||||||
windowrulev2 = opacity 1 1, tag:pip
|
|
||||||
windowrulev2 = move (monitor_w-window_w-40) (monitor_h*0.04), tag:pip
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
windowrulev2 = tag -default-opacity, class:qemu
|
|
||||||
windowrulev2 = opacity 1 1, class:qemu
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
windowrulev2 = fullscreen, class:com.libretro.RetroArch
|
|
||||||
windowrulev2 = tag -default-opacity, class:com.libretro.RetroArch
|
|
||||||
windowrulev2 = opacity 1 1, class:com.libretro.RetroArch
|
|
||||||
windowrulev2 = idleinhibit fullscreen, class:com.libretro.RetroArch
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
# Float Steam
|
|
||||||
windowrulev2 = float, class:steam
|
|
||||||
windowrulev2 = center, class:steam, title:Steam
|
|
||||||
windowrulev2 = tag -default-opacity, class:steam.*
|
|
||||||
windowrulev2 = opacity 1 1, class:steam.*
|
|
||||||
windowrulev2 = size 1100 700, class:steam, title:Steam
|
|
||||||
windowrulev2 = size 460 800, class:steam, title:Friends List
|
|
||||||
windowrulev2 = idleinhibit fullscreen, class:steam
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
# Floating windows
|
|
||||||
windowrulev2 = float, tag:floating-window
|
|
||||||
windowrulev2 = center, tag:floating-window
|
|
||||||
windowrulev2 = size 875 600, tag:floating-window
|
|
||||||
|
|
||||||
windowrulev2 = tag +floating-window, class:(org.nomarchy.bluetui|org.nomarchy.impala|org.nomarchy.wiremix|org.nomarchy.btop|org.nomarchy.terminal|org.nomarchy.bash|org.gnome.NautilusPreviewer|org.gnome.Evince|com.gabm.satty|Nomarchy|About|TUI.float|imv|mpv)
|
|
||||||
windowrulev2 = tag +floating-window, class:(xdg-desktop-portal-gtk|sublime_text|DesktopEditors|org.gnome.Nautilus), title:^(Open.*Files?|Open [F|f]older.*|Save.*Files?|Save.*As|Save|All Files|.*wants to [open|save].*|[C|c]hoose.*)
|
|
||||||
windowrulev2 = float, class:org.gnome.Calculator
|
|
||||||
|
|
||||||
# Fullscreen screensaver
|
|
||||||
windowrulev2 = fullscreen, class:org.nomarchy.screensaver
|
|
||||||
windowrulev2 = float, class:org.nomarchy.screensaver
|
|
||||||
windowrulev2 = animation slide, class:org.nomarchy.screensaver
|
|
||||||
|
|
||||||
# No transparency on media windows
|
|
||||||
windowrulev2 = tag -default-opacity, class:^(zoom|vlc|mpv|org.kde.kdenlive|com.obsproject.Studio|com.github.PintaProject.Pinta|imv|org.gnome.NautilusPreviewer)$
|
|
||||||
windowrulev2 = opacity 1 1, class:^(zoom|vlc|mpv|org.kde.kdenlive|com.obsproject.Studio|com.github.PintaProject.Pinta|imv|org.gnome.NautilusPreviewer)$
|
|
||||||
|
|
||||||
# Popped window rounding
|
|
||||||
windowrulev2 = rounding 8, tag:pop
|
|
||||||
|
|
||||||
# Prevent idle while open
|
|
||||||
windowrulev2 = idleinhibit always, tag:noidle
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
# Prevent Telegram from stealing focus on new messages
|
|
||||||
windowrulev2 = focusonactivate off, class:org.telegram.desktop
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
# Define terminal tag to style them uniformly
|
|
||||||
windowrulev2 = tag +terminal, class:(Alacritty|kitty|com.mitchellh.ghostty)
|
|
||||||
windowrulev2 = tag -default-opacity, tag:terminal
|
|
||||||
windowrulev2 = opacity 0.97 0.9, tag:terminal
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
# Application-specific animation
|
|
||||||
layerrule = noanim, namespace:walker
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
# Webcam overlay for screen recording
|
|
||||||
windowrulev2 = float, title:WebcamOverlay
|
|
||||||
windowrulev2 = pin, title:WebcamOverlay
|
|
||||||
windowrulev2 = noinitialfocus, title:WebcamOverlay
|
|
||||||
windowrulev2 = nodim, title:WebcamOverlay
|
|
||||||
windowrulev2 = move (monitor_w-window_w-40) (monitor_h-window_h-40), title:WebcamOverlay
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
exec-once = uwsm-app -- hypridle
|
|
||||||
exec-once = uwsm-app -- mako
|
|
||||||
exec-once = nomarchy-welcome
|
|
||||||
# exec-once = uwsm-app -- waybar
|
|
||||||
# fcitx5 is autostarted by NixOS's i18n.inputMethod when
|
|
||||||
# nomarchy.system.inputMethod.enable = true; no manual exec-once needed.
|
|
||||||
# swaybg is started as a systemd user service (nomarchy-wallpaper.service)
|
|
||||||
# so failures surface in logs and the wallpaper survives Hyprland restarts.
|
|
||||||
exec-once = uwsm-app -- swayosd-server
|
|
||||||
exec-once = nomarchy-on-boot
|
|
||||||
|
|
||||||
# Slow app launch fix -- set systemd vars
|
|
||||||
exec-once = systemctl --user import-environment $(env | cut -d'=' -f 1)
|
|
||||||
exec-once = dbus-update-activation-environment --systemd --all
|
|
||||||
|
|
||||||
# Network Manager
|
|
||||||
exec-once = uwsm-app 'nm-applet --indicator'
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# Copy / Paste
|
|
||||||
bindd = SUPER, C, Universal copy, sendshortcut, CTRL, Insert,
|
|
||||||
bindd = SUPER, V, Universal paste, sendshortcut, SHIFT, Insert,
|
|
||||||
bindd = SUPER, X, Universal cut, sendshortcut, CTRL, X,
|
|
||||||
bindd = SUPER CTRL, V, Clipboard manager, exec, nomarchy-launch-walker -m clipboard
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
# Only display the OSD on the currently focused monitor
|
|
||||||
$osdclient = swayosd-client --monitor "$(hyprctl monitors -j | jq -r '.[] | select(.focused == true).name')"
|
|
||||||
|
|
||||||
# Laptop multimedia keys for volume and LCD brightness (with OSD)
|
|
||||||
bindeld = ,XF86AudioRaiseVolume, Volume up, exec, $osdclient --output-volume raise
|
|
||||||
bindeld = ,XF86AudioLowerVolume, Volume down, exec, $osdclient --output-volume lower
|
|
||||||
bindeld = ,XF86AudioMute, Mute, exec, $osdclient --output-volume mute-toggle
|
|
||||||
bindeld = ,XF86AudioMicMute, Mute microphone, exec, $osdclient --input-volume mute-toggle
|
|
||||||
bindeld = ,XF86MonBrightnessUp, Brightness up, exec, nomarchy-brightness-display +5%
|
|
||||||
bindeld = ,XF86MonBrightnessDown, Brightness down, exec, nomarchy-brightness-display 5%-
|
|
||||||
bindeld = ,XF86KbdBrightnessUp, Keyboard brightness up, exec, nomarchy-brightness-keyboard up
|
|
||||||
bindeld = ,XF86KbdBrightnessDown, Keyboard brightness down, exec, nomarchy-brightness-keyboard down
|
|
||||||
bindld = ,XF86KbdLightOnOff, Keyboard backlight cycle, exec, nomarchy-brightness-keyboard cycle
|
|
||||||
|
|
||||||
# Precise 1% multimedia adjustments with Alt modifier
|
|
||||||
bindeld = ALT, XF86AudioRaiseVolume, Volume up precise, exec, $osdclient --output-volume +1
|
|
||||||
bindeld = ALT, XF86AudioLowerVolume, Volume down precise, exec, $osdclient --output-volume -1
|
|
||||||
bindeld = ALT, XF86MonBrightnessUp, Brightness up precise, exec, nomarchy-brightness-display +1%
|
|
||||||
bindeld = ALT, XF86MonBrightnessDown, Brightness down precise, exec, nomarchy-brightness-display 1%-
|
|
||||||
|
|
||||||
# Requires playerctl
|
|
||||||
bindld = , XF86AudioNext, Next track, exec, $osdclient --playerctl next
|
|
||||||
bindld = , XF86AudioPause, Pause, exec, $osdclient --playerctl play-pause
|
|
||||||
bindld = , XF86AudioPlay, Play, exec, $osdclient --playerctl play-pause
|
|
||||||
bindld = , XF86AudioPrev, Previous track, exec, $osdclient --playerctl previous
|
|
||||||
|
|
||||||
# Switch audio output with Super + Mute
|
|
||||||
bindld = SUPER, XF86AudioMute, Switch audio output, exec, nomarchy-cmd-audio-switch
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
# Close windows
|
|
||||||
bindd = SUPER, W, Close window, killactive,
|
|
||||||
bindd = CTRL ALT, DELETE, Close all windows, exec, nomarchy-hyprland-window-close-all
|
|
||||||
|
|
||||||
# Control tiling
|
|
||||||
bindd = SUPER, J, Toggle window split, layoutmsg, togglesplit
|
|
||||||
bindd = SUPER, P, Pseudo window, pseudo, # dwindle
|
|
||||||
bindd = SUPER, T, Toggle window floating/tiling, togglefloating,
|
|
||||||
bindd = SUPER, F, Full screen, fullscreen, 0
|
|
||||||
bindd = SUPER CTRL, F, Tiled full screen, fullscreenstate, 0 2
|
|
||||||
bindd = SUPER ALT, F, Full width, fullscreen, 1
|
|
||||||
bindd = SUPER, O, Pop window out (float & pin), exec, nomarchy-hyprland-window-pop
|
|
||||||
bindd = SUPER, L, Toggle workspace layout, exec, nomarchy-hyprland-workspace-layout-toggle
|
|
||||||
|
|
||||||
# Move focus with SUPER + arrow keys
|
|
||||||
bindd = SUPER, LEFT, Move window focus left, movefocus, l
|
|
||||||
bindd = SUPER, RIGHT, Move window focus right, movefocus, r
|
|
||||||
bindd = SUPER, UP, Move window focus up, movefocus, u
|
|
||||||
bindd = SUPER, DOWN, Move window focus down, movefocus, d
|
|
||||||
|
|
||||||
# Switch workspaces with SUPER + [1-9; 0]
|
|
||||||
bindd = SUPER, code:10, Switch to workspace 1, workspace, 1
|
|
||||||
bindd = SUPER, code:11, Switch to workspace 2, workspace, 2
|
|
||||||
bindd = SUPER, code:12, Switch to workspace 3, workspace, 3
|
|
||||||
bindd = SUPER, code:13, Switch to workspace 4, workspace, 4
|
|
||||||
bindd = SUPER, code:14, Switch to workspace 5, workspace, 5
|
|
||||||
bindd = SUPER, code:15, Switch to workspace 6, workspace, 6
|
|
||||||
bindd = SUPER, code:16, Switch to workspace 7, workspace, 7
|
|
||||||
bindd = SUPER, code:17, Switch to workspace 8, workspace, 8
|
|
||||||
bindd = SUPER, code:18, Switch to workspace 9, workspace, 9
|
|
||||||
bindd = SUPER, code:19, Switch to workspace 10, workspace, 10
|
|
||||||
|
|
||||||
# Move active window to a workspace with SUPER + SHIFT + [1-9; 0]
|
|
||||||
bindd = SUPER SHIFT, code:10, Move window to workspace 1, movetoworkspace, 1
|
|
||||||
bindd = SUPER SHIFT, code:11, Move window to workspace 2, movetoworkspace, 2
|
|
||||||
bindd = SUPER SHIFT, code:12, Move window to workspace 3, movetoworkspace, 3
|
|
||||||
bindd = SUPER SHIFT, code:13, Move window to workspace 4, movetoworkspace, 4
|
|
||||||
bindd = SUPER SHIFT, code:14, Move window to workspace 5, movetoworkspace, 5
|
|
||||||
bindd = SUPER SHIFT, code:15, Move window to workspace 6, movetoworkspace, 6
|
|
||||||
bindd = SUPER SHIFT, code:16, Move window to workspace 7, movetoworkspace, 7
|
|
||||||
bindd = SUPER SHIFT, code:17, Move window to workspace 8, movetoworkspace, 8
|
|
||||||
bindd = SUPER SHIFT, code:18, Move window to workspace 9, movetoworkspace, 9
|
|
||||||
bindd = SUPER SHIFT, code:19, Move window to workspace 10, movetoworkspace, 10
|
|
||||||
|
|
||||||
# Move active window silently to a workspace with SUPER + SHIFT + ALT + [1-9; 0]
|
|
||||||
bindd = SUPER SHIFT ALT, code:10, Move window silently to workspace 1, movetoworkspacesilent, 1
|
|
||||||
bindd = SUPER SHIFT ALT, code:11, Move window silently to workspace 2, movetoworkspacesilent, 2
|
|
||||||
bindd = SUPER SHIFT ALT, code:12, Move window silently to workspace 3, movetoworkspacesilent, 3
|
|
||||||
bindd = SUPER SHIFT ALT, code:13, Move window silently to workspace 4, movetoworkspacesilent, 4
|
|
||||||
bindd = SUPER SHIFT ALT, code:14, Move window silently to workspace 5, movetoworkspacesilent, 5
|
|
||||||
bindd = SUPER SHIFT ALT, code:15, Move window silently to workspace 6, movetoworkspacesilent, 6
|
|
||||||
bindd = SUPER SHIFT ALT, code:16, Move window silently to workspace 7, movetoworkspacesilent, 7
|
|
||||||
bindd = SUPER SHIFT ALT, code:17, Move window silently to workspace 8, movetoworkspacesilent, 8
|
|
||||||
bindd = SUPER SHIFT ALT, code:18, Move window silently to workspace 9, movetoworkspacesilent, 9
|
|
||||||
bindd = SUPER SHIFT ALT, code:19, Move window silently to workspace 10, movetoworkspacesilent, 10
|
|
||||||
|
|
||||||
# Control scratchpad
|
|
||||||
bindd = SUPER, S, Toggle scratchpad, togglespecialworkspace, scratchpad
|
|
||||||
bindd = SUPER ALT, S, Move window to scratchpad, movetoworkspacesilent, special:scratchpad
|
|
||||||
|
|
||||||
# TAB between workspaces
|
|
||||||
bindd = SUPER, TAB, Next workspace, workspace, e+1
|
|
||||||
bindd = SUPER SHIFT, TAB, Previous workspace, workspace, e-1
|
|
||||||
bindd = SUPER CTRL, TAB, Former workspace, workspace, previous
|
|
||||||
|
|
||||||
# Move workspaces to other monitors
|
|
||||||
bindd = SUPER SHIFT ALT, LEFT, Move workspace to left monitor, movecurrentworkspacetomonitor, l
|
|
||||||
bindd = SUPER SHIFT ALT, RIGHT, Move workspace to right monitor, movecurrentworkspacetomonitor, r
|
|
||||||
bindd = SUPER SHIFT ALT, UP, Move workspace to up monitor, movecurrentworkspacetomonitor, u
|
|
||||||
bindd = SUPER SHIFT ALT, DOWN, Move workspace to down monitor, movecurrentworkspacetomonitor, d
|
|
||||||
|
|
||||||
# Swap active window with the one next to it with SUPER + SHIFT + arrow keys
|
|
||||||
bindd = SUPER SHIFT, LEFT, Swap window to the left, swapwindow, l
|
|
||||||
bindd = SUPER SHIFT, RIGHT, Swap window to the right, swapwindow, r
|
|
||||||
bindd = SUPER SHIFT, UP, Swap window up, swapwindow, u
|
|
||||||
bindd = SUPER SHIFT, DOWN, Swap window down, swapwindow, d
|
|
||||||
|
|
||||||
# Cycle through applications on active workspace
|
|
||||||
bindd = ALT, TAB, Cycle to next window, cyclenext
|
|
||||||
bindd = ALT SHIFT, TAB, Cycle to prev window, cyclenext, prev
|
|
||||||
bindd = ALT, TAB, Reveal active window on top, bringactivetotop
|
|
||||||
bindd = ALT SHIFT, TAB, Reveal active window on top, bringactivetotop
|
|
||||||
|
|
||||||
# Resize active window
|
|
||||||
bindd = SUPER, code:20, Expand window left, resizeactive, -100 0 # - key
|
|
||||||
bindd = SUPER, code:21, Shrink window left, resizeactive, 100 0 # = key
|
|
||||||
bindd = SUPER SHIFT, code:20, Shrink window up, resizeactive, 0 -100
|
|
||||||
bindd = SUPER SHIFT, code:21, Expand window down, resizeactive, 0 100
|
|
||||||
|
|
||||||
# Scroll through existing workspaces with SUPER + scroll
|
|
||||||
bindd = SUPER, mouse_down, Scroll active workspace forward, workspace, e+1
|
|
||||||
bindd = SUPER, mouse_up, Scroll active workspace backward, workspace, e-1
|
|
||||||
|
|
||||||
# Move/resize windows with mainMod + LMB/RMB and dragging
|
|
||||||
bindmd = SUPER, mouse:272, Move window, movewindow
|
|
||||||
bindmd = SUPER, mouse:273, Resize window, resizewindow
|
|
||||||
|
|
||||||
# Toggle groups
|
|
||||||
bindd = SUPER, G, Toggle window grouping, togglegroup
|
|
||||||
bindd = SUPER ALT, G, Move active window out of group, moveoutofgroup
|
|
||||||
|
|
||||||
# Join groups
|
|
||||||
bindd = SUPER ALT, LEFT, Move window to group on left, moveintogroup, l
|
|
||||||
bindd = SUPER ALT, RIGHT, Move window to group on right, moveintogroup, r
|
|
||||||
bindd = SUPER ALT, UP, Move window to group on top, moveintogroup, u
|
|
||||||
bindd = SUPER ALT, DOWN, Move window to group on bottom, moveintogroup, d
|
|
||||||
|
|
||||||
# Navigate a single set of grouped windows
|
|
||||||
bindd = SUPER ALT, TAB, Next window in group, changegroupactive, f
|
|
||||||
bindd = SUPER ALT SHIFT, TAB, Previous window in group, changegroupactive, b
|
|
||||||
|
|
||||||
# Window navigation for grouped windows
|
|
||||||
bindd = SUPER CTRL, LEFT, Move grouped window focus left, changegroupactive, b
|
|
||||||
bindd = SUPER CTRL, RIGHT, Move grouped window focus right, changegroupactive, f
|
|
||||||
|
|
||||||
# Scroll through a set of grouped windows with SUPER + ALT + scroll
|
|
||||||
bindd = SUPER ALT, mouse_down, Next window in group, changegroupactive, f
|
|
||||||
bindd = SUPER ALT, mouse_up, Previous window in group, changegroupactive, b
|
|
||||||
|
|
||||||
# Activate window in a group by number
|
|
||||||
bindd = SUPER ALT, code:10, Switch to group window 1, changegroupactive, 1
|
|
||||||
bindd = SUPER ALT, code:11, Switch to group window 2, changegroupactive, 2
|
|
||||||
bindd = SUPER ALT, code:12, Switch to group window 3, changegroupactive, 3
|
|
||||||
bindd = SUPER ALT, code:13, Switch to group window 4, changegroupactive, 4
|
|
||||||
bindd = SUPER ALT, code:14, Switch to group window 5, changegroupactive, 5
|
|
||||||
|
|
||||||
# Cycle monitor scaling
|
|
||||||
bindd = SUPER, Slash, Cycle monitor scaling, exec, nomarchy-hyprland-monitor-scaling-cycle
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
# Menus
|
|
||||||
bindd = SUPER, SPACE, Launch apps, exec, nomarchy-launch-walker
|
|
||||||
bindd = SUPER CTRL, E, Emoji picker, exec, nomarchy-menu symbols
|
|
||||||
bindd = SUPER CTRL, C, Capture menu, exec, nomarchy-menu capture
|
|
||||||
bindd = SUPER CTRL, O, Toggle menu, exec, nomarchy-menu toggle
|
|
||||||
bindd = SUPER ALT, SPACE, Toggle top bar, exec, nomarchy-toggle-waybar
|
|
||||||
bindd = SUPER, ESCAPE, System menu, exec, nomarchy-menu system
|
|
||||||
bindld = , XF86PowerOff, Power menu, exec, nomarchy-menu system
|
|
||||||
bindd = SUPER, K, Show key bindings, exec, nomarchy-menu-keybindings
|
|
||||||
bindd = , XF86Calculator, Calculator, exec, gnome-calculator
|
|
||||||
|
|
||||||
# Aesthetics
|
|
||||||
bindd = SUPER SHIFT, SPACE, Nomarchy menu, exec, nomarchy-menu
|
|
||||||
bindd = SUPER CTRL, SPACE, Theme background menu, exec, nomarchy-menu background
|
|
||||||
bindd = SUPER SHIFT CTRL, SPACE, Theme menu, exec, nomarchy-menu theme
|
|
||||||
bindd = SUPER, BACKSPACE, Toggle window transparency, exec, nomarchy-hyprland-active-window-transparency-toggle
|
|
||||||
bindd = SUPER SHIFT, BACKSPACE, Toggle window gaps, exec, nomarchy-hyprland-window-gaps-toggle
|
|
||||||
bindd = SUPER CTRL, BACKSPACE, Toggle single-window square aspect, exec, nomarchy-hyprland-window-single-square-aspect-toggle
|
|
||||||
|
|
||||||
# Notifications
|
|
||||||
bindd = SUPER, COMMA, Dismiss last notification, exec, makoctl dismiss
|
|
||||||
bindd = SUPER SHIFT, COMMA, Dismiss all notifications, exec, makoctl dismiss --all
|
|
||||||
bindd = SUPER CTRL, COMMA, Toggle silencing notifications, exec, nomarchy-toggle-notification-silencing
|
|
||||||
bindd = SUPER ALT, COMMA, Invoke last notification, exec, makoctl invoke
|
|
||||||
bindd = SUPER SHIFT ALT, COMMA, Restore last notification, exec, makoctl restore
|
|
||||||
|
|
||||||
# Toggles
|
|
||||||
bindd = SUPER CTRL, I, Toggle locking on idle, exec, nomarchy-toggle-idle
|
|
||||||
bindd = SUPER CTRL, N, Toggle nightlight, exec, nomarchy-toggle-nightlight
|
|
||||||
|
|
||||||
# Control Apple Display brightness
|
|
||||||
bindd = CTRL, F1, Apple Display brightness down, exec, nomarchy-brightness-display-apple -5000
|
|
||||||
bindd = CTRL, F2, Apple Display brightness up, exec, nomarchy-brightness-display-apple +5000
|
|
||||||
bindd = SHIFT CTRL, F2, Apple Display full brightness, exec, nomarchy-brightness-display-apple +60000
|
|
||||||
|
|
||||||
# Captures
|
|
||||||
bindd = , PRINT, Screenshot, exec, nomarchy-cmd-screenshot
|
|
||||||
bindd = ALT, PRINT, Screenrecording, exec, nomarchy-menu screenrecord
|
|
||||||
bindd = SUPER, PRINT, Color picker, exec, pkill hyprpicker || hyprpicker -a
|
|
||||||
|
|
||||||
# File sharing
|
|
||||||
bindd = SUPER CTRL, S, Share, exec, nomarchy-menu share
|
|
||||||
|
|
||||||
# Waybar-less information
|
|
||||||
bindd = SUPER CTRL ALT, T, Show time, exec, notify-send -u low " $(date +"%A %H:%M · %d %B %Y · Week %V")"
|
|
||||||
bindd = SUPER CTRL ALT, B, Show battery remaining, exec, notify-send -u low "$(nomarchy-battery-status)"
|
|
||||||
|
|
||||||
# Control panels
|
|
||||||
bindd = SUPER CTRL, A, Audio controls, exec, nomarchy-launch-audio
|
|
||||||
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
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# Lock system
|
|
||||||
bindd = SUPER CTRL, L, Lock system, exec, nomarchy-lock-screen
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# Hyprland Color Configuration (Visual)
|
|
||||||
# This file contains only color-related settings.
|
|
||||||
# It's sourced AFTER theme colors are applied, allowing theme-specific overrides.
|
|
||||||
|
|
||||||
# These are placeholder values - actual colors come from the active theme
|
|
||||||
# via ~/.config/nomarchy/current/theme/hyprland.conf
|
|
||||||
|
|
||||||
# Border colors (set by theme-loader based on active theme)
|
|
||||||
# The theme's hyprland.conf will define $activeBorderColor and $inactiveBorderColor
|
|
||||||
|
|
||||||
# Group bar colors (set by theme)
|
|
||||||
# Themes can override group bar colors in their hyprland.conf
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
# Cursor size
|
|
||||||
env = XCURSOR_SIZE,24
|
|
||||||
env = HYPRCURSOR_SIZE,24
|
|
||||||
|
|
||||||
# Force all apps to use Wayland
|
|
||||||
env = GDK_BACKEND,wayland,x11,*
|
|
||||||
env = QT_QPA_PLATFORM,wayland;xcb
|
|
||||||
env = QT_STYLE_OVERRIDE,kvantum
|
|
||||||
env = SDL_VIDEODRIVER,wayland,x11
|
|
||||||
env = MOZ_ENABLE_WAYLAND,1
|
|
||||||
env = ELECTRON_OZONE_PLATFORM_HINT,wayland
|
|
||||||
env = OZONE_PLATFORM,wayland
|
|
||||||
env = XDG_SESSION_TYPE,wayland
|
|
||||||
|
|
||||||
# Allow better support for screen sharing (Google Meet, Discord, etc)
|
|
||||||
env = XDG_CURRENT_DESKTOP,Hyprland
|
|
||||||
env = XDG_SESSION_DESKTOP,Hyprland
|
|
||||||
|
|
||||||
xwayland {
|
|
||||||
force_zero_scaling = true
|
|
||||||
}
|
|
||||||
|
|
||||||
# Use XCompose file
|
|
||||||
env = XCOMPOSEFILE,~/.XCompose
|
|
||||||
|
|
||||||
# Don't show update on first launch
|
|
||||||
ecosystem {
|
|
||||||
no_update_news = true
|
|
||||||
}
|
|
||||||
@@ -1,146 +0,0 @@
|
|||||||
# Refer to https://wiki.hyprland.org/Configuring/Variables/
|
|
||||||
|
|
||||||
# Variables
|
|
||||||
$activeBorderColor = rgba(33ccffee) rgba(00ff99ee) 45deg
|
|
||||||
$inactiveBorderColor = rgba(595959aa)
|
|
||||||
|
|
||||||
# https://wiki.hyprland.org/Configuring/Variables/#general
|
|
||||||
general {
|
|
||||||
gaps_in = 5
|
|
||||||
gaps_out = 10
|
|
||||||
|
|
||||||
border_size = 2
|
|
||||||
|
|
||||||
# https://wiki.hyprland.org/Configuring/Variables/#variable-types for info about colors
|
|
||||||
col.active_border = $activeBorderColor
|
|
||||||
col.inactive_border = $inactiveBorderColor
|
|
||||||
|
|
||||||
# Set to true enable resizing windows by clicking and dragging on borders and gaps
|
|
||||||
resize_on_border = false
|
|
||||||
|
|
||||||
# Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
|
|
||||||
allow_tearing = false
|
|
||||||
|
|
||||||
layout = dwindle
|
|
||||||
}
|
|
||||||
|
|
||||||
# https://wiki.hyprland.org/Configuring/Variables/#decoration
|
|
||||||
decoration {
|
|
||||||
rounding = 0
|
|
||||||
|
|
||||||
shadow {
|
|
||||||
enabled = true
|
|
||||||
range = 2
|
|
||||||
render_power = 3
|
|
||||||
color = rgba(1a1a1aee)
|
|
||||||
}
|
|
||||||
|
|
||||||
# https://wiki.hyprland.org/Configuring/Variables/#blur
|
|
||||||
blur {
|
|
||||||
enabled = true
|
|
||||||
size = 2
|
|
||||||
passes = 2
|
|
||||||
special = true
|
|
||||||
brightness = 0.60
|
|
||||||
contrast = 0.75
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# https://wiki.hypr.land/Configuring/Variables/#group
|
|
||||||
group {
|
|
||||||
col.border_active = $activeBorderColor
|
|
||||||
col.border_inactive = $inactiveBorderColor
|
|
||||||
col.border_locked_active = -1
|
|
||||||
col.border_locked_inactive = -1
|
|
||||||
|
|
||||||
groupbar {
|
|
||||||
font_size = 12
|
|
||||||
font_family = monospace
|
|
||||||
font_weight_active = ultraheavy
|
|
||||||
font_weight_inactive = normal
|
|
||||||
|
|
||||||
indicator_height = 0
|
|
||||||
indicator_gap = 5
|
|
||||||
height = 22
|
|
||||||
gaps_in = 5
|
|
||||||
gaps_out = 0
|
|
||||||
|
|
||||||
text_color = rgb(ffffff)
|
|
||||||
text_color_inactive = rgba(ffffff90)
|
|
||||||
col.active = rgba(00000040)
|
|
||||||
col.inactive = rgba(00000020)
|
|
||||||
|
|
||||||
gradients = true
|
|
||||||
gradient_rounding = 0
|
|
||||||
gradient_round_only_edges = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# https://wiki.hyprland.org/Configuring/Variables/#animations
|
|
||||||
animations {
|
|
||||||
enabled = yes
|
|
||||||
|
|
||||||
# Default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
|
|
||||||
|
|
||||||
bezier = easeOutQuint,0.23,1,0.32,1
|
|
||||||
bezier = easeInOutCubic,0.65,0.05,0.36,1
|
|
||||||
bezier = linear,0,0,1,1
|
|
||||||
bezier = almostLinear,0.5,0.5,0.75,1.0
|
|
||||||
bezier = quick,0.15,0,0.1,1
|
|
||||||
|
|
||||||
animation = global, 1, 10, default
|
|
||||||
animation = border, 1, 5.39, easeOutQuint
|
|
||||||
animation = windows, 1, 4.79, easeOutQuint
|
|
||||||
animation = windowsIn, 1, 4.1, easeOutQuint, popin 87%
|
|
||||||
animation = windowsOut, 1, 1.49, linear, popin 87%
|
|
||||||
animation = fadeIn, 1, 1.73, almostLinear
|
|
||||||
animation = fadeOut, 1, 1.46, almostLinear
|
|
||||||
animation = fade, 1, 3.03, quick
|
|
||||||
animation = layers, 1, 3.81, easeOutQuint
|
|
||||||
animation = layersIn, 1, 4, easeOutQuint, fade
|
|
||||||
animation = layersOut, 1, 1.5, linear, fade
|
|
||||||
animation = fadeLayersIn, 1, 1.79, almostLinear
|
|
||||||
animation = fadeLayersOut, 1, 1.39, almostLinear
|
|
||||||
animation = workspaces, 0, 0, ease
|
|
||||||
animation = specialWorkspace, 1, 4, easeOutQuint, slidevert
|
|
||||||
}
|
|
||||||
|
|
||||||
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
|
|
||||||
dwindle {
|
|
||||||
pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
|
|
||||||
preserve_split = true # You probably want this
|
|
||||||
force_split = 2 # Always split on the right
|
|
||||||
}
|
|
||||||
|
|
||||||
# See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
|
|
||||||
master {
|
|
||||||
new_status = master
|
|
||||||
}
|
|
||||||
|
|
||||||
# https://wiki.hyprland.org/Configuring/Variables/#misc
|
|
||||||
misc {
|
|
||||||
disable_hyprland_logo = true
|
|
||||||
disable_splash_rendering = true
|
|
||||||
disable_scale_notification = true
|
|
||||||
focus_on_activate = true
|
|
||||||
}
|
|
||||||
|
|
||||||
# https://wiki.hypr.land/Configuring/Variables/#cursor
|
|
||||||
cursor {
|
|
||||||
hide_on_key_press = true
|
|
||||||
warp_on_change_workspace = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Auto toggle scratchpad on switching workspace from scratchpad
|
|
||||||
binds {
|
|
||||||
hide_special_on_workspace_change = true
|
|
||||||
}
|
|
||||||
|
|
||||||
# Style Gum confirm to match terminal theme
|
|
||||||
env = GUM_CONFIRM_PROMPT_FOREGROUND,6 # Cyan
|
|
||||||
env = GUM_CONFIRM_SELECTED_FOREGROUND,0 # Black
|
|
||||||
env = GUM_CONFIRM_SELECTED_BACKGROUND,2 # Green
|
|
||||||
env = GUM_CONFIRM_UNSELECTED_FOREGROUND,7 # White
|
|
||||||
env = GUM_CONFIRM_UNSELECTED_BACKGROUND,8 # Dark grey
|
|
||||||
# Dark grey
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
|
|
||||||
# Hyprland 0.53+ syntax
|
|
||||||
#windowrulev2 = suppressevent maximize, class:.*
|
|
||||||
|
|
||||||
# Tag all windows for default opacity (apps can override with -default-opacity tag)
|
|
||||||
#windowrulev2 = tag +default-opacity, class:.*
|
|
||||||
|
|
||||||
# Fix some dragging issues with XWayland
|
|
||||||
#windowrulev2 = nofocus, class:^$, title:^$, xwayland:1, float:1, fullscreen:0, pin:0
|
|
||||||
|
|
||||||
# App-specific tweaks (may remove default-opacity tag)
|
|
||||||
source = ~/.config/nomarchy/default/hypr/apps.conf
|
|
||||||
|
|
||||||
# Apply default opacity after apps have had a chance to opt out
|
|
||||||
#windowrulev2 = opacity 0.97 0.9, tag:default-opacity
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
anchor=top-right
|
|
||||||
default-timeout=5000
|
|
||||||
width=420
|
|
||||||
outer-margin=20
|
|
||||||
padding=10,15
|
|
||||||
border-size=2
|
|
||||||
max-icon-size=32
|
|
||||||
font=sans-serif 14px
|
|
||||||
|
|
||||||
[app-name=Spotify]
|
|
||||||
invisible=1
|
|
||||||
|
|
||||||
[mode=do-not-disturb]
|
|
||||||
invisible=true
|
|
||||||
|
|
||||||
[mode=do-not-disturb app-name=notify-send]
|
|
||||||
invisible=false
|
|
||||||
|
|
||||||
[urgency=critical]
|
|
||||||
default-timeout=0
|
|
||||||
layer=overlay
|
|
||||||
|
|
||||||
[summary~="Setup Wi-Fi"]
|
|
||||||
on-button-left=exec sh -c 'nomarchy-notification-dismiss "Setup Wi-Fi"; nomarchy-launch-wifi'
|
|
||||||
on-click=exec sh -c 'nomarchy-notification-dismiss "Setup Wi-Fi"; nomarchy-launch-wifi'
|
|
||||||
|
|
||||||
[summary~="Update System"]
|
|
||||||
on-button-left=exec sh -c 'nomarchy-notification-dismiss "Update System"; nomarchy-launch-floating-terminal-with-presentation nomarchy-update'
|
|
||||||
on-click=exec sh -c 'nomarchy-notification-dismiss "Update System"; nomarchy-launch-floating-terminal-with-presentation nomarchy-update'
|
|
||||||
|
|
||||||
[summary~="Learn Keybindings"]
|
|
||||||
on-button-left=exec sh -c 'nomarchy-notification-dismiss "Learn Keybindings"; nomarchy-menu-keybindings'
|
|
||||||
on-click=exec sh -c 'nomarchy-notification-dismiss "Learn Keybindings"; nomarchy-menu-keybindings'
|
|
||||||
|
|
||||||
[summary~="Screenshot copied & saved"]
|
|
||||||
max-icon-size=80
|
|
||||||
format=<b>%s</b>\n%b
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
[Service]
|
|
||||||
Restart=always
|
|
||||||
RestartSec=2
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<interface>
|
|
||||||
<requires lib="gtk" version="4.0"></requires>
|
|
||||||
<object class="GtkWindow" id="Window">
|
|
||||||
<style>
|
|
||||||
<class name="window"></class>
|
|
||||||
</style>
|
|
||||||
<property name="resizable">true</property>
|
|
||||||
<property name="title">Walker</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkBox" id="BoxWrapper">
|
|
||||||
<style>
|
|
||||||
<class name="box-wrapper"></class>
|
|
||||||
</style>
|
|
||||||
<property name="width-request">644</property>
|
|
||||||
<property name="overflow">hidden</property>
|
|
||||||
<property name="orientation">horizontal</property>
|
|
||||||
<property name="valign">center</property>
|
|
||||||
<property name="halign">center</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkBox" id="Box">
|
|
||||||
<style>
|
|
||||||
<class name="box"></class>
|
|
||||||
</style>
|
|
||||||
<property name="orientation">vertical</property>
|
|
||||||
<property name="hexpand-set">true</property>
|
|
||||||
<property name="hexpand">true</property>
|
|
||||||
<property name="spacing">10</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkBox" id="SearchContainer">
|
|
||||||
<style>
|
|
||||||
<class name="search-container"></class>
|
|
||||||
</style>
|
|
||||||
<property name="overflow">hidden</property>
|
|
||||||
<property name="orientation">horizontal</property>
|
|
||||||
<property name="halign">fill</property>
|
|
||||||
<property name="hexpand-set">true</property>
|
|
||||||
<property name="hexpand">true</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkEntry" id="Input">
|
|
||||||
<style>
|
|
||||||
<class name="input"></class>
|
|
||||||
</style>
|
|
||||||
<property name="halign">fill</property>
|
|
||||||
<property name="hexpand-set">true</property>
|
|
||||||
<property name="hexpand">true</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkBox" id="ContentContainer">
|
|
||||||
<style>
|
|
||||||
<class name="content-container"></class>
|
|
||||||
</style>
|
|
||||||
<property name="orientation">horizontal</property>
|
|
||||||
<property name="spacing">10</property>
|
|
||||||
<property name="vexpand">true</property>
|
|
||||||
<property name="vexpand-set">true</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkLabel" id="ElephantHint">
|
|
||||||
<style>
|
|
||||||
<class name="elephant-hint"></class>
|
|
||||||
</style>
|
|
||||||
<property name="hexpand">true</property>
|
|
||||||
<property name="height-request">100</property>
|
|
||||||
<property name="label">Waiting for elephant...</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkLabel" id="Placeholder">
|
|
||||||
<style>
|
|
||||||
<class name="placeholder"></class>
|
|
||||||
</style>
|
|
||||||
<property name="label">No Results</property>
|
|
||||||
<property name="yalign">0.0</property>
|
|
||||||
<property name="hexpand">true</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkScrolledWindow" id="Scroll">
|
|
||||||
<style>
|
|
||||||
<class name="scroll"></class>
|
|
||||||
</style>
|
|
||||||
<property name="hexpand">true</property>
|
|
||||||
<property name="can_focus">false</property>
|
|
||||||
<property name="overlay-scrolling">true</property>
|
|
||||||
<property name="max-content-width">600</property>
|
|
||||||
<property name="max-content-height">300</property>
|
|
||||||
<property name="min-content-height">0</property>
|
|
||||||
<property name="propagate-natural-height">true</property>
|
|
||||||
<property name="propagate-natural-width">true</property>
|
|
||||||
<property name="hscrollbar-policy">automatic</property>
|
|
||||||
<property name="vscrollbar-policy">automatic</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkGridView" id="List">
|
|
||||||
<style>
|
|
||||||
<class name="list"></class>
|
|
||||||
</style>
|
|
||||||
<property name="max_columns">1</property>
|
|
||||||
<property name="can_focus">false</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkBox" id="Preview">
|
|
||||||
<style>
|
|
||||||
<class name="preview"></class>
|
|
||||||
</style>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkBox" id="Keybinds">
|
|
||||||
<property name="hexpand">true</property>
|
|
||||||
<property name="margin-top">10</property>
|
|
||||||
<style>
|
|
||||||
<class name="keybinds"></class>
|
|
||||||
</style>
|
|
||||||
<child>
|
|
||||||
<object class="GtkBox" id="GlobalKeybinds">
|
|
||||||
<property name="spacing">10</property>
|
|
||||||
<style>
|
|
||||||
<class name="global-keybinds"></class>
|
|
||||||
</style>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkBox" id="ItemKeybinds">
|
|
||||||
<property name="hexpand">true</property>
|
|
||||||
<property name="halign">end</property>
|
|
||||||
<property name="spacing">10</property>
|
|
||||||
<style>
|
|
||||||
<class name="item-keybinds"></class>
|
|
||||||
</style>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkLabel" id="Error">
|
|
||||||
<style>
|
|
||||||
<class name="error"></class>
|
|
||||||
</style>
|
|
||||||
<property name="xalign">0</property>
|
|
||||||
<property name="visible">false</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</interface>
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
@import "../../../../../../../.config/nomarchy/current/theme/walker.css";
|
|
||||||
|
|
||||||
* {
|
|
||||||
all: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
|
||||||
font-family: monospace;
|
|
||||||
font-size: 18px;
|
|
||||||
color: @text;
|
|
||||||
}
|
|
||||||
|
|
||||||
scrollbar {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.normal-icons {
|
|
||||||
-gtk-icon-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.large-icons {
|
|
||||||
-gtk-icon-size: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.box-wrapper {
|
|
||||||
background: alpha(@base, 0.95);
|
|
||||||
padding: 20px;
|
|
||||||
border: 2px solid @border;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-box {
|
|
||||||
}
|
|
||||||
|
|
||||||
.box {
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-container {
|
|
||||||
background: @base;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input placeholder {
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input {
|
|
||||||
}
|
|
||||||
|
|
||||||
.input:focus,
|
|
||||||
.input:active {
|
|
||||||
box-shadow: none;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-container {
|
|
||||||
}
|
|
||||||
|
|
||||||
.placeholder {
|
|
||||||
}
|
|
||||||
|
|
||||||
.scroll {
|
|
||||||
}
|
|
||||||
|
|
||||||
.list {
|
|
||||||
}
|
|
||||||
|
|
||||||
child,
|
|
||||||
child > * {
|
|
||||||
}
|
|
||||||
|
|
||||||
child:hover .item-box {
|
|
||||||
}
|
|
||||||
|
|
||||||
child:selected .item-box {
|
|
||||||
background-color: @selected-background;
|
|
||||||
}
|
|
||||||
|
|
||||||
child:selected .item-box * {
|
|
||||||
color: @selected-text;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-box {
|
|
||||||
padding-left: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-text-box {
|
|
||||||
all: unset;
|
|
||||||
padding: 14px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-text {
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-subtext {
|
|
||||||
font-size: 0px;
|
|
||||||
min-height: 0px;
|
|
||||||
margin: 0px;
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-image {
|
|
||||||
margin-right: 14px;
|
|
||||||
-gtk-icon-transform: scale(0.9);
|
|
||||||
}
|
|
||||||
|
|
||||||
.current {
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
.keybind-hints {
|
|
||||||
background: @background;
|
|
||||||
padding: 10px;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview {
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
[Desktop Entry]
|
|
||||||
Name=Walker
|
|
||||||
Comment=Walker Service
|
|
||||||
Exec=walker --gapplication-service
|
|
||||||
StartupNotify=false
|
|
||||||
Terminal=false
|
|
||||||
Type=Application
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
if pgrep -x hypridle >/dev/null; then
|
|
||||||
echo '{"text": ""}'
|
|
||||||
else
|
|
||||||
echo '{"text": "", "tooltip": "Idle lock disabled", "class": "active"}'
|
|
||||||
fi
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
if makoctl mode | grep -q 'do-not-disturb'; then
|
|
||||||
echo '{"text": "", "tooltip": "Notifications silenced", "class": "active"}'
|
|
||||||
else
|
|
||||||
echo '{"text": ""}'
|
|
||||||
fi
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
if pgrep -f "^gpu-screen-recorder" >/dev/null; then
|
|
||||||
echo '{"text": "", "tooltip": "Stop recording", "class": "active"}'
|
|
||||||
else
|
|
||||||
echo '{"text": ""}'
|
|
||||||
fi
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
## Use software volume control for all ALSA devices.
|
|
||||||
## This prevents hardware mixer quirks (like muffled audio on Realtek codecs)
|
|
||||||
## and provides consistent volume behavior across all hardware.
|
|
||||||
|
|
||||||
monitor.alsa.rules = [
|
|
||||||
{
|
|
||||||
matches = [
|
|
||||||
{
|
|
||||||
device.name = "~alsa_card.*"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
actions = {
|
|
||||||
update-props = {
|
|
||||||
api.alsa.soft-mixer = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
include "%L"
|
|
||||||
|
|
||||||
# Emoji
|
|
||||||
<Multi_key> <m> <s> : "😄" # smile
|
|
||||||
<Multi_key> <m> <c> : "😂" # cry
|
|
||||||
<Multi_key> <m> <l> : "😍" # love
|
|
||||||
<Multi_key> <m> <v> : "✌️" # victory
|
|
||||||
<Multi_key> <m> <h> : "❤️" # heart
|
|
||||||
<Multi_key> <m> <y> : "👍" # yes
|
|
||||||
<Multi_key> <m> <n> : "👎" # no
|
|
||||||
<Multi_key> <m> <f> : "🖕" # fuck
|
|
||||||
<Multi_key> <m> <w> : "🤞" # wish
|
|
||||||
<Multi_key> <m> <r> : "🤘" # rock
|
|
||||||
<Multi_key> <m> <k> : "😘" # kiss
|
|
||||||
<Multi_key> <m> <e> : "🙄" # eyeroll
|
|
||||||
<Multi_key> <m> <d> : "🤤" # droll
|
|
||||||
<Multi_key> <m> <m> : "💰" # money
|
|
||||||
<Multi_key> <m> <x> : "🎉" # xellebrate
|
|
||||||
<Multi_key> <m> <1> : "💯" # 100%
|
|
||||||
<Multi_key> <m> <t> : "🥂" # toast
|
|
||||||
<Multi_key> <m> <p> : "🙏" # pray
|
|
||||||
<Multi_key> <m> <i> : "😉" # wink
|
|
||||||
<Multi_key> <m> <o> : "👌" # OK
|
|
||||||
<Multi_key> <m> <g> : "👋" # greeting
|
|
||||||
<Multi_key> <m> <a> : "💪" # arm
|
|
||||||
<Multi_key> <m> <b> : "🤯" # blowing
|
|
||||||
|
|
||||||
# Typography
|
|
||||||
<Multi_key> <space> <space> : "—"
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
# Overwrite parts of the nomarchy-menu with user-specific submenus.
|
|
||||||
# See $OMARCHY_PATH/bin/nomarchy-menu for functions that can be overwritten.
|
|
||||||
#
|
|
||||||
# WARNING: Overwritten functions will obviously not be updated when Nomarchy changes.
|
|
||||||
#
|
|
||||||
# Example of minimal system menu:
|
|
||||||
#
|
|
||||||
# show_system_menu() {
|
|
||||||
# case $(menu "System" " Lock\n Shutdown") in
|
|
||||||
# *Lock*) nomarchy-lock-screen ;;
|
|
||||||
# *Shutdown*) nomarchy-system-shutdown ;;
|
|
||||||
# *) back_to show_main_menu ;;
|
|
||||||
# esac
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# Example of overriding just the about menu action: (Using zsh instead of bash (default))
|
|
||||||
#
|
|
||||||
# show_about() {
|
|
||||||
# exec nomarchy-launch-or-focus-tui "zsh -c 'fastfetch; read -k 1'"
|
|
||||||
# }
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# This hook is called with the current battery percentage when the low battery
|
|
||||||
# notification is sent. To put it into use, remove .sample from the name.
|
|
||||||
|
|
||||||
SOUND_FILE="/usr/share/sounds/freedesktop/stereo/dialog-warning.oga"
|
|
||||||
|
|
||||||
if nomarchy-cmd-present mpv && [[ -f $SOUND_FILE ]]; then
|
|
||||||
mpv --no-video "$SOUND_FILE" >/dev/null 2>&1
|
|
||||||
fi
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# This hook is called with the snake-cased name of the font that has just been set.
|
|
||||||
# To put it into use, remove .sample from the name.
|
|
||||||
|
|
||||||
# Example: Show the name of the theme that was just set.
|
|
||||||
# notify-send -u low "New font" "Your new font is $1"
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# This hook is called after the nomarchy-welcome wizard finishes successfully.
|
|
||||||
# Use it to run any custom first-boot logic (e.g. cloning your dotfiles repo,
|
|
||||||
# setting up SSH keys, or launching specific initial apps).
|
|
||||||
|
|
||||||
# Example: Open the manual and show a notification
|
|
||||||
# nomarchy-manual
|
|
||||||
# notify-send "Welcome home" "Your Nomarchy system is ready to use."
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# This hook is called after an Nomarchy system update has been performed.
|
|
||||||
# To put it into use, remove .sample from the name.
|
|
||||||
|
|
||||||
# Example: Show notification after the system has been updated.
|
|
||||||
# notify-send -u low "Update Performed" "Your system is now up to date"
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# This hook is called with the snake-cased name of the theme that has just been set.
|
|
||||||
# To put it into use, remove .sample from the name.
|
|
||||||
|
|
||||||
# Example: Show the name of the theme that was just set.
|
|
||||||
# notify-send -u low "New theme" "Your new theme is $1"
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
# Nomarchy User Template Example: Alacritty
|
|
||||||
#
|
|
||||||
# This is a sample template file demonstrating how to create custom themed
|
|
||||||
# configurations. Templates use placeholder variables that get replaced with
|
|
||||||
# your current theme's colors when you switch themes.
|
|
||||||
#
|
|
||||||
# HOW TO USE:
|
|
||||||
# 1. Rename this file to: alacritty.toml.tpl (remove the .sample extension)
|
|
||||||
# 2. Customize it as needed
|
|
||||||
# 3. Change your theme to apply the template
|
|
||||||
#
|
|
||||||
# User templates in ~/.config/nomarchy/themed/ take priority over the built-in
|
|
||||||
# templates in the Nomarchy default/themed/ directory. This lets you override
|
|
||||||
# any built-in template or create templates for applications not included
|
|
||||||
# by default.
|
|
||||||
#
|
|
||||||
# AVAILABLE VARIABLES:
|
|
||||||
# {{ background }} - Main background color (e.g., "#1a1b26")
|
|
||||||
# {{ foreground }} - Main foreground/text color
|
|
||||||
# {{ cursor }} - Cursor color
|
|
||||||
# {{ accent }} - Theme accent color
|
|
||||||
# {{ selection_background }} - Selection highlight background
|
|
||||||
# {{ selection_foreground }} - Selection highlight foreground
|
|
||||||
#
|
|
||||||
# {{ color0 }} through {{ color15 }} - Standard 16-color terminal palette
|
|
||||||
# color0-7: Normal colors (black, red, green, yellow, blue, magenta, cyan, white)
|
|
||||||
# color8-15: Bright variants
|
|
||||||
#
|
|
||||||
# VARIABLE MODIFIERS:
|
|
||||||
# {{ variable_strip }} - Hex color without the # prefix (e.g., "1a1b26")
|
|
||||||
# {{ variable_rgb }} - Decimal RGB values (e.g., "26,27,38")
|
|
||||||
#
|
|
||||||
# Example using modifiers:
|
|
||||||
# background = "{{ background }}" -> background = "#1a1b26"
|
|
||||||
# background = "{{ background_strip }}" -> background = "1a1b26"
|
|
||||||
# background = "rgb({{ background_rgb }})" -> background = "rgb(26,27,38)"
|
|
||||||
#
|
|
||||||
# ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
[colors.primary]
|
|
||||||
background = "{{ background }}"
|
|
||||||
foreground = "{{ foreground }}"
|
|
||||||
|
|
||||||
[colors.cursor]
|
|
||||||
text = "{{ background }}"
|
|
||||||
cursor = "{{ cursor }}"
|
|
||||||
|
|
||||||
[colors.vi_mode_cursor]
|
|
||||||
text = "{{ background }}"
|
|
||||||
cursor = "{{ cursor }}"
|
|
||||||
|
|
||||||
[colors.search.matches]
|
|
||||||
foreground = "{{ background }}"
|
|
||||||
background = "{{ color3 }}"
|
|
||||||
|
|
||||||
[colors.search.focused_match]
|
|
||||||
foreground = "{{ background }}"
|
|
||||||
background = "{{ color1 }}"
|
|
||||||
|
|
||||||
[colors.footer_bar]
|
|
||||||
foreground = "{{ background }}"
|
|
||||||
background = "{{ foreground }}"
|
|
||||||
|
|
||||||
[colors.selection]
|
|
||||||
text = "{{ selection_foreground }}"
|
|
||||||
background = "{{ selection_background }}"
|
|
||||||
|
|
||||||
[colors.normal]
|
|
||||||
black = "{{ color0 }}"
|
|
||||||
red = "{{ color1 }}"
|
|
||||||
green = "{{ color2 }}"
|
|
||||||
yellow = "{{ color3 }}"
|
|
||||||
blue = "{{ color4 }}"
|
|
||||||
magenta = "{{ color5 }}"
|
|
||||||
cyan = "{{ color6 }}"
|
|
||||||
white = "{{ color7 }}"
|
|
||||||
|
|
||||||
[colors.bright]
|
|
||||||
black = "{{ color8 }}"
|
|
||||||
red = "{{ color9 }}"
|
|
||||||
green = "{{ color10 }}"
|
|
||||||
yellow = "{{ color11 }}"
|
|
||||||
blue = "{{ color12 }}"
|
|
||||||
magenta = "{{ color13 }}"
|
|
||||||
cyan = "{{ color14 }}"
|
|
||||||
white = "{{ color15 }}"
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
add_newline = true
|
|
||||||
command_timeout = 200
|
|
||||||
format = "[$directory$git_branch$git_status]($style)$character"
|
|
||||||
|
|
||||||
[character]
|
|
||||||
error_symbol = "[✗](bold cyan)"
|
|
||||||
success_symbol = "[❯](bold cyan)"
|
|
||||||
|
|
||||||
[directory]
|
|
||||||
truncation_length = 2
|
|
||||||
truncation_symbol = "…/"
|
|
||||||
repo_root_style = "bold cyan"
|
|
||||||
repo_root_format = "[$repo_root]($repo_root_style)[$path]($style)[$read_only]($read_only_style) "
|
|
||||||
|
|
||||||
[git_branch]
|
|
||||||
format = "[$branch]($style) "
|
|
||||||
style = "italic cyan"
|
|
||||||
|
|
||||||
[git_status]
|
|
||||||
format = '[$all_status]($style)'
|
|
||||||
style = "cyan"
|
|
||||||
ahead = "⇡${count} "
|
|
||||||
diverged = "⇕⇡${ahead_count}⇣${behind_count} "
|
|
||||||
behind = "⇣${count} "
|
|
||||||
conflicted = " "
|
|
||||||
up_to_date = " "
|
|
||||||
untracked = "? "
|
|
||||||
modified = " "
|
|
||||||
stashed = ""
|
|
||||||
staged = ""
|
|
||||||
renamed = ""
|
|
||||||
deleted = ""
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# Changes require a restart to take effect.
|
|
||||||
|
|
||||||
# Install other terminals via Install > Terminal
|
|
||||||
export TERMINAL=xdg-terminal-exec
|
|
||||||
|
|
||||||
# Use code for VSCode
|
|
||||||
export EDITOR=nvim
|
|
||||||
|
|
||||||
# Use a custom directory for screenshots (remember to make the directory!)
|
|
||||||
# export OMARCHY_SCREENSHOT_DIR="$HOME/Pictures/Screenshots"
|
|
||||||
|
|
||||||
# Use a custom directory for screenrecordings (remember to make the directory!)
|
|
||||||
# export OMARCHY_SCREENRECORD_DIR="$HOME/Videos/Screencasts"
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user