cc: extract hm odule

This commit is contained in:
Sridhar Ratnakumar 2025-11-10 20:10:05 -05:00
parent 35bd34a271
commit 9a64b12e32
3 changed files with 154 additions and 77 deletions

21
claude-code/README.md Normal file
View file

@ -0,0 +1,21 @@
# Srid's Claude Code Configuration
## Nix module
- `nix/home-manager-module.nix` - Home-manager module for auto-wiring this directory layout.
### Usage
Import the home-manager module and set `autoWire.dir`:
```nix
{
imports = [ ./claude-code/nix/home-manager-module.nix ];
programs.claude-code = {
enable = true;
autoWire.dir = ./claude-code;
};
}
```

View file

@ -0,0 +1,124 @@
{ config, lib, pkgs, ... }:
let
cfg = config.programs.claude-code;
# Auto-wire subagents from subagents/ directory
subagentsDir = cfg.autoWire.dir + "/subagents";
autoAgents = lib.optionalAttrs (builtins.pathExists subagentsDir)
(lib.mapAttrs'
(fileName: _:
lib.nameValuePair
(lib.removeSuffix ".md" fileName)
(builtins.readFile (subagentsDir + "/${fileName}"))
)
(builtins.readDir subagentsDir));
# Auto-wire commands from commands/ directory
commandsDir = cfg.autoWire.dir + "/commands";
autoCommands = lib.optionalAttrs (builtins.pathExists commandsDir)
(lib.mapAttrs'
(fileName: _:
lib.nameValuePair
(lib.removeSuffix ".md" fileName)
(builtins.readFile (commandsDir + "/${fileName}"))
)
(builtins.readDir commandsDir));
# Auto-wire skills from skills/ directory
skillsDir = cfg.autoWire.dir + "/skills";
skillDirs = lib.optionalAttrs (builtins.pathExists skillsDir)
(lib.filterAttrs (_: type: type == "directory") (builtins.readDir skillsDir));
# Process skill: if it has default.nix, build and substitute; otherwise use as-is
processSkill = skillName:
let
skillPath = skillsDir + "/${skillName}";
hasDefaultNix = builtins.pathExists (skillPath + "/default.nix");
in
if hasDefaultNix then
let
skillPkg = pkgs.callPackage skillPath { };
in
pkgs.runCommand "${skillName}-skill" { } ''
mkdir -p $out
substitute ${skillPath}/SKILL.md $out/SKILL.md \
--replace-fail '@${skillName}@' '${skillPkg}/bin/${skillName}'
''
else
skillPath;
# Auto-wire MCP servers from mcp/ directory
mcpDir = cfg.autoWire.dir + "/mcp";
autoMcpServers = lib.optionalAttrs (builtins.pathExists mcpDir)
(lib.mapAttrs'
(fileName: _:
lib.nameValuePair
(lib.removeSuffix ".nix" fileName)
(import (mcpDir + "/${fileName}"))
)
(builtins.readDir mcpDir));
# Auto-load settings from settings.nix
settingsFile = cfg.autoWire.dir + "/settings.nix";
autoSettings = lib.optionalAttrs (builtins.pathExists settingsFile)
(import settingsFile);
# Auto-load memory from memory.md
memoryFile = cfg.autoWire.dir + "/memory.md";
autoMemory = lib.optionalAttrs (builtins.pathExists memoryFile)
{ text = builtins.readFile memoryFile; };
in
{
options.programs.claude-code = {
autoWire = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Whether to automatically wire up subagents, commands, skills, and MCP servers from autoWire.dir.
Set to false if you want to manually configure these.
'';
};
dir = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
description = ''
Path to the claude-code directory containing subagents/, commands/, skills/, mcp/, settings.nix, and memory.md.
When set, these will be automatically discovered and configured.
'';
};
};
};
config = lib.mkIf (cfg.enable && cfg.autoWire.dir != null && cfg.autoWire.enable) {
# Link skill directories to ~/.claude/skills/
home.file = lib.mapAttrs'
(skillName: _:
lib.nameValuePair ".claude/skills/${skillName}" {
source = processSkill skillName;
recursive = true;
}
)
skillDirs;
programs.claude-code = {
# Auto-wire settings if settings.nix exists
settings = lib.mkDefault autoSettings;
# Auto-wire memory if memory.md exists
memory = lib.mkDefault autoMemory;
# Auto-wire commands from commands/ directory
commands = lib.mkDefault autoCommands;
# Auto-wire agents from subagents/ directory
agents = lib.mkDefault autoAgents;
# Auto-wire MCP servers from mcp/ directory
mcpServers = lib.mkDefault autoMcpServers;
};
};
}

View file

@ -1,71 +1,15 @@
{ flake, pkgs, lib, ... }:
let
claudeCodeDir = flake.inputs.self + /claude-code;
subagentsDir = claudeCodeDir + "/subagents";
agents = lib.mapAttrs'
(fileName: _:
lib.nameValuePair
(lib.removeSuffix ".md" fileName)
(builtins.readFile (subagentsDir + "/${fileName}"))
)
(builtins.readDir subagentsDir);
commandsDir = claudeCodeDir + "/commands";
commands = lib.mapAttrs'
(fileName: _:
lib.nameValuePair
(lib.removeSuffix ".md" fileName)
(builtins.readFile (commandsDir + "/${fileName}"))
)
(builtins.readDir commandsDir);
skillsDir = claudeCodeDir + "/skills";
skillDirs = lib.filterAttrs (_: type: type == "directory") (builtins.readDir skillsDir);
# Process skill: if it has default.nix, build and substitute; otherwise use as-is
processSkill = skillName:
let
skillPath = skillsDir + "/${skillName}";
hasDefaultNix = builtins.pathExists (skillPath + "/default.nix");
in
if hasDefaultNix then
let
skillPkg = pkgs.callPackage skillPath { };
in
pkgs.runCommand "${skillName}-skill" { } ''
mkdir -p $out
substitute ${skillPath}/SKILL.md $out/SKILL.md \
--replace-fail '@${skillName}@' '${skillPkg}/bin/${skillName}'
''
else
skillPath;
mcpDir = claudeCodeDir + "/mcp";
mcpServers = lib.mapAttrs'
(fileName: _:
lib.nameValuePair
(lib.removeSuffix ".nix" fileName)
(import (mcpDir + "/${fileName}"))
)
(builtins.readDir mcpDir);
in
{ flake, pkgs, ... }:
{
# Packages often used by Claude Code CLI.
# Import the general home-manager module
imports = [
../../../claude-code/nix/home-manager-module.nix
];
# Packages often used by Claude Code CLI
home.packages = with pkgs; [
tree
];
# Link skill directories to ~/.claude/skills/
# (home-manager module doesn't support skills yet, so we link manually)
home.file = lib.mapAttrs'
(skillName: _:
lib.nameValuePair ".claude/skills/${skillName}" {
source = processSkill skillName;
recursive = true;
}
)
skillDirs;
programs.claude-code = {
enable = true;
@ -75,19 +19,7 @@ in
then flake.inputs.self.packages.${pkgs.system}.claude # see claude-sandboxed.nix
else pkgs.claude-code;
# Basic settings for Claude Code
settings = import (claudeCodeDir + "/settings.nix");
# System prompt / memory
memory.text = builtins.readFile (claudeCodeDir + "/memory.md");
# Automatically discovered commands from commands/ directory
commands = commands;
# Automatically discovered agents from subagents/ directory
agents = agents;
# Automatically discovered MCP servers from mcp/ directory
mcpServers = mcpServers;
# Set the claude-code directory for auto-wiring
autoWire.dir = ../../../claude-code;
};
}