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.
3.5 KiB
3.5 KiB
spec, blocked-by
| spec | blocked-by |
|---|---|
| laptop-mvi | 0001-skeleton-and-building-host |
What to build
Install Claude Code declaratively on neogaia, and make it authenticatable without a browser on the laptop so it can be used over the console/SSH via the paste-code flow or an API key.
Acceptance criteria
- Claude Code is installed declaratively (following the
Enable conventionif expressed as aModule) and enabled onneogaia. - The browserless authentication path (paste-code flow or API key) is documented so it works over console/SSH.
- The
neogaiatoplevel still builds with Claude Code included.
Implementation Notes
- Native home-manager module, not a raw package. Claude Code is enabled through home-manager's own
programs.claude-codemodule (home-manager.users.<user>.programs.claude-code.enable = true), mirroring howtmux/fishuse their native home-manager options rather than dropping a package intohome.packages. The module ships within home-manager itself, so — unlikenvim/nixvim — no new flake input is needed. Per the invocation's steer to prefer the tmux/nvim conventions over the task wording, the featureModuleatmodules/claude-code/claude-code.nixis kept as thin as thetmuxmodule: just theenableoption and the delegation. - No settings written. The module manages no
~/.claudecontents and writes nosettings.json, so login and first-run configuration stay interactive. This keeps auth material (subscription token or API key) out of the repo. - Auth docs co-located with the module. The browserless authentication guide lives at
modules/claude-code/authentication.md, next to the module, following the repo pattern where each module directory holds its own supporting files. It covers both the paste-code OAuth flow (open the printed URL on another device, paste the code back — works unchanged over SSH) and theANTHROPIC_API_KEYpath. This is distinct from task 0009's OS-install docs, which coverdisko-install, not the CLI login. - Verification.
nix build .#checks.x86_64-linux.neogaia(the primary Host seam) builds the toplevel withclaude-code-2.1.209included;config.modules.claude-code.enableand the home-managerprograms.claude-code.enableboth evaluatetrue. - Note on flake evaluation. The new module file had to be
git added before the flake could see it — flakes evaluate the git tree, so an untracked Module is invisible to the Auto-loader and the host errors with "option does not exist". - Personal config ported into the Module (beyond the acceptance criteria). At the operator's request the declarative half of
~/.claudenow lives in the Module and is applied when it is enabled: the global agent instructions (context = ./CLAUDE.md), the skills tree (skills = ./skills, 15 skills), the attention-bell hook (hooks."attention-bell.sh"), andsettings.json(model = "opus"plus the Stop/Notification/SessionStart hook wiring). Runtime state (projects/,plugins/,cache/,history.jsonl, sessions) and the~/.claude/.credentials.jsonsecret are deliberately left out, so login survives rebuilds and no secret enters the repo. Staleagents/commandssymlinks (into an outdated~/wrk/claude) were skipped. Verified against the builthome-files:~/.claude/{CLAUDE.md,settings.json,skills/,hooks/attention-bell.sh}are all generated, with the hook executable. Thegitea-axiSessionStart hook depends on that binary being onPATH; the flake does not yet provide it, so the hook is a no-op on a host until it is installed.