Compare commits

..

2 Commits

Author SHA1 Message Date
sascha.koenig
57ebad1358 refactor: remove legacy mkOpencodeRules alias and opencode-rules compat entry
- Remove mkOpencodeRules backward-compat alias from lib/coding-rules.nix
- Remove opencode-rules alias from lib/default.nix
- Update shells/opencode.nix to use mkCodingRules / coding-rules
- Remove backward-compat test from tests/lib/coding-rules-test.nix
- Update AGENTS.md and modules/home-manager/AGENTS.md docs
- Apply nix fmt formatting to shared-options.nix
2026-04-20 19:16:22 +02:00
sascha.koenig
35f4821bc5 refactor: centralize agent skills at ~/.agents/skills 2026-04-20 08:58:15 +02:00
11 changed files with 70 additions and 69 deletions

View File

@@ -126,12 +126,11 @@ Harness-agnostic agent management. Reads canonical `agent.toml` +
### `lib.coding-rules` ### `lib.coding-rules`
Coding rules injection. Generates `coding-rules.json` + symlinks rules from Coding rules injection. Generates `coding-rules.json` + symlinks rules from
the AGENTS repository. The old `lib.opencode-rules` name still works. the AGENTS repository.
| Function | Purpose | | Function | Purpose |
|----------|--------| |----------|--------|
| `mkCodingRules { agents, languages, concerns, frameworks, rulesDir }` | Generate rules config + shellHook. `rulesDir` defaults to `.opencode-rules` | | `mkCodingRules { agents, languages, concerns, frameworks, rulesDir }` | Generate rules config + shellHook. `rulesDir` defaults to `.opencode-rules` |
| `mkOpencodeRules` | Backward-compat alias for `mkCodingRules` |
## PORT MANAGEMENT ## PORT MANAGEMENT

View File

@@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
### Removed ### Removed
- Dead overlay entries for non-existent flake inputs - Dead overlay entries for non-existent flake inputs
- Legacy `mkOpencodeRules` alias and `lib.opencode-rules` backward-compat entry (use `mkCodingRules` / `lib.coding-rules`)
## [0.4.0] - 2026-04-15 ## [0.4.0] - 2026-04-15

View File

@@ -112,9 +112,6 @@
RULES_EOF RULES_EOF
''; '';
}; };
# Backward-compat alias
mkOpencodeRules = mkCodingRules;
in { in {
inherit mkCodingRules mkOpencodeRules; inherit mkCodingRules;
} }

View File

@@ -7,12 +7,9 @@
# Port management utilities # Port management utilities
ports = import ./ports.nix {inherit lib;}; ports = import ./ports.nix {inherit lib;};
# Coding rules injection utilities (renamed from opencode-rules) # Coding rules injection utilities
coding-rules = import ./coding-rules.nix {inherit lib;}; coding-rules = import ./coding-rules.nix {inherit lib;};
# Backward-compat alias: opencode-rules → coding-rules
opencode-rules = import ./coding-rules.nix {inherit lib;};
# Agent configuration management utilities # Agent configuration management utilities
agents = import ./agents.nix {inherit lib;}; agents = import ./agents.nix {inherit lib;};
} }

View File

@@ -163,7 +163,7 @@ The agent system was migrated from embedded `agents.json` to file-based canonica
| `coding.opencode.externalSkills` | `coding.agents.opencode.externalSkills` | | `coding.opencode.externalSkills` | `coding.agents.opencode.externalSkills` |
| Agents embedded in `config.json` | File-based `~/.config/opencode/agents/*.md` | | Agents embedded in `config.json` | File-based `~/.config/opencode/agents/*.md` |
| Model hardcoded in `agents.json` | Per-machine `modelOverrides` | | Model hardcoded in `agents.json` | Per-machine `modelOverrides` |
| `mkOpencodeRules` | `mkCodingRules` (old name still works) | | `mkOpencodeRules` | `mkCodingRules` |
### Migration steps ### Migration steps

View File

@@ -1,10 +1,39 @@
# Per-tool agent sub-modules # Per-tool agent sub-modules
# Each module handles rendering canonical agent.toml definitions # Each module handles rendering canonical agent.toml definitions
# for a specific AI coding tool. # 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 = [ imports = [
./opencode.nix ./opencode.nix
./claude-code.nix ./claude-code.nix
./pi.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;
};
};
} }

View File

@@ -17,8 +17,6 @@ in
''; '';
modelOverrides = shared.mkModelOverridesOption; modelOverrides = shared.mkModelOverridesOption;
externalSkills = shared.externalSkillsOption;
}; };
config = mkIf config.coding.agents.opencode.enable { 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 # Static config dirs from AGENTS repo
xdg.configFile."opencode/context" = let xdg.configFile."opencode/context" = let
cfg = config.coding.agents.opencode; cfg = config.coding.agents.opencode;

View File

@@ -15,7 +15,10 @@ in
mcpServers = mkOption { mcpServers = mkOption {
type = types.attrsOf types.anything; 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"; defaultText = literalExpression "config.programs.mcp.servers";
description = '' description = ''
MCP server configurations for Pi (pi-mcp-adapter). MCP server configurations for Pi (pi-mcp-adapter).
@@ -41,8 +44,6 @@ in
''; '';
}; };
externalSkills = shared.externalSkillsOption;
settings = mkOption { settings = mkOption {
type = types.submodule { type = types.submodule {
freeformType = types.attrsOf types.anything; freeformType = types.attrsOf types.anything;
@@ -156,8 +157,11 @@ in
then let then let
filtered = filterNulls v; filtered = filterNulls v;
in in
if filtered == {} then null else filtered if filtered == {}
else v) attrs then null
else filtered
else v)
attrs
); );
piSettings = filterNulls cfg.settings; piSettings = filterNulls cfg.settings;
@@ -177,17 +181,16 @@ in
# Dynamic home.file entries for agent .md files # Dynamic home.file entries for agent .md files
agentFiles = agentFiles =
if cfg.agentsInput != null if cfg.agentsInput != null
then then let
let agentNames = builtins.attrNames cfg.agentsInput.lib.loadAgents;
agentNames = builtins.attrNames cfg.agentsInput.lib.loadAgents; in
in builtins.listToAttrs (
builtins.listToAttrs ( map (name: {
map (name: { name = ".pi/agent/agents/${name}.md";
name = ".pi/agent/agents/${name}.md"; value = {source = "${rendered}/agents/${name}.md";};
value = {source = "${rendered}/agents/${name}.md";}; })
}) agentNames
agentNames )
)
else {}; else {};
in { in {
home.file = mkMerge [ home.file = mkMerge [
@@ -213,15 +216,6 @@ in
# ── Agents — pi-subagents .md files ──────────────────────────── # ── Agents — pi-subagents .md files ────────────────────────────
agentFiles 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;
};
})
]; ];
}); });
} }

View File

@@ -4,11 +4,12 @@
inherit (lib) mkOption mkEnableOption types literalExpression; inherit (lib) mkOption mkEnableOption types literalExpression;
in { in {
# Common agentsInput option used by all agent modules. # Common agentsInput option used by all agent modules.
mkAgentsInputOption = description: mkOption { mkAgentsInputOption = description:
type = types.nullOr types.anything; mkOption {
default = null; type = types.nullOr types.anything;
inherit description; default = null;
}; inherit description;
};
# Common modelOverrides option. # Common modelOverrides option.
mkModelOverridesOption = mkOption { mkModelOverridesOption = mkOption {
@@ -62,7 +63,7 @@ in {
{ src = inputs.skills-anthropic; selectSkills = [ "claude-api" ]; } { src = inputs.skills-anthropic; selectSkills = [ "claude-api" ]; }
{ src = inputs.basecamp; } { src = inputs.basecamp; }
] ]
''; '';
}; };
# Helper to map externalSkills from module config to mkOpencodeSkills format. # Helper to map externalSkills from module config to mkOpencodeSkills format.
@@ -71,5 +72,6 @@ in {
entry: entry:
{inherit (entry) src skillsDir;} {inherit (entry) src skillsDir;}
// lib.optionalAttrs (entry.selectSkills != null) {inherit (entry) selectSkills;} // lib.optionalAttrs (entry.selectSkills != null) {inherit (entry) selectSkills;}
) cfgEntries; )
cfgEntries;
} }

View File

@@ -1,5 +1,5 @@
# OpenCode development environment with AI coding rules # OpenCode development environment with AI coding rules
# This shell demonstrates the mkOpencodeRules library provided by this repository # This shell demonstrates the mkCodingRules library provided by this repository
# Usage: nix develop .#opencode # Usage: nix develop .#opencode
# #
# To enable OpenCode rules, add the agents input to your flake: # To enable OpenCode rules, add the agents input to your flake:
@@ -13,16 +13,16 @@
inputs ? null, inputs ? null,
agents ? null, agents ? null,
}: let }: let
# Import the opencode-rules library # Import the coding-rules library
m3taLib = import ../lib {lib = pkgs.lib;}; m3taLib = import ../lib {lib = pkgs.lib;};
# Import custom packages # Import custom packages
customPackages = import ../pkgs {inherit pkgs inputs;}; customPackages = import ../pkgs {inherit pkgs inputs;};
# Create rules configuration only if agents input is provided # Create rules configuration only if agents input is provided
# This demonstrates how to use mkOpencodeRules in a real project # This demonstrates how to use mkCodingRules in a real project
rulesConfig = lib.optionalAttrs (agents != null) { rulesConfig = lib.optionalAttrs (agents != null) {
rules = m3taLib.opencode-rules.mkOpencodeRules { rules = m3taLib.coding-rules.mkCodingRules {
# Pass the AGENTS repository path # Pass the AGENTS repository path
inherit agents; inherit agents;
@@ -75,7 +75,7 @@ in
shellHook = '' shellHook = ''
echo "🤖 OpenCode Development Environment" echo "🤖 OpenCode Development Environment"
echo "" echo ""
echo "This environment demonstrates the mkOpencodeRules library" echo "This environment demonstrates the mkCodingRules library"
echo "provided by the m3ta-nixpkgs repository." echo "provided by the m3ta-nixpkgs repository."
echo "" echo ""
@@ -121,7 +121,7 @@ in
${ ${
if (agents == null) if (agents == null)
then '' then ''
echo "💡 Using mkOpencodeRules in your project:" echo "💡 Using mkCodingRules in your project:"
echo "" echo ""
echo "Add to your flake.nix:" echo "Add to your flake.nix:"
echo " inputs = {" echo " inputs = {"
@@ -137,7 +137,7 @@ in
echo " system = \"x86_64-linux\";" echo " system = \"x86_64-linux\";"
echo " pkgs = nixpkgs.legacyPackages.''${system};" echo " pkgs = nixpkgs.legacyPackages.''${system};"
echo " m3taLib = m3ta-nixpkgs.lib.''${system};" echo " m3taLib = m3ta-nixpkgs.lib.''${system};"
echo " rules = m3taLib.opencode-rules.mkOpencodeRules {" echo " rules = m3taLib.coding-rules.mkCodingRules {
echo " inherit agents;" echo " inherit agents;"
echo " languages = [\"python\" \"typescript\"];" echo " languages = [\"python\" \"typescript\"];"
echo " frameworks = [\"n8n\"];" echo " frameworks = [\"n8n\"];"

View File

@@ -26,10 +26,7 @@ let
in in
assert hasCorrectPrefix == true; {result = "pass";}; assert hasCorrectPrefix == true; {result = "pass";};
# Test 3: backward-compat alias exists # Test 3: shellHook contains both the symlink command and the config generation
testBackwardCompat = assert codingRulesLib.mkOpencodeRules == codingRulesLib.mkCodingRules; {result = "pass";};
# Test 4: shellHook contains both the symlink command and the config generation
testShellHook = let testShellHook = let
rules = codingRulesLib.mkCodingRules { rules = codingRulesLib.mkCodingRules {
agents = "/tmp/fake-agents"; agents = "/tmp/fake-agents";
@@ -43,6 +40,5 @@ let
in { in {
instructions-correct = testInstructions; instructions-correct = testInstructions;
default-rules-dir = testDefaultRulesDir; default-rules-dir = testDefaultRulesDir;
backward-compat = testBackwardCompat;
shell-hook = testShellHook; shell-hook = testShellHook;
} }