Files
dotfiles/.claude/tasks/0008-claude-code-module.md
alexion 20e968c709 Manage the user's global Claude config in the Module (task 0008)
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

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 convention if expressed as a Module) and enabled on neogaia.
  • The browserless authentication path (paste-code flow or API key) is documented so it works over console/SSH.
  • The neogaia toplevel 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-code module (home-manager.users.<user>.programs.claude-code.enable = true), mirroring how tmux/fish use their native home-manager options rather than dropping a package into home.packages. The module ships within home-manager itself, so — unlike nvim/nixvim — no new flake input is needed. Per the invocation's steer to prefer the tmux/nvim conventions over the task wording, the feature Module at modules/claude-code/claude-code.nix is kept as thin as the tmux module: just the enable option and the delegation.
  • No settings written. The module manages no ~/.claude contents and writes no settings.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 the ANTHROPIC_API_KEY path. This is distinct from task 0009's OS-install docs, which cover disko-install, not the CLI login.
  • Verification. nix build .#checks.x86_64-linux.neogaia (the primary Host seam) builds the toplevel with claude-code-2.1.209 included; config.modules.claude-code.enable and the home-manager programs.claude-code.enable both evaluate true.
  • 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 ~/.claude now 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"), and settings.json (model = "opus" plus the Stop/Notification/SessionStart hook wiring). Runtime state (projects/, plugins/, cache/, history.jsonl, sessions) and the ~/.claude/.credentials.json secret are deliberately left out, so login survives rebuilds and no secret enters the repo. Stale agents/commands symlinks (into an outdated ~/wrk/claude) were skipped. Verified against the built home-files: ~/.claude/{CLAUDE.md,settings.json,skills/,hooks/attention-bell.sh} are all generated, with the hook executable. The gitea-axi SessionStart hook depends on that binary being on PATH; the flake does not yet provide it, so the hook is a no-op on a host until it is installed.