diff options
| author | 2026-09-24 09:43:13 +0000 | |
|---|---|---|
| committer | 2026-09-24 09:43:13 +0000 | |
| commit | a1678f084e757c5464d167a937ac06460d9529df (patch) | |
| tree | 9cabf3b51fe6972bc7bfa216dd660e8cef0e415c /CLAUDE.md | |
| parent | a86bc9249f33bfd5701c861383a543279a12c23b (diff) | |
| download | desktop-flake-a1678f084e757c5464d167a937ac06460d9529df.tar.gz desktop-flake-a1678f084e757c5464d167a937ac06460d9529df.tar.bz2 desktop-flake-a1678f084e757c5464d167a937ac06460d9529df.zip | |
Added CLAUDE.md
Diffstat (limited to 'CLAUDE.md')
| -rw-r--r-- | CLAUDE.md | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..8223b54 --- /dev/null +++ b/CLAUDE.md | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | # CLAUDE.md | ||
| 2 | |||
| 3 | This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. | ||
| 4 | |||
| 5 | ## What this is | ||
| 6 | |||
| 7 | A single Nix flake that provisions both NixOS hosts and non-NixOS systems (any Linux, macOS via nix-darwin later) from one shared set of home-manager modules. Two users of the shared config exist: real NixOS machines (`nixosConfigurations`) and standalone home-manager-only machines (`homeConfigurations`). | ||
| 8 | |||
| 9 | ## Commands | ||
| 10 | |||
| 11 | - `nix fmt` — format all `.nix` files with `nixfmt-rfc-style`. | ||
| 12 | - `nix develop` — shell with `statix` and `deadnix` (linters) available. | ||
| 13 | - `nix flake check` — validates `homeConfigurations."tom@linux"`, `apps.bootstrap-host`, and other flake outputs. There are no real `nixosConfigurations` checked here unless a host has been scaffolded under `hosts/`. | ||
| 14 | - `nix eval '.#homeConfigurations."tom@linux".config.home.packages'` (or `"tom@darwin"`) — inspect the resolved package set for a given platform without building it. | ||
| 15 | - `nix build '.#homeConfigurations."tom@linux".activationPackage'` — build a standalone home-manager activation. | ||
| 16 | - `nix build '.#nixosConfigurations.<hostname>.config.system.build.toplevel'` — build a full NixOS system closure for an existing host directory. | ||
| 17 | - `nix run .#bootstrap-host -- <hostname> --root <path> --state-version <ver>` — scaffold `hosts/<hostname>/` from `hosts/template/` (see `scripts/bootstrap-host.sh --help`). This is the only supported way to add a new NixOS host; never hand-edit `flake.nix` to add one. | ||
| 18 | |||
| 19 | ## Architecture | ||
| 20 | |||
| 21 | **Host discovery is automatic.** Any directory under `hosts/` other than `hosts/template` that contains a `system` file becomes a real `nixosConfigurations.<name>` output (see `flake.nix`). `hosts/template/` is a copy-source only, excluded by name, and is never built directly — `scripts/bootstrap-host.sh` copies it into a new `hosts/<hostname>/`. | ||
| 22 | |||
| 23 | **`lib/mkNixos.nix` and `lib/mkHome.nix`** are the two entry points that turn a hostname/username into a flake output: | ||
| 24 | - `mkNixos` builds a `nixosSystem`: shared `modules/nixos/common.nix` + the host's own `hosts/<hostname>/configuration.nix` + the home-manager NixOS module (wired with `useGlobalPkgs`/`useUserPackages`, importing each user's `users/<name>.nix`). | ||
| 25 | - `mkHome` builds a standalone `homeManagerConfiguration` from just `users/<username>.nix` — no NixOS involved. | ||
| 26 | - Both apply the same `nixpkgs.config.allowUnfreePredicate`, sourced from `lib/unfree-allowlist.nix` (a flat list of package names — add unfree packages here, never flip `allowUnfree = true` globally). | ||
| 27 | |||
| 28 | **`modules/home/` is the shared, cross-platform profile** — the same modules are consumed whether activated via a NixOS host's home-manager integration or a standalone `home-manager switch`. Because of this dual use, any module that needs to know whether it's running on a real NixOS/GNOME system (vs. a bare Linux or macOS home-manager-only box) must not assume Linux implies NixOS or GNOME: | ||
| 29 | - Platform-only differences (`pkgs.stdenv.hostPlatform.isLinux`/`isDarwin`) are fine and used throughout (see `modules/home/dotfiles.nix`'s `platformDefaultExcludes`, `modules/home/desktop-apps.nix`'s `linuxOnlyApps`). | ||
| 30 | - Package availability differences are handled via `lib.meta.availableOn pkgs.stdenv.hostPlatform`, filtered over a candidate list (`modules/home/desktop-apps.nix`) — this lets an unsupported platform's package silently drop out rather than fail evaluation. | ||
| 31 | - Anything that actually depends on NixOS-level config (e.g. whether GNOME is enabled) must read the `osConfig` special arg, which home-manager's NixOS integration sets to the full NixOS `config` — but which is absent when a module is evaluated standalone via `mkHome`. Modules that reference it need `osConfig ? null` in their argument list and should treat a missing/false value as "not applicable" rather than erroring. | ||
| 32 | |||
| 33 | **`modules/nixos/common.nix`** holds everything applied unconditionally to every NixOS host: flakes enabled, the `tom` user (SSH keys pinned as a static literal, not fetched at build time), locale/timezone defaults (`mkDefault`, so a host can override), nix gc policy, sshd (key-only auth, firewall open only on 22), and the GNOME desktop stack (GDM, NetworkManager, PipeWire/rtkit, CUPS+Avahi). Per-host files under `hosts/<name>/configuration.nix` layer on top of this, not instead of it. | ||
| 34 | |||
| 35 | **`users/<name>.nix`** is the identity/profile file consumed by both `mkNixos` (as a home-manager user module) and `mkHome` (as the top-level module) — it's the one place that's the same regardless of which entry point is used. | ||
| 36 | |||
| 37 | **Personal dotfiles integration** (`modules/home/dotfiles.nix`) is opt-in via `home.dotfiles.repoUrl`. When set, it clones a separate personal dotfiles git repo to `~/dotfiles` and GNU-Stow-symlinks every top-level, non-hidden directory into `$HOME`, skipping platform-mismatched packages (built-in defaults in `platformDefaultExcludes`, plus anything listed in `home.dotfiles.excludePackages`) and skipping (with a warning, not a failure) any package whose target path conflicts with an existing file. An existing `~/dotfiles` checkout is never re-cloned or modified. Because `~/dotfiles/git/.gitconfig` and `~/dotfiles/bash/.bashrc` are the sole source of git/bash config once stowed, this repo's own `programs.git`/`programs.bash` home-manager management has been deliberately removed. | ||
| 38 | |||
| 39 | **Neovim** (`modules/home/editor.nix`) sets `programs.neovim.sideloadInitLua = true` specifically so home-manager never writes `~/.config/nvim/init.lua` — that path is owned exclusively by the dotfiles repo's `neovim` Stow package. Do not add `programs.neovim.extraConfig`/`plugins`/anything else that writes into `~/.config/nvim`; it will silently lose to the dotfiles automation's skip-on-conflict behavior and break plugin loading. | ||
| 40 | |||
| 41 | ## Planning changes with OpenSpec | ||
| 42 | |||
| 43 | This repo uses OpenSpec (`openspec/`) for structured change proposals: `openspec/specs/<capability>/spec.md` are the current-truth capability specs, `openspec/changes/` holds in-flight change proposals (proposal/specs-delta/design/tasks), and `openspec/changes/archive/` holds completed ones. Use the `openspec-propose` / `openspec-update-change` / `openspec-apply-change` / `openspec-archive-change` skills (or their `/opsx:*` equivalents) rather than hand-editing these — they keep proposal, delta spec, design, and tasks coherent and validate via `openspec validate`. Read `openspec/changes/archive/*/proposal.md` for examples of this project's expected proposal depth (verified license/platform facts, explicit non-goals, precise file-level impact). | ||
