Add gitea-axi as a flake input and a new modules.gitea-axi module that
installs the CLI through its home-manager module. That module also declares
the Claude Code context — the Agent Skill and the SessionStart dashboard hook
— when claude-code is enabled on the host, so neogaia gets both while a host
without the harness would get the CLI alone.
Drop the hand-written SessionStart hook from the claude-code module, which
named a gitea-axi binary nothing installed; the gitea-axi module owns it now.
Remove the vendored skill fork, which had drifted from upstream and would
collide with the copy the module writes.
The access policy was a separate fleet declaration mapping each machine to a
role and a client key, which the module looked up by hostname to derive what to
authorize. Authorizing a key needs the key text and nothing else, so the
per-machine names, the hostname lookup and the role existed only to reconstruct
a grouping that two lists already are.
The module now exposes those two lists and the set a machine admits, and a host
declares what it draws from in its own file. The fleet declaration is gone, and
with it a single-file directory at the repository root.
`authorizedKeys` defaults to the workstation keys. An option of a list type is
not mandatory the way a scalar one is: undeclared, it yields the empty list
rather than failing, and a machine admitting no key is unreachable. The default
makes the safe case the silent one.
Verified to produce the same system as the design it replaces, and against the
running machine in both directions.
Also note that `git config --global` lists only ~/.gitconfig and is not a
view of what git resolves, which misreads as the module's file being
ignored.
Defaulting the module on hid it from a host's config, leaving no single
place that lists what a host carries. Each host enables it explicitly
instead, at the cost of a step when adding one.
Default the module on rather than restating it per host, so a new host
commits without remembering the line. A host that should not carry a
personal identity sets enable to false.
Git identity lived only in one checkout's local configuration on one
machine, so it was invisible to every other checkout and lost on a
reimage. Declare it as a module instead, enabled on neogaia.
It is a module rather than base plumbing so a host that should not carry
a personal commit identity can decline it.
The sops secret declarations, the empty `hostKeys`, and the `HostKey`
lines were boilerplate sitting in the host, and every future host
restoring its identity would have repeated them.
`modules.ssh` takes the encrypted file and the key types, deriving the
secret names and the `HostKey` lines from one list, so the daemon and the
secrets cannot disagree about where a key lives. The resulting system
derivation is unchanged.
Also record two gotchas: reading PR review comments needs the Gitea API
rather than tea, and host keys are not user authentication keys.
Wire sops-nix into the shared base config as unconditional plumbing, with
a two-tier age identity model: an admin identity held outside the repo, and
a per-host identity generated on the machine and kept on its encrypted root.
Both `sshKeyPaths` defaults are cleared so the SSH host keys stay out of the
decryption path and remain free to become secrets in their own right.
The primary user's password hash moves into a shared secrets file encrypted
to admin plus neogaia, consumed through `hashedPasswordFile` and decrypted
before accounts are created.
This needs `users.mutableUsers = false`: NixOS applies a declared hash to an
already-existing account only when that flag is false, so at the default the
hand-set password would have been kept and the change would have been inert.
Root consequently has no password and is locked; sudo from wheel is the way
in, and generation rollback remains the recovery path.
Key sudo's credential cache per user rather than per terminal, holding it
for 60 minutes. An authentication made in the operator's own terminal then
covers commands issued by processes holding no terminal of their own, which
previously failed with a bare non-zero exit and no output.
No command is made passwordless. The password remains required; only the
cache holding it is shared, and any process running as the primary user can
spend that credential until it lapses.
A PreToolUse hook refuses a privileged command while the cache is cold,
naming the command that warms it, so the condition announces itself rather
than presenting as a stall. Both states were exercised against the running
system.
The reimage is done and verified on hardware: the boot partition is 2 GiB
and reports it, the hardware profile's kernel parameter and module blacklist
are live, and the encrypted root unlocks to a console login.
The install procedure ran without divergence, which is the reproducibility
evidence the task was after.
The reimage also wiped the hand-written git identity, so the gotcha
describing it is updated to record the failure it now provokes.
Each generation stores a kernel and an initrd on the EFI system partition,
and this host runs a large third-party kernel, so 512 MiB holds only about
seven. An exhausted partition fails at bootloader installation, after the
build has already succeeded.
The partition cannot grow in place: it sits first on the disk with the
encrypted container immediately behind it, and an encrypted volume's start
offset cannot move without rewriting its whole payload. Only an install
applies this layout, so the change takes effect at the next reimage and
does nothing to the running machine until then.
Record that a flake only sees git-tracked files, which cost an evaluation
earlier, and correct the git identity gotcha that a hand-written gitconfig
had made false.
No gitea-axi, tea or gh exists on the NixOS build, and there is no tea
login or GITEA_* environment to authenticate with. The flake names
gitea-axi only in the claude-code module's permissions and never packages
it, so pull requests cannot be opened from this machine.
The previous wording described the laptop while it still ran CachyOS with
these tools installed by hand.
The dev host no longer runs CachyOS, so the per-command experimental-features
export and the from-source CachyOS kernel build no longer apply. Records the
missing git identity in their place.
~/.claude/skills is generated by home-manager: the directories are real
but every leaf file is a read-only symlink into the store. The skills
that author and install skills assumed it was an ordinary writable tree.
- craft-skill: personal skills are authored in modules/claude-code/skills
and applied by a rebuild, never edited under ~/.claude/skills; writing
there succeeds silently and strands the skill outside the repo.
- setup-skills, update-skills: copy out of the library with cp -rL and
chmod -R u+w. A plain cp -r copies the symlinks, committing store paths
into the project, and dereferenced files keep the store's read-only mode.
- craft-skill also staged through `dot add`, a fish function this repo no
longer carries; plain git add replaces it.
The Gotchas entry named `tea` as the CLI for issue and pull-request work.
`gitea-axi` supersedes it; `tea` stays installed only to hold the `axi`
login that `gitea-axi` authenticates from.
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.
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.
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.
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.
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.
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).