From 35f4821bc5cfbeec61a6970fc8ed0d8900713960 Mon Sep 17 00:00:00 2001 From: "sascha.koenig" Date: Mon, 20 Apr 2026 08:58:15 +0200 Subject: [PATCH] refactor: centralize agent skills at ~/.agents/skills --- .../home-manager/coding/agents/default.nix | 29 ++++++++++++ .../home-manager/coding/agents/opencode.nix | 14 ------ modules/home-manager/coding/agents/pi.nix | 44 ++++++++----------- 3 files changed, 48 insertions(+), 39 deletions(-) diff --git a/modules/home-manager/coding/agents/default.nix b/modules/home-manager/coding/agents/default.nix index 681a47a..c0e3180 100644 --- a/modules/home-manager/coding/agents/default.nix +++ b/modules/home-manager/coding/agents/default.nix @@ -1,10 +1,39 @@ # Per-tool agent sub-modules # Each module handles rendering canonical agent.toml definitions # for a specific AI coding tool. +# +# Also provides the shared coding.agents.skills submodule that writes +# ~/.agents/skills — the central skills directory used by Pi, OpenCode, etc. { + config, + lib, + pkgs, + ... +}: let + shared = import ./shared-options.nix {inherit lib;}; + cfg = config.coding.agents.skills; + mkIf = lib.mkIf; +in { imports = [ ./opencode.nix ./claude-code.nix ./pi.nix ]; + + options.coding.agents.skills = { + agentsInput = shared.mkAgentsInputOption '' + The `agents` flake input (your personal AGENTS repo). + When set, skills are symlinked to ~/.agents/skills. + ''; + + externalSkills = shared.externalSkillsOption; + }; + + config = mkIf (cfg.agentsInput != null) { + home.file.".agents/skills".source = cfg.agentsInput.lib.mkOpencodeSkills { + inherit pkgs; + customSkills = "${cfg.agentsInput}/skills"; + externalSkills = shared.mapExternalSkills cfg.externalSkills; + }; + }; } diff --git a/modules/home-manager/coding/agents/opencode.nix b/modules/home-manager/coding/agents/opencode.nix index ef99aa6..2f9ac77 100644 --- a/modules/home-manager/coding/agents/opencode.nix +++ b/modules/home-manager/coding/agents/opencode.nix @@ -17,8 +17,6 @@ in ''; modelOverrides = shared.mkModelOverridesOption; - - externalSkills = shared.externalSkillsOption; }; config = mkIf config.coding.agents.opencode.enable { @@ -34,18 +32,6 @@ in }; }; - # Skills (merged from personal AGENTS repo + optional external skills) - xdg.configFile."opencode/skills" = let - cfg = config.coding.agents.opencode; - in - mkIf (cfg.agentsInput != null) { - source = cfg.agentsInput.lib.mkOpencodeSkills { - inherit pkgs; - customSkills = "${cfg.agentsInput}/skills"; - externalSkills = shared.mapExternalSkills cfg.externalSkills; - }; - }; - # Static config dirs from AGENTS repo xdg.configFile."opencode/context" = let cfg = config.coding.agents.opencode; diff --git a/modules/home-manager/coding/agents/pi.nix b/modules/home-manager/coding/agents/pi.nix index d56f572..9c5bab6 100644 --- a/modules/home-manager/coding/agents/pi.nix +++ b/modules/home-manager/coding/agents/pi.nix @@ -15,7 +15,10 @@ in mcpServers = mkOption { type = types.attrsOf types.anything; - default = if mcpCfg != null then mcpCfg.servers else {}; + default = + if mcpCfg != null + then mcpCfg.servers + else {}; defaultText = literalExpression "config.programs.mcp.servers"; description = '' MCP server configurations for Pi (pi-mcp-adapter). @@ -41,8 +44,6 @@ in ''; }; - externalSkills = shared.externalSkillsOption; - settings = mkOption { type = types.submodule { freeformType = types.attrsOf types.anything; @@ -156,8 +157,11 @@ in then let filtered = filterNulls v; in - if filtered == {} then null else filtered - else v) attrs + if filtered == {} + then null + else filtered + else v) + attrs ); piSettings = filterNulls cfg.settings; @@ -177,17 +181,16 @@ in # Dynamic home.file entries for agent .md files agentFiles = if cfg.agentsInput != null - then - let - agentNames = builtins.attrNames cfg.agentsInput.lib.loadAgents; - in - builtins.listToAttrs ( - map (name: { - name = ".pi/agent/agents/${name}.md"; - value = {source = "${rendered}/agents/${name}.md";}; - }) - agentNames - ) + then let + agentNames = builtins.attrNames cfg.agentsInput.lib.loadAgents; + in + builtins.listToAttrs ( + map (name: { + name = ".pi/agent/agents/${name}.md"; + value = {source = "${rendered}/agents/${name}.md";}; + }) + agentNames + ) else {}; in { home.file = mkMerge [ @@ -213,15 +216,6 @@ in # ── Agents — pi-subagents .md files ──────────────────────────── agentFiles - - # ── Skills symlinked from AGENTS repo + external skills ──────── - (mkIf (cfg.agentsInput != null) { - ".pi/agent/skills".source = cfg.agentsInput.lib.mkOpencodeSkills { - inherit pkgs; - customSkills = "${cfg.agentsInput}/skills"; - externalSkills = shared.mapExternalSkills cfg.externalSkills; - }; - }) ]; }); }