diff --git a/docs/superpowers/plans/2026-05-25-mibook-claude-code.md b/docs/superpowers/plans/2026-05-25-mibook-claude-code.md new file mode 100644 index 0000000..40e9ee3 --- /dev/null +++ b/docs/superpowers/plans/2026-05-25-mibook-claude-code.md @@ -0,0 +1,232 @@ +# MiBook Claude Code Module Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add a `my.profiles.claude-code` NixOS module that installs the Claude Code CLI and companion tooling on the MiBook. + +**Architecture:** A single new environment module (`modules/environments/claude-code/default.nix`) declares the `my.profiles.claude-code.enable` option and installs packages for user `finn`. It is registered in `modules/environments/default.nix` and toggled on in `machines/mibook/environments.nix`. + +**Tech Stack:** Nix flakes, NixOS module system, `pkgs.unstable` overlay (already present in repo) + +--- + +## File Map + +| Action | Path | Responsibility | +|---|---|---| +| Create | `modules/environments/claude-code/default.nix` | Declares option + installs packages | +| Modify | `modules/environments/default.nix` | Registers the new module so NixOS loads it | +| Modify | `machines/mibook/environments.nix` | Enables the profile for the MiBook host | + +--- + +### Task 1: Verify `claude-code` exists in `nixpkgs-unstable` + +**Files:** +- Read-only check — no file changes + +- [ ] **Step 1: Check if the package is available** + +Run: +```bash +nix eval --extra-experimental-features 'nix-command flakes' 'github:NixOS/nixpkgs/nixos-unstable#claude-code.version' 2>&1 +``` + +Expected (success): prints a version string like `"0.2.x"` + +Expected (failure): `error: attribute 'claude-code' missing` + +- [ ] **Step 2: If the package exists — note the attribute path and continue to Task 2** + +The module will use `pkgs.unstable.claude-code`. + +- [ ] **Step 3: If the package does NOT exist — add a custom derivation first** + +Create `pkgs/claude-code/default.nix`: +```nix +{ lib, buildNpmPackage, fetchFromGitHub }: +buildNpmPackage rec { + pname = "claude-code"; + version = "0.2.116"; # update to latest release tag + + src = fetchFromGitHub { + owner = "anthropics"; + repo = "claude-code"; + rev = "v${version}"; + hash = lib.fakeHash; # run nix build to get real hash + }; + + npmDepsHash = lib.fakeHash; # run nix build to get real hash + + meta = { + description = "Claude Code CLI by Anthropic"; + homepage = "https://github.com/anthropics/claude-code"; + license = lib.licenses.unfree; + mainProgram = "claude"; + }; +} +``` + +Then register it in `pkgs/default.nix`: +```nix +final: prev: { + claude-code = final.callPackage ./claude-code { }; +} +``` + +And use `pkgs.claude-code` (not `pkgs.unstable.claude-code`) in the module. + +--- + +### Task 2: Create the `claude-code` module + +**Files:** +- Create: `modules/environments/claude-code/default.nix` + +- [ ] **Step 1: Create the module file** + +Create `modules/environments/claude-code/default.nix` with this exact content: +```nix +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.my.profiles.claude-code; +in +{ + options.my.profiles.claude-code = with lib; { + enable = mkEnableOption "Claude Code CLI"; + }; + + config = lib.mkIf cfg.enable { + users.users.finn.packages = with pkgs; [ + unstable.claude-code + ripgrep + fd + gh + jq + ]; + + # Future: headless Claude Code service + # A natural next step is exposing Claude Code as a persistent background service — + # e.g. a systemd user service that accepts work via an HTTP API or Unix socket, + # triggerable over SSH or a local network endpoint. This would turn the MiBook + # into a true remote execution node without requiring an interactive session. + # See: my.profiles.claude-code.service.enable (not yet implemented) + }; +} +``` + +> Note: if Task 1 Step 3 was taken (custom derivation), replace `unstable.claude-code` with `claude-code`. + +--- + +### Task 3: Register the module + +**Files:** +- Modify: `modules/environments/default.nix` + +- [ ] **Step 1: Add the import** + +In `modules/environments/default.nix`, add `./claude-code` to the imports list (alphabetical order puts it between `./audiobookshelf` and `./development`): + +```nix +{ ... }: +{ + imports = [ + ./actual + ./apps + ./audiobookshelf + ./claude-code + ./development + ./home-assistant + ./hyprland + ./zsh + ./paperless + ./prowlarr + ./radarr + ./docker + ./homepage + ./kde-desktop + ./readarr + ./sonarr + ./jellyfin + ./jellyseerr + ]; +} +``` + +- [ ] **Step 2: Verify the option is now defined (without enabling it)** + +Run: +```bash +nix eval --extra-experimental-features 'nix-command flakes' '.#nixosConfigurations.mibook.options.my.profiles.claude-code.enable.description' +``` + +Expected: `"Whether to enable Claude Code CLI."` + +If this errors, the module isn't loading — re-check the import path. + +--- + +### Task 4: Enable on MiBook and verify the build + +**Files:** +- Modify: `machines/mibook/environments.nix` + +- [ ] **Step 1: Enable the profile** + +In `machines/mibook/environments.nix`, add `claude-code.enable = true` inside the `my.profiles` block: + +```nix + my.profiles = { + kde-desktop.enable = true; + zsh.enable = true; + apps = { + desktop_apps = true; + dev_apps = true; + }; + development.enable = true; + docker.enable = true; + claude-code.enable = true; + }; +``` + +- [ ] **Step 2: Verify the package appears in finn's user packages** + +Run: +```bash +nix eval --extra-experimental-features 'nix-command flakes' '.#nixosConfigurations.mibook.config.users.users.finn.packages' --apply 'builtins.map (p: p.name)' 2>&1 | grep -i claude +``` + +Expected: a line containing `claude-code-` + +- [ ] **Step 3: Dry-run build to confirm the full config evaluates** + +Run: +```bash +nix build '.#nixosConfigurations.mibook.config.system.build.toplevel' --extra-experimental-features 'nix-command flakes' --dry-run 2>&1 | tail -5 +``` + +Expected: exits 0, output lists derivations to build (or "nothing to do" if already cached). No evaluation errors. + +--- + +### Task 5: Commit + +**Files:** +- All changed files from Tasks 1–4 + +- [ ] **Step 1: Stage and commit** + +```bash +git add modules/environments/claude-code/default.nix \ + modules/environments/default.nix \ + machines/mibook/environments.nix +git commit -m "feat(mibook): add claude-code profile module" +``` + +If Task 1 Step 3 was taken, also stage `pkgs/claude-code/default.nix` and `pkgs/default.nix`.