# 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`.