{ config, lib, pkgs, ... }: with lib; let cfg = config.services.ai-skills; skillsList = '' Available skills: - niri-window-capture: Invisibly capture window screenshots - screenshot-latest: Find latest screenshots - tufte-press: Generate study card JSON - worklog: Create org-mode worklogs - update-spec-kit: Update spec-kit ecosystem - update-opencode: Update OpenCode via Nix - web-search: Search the web via Claude - web-research: Deep web research with multiple backends ''; in { options.services.ai-skills = { enable = mkEnableOption "AI agent skills for Claude Code and OpenCode"; skillsPath = mkOption { type = types.path; default = null; description = "Path to skills repository (e.g., ~/proj/skills/skills)"; }; # Per-target skill lists claudeCodeSkills = mkOption { type = types.listOf types.str; default = []; description = "Skills to deploy to Claude Code (~/.claude/skills/). ${skillsList}"; example = [ "worklog" "niri-window-capture" ]; }; openCodeSkills = mkOption { type = types.listOf types.str; default = []; description = "Skills to deploy to OpenCode (~/.config/opencode/skills/). ${skillsList}"; example = [ "worklog" "web-search" ]; }; }; config = mkIf cfg.enable { home.file = mkMerge [ # Claude Code skills (mkIf (cfg.claudeCodeSkills != []) ( builtins.listToAttrs ( map (skillName: { name = ".claude/skills/${skillName}"; value = { source = "${cfg.skillsPath}/${skillName}"; recursive = true; }; }) cfg.claudeCodeSkills ) )) # OpenCode skills (mkIf (cfg.openCodeSkills != []) ( builtins.listToAttrs ( map (skillName: { name = ".config/opencode/skills/${skillName}"; value = { source = "${cfg.skillsPath}/${skillName}"; recursive = true; }; }) cfg.openCodeSkills ) )) ]; }; }