Feat/repo improvements #21

Merged
lyrathorpe merged 3 commits from feat/repo-improvements into main 2026-06-10 15:11:18 +01:00
20 changed files with 543 additions and 221 deletions
+19
View File
@@ -0,0 +1,19 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true
[*.{nix,yaml,yml,json,md,sh,toml}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true
# Markdown uses trailing whitespace for hard line breaks.
[*.md]
trim_trailing_whitespace = false
+1 -5
View File
@@ -1,10 +1,6 @@
{ {
"$schema": "https://docs.renovatebot.com/renovate-schema.json", "$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [ "extends": ["config:recommended", ":dependencyDashboard", ":semanticCommits"],
"config:recommended",
":dependencyDashboard",
":semanticCommits"
],
"nix": { "nix": {
"enabled": true "enabled": true
}, },
+27 -12
View File
@@ -7,13 +7,13 @@ single flake.
Defined in the host table in [`flake.nix`](./flake.nix): Defined in the host table in [`flake.nix`](./flake.nix):
| Configuration | System | Machine | | Configuration | System | Machine |
| ------------------- | --------------- | ---------------------------------------- | | --------------------- | ---------------- | --------------------------------------------------------------------------- |
| `lyrathorpe-mbp` | `aarch64-linux` | MacBook Pro (Apple Silicon, Asahi) | | `lyrathorpe-mbp` | `aarch64-linux` | MacBook Pro (Apple Silicon, Asahi) |
| `lyrathorpe-t400` | `x86_64-linux` | ThinkPad T400 — [install notes](./system/machine/T400/README.md) | | `lyrathorpe-t400` | `x86_64-linux` | ThinkPad T400 — [install notes](./system/machine/T400/README.md) |
| `lyrathorpe-macpro31` | `x86_64-linux` | Mac Pro 3,1, desktop — [install notes](./system/machine/MacPro31/README.md) | | `lyrathorpe-macpro31` | `x86_64-linux` | Mac Pro 3,1, desktop — [install notes](./system/machine/MacPro31/README.md) |
| `emmathorpe-edaas` | `x86_64-linux` | Work WSL box (NixOS-WSL) | | `emmathorpe-edaas` | `x86_64-linux` | Work WSL box (NixOS-WSL) |
| `lyrathorpe-mac` | `aarch64-darwin` | macOS (nix-darwin) | | `lyrathorpe-mac` | `aarch64-darwin` | macOS (nix-darwin) |
Shared layers: `lyrathorpe/home` (home-manager: shell, git, editor), Shared layers: `lyrathorpe/home` (home-manager: shell, git, editor),
`system/modules/common-nixos.nix` (all NixOS hosts), and `system/modules/common-nixos.nix` (all NixOS hosts), and
@@ -48,14 +48,29 @@ WSL work box) keep plain TTY login. The target account needs a password
## MacBook (Asahi) firmware ## MacBook (Asahi) firmware
The MBP host references `system/modules/firmware/` for Apple peripheral The MBP host references `system/modules/firmware/` for Apple peripheral
firmware (Wi-Fi/Bluetooth). Those blobs are **not** redistributable, so the firmware (Wi-Fi/Bluetooth). These blobs are **committed** (tracked) even though
directory is gitignored and a clean checkout will not build `lyrathorpe-mbp` `.gitignore` lists the directory: the flake is `git+file`, so it only sees
until it is populated out-of-band. tracked files — untracking them breaks `lyrathorpe-mbp` evaluation (and the CI
host-eval) because the config can't find the firmware. They are not
redistributable; the repo is private.
Copy the firmware extracted during the Asahi install (from To refresh them, copy the firmware extracted during the Asahi install (from
`/etc/nixos/firmware` on the freshly-installed machine, or re-extract per the `/etc/nixos/firmware`, or re-extract per the
[Asahi NixOS docs](https://github.com/tpwrules/nixos-apple-silicon)) into [Asahi NixOS docs](https://github.com/tpwrules/nixos-apple-silicon)) into
`system/modules/firmware/` before rebuilding that host. `system/modules/firmware/` and commit with `git add -f`.
## Development
A dev shell and a formatting/lint gate are wired through the flake:
- `nix develop` — shell with `deadnix`, `statix`, `treefmt`, and the git
`pre-commit` hooks (installed automatically on first entry).
- `nix fmt` — formats the tree via `treefmt` (nixfmt + shfmt + prettier;
generated files and `flake.lock` are excluded).
- `nix flake check` — runs formatting, `deadnix`, `statix`, the pre-commit
hooks, and evaluates every host. `.editorconfig` carries the base style;
`statix.toml` disables the two house-style lints (`repeated_keys`,
`empty_pattern`).
## CI ## CI
Generated
+85 -4
View File
@@ -40,6 +40,22 @@
} }
}, },
"flake-compat": { "flake-compat": {
"flake": false,
"locked": {
"lastModified": 1767039857,
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
"owner": "NixOS",
"repo": "flake-compat",
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_2": {
"locked": { "locked": {
"lastModified": 1761640442, "lastModified": 1761640442,
"narHash": "sha256-AtrEP6Jmdvrqiv4x2xa5mrtaIp3OEe8uBYCDZDS+hu8=", "narHash": "sha256-AtrEP6Jmdvrqiv4x2xa5mrtaIp3OEe8uBYCDZDS+hu8=",
@@ -54,7 +70,7 @@
"type": "github" "type": "github"
} }
}, },
"flake-compat_2": { "flake-compat_3": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1767039857, "lastModified": 1767039857,
@@ -90,6 +106,49 @@
"type": "github" "type": "github"
} }
}, },
"git-hooks": {
"inputs": {
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1778507602,
"narHash": "sha256-kTwur1wV+01SdqskVMSo6JMEpg71ps3HpbFY2GsflKs=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "61ab0e80d9c7ab14c256b5b453d8b3fb0189ba0a",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"git-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"home-manager": { "home-manager": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -172,7 +231,7 @@
}, },
"nixos-apple-silicon": { "nixos-apple-silicon": {
"inputs": { "inputs": {
"flake-compat": "flake-compat", "flake-compat": "flake-compat_2",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
] ]
@@ -193,7 +252,7 @@
}, },
"nixos-wsl": { "nixos-wsl": {
"inputs": { "inputs": {
"flake-compat": "flake-compat_2", "flake-compat": "flake-compat_3",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
] ]
@@ -248,6 +307,7 @@
"inputs": { "inputs": {
"firefox-addons": "firefox-addons", "firefox-addons": "firefox-addons",
"flake-parts": "flake-parts", "flake-parts": "flake-parts",
"git-hooks": "git-hooks",
"home-manager": "home-manager", "home-manager": "home-manager",
"nix-darwin": "nix-darwin", "nix-darwin": "nix-darwin",
"nix-homebrew": "nix-homebrew", "nix-homebrew": "nix-homebrew",
@@ -255,7 +315,28 @@
"nixos-apple-silicon": "nixos-apple-silicon", "nixos-apple-silicon": "nixos-apple-silicon",
"nixos-wsl": "nixos-wsl", "nixos-wsl": "nixos-wsl",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"nixpkgs-unstable": "nixpkgs-unstable" "nixpkgs-unstable": "nixpkgs-unstable",
"treefmt-nix": "treefmt-nix"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1780220602,
"narHash": "sha256-eynAfOmbmxJnkp7YewvCEbShNnnYJ9gLLqkzsYtBPeM=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "db947814a175b7ca6ded66e21383d938df01c227",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
} }
} }
}, },
+77 -14
View File
@@ -34,6 +34,18 @@
url = "github:nix-community/nix-index-database"; url = "github:nix-community/nix-index-database";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
# treefmt-nix: one multi-language formatter driving `nix fmt` and the
# formatting flake check (nixfmt + shfmt + prettier).
treefmt-nix = {
url = "github:numtide/treefmt-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
# git-hooks.nix: declarative pre-commit hooks (nixfmt/deadnix/statix),
# installed into the repo via the devShell.
git-hooks = {
url = "github:cachix/git-hooks.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
}; };
outputs = outputs =
@@ -53,12 +65,14 @@
let let
# claude-code tracks nixpkgs-unstable regardless of the pinned nixpkgs. # claude-code tracks nixpkgs-unstable regardless of the pinned nixpkgs.
overlays = [ overlays = [
(final: prev: { (_final: prev: {
claude-code = inherit
(import nixpkgs-unstable { (import nixpkgs-unstable {
inherit (prev.stdenv.hostPlatform) system; inherit (prev.stdenv.hostPlatform) system;
config.allowUnfree = true; config.allowUnfree = true;
}).claude-code; })
claude-code
;
}) })
]; ];
@@ -245,7 +259,7 @@
]; ];
homeModules = [ homeModules = [
./lyrathorpe/home ./lyrathorpe/home
./system/modules/work/default.nix ./lyrathorpe/home/work.nix
]; ];
}; };
}; };
@@ -268,6 +282,13 @@
}; };
in in
{ {
# flake-parts modules: treefmt-nix wires `nix fmt` + a formatting check;
# git-hooks.nix wires the pre-commit check + devShell installation script.
imports = [
inputs.treefmt-nix.flakeModule
inputs.git-hooks.flakeModule
];
systems = [ systems = [
"x86_64-linux" "x86_64-linux"
"aarch64-linux" "aarch64-linux"
@@ -279,26 +300,68 @@
# nixpkgs instance for that system. Outputs here become per-system # nixpkgs instance for that system. Outputs here become per-system
# attrsets automatically (e.g. devShells.<system>.default). # attrsets automatically (e.g. devShells.<system>.default).
perSystem = perSystem =
{ pkgs, ... }: { config, pkgs, ... }:
{ {
# `nix fmt` formatter for the repo. # treefmt drives `nix fmt` and the formatting check below. nixfmt
formatter = pkgs.nixfmt; # stays the .nix formatter (the tree is already nixfmt-formatted);
# shfmt covers shell and prettier covers markdown/yaml/json.
treefmt = {
projectRootFile = "flake.nix";
programs.nixfmt.enable = true;
programs.shfmt.enable = true;
programs.prettier.enable = true;
# Generated hardware-configuration.nix files are not hand-edited.
settings.global.excludes = [
"*/hardware-configuration.nix" # generated by nixos-generate-config
"flake.lock" # generated by `nix flake lock`
];
};
# Pre-commit hooks: format + lint gate run on commit. The same hooks
# are exposed as a flake check (pre-commit.check.enable defaults true).
pre-commit.settings = {
# Generated by nixos-generate-config; don't lint/reformat (treefmt
# excludes them too).
excludes = [ "hardware-configuration\\.nix$" ];
hooks = {
nixfmt-rfc-style.enable = true;
deadnix = {
enable = true;
# Unused module args ({config,lib,pkgs,...}) are normal; only
# flag genuinely dead bindings.
settings.noLambdaPatternNames = true;
};
statix.enable = true; # reads statix.toml (repeated_keys/empty_pattern disabled)
};
};
# treefmt-nix exposes its own `checks.treefmt`; alias it to
# `formatting` so the existing CI gate (.#checks.*.formatting) keeps
# working without churn.
checks.formatting = config.treefmt.build.check inputs.self;
# deadnix / statix lints as standalone flake checks so `nix flake
# check` flags dead code and antipatterns independently of pre-commit.
checks.deadnix = pkgs.runCommandLocal "check-deadnix" { nativeBuildInputs = [ pkgs.deadnix ]; } ''
deadnix --fail --no-lambda-pattern-names ${./.} && touch $out
'';
checks.statix = pkgs.runCommandLocal "check-statix" { nativeBuildInputs = [ pkgs.statix ]; } ''
statix check -c ${./.} ${./.} && touch $out
'';
# `nix develop` shell with the tooling needed to hack on this flake. # `nix develop` shell with the tooling needed to hack on this flake.
# shellHook installs the git pre-commit hooks into the working tree.
devShells.default = pkgs.mkShellNoCC { devShells.default = pkgs.mkShellNoCC {
packages = with pkgs; [ packages = with pkgs; [
nixfmt nixfmt
nil nil
git git
deadnix
statix
treefmt
]; ];
shellHook = config.pre-commit.installationScript;
}; };
checks.formatting =
pkgs.runCommandLocal "check-formatting" { nativeBuildInputs = [ pkgs.nixfmt ]; }
''
# Generated hardware-configuration.nix files are excluded.
nixfmt --check $(find ${./.} -name '*.nix' -not -name 'hardware-configuration.nix') && touch $out
'';
}; };
# Realise the host tables: each entry becomes a {nixos,darwin}Configuration. # Realise the host tables: each entry becomes a {nixos,darwin}Configuration.
+82 -82
View File
@@ -4,12 +4,12 @@ Every keyboard shortcut configured across this desktop, and where it is defined.
Everything here is managed declaratively through Nix — edit the listed file and Everything here is managed declaratively through Nix — edit the listed file and
rebuild, never the generated dotfiles. rebuild, never the generated dotfiles.
| Area | Defined in | | Area | Defined in |
| --- | --- | | ----------------- | --------------------------------------------------------------------------------------------------------------------- |
| Sway (compositor) | [`sway.nix`](./sway.nix) `config.keybindings` + `config.modes`, plus the home-manager Sway module's built-in defaults | | Sway (compositor) | [`sway.nix`](./sway.nix) `config.keybindings` + `config.modes`, plus the home-manager Sway module's built-in defaults |
| tmux | [`shell.nix`](./shell.nix) `programs.tmux` | | tmux | [`shell.nix`](./shell.nix) `programs.tmux` |
| zsh line editor | [`shell.nix`](./shell.nix) `programs.zsh.historySubstringSearch` | | zsh line editor | [`shell.nix`](./shell.nix) `programs.zsh.historySubstringSearch` |
| foot (terminal) | foot package defaults — only colours are themed (in `sway.nix`) | | foot (terminal) | foot package defaults — only colours are themed (in `sway.nix`) |
**Conventions** **Conventions**
@@ -26,49 +26,49 @@ rebuild, never the generated dotfiles.
### Applications & session ### Applications & session
| Shortcut | Action | | Shortcut | Action |
| --- | --- | | ------------------- | ------------------------------------------------------- |
| `Super`+`Return` | Open a terminal (foot) | | `Super`+`Return` | Open a terminal (foot) |
| `Super`+`Space` | App launcher (sway-launcher-desktop in a floating foot) | | `Super`+`Space` | App launcher (sway-launcher-desktop in a floating foot) |
| `Super`+`d` | App launcher (same as above; module default) | | `Super`+`d` | App launcher (same as above; module default) |
| `Super`+`e` | File manager (nemo) | | `Super`+`e` | File manager (nemo) |
| `Super`+`c` | Clipboard history picker (clipman → fuzzel) | | `Super`+`c` | Clipboard history picker (clipman → fuzzel) |
| `Super`+`l` | Lock screen (swaylock) | | `Super`+`l` | Lock screen (swaylock) |
| `Super`+`Shift`+`q` | Close the focused window | | `Super`+`Shift`+`q` | Close the focused window |
| `Super`+`Shift`+`c` | Reload the Sway config | | `Super`+`Shift`+`c` | Reload the Sway config |
| `Super`+`Shift`+`e` | Exit Sway (asks for confirmation) | | `Super`+`Shift`+`e` | Exit Sway (asks for confirmation) |
### Focus ### Focus
| Shortcut | Action | | Shortcut | Action |
| --- | --- | | ----------------------- | ---------------------------------------- |
| `Super`+`←`/`↓`/`↑`/`→` | Move focus by direction | | `Super`+`←`/`↓`/`↑`/`→` | Move focus by direction |
| `Super`+`h`/`j`/`k` | Move focus left / down / up (vim-style) | | `Super`+`h`/`j`/`k` | Move focus left / down / up (vim-style) |
| `Super`+`a` | Focus the parent container | | `Super`+`a` | Focus the parent container |
| `Super`+`Alt`+`Space` | Toggle focus between tiling and floating | | `Super`+`Alt`+`Space` | Toggle focus between tiling and floating |
> Note: vim focus-right would be `Super`+`l`, but that is bound to **lock** here; > Note: vim focus-right would be `Super`+`l`, but that is bound to **lock** here;
> use `Super`+`→`. > use `Super`+`→`.
### Moving windows ### Moving windows
| Shortcut | Action | | Shortcut | Action |
| --- | --- | | ------------------------------- | ---------------------------------------- |
| `Super`+`Shift`+`←`/`↓`/`↑`/`→` | Move the window by direction | | `Super`+`Shift`+`←`/`↓`/`↑`/`→` | Move the window by direction |
| `Super`+`Shift`+`h`/`j`/`k`/`l` | Move the window left / down / up / right | | `Super`+`Shift`+`h`/`j`/`k`/`l` | Move the window left / down / up / right |
| `Super`+`Shift`+`Space` | Toggle the window floating | | `Super`+`Shift`+`Space` | Toggle the window floating |
Mouse (with `Super` held): left-drag moves a window, right-drag resizes it. Mouse (with `Super` held): left-drag moves a window, right-drag resizes it.
### Layout ### Layout
| Shortcut | Action | | Shortcut | Action |
| --- | --- | | ----------- | -------------------------------------------------------------------------------------- |
| `Super`+`b` | Split horizontally | | `Super`+`b` | Split horizontally |
| `Super`+`v` | Split vertically | | `Super`+`v` | Split vertically |
| `Super`+`s` | Stacking layout | | `Super`+`s` | Stacking layout |
| `Super`+`w` | Tabbed layout | | `Super`+`w` | Tabbed layout |
| `Super`+`f` | Toggle fullscreen | | `Super`+`f` | Toggle fullscreen |
| `Super`+`y` | **Layout submenu**: `s` stacking · `w` tabbed · `e` toggle split · `Return`/`Esc` exit | | `Super`+`y` | **Layout submenu**: `s` stacking · `w` tabbed · `e` toggle split · `Return`/`Esc` exit |
> The layout submenu's `e` (toggle split) is the home for that action since > The layout submenu's `e` (toggle split) is the home for that action since
@@ -76,49 +76,49 @@ Mouse (with `Super` held): left-drag moves a window, right-drag resizes it.
### Workspaces ### Workspaces
| Shortcut | Action | | Shortcut | Action |
| --- | --- | | ----------------------- | --------------------------------- |
| `Super`+`1``0` | Switch to workspace 1…10 | | `Super`+`1``0` | Switch to workspace 1…10 |
| `Super`+`Shift`+`1``0` | Move the window to workspace 1…10 | | `Super`+`Shift`+`1``0` | Move the window to workspace 1…10 |
| `Super`+`z` | Previous workspace | | `Super`+`z` | Previous workspace |
| `Super`+`x` | Next workspace | | `Super`+`x` | Next workspace |
### Scratchpad ### Scratchpad
| Shortcut | Action | | Shortcut | Action |
| --- | --- | | ------------------- | --------------------------------- |
| `Super`+`Shift`+`-` | Move the window to the scratchpad | | `Super`+`Shift`+`-` | Move the window to the scratchpad |
| `Super`+`-` | Show / cycle the scratchpad | | `Super`+`-` | Show / cycle the scratchpad |
### Modes (submenus) ### Modes (submenus)
| Shortcut | Action | | Shortcut | Action |
| --- | --- | | ------------------- | ------------------------------------------------------------------------------------------------------------ |
| `Super`+`r` | **Resize mode**: arrow keys resize; `Return`/`Esc` exit | | `Super`+`r` | **Resize mode**: arrow keys resize; `Return`/`Esc` exit |
| `Super`+`y` | **Layout mode** (see Layout above) | | `Super`+`y` | **Layout mode** (see Layout above) |
| `Super`+`Shift`+`x` | **Power menu**: `l` lock · `e` log out · `s` sleep · `r` reboot · `Shift`+`s` shutdown · `Return`/`Esc` exit | | `Super`+`Shift`+`x` | **Power menu**: `l` lock · `e` log out · `s` sleep · `r` reboot · `Shift`+`s` shutdown · `Return`/`Esc` exit |
### Screenshots ### Screenshots
| Shortcut | Action | | Shortcut | Action |
| --- | --- | | --------------- | ---------------------------------------- |
| `Print` | Select a region → swappy (annotate/save) | | `Print` | Select a region → swappy (annotate/save) |
| `Shift`+`Print` | Focused window → swappy | | `Shift`+`Print` | Focused window → swappy |
### Audio & media ### Audio & media
| Shortcut | Action | | Shortcut | Action |
| --- | --- | | ----------------------------------------------- | ---------------------- |
| `XF86AudioRaiseVolume` / `XF86AudioLowerVolume` | Volume ±5% (wpctl) | | `XF86AudioRaiseVolume` / `XF86AudioLowerVolume` | Volume ±5% (wpctl) |
| `XF86AudioMute` | Toggle output mute | | `XF86AudioMute` | Toggle output mute |
| `XF86AudioMicMute` | Toggle microphone mute | | `XF86AudioMicMute` | Toggle microphone mute |
| `XF86AudioPlay` | Play/pause (playerctl) | | `XF86AudioPlay` | Play/pause (playerctl) |
| `XF86AudioNext` / `XF86AudioPrev` | Next / previous track | | `XF86AudioNext` / `XF86AudioPrev` | Next / previous track |
### Brightness — laptops only ### Brightness — laptops only
| Shortcut | Action | | Shortcut | Action |
| --- | --- | | ----------------------------------------------- | ----------------------------- |
| `XF86MonBrightnessUp` / `XF86MonBrightnessDown` | Backlight ±5% (brightnessctl) | | `XF86MonBrightnessUp` / `XF86MonBrightnessDown` | Backlight ±5% (brightnessctl) |
Present only on portable hosts (T400, MBP); desktops have no internal backlight. Present only on portable hosts (T400, MBP); desktops have no internal backlight.
@@ -129,19 +129,19 @@ Present only on portable hosts (T400, MBP); desktops have no internal backlight.
Prefix is **`Ctrl`+`b`** (default). Copy mode uses **vi** keys. Prefix is **`Ctrl`+`b`** (default). Copy mode uses **vi** keys.
| Shortcut | Action | | Shortcut | Action |
| --- | --- | | --------------------------------------- | -------------------------------------------------------------------------------------------- |
| `Ctrl`+`b` then `v` | Split into left/right panes | | `Ctrl`+`b` then `v` | Split into left/right panes |
| `Ctrl`+`b` then `s` | Split into top/bottom panes | | `Ctrl`+`b` then `s` | Split into top/bottom panes |
| `Ctrl`+`h`/`j`/`k`/`l` | Move between panes — and into/out of vim splits — seamlessly (vim-tmux-navigator, no prefix) | | `Ctrl`+`h`/`j`/`k`/`l` | Move between panes — and into/out of vim splits — seamlessly (vim-tmux-navigator, no prefix) |
| `Alt`+`←`/`→`/`↑`/`↓` | Switch pane by direction (no prefix needed) | | `Alt`+`←`/`→`/`↑`/`↓` | Switch pane by direction (no prefix needed) |
| `Ctrl`+`b` then `[` | Enter copy mode (then vi motions; `Space`/`Enter` to select/copy) | | `Ctrl`+`b` then `[` | Enter copy mode (then vi motions; `Space`/`Enter` to select/copy) |
| `Ctrl`+`b` then `z` | Zoom / unzoom the focused pane | | `Ctrl`+`b` then `z` | Zoom / unzoom the focused pane |
| `Ctrl`+`b` then `c` | New window | | `Ctrl`+`b` then `c` | New window |
| `Ctrl`+`b` then `n` / `p` | Next / previous window | | `Ctrl`+`b` then `n` / `p` | Next / previous window |
| `Ctrl`+`b` then `d` | Detach | | `Ctrl`+`b` then `d` | Detach |
| `Ctrl`+`b` then `Ctrl`+`s` / `Ctrl`+`r` | Save / restore the session (resurrect; continuum also auto-saves and restores on start) | | `Ctrl`+`b` then `Ctrl`+`s` / `Ctrl`+`r` | Save / restore the session (resurrect; continuum also auto-saves and restores on start) |
| Mouse | Enabled — click to focus, drag borders, scroll, select | | Mouse | Enabled — click to focus, drag borders, scroll, select |
> The stock split keys `%` and `"` are unbound; use `v` / `s` above. `Ctrl`+`b` > The stock split keys `%` and `"` are unbound; use `v` / `s` above. `Ctrl`+`b`
> then `s` is therefore a split, not the session tree. > then `s` is therefore a split, not the session tree.
@@ -155,22 +155,22 @@ Prefix is **`Ctrl`+`b`** (default). Copy mode uses **vi** keys.
Only colours are themed; these are foot's default key bindings. Only colours are themed; these are foot's default key bindings.
| Shortcut | Action | | Shortcut | Action |
| --- | --- | | --------------------------------------- | ----------------------------- |
| `Ctrl`+`Shift`+`c` / `Ctrl`+`Shift`+`v` | Copy / paste (clipboard) | | `Ctrl`+`Shift`+`c` / `Ctrl`+`Shift`+`v` | Copy / paste (clipboard) |
| `Shift`+`Insert` | Paste primary selection | | `Shift`+`Insert` | Paste primary selection |
| `Ctrl`+`Shift`+`r` | Search scrollback | | `Ctrl`+`Shift`+`r` | Search scrollback |
| `Ctrl`+`+` / `Ctrl`+`-` / `Ctrl`+`0` | Font larger / smaller / reset | | `Ctrl`+`+` / `Ctrl`+`-` / `Ctrl`+`0` | Font larger / smaller / reset |
| `Ctrl`+`Shift`+`u` | URL mode (jump to/open links) | | `Ctrl`+`Shift`+`u` | URL mode (jump to/open links) |
| `Ctrl`+`Shift`+`n` | Spawn a new terminal | | `Ctrl`+`Shift`+`n` | Spawn a new terminal |
| `Shift`+`PageUp` / `Shift`+`PageDown` | Scroll back / forward | | `Shift`+`PageUp` / `Shift`+`PageDown` | Scroll back / forward |
--- ---
## zsh ## zsh
| Shortcut | Action | | Shortcut | Action |
| --- | --- | | --------- | -------------------------------------------------------------------------------------------------- |
| `↑` / `↓` | History **substring** search — type a fragment first, then the arrows cycle matching past commands | | `↑` / `↓` | History **substring** search — type a fragment first, then the arrows cycle matching past commands |
Bound for both CSI and SS3 cursor sequences, so it works in foot, iTerm2 and Bound for both CSI and SS3 cursor sequences, so it works in foot, iTerm2 and
+76 -66
View File
@@ -6,11 +6,11 @@ home-manager — edit the listed file and rebuild, never the generated dotfiles.
Keyboard shortcuts have their own reference: [`KEYBINDINGS.md`](./KEYBINDINGS.md). Keyboard shortcuts have their own reference: [`KEYBINDINGS.md`](./KEYBINDINGS.md).
| Area | Defined in | | Area | Defined in |
| --- | --- | | ------------------------------------- | ----------------------------------------------------- |
| zsh, CLI tools, tmux, ssh, auto-tmux | [`shell.nix`](./shell.nix) | | zsh, CLI tools, tmux, ssh, auto-tmux | [`shell.nix`](./shell.nix) |
| git (+ delta, commitizen) | [`git.nix`](./git.nix) | | git (+ delta, commitizen) | [`git.nix`](./git.nix) |
| vim | [`editor.nix`](./editor.nix) | | vim | [`editor.nix`](./editor.nix) |
| GUI apps, GTK/Firefox theming, cursor | [`desktop.nix`](./desktop.nix) (graphical hosts only) | | GUI apps, GTK/Firefox theming, cursor | [`desktop.nix`](./desktop.nix) (graphical hosts only) |
Shared by every host via [`default.nix`](./default.nix); the work box also layers Shared by every host via [`default.nix`](./default.nix); the work box also layers
@@ -21,30 +21,40 @@ on top (work email, its own ssh config, extra packages).
## zsh ## zsh
| Feature | Notes | | Feature | Notes |
| --- | --- | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
| oh-my-zsh | plugins `git`, `man`, `sudo` (Esc-Esc to prepend sudo), `colored-man-pages`, `extract`; theme `robbyrussell` | | oh-my-zsh | plugins `git`, `man`, `sudo` (Esc-Esc to prepend sudo), `colored-man-pages`, `extract`; theme `robbyrussell` |
| Autosuggestion | fish-style history suggestions as you type (→ to accept) | | Autosuggestion | fish-style history suggestions as you type (→ to accept) |
| Syntax highlighting | commands coloured by validity as you type | | Syntax highlighting | commands coloured by validity as you type |
| Completion | menu completion; the dump is rebuilt on every activation (see Maintenance) | | Completion | menu completion; the dump is rebuilt on every activation (see Maintenance) |
| History | 100k in-memory/on-disk, deduped, space-prefixed commands ignored, timestamped, **shared live across sessions** | | History | 100k in-memory/on-disk, deduped, space-prefixed commands ignored, timestamped, **shared live across sessions** |
| History substring search | type a fragment, then ↑/↓ cycles matching past commands — works in foot, iTerm2 and the Linux TTY (both CSI and SS3 arrow encodings bound) | | History substring search | type a fragment, then ↑/↓ cycles matching past commands — works in foot, iTerm2 and the Linux TTY (both CSI and SS3 arrow encodings bound) |
| Prompt | hostname is prefixed when over SSH | | Prompt | hostname is prefixed when over SSH |
**Aliases:** `ls`/`ll`/`la`/`lt``eza` (icons + git), `cls``clear`. git aliases live in git.nix (below). **Aliases:** `ls`/`ll`/`la`/`lt``eza` (icons + git), `cls``clear`. git aliases live in git.nix (below).
## CLI tools ## CLI tools
| Tool | What it gives you | | Tool | What it gives you |
| --- | --- | | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `fzf` | `Ctrl-R` fuzzy history, `Ctrl-T` file picker, `Alt-C` fuzzy cd | | `fzf` | `Ctrl-R` fuzzy history, `Ctrl-T` file picker, `Alt-C` fuzzy cd (Catppuccin-themed) |
| `zoxide` | `z <fragment>` jumps to frecent directories | | `zoxide` | `z <fragment>` jumps to frecent directories |
| `direnv` + `nix-direnv` | per-project environments auto-loaded on `cd` (cached Nix dev shells) | | `direnv` + `nix-direnv` | per-project environments auto-loaded on `cd` (cached Nix dev shells) |
| `eza` | modern `ls` (drives the ls aliases) | | `eza` | modern `ls` (drives the ls aliases) |
| `bat` | syntax-highlighting pager; behaves like `cat` when piped | | `bat` | syntax-highlighting pager (Catppuccin Mocha theme); behaves like `cat` when piped; also the `MANPAGER` |
| `nix-index` | `command-not-found`: an unknown command tells you which Nix package provides it (prebuilt DB, no manual indexing) | | `ripgrep` / `fd` | fast search (`rg`) and find (`fd`); also back `fzf` |
| `comma` (`,`) | run an uninstalled program once: `, cowsay hi` | | `jq` / `btop` | JSON processor; resource monitor |
| `nh` | nicer `nixos-rebuild`/`home-manager` with diffs; `$NH_FLAKE` set to the repo. No scheduled GC (it could reap paths a running generation still references) — collect garbage manually with `nh clean all` / `nix-collect-garbage -d` | | `gh` / `tea` | GitHub and Gitea (`code.emmathe.dev`) CLIs; `gh` uses SSH |
| `nix-index` | `command-not-found`: an unknown command tells you which Nix package provides it (prebuilt DB, no manual indexing) |
| `comma` (`,`) | run an uninstalled program once: `, cowsay hi` |
| `nh` | nicer `nixos-rebuild`/`home-manager` with diffs; `$NH_FLAKE` set to the repo. No scheduled GC (it could reap paths a running generation still references) — collect garbage manually with `nh clean all` / `nix-collect-garbage -d` |
**Theming:** `fzf`, `bat` and `git`'s `delta` pager are all Catppuccin Mocha,
driven from the shared `../catppuccin-mocha.nix` palette / the catppuccin/bat
theme.
**Env & defaults:** `xdg.enable` on; `PAGER`/`MANPAGER` (bat)/`VISUAL` set in
`default.nix`; `xdg.mimeApps` maps web→Firefox, directories→nemo (`desktop.nix`).
## tmux ## tmux
@@ -54,18 +64,18 @@ exists, else create). Panes run a plain non-login zsh. It deliberately does **no
fire for SSH sessions, VS Code's integrated terminal, already-inside-tmux, or fire for SSH sessions, VS Code's integrated terminal, already-inside-tmux, or
non-interactive shells. Escape hatch: `NO_TMUX=1 <terminal>` opens a bare shell. non-interactive shells. Escape hatch: `NO_TMUX=1 <terminal>` opens a bare shell.
| Setting | Value | | Setting | Value |
| --- | --- | | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| Mode keys | vi | | Mode keys | vi |
| Mouse | on | | Mouse | on |
| Scrollback | 500000 lines | | Scrollback | 500000 lines |
| `escape-time` | 10ms (the 500ms default lagged vim's ESC) | | `escape-time` | 10ms (the 500ms default lagged vim's ESC) |
| `focus-events` | on (vim autoread) | | `focus-events` | on (vim autoread) |
| `base-index` / `pane-base-index` | 1 | | `base-index` / `pane-base-index` | 1 |
| Splits | `prefix s` vertical, `prefix v` horizontal (stock `%`/`"` unbound) | | Splits | `prefix s` vertical, `prefix v` horizontal (stock `%`/`"` unbound) |
| Pane nav | `Alt`+arrows (no prefix) | | Pane nav | `Alt`+arrows (no prefix) |
| Terminal | `default-terminal tmux-256color`; truecolor advertised per outer terminal (`foot*`, `xterm-256color`/iTerm2) via `terminal-features … RGB` | | Terminal | `default-terminal tmux-256color`; truecolor advertised per outer terminal (`foot*`, `xterm-256color`/iTerm2) via `terminal-features … RGB` |
| Clipboard | `set-clipboard on`; foot `terminal-features` advertise truecolor/sync/OSC52/title/cursor | | Clipboard | `set-clipboard on`; foot `terminal-features` advertise truecolor/sync/OSC52/title/cursor |
**Plugins:** `sensible`, `vim-tmux-navigator` (Ctrl-h/j/k/l across vim ↔ tmux), **Plugins:** `sensible`, `vim-tmux-navigator` (Ctrl-h/j/k/l across vim ↔ tmux),
`yank`, `catppuccin` (Mocha statusline), `resurrect` + `continuum` `yank`, `catppuccin` (Mocha statusline), `resurrect` + `continuum`
@@ -77,7 +87,7 @@ glyphs — see Fonts.
**JetBrainsMono Nerd Font** is installed on every host (in `common-nixos.nix`, **JetBrainsMono Nerd Font** is installed on every host (in `common-nixos.nix`,
because tmux runs everywhere; the Mac installs it to `/Library/Fonts` via the because tmux runs everywhere; the Mac installs it to `/Library/Fonts` via the
Darwin config). foot uses it as its main font automatically. iTerm2's font is a Darwin config). foot uses it as its main font automatically. iTerm2's font is a
GUI setting — set it to *JetBrainsMono Nerd Font* (Settings → Profiles → Text → GUI setting — set it to _JetBrainsMono Nerd Font_ (Settings → Profiles → Text →
Font) so the tmux statusline glyphs render instead of `?`. Font) so the tmux statusline glyphs render instead of `?`.
## git ## git
@@ -85,33 +95,33 @@ Font) so the tmux statusline glyphs render instead of `?`.
Pager is **delta**. **commitizen** is installed on every host; `cz` defaults to Pager is **delta**. **commitizen** is installed on every host; `cz` defaults to
Conventional Commits. Conventional Commits.
| Aliases | | | Aliases | |
| --- | --- | | ------------------------ | ----------------------------------------------------------------- |
| `st` `co` `sw` `br` `ci` | status / checkout / switch / branch / commit | | `st` `co` `sw` `br` `ci` | status / checkout / switch / branch / commit |
| `last` `unstage` | last commit / unstage | | `last` `unstage` | last commit / unstage |
| `lg` | graph log, all branches | | `lg` | graph log, all branches |
| `cz` `cc` | `git cz <sub>` (e.g. `git cz c`) and `git cc` → commitizen prompt | | `cz` `cc` | `git cz <sub>` (e.g. `git cz c`) and `git cc` → commitizen prompt |
| Behaviour | | | Behaviour | |
| --- | --- | | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Pulls | rebase, with autostash + autosquash | | Pulls | rebase, with autostash + autosquash |
| Fetch | prune deleted remote branches | | Fetch | prune deleted remote branches |
| Conflicts | `zdiff3` (shows the common ancestor) | | Conflicts | `zdiff3` (shows the common ancestor) |
| Diffs | histogram algorithm, colour-moved | | Diffs | histogram algorithm, colour-moved |
| `rerere` | remembers + replays conflict resolutions | | `rerere` | remembers + replays conflict resolutions |
| Commit editor | full diff shown (`commit.verbose`) | | Commit editor | full diff shown (`commit.verbose`) |
| Misc | branches sorted by date, `column.ui = auto`, `help.autocorrect = prompt`, `push.autoSetupRemote` | | Misc | branches sorted by date, `column.ui = auto`, `help.autocorrect = prompt`, `push.autoSetupRemote` |
| Global ignores | `result`, `result-*`, `.direnv`, `*.swp`, `.DS_Store` | | Global ignores | `result`, `result-*`, `.direnv`, `*.swp`, `.DS_Store` |
| Signing | SSH commit + tag signing (`mkDefault`, so a host without the key in its agent can disable it). Personal email `iam@emmathe.dev`; the work box overrides email + signing. | | Signing | SSH commit + tag signing (`mkDefault`, so a host without the key in its agent can disable it). Personal email `iam@emmathe.dev`; the work box overrides email + signing. |
## ssh ## ssh
| Feature | Notes | | Feature | Notes |
| --- | --- | | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| ssh-agent | runs on Linux (launchd on macOS); keys added on **first use** so the passphrase is typed once per login session — this also feeds git commit signing | | ssh-agent | runs on Linux (launchd on macOS); keys added on **first use** so the passphrase is typed once per login session — this also feeds git commit signing |
| macOS | `UseKeychain` caches the passphrase in the login keychain (guarded by `IgnoreUnknown`, so a non-Apple `ssh` skips it instead of erroring) | | macOS | `UseKeychain` caches the passphrase in the login keychain (guarded by `IgnoreUnknown`, so a non-Apple `ssh` skips it instead of erroring) |
| Gitea remote | `code.emmathe.dev``HostName 10.187.1.76` (DNS-override), `Port 30009`, user `git`, dedicated key, `identitiesOnly` | | Gitea remote | `code.emmathe.dev``HostName 10.187.1.76` (DNS-override), `Port 30009`, user `git`, dedicated key, `identitiesOnly` |
| Defaults | the module's deprecated default block is opted out; equivalents kept under `settings."*"` | | Defaults | the module's deprecated default block is opted out; equivalents kept under `settings."*"` |
The **work box keeps its own `~/.ssh/config`** (home-manager's `programs.ssh` is The **work box keeps its own `~/.ssh/config`** (home-manager's `programs.ssh` is
forced off there) but still runs the agent. forced off there) but still runs the agent.
@@ -126,10 +136,10 @@ forced off there) but still runs the agent.
## Per-host differences ## Per-host differences
| | Personal Linux (sway) | macOS | Work WSL (EDaaS) | | | Personal Linux (sway) | macOS | Work WSL (EDaaS) |
| --- | --- | --- | --- | | --------------------------- | --------------------- | ----------------- | --------------------------- |
| Auto-tmux | yes (foot/TTY) | yes (iTerm2) | yes (WSL shell) | | Auto-tmux | yes (foot/TTY) | yes (iTerm2) | yes (WSL shell) |
| git email | `iam@emmathe.dev` | `iam@emmathe.dev` | `…@citrix.com` (work) | | git email | `iam@emmathe.dev` | `iam@emmathe.dev` | `…@citrix.com` (work) |
| ssh config managed | yes | yes | no (keeps corporate config) | | ssh config managed | yes | yes | no (keeps corporate config) |
| ssh-agent | yes | launchd | yes (work module) | | ssh-agent | yes | launchd | yes (work module) |
| GUI / theming (desktop.nix) | yes | no | no | | GUI / theming (desktop.nix) | yes | no | no |
+21
View File
@@ -9,5 +9,26 @@
./editor.nix ./editor.nix
]; ];
# Manage the XDG base-directory layout and ~/.config files. Tools above
# (bat themes, gh config, ...) write under xdg.configHome; enabling this
# makes the paths explicit and consistent across hosts. No regression: the
# defaults match the conventional ~/.config, ~/.cache, ~/.local/share.
xdg.enable = true;
# Editor itself comes from vim.defaultEditor (sets $EDITOR). Round out the
# rest of the standard env. desktop.nix adds its own Wayland session vars;
# home-manager merges the two attrsets, so these do not clash.
home.sessionVariables = {
VISUAL = "vim";
PAGER = "less -FRX"; # -F quit-if-one-screen, -R raw colour, -X no clear
# Render man pages through bat (themed): col strips backspace overstrike,
# bat -l man -p highlights without its own pager decorations.
MANPAGER = "sh -c 'col -bx | bat -l man -p'";
};
# Pinned to the release first installed on these hosts, NOT the current
# nixpkgs (26.05). stateVersion freezes stateful defaults (file locations,
# service data formats) to that release; bumping it silently migrates that
# state and can break it. Leave it -- it is intentional, not stale.
home.stateVersion = "25.05"; home.stateVersion = "25.05";
} }
+24
View File
@@ -27,6 +27,30 @@
XDG_CURRENT_DESKTOP = "sway"; XDG_CURRENT_DESKTOP = "sway";
}; };
# Default apps for the desktop (writes ~/.config/mimeapps.list). Firefox owns
# the web; nemo owns directories/file URIs; images, PDFs and plain text open
# in Firefox too -- no dedicated GUI viewer/editor is installed and vim is
# terminal-only (no usable GUI .desktop for double-click handoff). Kept
# minimal -- only the handlers actually present on these hosts.
xdg.mimeApps = {
enable = true;
defaultApplications = {
"text/html" = "firefox.desktop";
"x-scheme-handler/http" = "firefox.desktop";
"x-scheme-handler/https" = "firefox.desktop";
"x-scheme-handler/about" = "firefox.desktop";
"x-scheme-handler/unknown" = "firefox.desktop";
"inode/directory" = "nemo.desktop";
"image/png" = "firefox.desktop";
"image/jpeg" = "firefox.desktop";
"image/gif" = "firefox.desktop";
"image/webp" = "firefox.desktop";
"image/svg+xml" = "firefox.desktop";
"application/pdf" = "firefox.desktop";
"text/plain" = "firefox.desktop";
};
};
# Theme GTK apps (nemo, etc.) to match the Catppuccin Mocha desktop. Under # Theme GTK apps (nemo, etc.) to match the Catppuccin Mocha desktop. Under
# Sway there is no XSettings daemon, so GTK reads these from the generated # Sway there is no XSettings daemon, so GTK reads these from the generated
# ~/.config/gtk-{3,4}.0/settings.ini directly. The Mocha theme is dark by # ~/.config/gtk-{3,4}.0/settings.ini directly. The Mocha theme is dark by
+11
View File
@@ -37,6 +37,17 @@
colorMoved = "default"; colorMoved = "default";
}; };
rerere.enabled = true; # remember + replay conflict resolutions rerere.enabled = true; # remember + replay conflict resolutions
# delta pager config (programs.delta is enabled below, with git
# integration; these keys land under [delta] in the git config).
# syntax-theme reuses the Catppuccin Mocha tmTheme vendored for bat in
# shell.nix -- delta reads bat's theme directory.
delta = {
syntax-theme = "Catppuccin Mocha";
navigate = true; # n/N to jump between diff hunks
line-numbers = true;
side-by-side = true;
};
commit.verbose = true; # full diff in the commit-message editor commit.verbose = true; # full diff in the commit-message editor
branch.sort = "-committerdate"; # most-recent branches first branch.sort = "-committerdate"; # most-recent branches first
column.ui = "auto"; column.ui = "auto";
+54 -2
View File
@@ -5,6 +5,10 @@
inputs, inputs,
... ...
}: }:
let
# Shared Catppuccin Mocha palette: raw 6-hex strings, no leading "#".
ctp = import ../catppuccin-mocha.nix;
in
{ {
imports = [ imports = [
# Prebuilt nix-index database -> working command-not-found # Prebuilt nix-index database -> working command-not-found
@@ -12,6 +16,16 @@
inputs.nix-index-database.homeModules.default inputs.nix-index-database.homeModules.default
]; ];
# CLI staples wanted on every host (search, parse, monitor). ripgrep/fd also
# back fzf and editor integrations; tea is the Gitea CLI for code.emmathe.dev.
home.packages = [
pkgs.ripgrep
pkgs.fd
pkgs.jq
pkgs.btop
pkgs.tea
];
programs.zsh = { programs.zsh = {
enable = true; enable = true;
enableCompletion = true; enableCompletion = true;
@@ -99,6 +113,23 @@
programs.fzf = { programs.fzf = {
enable = true; enable = true;
enableZshIntegration = true; enableZshIntegration = true;
# Catppuccin Mocha colours (rendered into FZF_DEFAULT_OPTS --color). Each
# value needs a leading "#"; the palette stores raw hex.
colors = {
"bg" = "#${ctp.base}";
"bg+" = "#${ctp.surface1}"; # current line / selected row
"fg" = "#${ctp.text}";
"fg+" = "#${ctp.text}";
"hl" = "#${ctp.blue}"; # match highlights
"hl+" = "#${ctp.blue}";
"header" = "#${ctp.red}";
"info" = "#${ctp.mauve}";
"marker" = "#${ctp.green}";
"pointer" = "#${ctp.pink}";
"prompt" = "#${ctp.mauve}";
"spinner" = "#${ctp.pink}";
"border" = "#${ctp.surface1}";
};
}; };
# Frecency directory jumping: `z <fragment>`. # Frecency directory jumping: `z <fragment>`.
@@ -120,8 +151,22 @@
icons = "auto"; # boolean form is deprecated icons = "auto"; # boolean form is deprecated
}; };
# Syntax-highlighting pager, used as `bat` (acts like cat when piped). # Syntax-highlighting pager, used as `bat` (acts like cat when piped). bat
programs.bat.enable = true; # ships no Catppuccin theme, so vendor the upstream tmTheme from catppuccin/bat
# (delta in git.nix reuses it as its syntax-theme).
programs.bat = {
enable = true;
config.theme = "Catppuccin Mocha";
themes."Catppuccin Mocha" = {
src = pkgs.fetchFromGitHub {
owner = "catppuccin";
repo = "bat";
rev = "6810349b28055dce54076712fc05fc68da4b8ec0";
sha256 = "1y5sfi7jfr97z1g6vm2mzbsw59j1jizwlmbadvmx842m0i5ak5ll";
};
file = "themes/Catppuccin Mocha.tmTheme";
};
};
# command-not-found backed by the prebuilt nix-index DB (module imported # command-not-found backed by the prebuilt nix-index DB (module imported
# above). `comma` runs an uninstalled program once: `, cowsay hi`. # above). `comma` runs an uninstalled program once: `, cowsay hi`.
@@ -138,6 +183,13 @@
flake = "$HOME/code/nixfiles"; flake = "$HOME/code/nixfiles";
}; };
# GitHub CLI. Prefer SSH for any git operations it drives, matching the
# ssh-based remotes used elsewhere.
programs.gh = {
enable = true;
settings.git_protocol = "ssh";
};
programs.tmux = { programs.tmux = {
enable = true; enable = true;
reverseSplit = true; reverseSplit = true;
@@ -1,3 +1,5 @@
# Home-manager module for the work (EDaaS/WSL) profile: corporate git signing,
# work toolchain packages and tmux tweaks. Imported only by the work host.
{ pkgs, lib, ... }: { pkgs, lib, ... }:
{ {
+8
View File
@@ -0,0 +1,8 @@
# statix lint config. Two default lints are disabled because they flag this
# repo's intentional house style, not bugs:
# repeated_keys - we use `foo.a = ...; foo.b = ...;` (dotted) over nesting.
# empty_pattern - module files use `{ ... }:` / `{ }:` deliberately.
disabled = [
"repeated_keys",
"empty_pattern",
]
+12 -3
View File
@@ -14,9 +14,18 @@
networking.hostName = "Emma-Asahi"; networking.hostName = "Emma-Asahi";
# No fingerprint reader on this machine; empty service still lets swaylock # Audio (PipeWire) and the swaylock PAM stack are inherited from
# authenticate via password. # workstation.nix. hardware.enableRedistributableFirmware is also set there;
security.pam.services.swaylock = { }; # it is harmless here since Asahi supplies its own peripheral firmware below.
# Binary cache for the Asahi kernel/build artifacts, so the MBP pulls prebuilt
# outputs instead of compiling the Asahi kernel locally.
nix.settings = {
substituters = [ "https://nixos-apple-silicon.cachix.org" ];
trusted-public-keys = [
"nixos-apple-silicon.cachix.org-1:8psDu5SA5dAD7qA0zMy5UT292TxeEPzIz8VVEr2Js20="
];
};
# Apple peripheral firmware (Wi-Fi/Bluetooth). The directory is gitignored and # Apple peripheral firmware (Wi-Fi/Bluetooth). The directory is gitignored and
# populated out-of-band -- see README. # populated out-of-band -- see README.
+5 -4
View File
@@ -6,10 +6,11 @@ Flake host: `lyrathorpe-macpro31`. Desktop (`portable = false`, imports
## Hardware configuration ## Hardware configuration
`hardware-configuration.nix` here is a hand-written **placeholder**. On the real `hardware-configuration.nix` here is the real config generated by
machine, run `nixos-generate-config`, replace the file, and commit it. It assumes `nixos-generate-config` on the machine. Root is an **LVM** logical volume
by-label partitions — ESP `ESP` (vfat, mounted at `/boot`), root `nixos` (ext4), (`/dev/mapper/MacPro-Root`, ext4); the ESP (vfat) and swap are referenced by
and `swap` — so either label them at install time or swap in the generated UUIDs. UUID. The initrd carries `dm-snapshot` for the LVM root. Regenerate and commit
if the disk layout changes.
## Bootloader ## Bootloader
+2 -12
View File
@@ -27,19 +27,9 @@
services.openssh.enable = true; services.openssh.enable = true;
networking.firewall.allowedTCPPorts = [ 22 ]; networking.firewall.allowedTCPPorts = [ 22 ];
services.pipewire = { # Dual Harpertown Xeon microcode. Redistributable firmware (GPU/NIC blobs) is
enable = true; # enabled in workstation.nix.
pulse.enable = true;
};
# No fingerprint hardware; empty service still lets swaylock authenticate via
# password.
security.pam.services.swaylock = { };
# Dual Harpertown Xeon microcode + redistributable firmware (e.g. GPU/NIC
# blobs).
hardware.cpu.intel.updateMicrocode = true; hardware.cpu.intel.updateMicrocode = true;
hardware.enableRedistributableFirmware = true;
# GPU note: the stock card varies between units -- ATI Radeon HD 2600 XT or # GPU note: the stock card varies between units -- ATI Radeon HD 2600 XT or
# NVIDIA GeForce 8800 GT. Sway needs a working KMS/modesetting driver; do NOT # NVIDIA GeForce 8800 GT. Sway needs a working KMS/modesetting driver; do NOT
+5 -5
View File
@@ -15,11 +15,11 @@ install time or swap in the generated UUIDs.
`configuration.nix` imports exactly one boot module. Default is `boot-bios.nix`; `configuration.nix` imports exactly one boot module. Default is `boot-bios.nix`;
switch by commenting it out and uncommenting the relevant alternative. switch by commenting it out and uncommenting the relevant alternative.
| Firmware | Module | Notes | | Firmware | Module | Notes |
| --- | --- | --- | | ---------------------------------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Stock Lenovo BIOS, or coreboot + **SeaBIOS** payload | `boot-bios.nix` | GRUB on the MBR. Set `device` to the real install disk (`/dev/sda` by default). MBR/legacy layout. | | Stock Lenovo BIOS, or coreboot + **SeaBIOS** payload | `boot-bios.nix` | GRUB on the MBR. Set `device` to the real install disk (`/dev/sda` by default). MBR/legacy layout. |
| coreboot + **GRUB** payload | `boot-coreboot-grub.nix` | GRUB is config-only (`device = "nodev"`); NixOS does **not** write to a disk. Your coreboot `grub.cfg` (in the flash chip) must `search` for and `configfile` the on-disk `/boot/grub/grub.cfg`, or chainload the disk's GRUB. | | coreboot + **GRUB** payload | `boot-coreboot-grub.nix` | GRUB is config-only (`device = "nodev"`); NixOS does **not** write to a disk. Your coreboot `grub.cfg` (in the flash chip) must `search` for and `configfile` the on-disk `/boot/grub/grub.cfg`, or chainload the disk's GRUB. |
| coreboot + **Tianocore/edk2 (UEFI)** payload | `boot-coreboot-uefi.nix` | systemd-boot. `canTouchEfiVariables = true` (coreboot honours NVRAM writes). The module **declares its own ESP** (`/boot` vfat, label `ESP`) — when you regenerate `hardware-configuration.nix`, do **not** let it also define `/boot`. Create + label an `ESP` vfat partition (GPT). | | coreboot + **Tianocore/edk2 (UEFI)** payload | `boot-coreboot-uefi.nix` | systemd-boot. `canTouchEfiVariables = true` (coreboot honours NVRAM writes). The module **declares its own ESP** (`/boot` vfat, label `ESP`) — when you regenerate `hardware-configuration.nix`, do **not** let it also define `/boot`. Create + label an `ESP` vfat partition (GPT). |
## Graphics ## Graphics
+5 -12
View File
@@ -18,25 +18,18 @@
console.font = "Lat2-Terminus16"; console.font = "Lat2-Terminus16";
services.pipewire = { # Low-RAM host (4 GiB max): a compressed RAM swap reduces disk paging.
enable = true; zramSwap.enable = true;
pulse.enable = true;
};
# This host accepts SSH, so open 22 (the firewall itself is enabled in # This host accepts SSH, so open 22 (the firewall itself is enabled in
# laptop.nix with a default-deny policy). # laptop.nix with a default-deny policy).
services.openssh.enable = true; services.openssh.enable = true;
networking.firewall.allowedTCPPorts = [ 22 ]; networking.firewall.allowedTCPPorts = [ 22 ];
# The T400's fingerprint reader differs/may be absent; empty service still # Intel Core 2 (Penryn) microcode. Redistributable firmware (enabled in
# lets swaylock authenticate via password. # workstation.nix) supplies the iwlwifi blobs (Intel WiFi Link 5100/5300) and
security.pam.services.swaylock = { }; # the radeon firmware needed by the discrete GPU below.
# Intel Core 2 (Penryn) microcode + redistributable firmware. The latter also
# supplies the iwlwifi blobs (Intel WiFi Link 5100/5300) and the radeon
# firmware needed by the discrete GPU below.
hardware.cpu.intel.updateMicrocode = true; hardware.cpu.intel.updateMicrocode = true;
hardware.enableRedistributableFirmware = true;
# This T400 has the optional discrete GPU fitted: an ATI Mobility Radeon HD # This T400 has the optional discrete GPU fitted: an ATI Mobility Radeon HD
# 3470 (RV620), driven by the open `radeon` KMS driver. Load it in the initrd # 3470 (RV620), driven by the open `radeon` KMS driver. Load it in the initrd
+7
View File
@@ -6,6 +6,13 @@
time.timeZone = "Europe/London"; time.timeZone = "Europe/London";
i18n.defaultLocale = "en_GB.UTF-8"; i18n.defaultLocale = "en_GB.UTF-8";
# Store hygiene. auto-optimise-store hard-links identical files in the store
# after each build (cheap dedupe; NOT a garbage collector -- there is
# deliberately no automatic GC timer). The larger download buffer avoids
# "buffer full" stalls when fetching big NARs over a fast link.
nix.settings.auto-optimise-store = true;
nix.settings.download-buffer-size = 134217728; # 128 MiB
# Minimal system-level CLI available before the home-manager profile loads # Minimal system-level CLI available before the home-manager profile loads
# (e.g. early boot / rescue). User-level tooling lives in home-manager. # (e.g. early boot / rescue). User-level tooling lives in home-manager.
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
+20
View File
@@ -14,4 +14,24 @@
# Default-deny inbound. Hosts that run a listening service open their own # Default-deny inbound. Hosts that run a listening service open their own
# ports next to where the service is enabled (e.g. sshd -> 22 on X1). # ports next to where the service is enabled (e.g. sshd -> 22 on X1).
networking.firewall.enable = true; networking.firewall.enable = true;
# Disk hygiene for the physical hosts. fstrim reclaims unused SSD blocks on a
# weekly timer; cleanOnBoot wipes /tmp at every boot.
services.fstrim.enable = true;
boot.tmp.cleanOnBoot = true;
# Audio. PipeWire with the PulseAudio shim covers every graphical host; no
# per-machine audio config is needed.
services.pipewire = {
enable = true;
pulse.enable = true;
};
# swaylock PAM stack. None of these machines has working fingerprint auth, so
# an empty service is enough -- swaylock falls back to password.
security.pam.services.swaylock = { };
# Redistributable firmware (GPU/Wi-Fi/NIC blobs) for the x86 hosts. Harmless
# on the Asahi MBP, which supplies its own peripheral firmware out-of-band.
hardware.enableRedistributableFirmware = true;
} }