docs(plan): mibook claude-code module implementation plan
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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-<version>`
|
||||
|
||||
- [ ] **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`.
|
||||
Reference in New Issue
Block a user