Compare commits

..

30 Commits

Author SHA1 Message Date
064971f601 docs: adopt Conventional Commits for commit messages
Vendor the v1.0.0 specification as docs/conventional-commits.md and record
the convention in CLAUDE.md: type and optional scope, where the scope names
the module or host, and no Gitea-specific references, since this repository
is mirrored to GitHub where issue and pull-request numbers resolve to
unrelated things.
2026-07-19 08:24:54 -04:00
41709bb977 chore!: remove the pre-NixOS dotfiles tree
The flake and its modules now own every config these files provided;
they remain in history for reference while the migration finishes.

BREAKING CHANGE: `.config/`, `.gitconfig`, and `.github/` no longer exist
at the repository root. A checkout that deploys this tree into `$HOME`
will delete the live configs it previously installed.
2026-07-19 08:01:49 -04:00
77e853ab49 docs: rewrite the in-file comment convention
Encode the sharpened ruleset: why-over-what, self-containment, the
absence-only cross-file exception, no domain-glossary terms, no
against-alternative or future-state framing, one-line file headers,
placeholder wording, and how option description strings differ.
2026-07-19 07:57:44 -04:00
6a10f760cf refactor(lib): remove the unused scriptFromFile helper
It had no callers; the built system's derivation is unchanged by its
removal.
2026-07-19 07:57:44 -04:00
91d0a7d8e4 style: trim verbose comments to concise, self-contained notes
Cut restated "what", domain-glossary framing, cross-file consumption
narration, and against-alternative justification from in-file comments;
keep only non-obvious "why" and load-bearing pointers. Drop the
`generateCompletions` line (a no-op restatement of the upstream default)
and its comment.
2026-07-19 07:57:44 -04:00
7810425849 docs(neogaia): document the one-shot install flow
Add docs/install.md, the operator runbook that turns the completed
neogaia Host into a running encrypted laptop from the NixOS live ISO:
push the flake to its remote, join wifi, clone the repo locally,
disko-install against neogaia with the chaotic substituter handed to the
install-time daemon, set the bootstrap login password by hand via
nixos-enter, and reboot.
2026-07-19 07:57:43 -04:00
b7363ed7e1 feat(claude-code): manage the user's global config in the Module
Bring the declarative half of ~/.claude into modules/claude-code and apply
it when the Module is enabled: the global agent instructions (context =
./CLAUDE.md), the skills tree (skills = ./skills), the attention-bell hook,
and settings.json (model = opus plus the Stop/Notification/SessionStart
hook wiring).

Runtime state (projects, plugins, cache, history, sessions) and the
.credentials.json secret are left out, so login survives rebuilds and no
secret enters the repo. Verified against the built home-files that
~/.claude/{CLAUDE.md,settings.json,skills,hooks/attention-bell.sh} are
generated, the hook executable.
2026-07-19 07:57:43 -04:00
505002bb2b feat(claude-code): add a Module and enable it on neogaia
Install Claude Code through home-manager's native programs.claude-code
module, matching how the tmux and fish Modules use their home-manager
options rather than a raw home.packages entry. The feature Module at
modules/claude-code/claude-code.nix stays thin — just the enable option
and the delegation — and writes no settings, so login and first-run
configuration remain interactive and no auth material enters the repo.

Signing in without a browser (needed over the console or SSH) is
documented in modules/claude-code/authentication.md: the paste-code OAuth
flow, where the printed URL is opened on another device and the code
pasted back, and the ANTHROPIC_API_KEY path for non-interactive use.

The neogaia toplevel builds with claude-code-2.1.209 included.
2026-07-19 07:57:43 -04:00
6f9309d329 feat(nvim): configure Neovim via nixvim with Nix-managed plugins
Add an nvim Module that configures Neovim declaratively through nixvim,
wired as a flake input and consumed as its home-manager module. Options,
globals, keymaps, and plugin settings are typed Nix; the colorscheme
call and two autocmds live in modules/nvim/config.lua via extraConfigLua.
Plugins come from nixpkgs (no plugin manager, no runtime cloning); git,
ripgrep, and fd are provided from Nix; treesitter grammars are built by
Nix so no runtime compiler is needed.

Functionally matches the previous config (plugins, keymaps, options, the
nord colorscheme, markdown conceal, the Neogit blame toggle), verified
headless against the generated init.
2026-07-19 07:57:43 -04:00
98fecc314f chore: untrack the reference/ snapshot and gitignore it
reference/ is a read-only snapshot of the pre-migration machine, kept
locally for porting configs but not part of the flake. Stop tracking it
and ignore it so migrations don't churn the repo.
2026-07-19 07:57:43 -04:00
80d1587189 feat(tmux): add a native Module and enable it on neogaia
Configure tmux through home-manager's programs.tmux: the settings it exposes
as options (prefix, keyMode, mouse, baseIndex, clock24, escapeTime,
historyLimit, terminal) are set as options, and every setting it has no option
for is read verbatim from modules/tmux/extra.conf. No tmux plugin manager is
used. The generated config is behaviourally identical to the reference, verified
by parsing it with a live tmux binary.
2026-07-19 07:57:21 -04:00
7e53ecd946 style(fish): split the plugin comment and drop a redundant one 2026-07-19 07:57:21 -04:00
2d6eb929d7 refactor(fish): merge the config fragments back into one config.fish
The interactive init is small; four fragment files was over-splitting it.
Keep the mechanic (a real fish file inlined by Nix into config.fish) but
merge the fragments into a single modules/fish/config.fish read with
builtins.readFile. Rendered config is unchanged.
2026-07-19 07:57:21 -04:00
f54d0460ad refactor(fish): split config.fish into fragments concatenated by Nix
Break the interactive init into concern-scoped fish files under
modules/fish/config/ (bindings, env, done, path) and assemble them with
lib.concatMapStringsSep + readFile into a single interactiveShellInit, so
home-manager still writes one ~/.config/fish/config.fish. The pieces stay
editable as separate fish files; the rendered file is unchanged.
2026-07-19 07:57:21 -04:00
95869fb11f refactor(fish): assemble the interactive init in Nix, not at runtime
Fold the done plugin tuning back into config.fish and drop the conf.d
fragment: config.fish is read whole into interactiveShellInit, so Nix
assembles the interactive init at build time instead of fish autoloading
a separate conf.d file. functions/copy.fish stays a function file, the
idiomatic home for a lazily-autoloaded function.
2026-07-19 07:57:21 -04:00
5a89d4addb refactor(fish): lay the Module out like ~/.config/fish
Move the Module to modules/fish/fish.nix and mirror a real fish config
directory beside it: config.fish (interactive init), conf.d/done.fish
(the done plugin tuning, now a real conf.d file), and functions/copy.fish.
completions/ and themes/ are omitted as they have no content and git
cannot track empty directories.
2026-07-19 07:57:21 -04:00
b91e434c87 docs(fish): record the file-extraction in the project notes 2026-07-19 07:57:21 -04:00
16f29bd64a refactor(fish): read the non-trivial snippets from files
Move the interactiveShellInit block and the copy function body into
modules/fish/*.fish and pull them in with builtins.readFile, so the
non-trivial fish lives in real fish files (highlighting, fish_indent)
instead of inline Nix strings. The Auto-loader only collects .nix, so
the new .fish files are ignored by it. Rendered config is unchanged.
2026-07-19 07:57:21 -04:00
9eb0fe797a feat(fish): gate the default shell and prefer abbreviations
Move the login-shell switch behind a new modules.fish.defaultShell
option (default false; neogaia opts in). Convert every non-eza alias to
an abbreviation, set preferAbbrs and pin generateCompletions, and switch
the command line to vi-style editing. Cap navigation at four dots and
drop psmem/psmem10/dir/vdir/please. Comment the installed packages.
2026-07-19 07:57:21 -04:00
8346d63e64 feat(fish): add a native Module and set it as neogaia's login shell
Translate the CachyOS fish snapshot into a home-manager Module: the
fastfetch greeting, the bat-backed manpager, the done and bang-bang
plugins (from nixpkgs, not a plugin manager), the history/backup/copy
helper functions, and the eza and navigation aliases. Pacman-specific
aliases are dropped or replaced with NixOS equivalents (update ->
nixos-rebuild switch, cleanup -> nix-collect-garbage). Enabling the
Module also makes fish the user's default login shell.
2026-07-19 07:57:21 -04:00
20f5b33e00 feat(neogaia): enable networking and set the base locale
Turn the booted laptop into a usable, remotely reachable console: enable
NetworkManager so wifi can be joined from the console and an SSH daemon so
the rest of the setup can be driven over the network. Set the base locale to
timezone America/New_York, locale en_GB.UTF-8, and console keymap us.

These live inline in the neogaia Host rather than behind enable Modules,
matching the single-Host MVI precedent; a shared locale/networking Module can
be extracted once a second Host needs the same settings. SSH keeps default
password auth on, as first-boot access relies on the hand-set bootstrap
password until key/sops-based auth lands post-install.
2026-07-19 07:57:21 -04:00
194d64dacd docs: require an agent sign-off on Gitea comments
Add a convention: comments posted to Gitea go out under the operator's
account, so sign each with a — Claude sign-off to attribute them to the agent.
2026-07-19 07:57:21 -04:00
8f83c3ca8c refactor(neogaia): drop the zram Module and enable zram inline
modules/zram.nix only wrapped the native zramSwap.enable toggle without
adding anything. Rewrite the touched comments to describe only the current
file content, and record the in-file-comment convention in CLAUDE.md.
2026-07-19 07:57:21 -04:00
053c4de529 feat(neogaia): add the CachyOS kernel and hardware enablement
Select the CachyOS kernel per-Host via boot.kernelPackages, enable Intel
microcode and redistributable firmware (ath10k for the QCA6174 wifi), and
move zram behind a toggle Module. Declare the chaotic binary cache in the
base Nix settings (extra-substituters/keys) so the built system fetches the
kernel from nyx-cache rather than compiling it.
2026-07-19 07:57:21 -04:00
bfc9e6f75b style(neogaia): scope the hardware comments to the current file state 2026-07-19 07:57:21 -04:00
da30375413 feat(neogaia): declare the encrypted disk with disko
Add disko as a flake input (following nixpkgs) and wire its NixOS module
into the host-builder, so any Host can declare a disk layout while the
layout itself stays a per-Host concern.

neogaia's layout (hosts/neogaia/disk.nix): one GPT NVMe disk with a
systemd-boot EFI system partition and a LUKS container holding btrfs with
@root/@home/@nix subvolumes. The initrd prompts for the passphrase on a
normal boot. Swap is RAM-backed zram, so there is no on-disk swap
partition; zramSwap is enabled directly for now. The placeholder
fileSystems are removed since disko now derives them.
2026-07-19 07:57:21 -04:00
cfe8d4ff9f style: scope in-file comments to the current file state
In-file comments should describe only what the file currently is, not task
numbers, external tooling, or past/future states.

- hosts/neogaia: drop the "replaced by disko" / "arrive later" framing;
  describe the filesystems and hardware profile as the placeholder values
  they are.
- lib: drop the "no null-placeholder traversal hack" comparison to a prior
  implementation.
- system: drop "no impure environment lookup" from the user.name description
  and the sops/post-boot roadmap from the user comment.
2026-07-19 07:57:21 -04:00
25e12f79de build(deps): pin the stable overlay and stateVersion to 26.05
26.05 is the latest stable NixOS release as of now (26.11 is still the
in-development branch that nixos-unstable reports); the previous 25.05 pin
was a release behind.

- flake.nix / flake.lock: stable overlay tracks nixos-26.05.
- neogaia system.stateVersion and the base home.stateVersion set to 26.05
  (fresh install, so aligning to the current stable release).
- Refresh the "latest stable release" references in the project docs to
  match.

Other inputs are rolling branches (nixos-unstable, nixpkgs-unstable,
chaotic nyxpkgs-unstable) or master (home-manager, per spec), so they carry
no version to bump.
2026-07-19 07:57:21 -04:00
9b36cfadd6 feat: build the Skeleton and a minimal neogaia Host
Stand up the walking skeleton the rest of the laptop MVI extends and
re-verifies against: the whole neogaia Host evaluates and its system
toplevel builds (nix flake check green).

- flake.nix: hand-rolled flake (no flake-parts). Base nixos-unstable, plus
  nixpkgs-unstable and nixos-25.05 for the per-package unstable/stable
  overlays, home-manager (nixpkgs followed), and chaotic-nyx (deliberately
  not following our nixpkgs, to keep its binary cache usable). checks build
  each Host toplevel.
- lib/: trimmed helper lib — the Auto-loader (recursive .nix discovery, no
  null-placeholder hack), the host-builder, and the script-from-file helper.
  Deps inherited explicitly; no with lib.my, no nixosModules output.
- system/: shared base config — the unstable/stable overlays, the user
  option (defaults to alexion, in wheel, drives system + home-manager user
  in lockstep), flakes, git, and home-manager as a NixOS module.
- modules/example.nix: Auto-loader / Enable-convention reference Module,
  inert until enabled.
- hosts/neogaia/: minimal laptop Host — placeholder filesystems, bootloader,
  and hardware profile.
- CLAUDE.md: project agent instructions with a Gotchas section (nix on the
  CachyOS dev host, the chaotic overlay/cache behaviour, the Gitea CLI).
2026-07-19 07:57:21 -04:00
d5b67947f9 docs: establish domain model, MVI spec, and environment reference
Capture the design work for the NixOS migration before any implementation:

- .claude/CONTEXT.md: domain glossary (Host, Module, Skeleton, Auto-loader,
  Enable convention, unstable/stable overlay)
- .claude/adr/0001-sops-nix-for-secrets.md: secrets tooling decision
- .claude/spec/laptop-mvi.md: frozen minimum-viable-install spec for neogaia

- reference/: read-only snapshot of the current CachyOS configs (secrets and
  state excluded), plus ENVIRONMENT.md profiling the live environment to guide
  replication
2026-07-19 07:57:21 -04:00
2 changed files with 60 additions and 0 deletions

View File

@@ -18,6 +18,9 @@ The domain model (Host, Module, Skeleton, Auto-loader, Enable convention, overla
- Comments posted to Gitea (pull requests, issues, reviews) go out under the operator's account, so sign every one to make clear the author is the agent, not the operator. - Comments posted to Gitea (pull requests, issues, reviews) go out under the operator's account, so sign every one to make clear the author is the agent, not the operator.
End the comment with a `— Claude` sign-off. End the comment with a `— Claude` sign-off.
(A dedicated bot account may replace this later; until then, the sign-off is the only marker.) (A dedicated bot account may replace this later; until then, the sign-off is the only marker.)
- Commit messages follow Conventional Commits, specified in `docs/conventional-commits.md`.
Scope is the module or host the change belongs to (`fish`, `nvim`, `neogaia`), omitted for repo-wide changes.
Keep messages free of Gitea-specific references: this repository is mirrored to GitHub, where issue and pull-request numbers resolve to unrelated things.
## Gotchas ## Gotchas

View File

@@ -0,0 +1,57 @@
# Conventional Commits
> Sourced from [conventionalcommits.org/en/v1.0.0](https://www.conventionalcommits.org/en/v1.0.0/)
> by the Conventional Commits authors, licensed under
> [CC BY 3.0](https://creativecommons.org/licenses/by/3.0/).
---
## Summary
The Conventional Commits specification is a lightweight convention on top of commit messages.
It provides an easy set of rules for creating an explicit commit history; which makes it easier to write automated tools on top of.
This convention dovetails with [SemVer](http://semver.org), by describing the features, fixes, and breaking changes made in commit messages.
The commit message should be structured as follows:
```
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
```
The commit contains the following structural elements, to communicate intent to the consumers of your library:
1. **fix:** a commit of the _type_ `fix` patches a bug in your codebase (this correlates with `PATCH` in Semantic Versioning).
2. **feat:** a commit of the _type_ `feat` introduces a new feature to the codebase (this correlates with `MINOR` in Semantic Versioning).
3. **BREAKING CHANGE:** a commit that has a footer with a token `BREAKING CHANGE:`, or appends a `!` after the type/scope, introduces a breaking API change (correlating with `MAJOR` in Semantic Versioning). A BREAKING CHANGE can be part of commits of any _type_.
4. _types_ other than `fix:` and `feat:` are allowed, for example `build:`, `chore:`, `ci:`, `docs:`, `style:`, `refactor:`, `perf:`, `test:`, and others.
5. _footers_ other than `BREAKING CHANGE: <description>` may be provided and follow a convention similar to [git trailer format](https://git-scm.com/docs/git-interpret-trailers).
Additional types are not mandated by the Conventional Commits specification, and have no implicit effect in Semantic Versioning (unless they include a BREAKING CHANGE).
A scope may be provided to a commit's type, to provide additional contextual information and is contained within parenthesis, e.g., `feat(parser): add ability to parse arrays`.
---
## Specification
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt).
1. Commits MUST be prefixed with a type, which consists of a noun, `feat`, `fix`, etc., followed by the OPTIONAL scope, OPTIONAL `!`, and REQUIRED terminal colon and space.
2. The type `feat` MUST be used when a commit adds a new feature to your application or library.
3. The type `fix` MUST be used when a commit represents a bug fix for your application.
4. A scope MAY be provided after a type. A scope MUST consist of a noun describing a section of the codebase surrounded by parenthesis, e.g., `fix(parser):`.
5. A description MUST immediately follow the colon and space after the type/scope prefix. The description is a short summary of the code changes, e.g., _fix: array parsing issue when multiple spaces were contained in string_.
6. A longer commit body MAY be provided after the short description, providing additional contextual information about the code changes. The body MUST begin one blank line after the description.
7. A commit body is free-form and MAY consist of any number of newline separated paragraphs.
8. One or more footers MAY be provided one blank line after the body. Each footer MUST consist of a word token, followed by either a `:<space>` or `<space>#` separator, followed by a string value (this is inspired by the [git trailer convention](https://git-scm.com/docs/git-interpret-trailers)).
9. A footer's token MUST use `-` in place of whitespace characters, e.g., `Acked-by` (this helps differentiate the footer section from a multi-paragraph body). An exception is made for `BREAKING CHANGE`, which MAY also be used as a token.
10. A footer's value MAY contain spaces and newlines, and parsing MUST terminate when the next valid footer token/separator pair is observed.
11. Breaking changes MUST be indicated in the type/scope prefix of a commit, or as an entry in the footer section.
12. If included as a footer, a breaking change MUST consist of the uppercase text `BREAKING CHANGE`, followed by a colon, space, and description, e.g., _BREAKING CHANGE: environment variables now take precedence over config files_.
13. If included in the type/scope prefix, breaking changes MUST be indicated by a `!` immediately before the `:`. If `!` is used, `BREAKING CHANGE:` MAY be omitted from the footer section, and the commit description SHALL be used to describe the breaking change.
14. Types other than `feat` and `fix` MAY be used in your commit messages, e.g., _docs: correct spelling of CHANGELOG_.
15. The units of information that make up Conventional Commits MUST NOT be treated as case sensitive by implementors, with the exception of BREAKING CHANGE which MUST be uppercase.
16. BREAKING-CHANGE MUST be synonymous with BREAKING CHANGE, when used as a token in a footer.