Files
skills/flake.nix

118 lines
4.5 KiB
Nix

{
description = "Personal agent skills, packaged through Nix.";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
inputs.flake-utils.url = "github:numtide/flake-utils";
inputs.gitea-axi = {
url = "git+https://git.alexion.dev/alexion/gitea-axi";
inputs.nixpkgs.follows = "nixpkgs";
};
# Present only so `nix flake check` can evaluate `homeModules.default` against
# real home-manager (the home-manager-module check). Its nixpkgs follows this
# flake's, so the module is checked against the same nixpkgs-and-home-manager
# pairing a consumer following this flake would get. It has no bearing on the
# module a consumer imports — that module is a bare function taking the
# importing configuration's own home-manager and pkgs.
inputs.home-manager.url = "github:nix-community/home-manager";
inputs.home-manager.inputs.nixpkgs.follows = "nixpkgs";
outputs =
{ self, nixpkgs, flake-utils, home-manager, gitea-axi }:
let
mkSkill = import ./lib/mk-skill.nix;
mkSkillsShellHook = import ./lib/mk-skills-shell-hook.nix;
discoverSkills = import ./lib/discover.nix nixpkgs.lib;
discoveredSkills = discoverSkills ./skills;
skillPackages =
pkgs:
nixpkgs.lib.listToAttrs (
map (skill: {
inherit (skill) name;
value = mkSkill { inherit pkgs; inherit (skill) name src; };
}) discoveredSkills
);
in
{
lib = { inherit mkSkill mkSkillsShellHook; };
# Global placement: an operator selects skills into enabled agent harnesses
# via `programs.agents.skills`. Not per-system — it is a module function,
# and the skills it places come from the importing configuration's own
# selection rather than this flake's nixpkgs.
homeModules = rec {
agents-skills = ./home-manager-module.nix;
default = agents-skills;
};
}
//
# An explicit system list rather than `eachDefaultSystem`.
# That default set includes x86_64-darwin, which current nixpkgs no longer
# evaluates (its `legacyPackages` throws).
flake-utils.lib.eachSystem
[
"x86_64-linux"
"aarch64-linux"
"aarch64-darwin"
]
(
system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
{
# No `default`: a catalog has no single default skill.
packages = skillPackages pkgs;
# Each discovered skill is folded in as its own check, so
# `nix flake check` builds every skill and fails on a malformed one.
checks = (skillPackages pkgs) // {
skill-build = import ./checks/skill-build.nix {
inherit pkgs mkSkill discoverSkills;
};
# Proves the global-placement module composes: it builds the
# home-files derivation `homeModules.default` produces under several
# operator configurations. Reuses this flake's `mkSkill` so the
# sample skills carry the same name contract real ones do.
home-manager-module = import ./checks/home-manager-module.nix {
inherit pkgs home-manager mkSkill;
module = self.homeModules.default;
};
# Proves the per-project dev-shell helper: it runs the produced hook
# against a fixture project and asserts placement, stateless
# stale-removal, and that hand-authored skills stay untouched.
shell-hook = import ./checks/shell-hook.nix {
inherit pkgs mkSkill mkSkillsShellHook;
};
# Proves the benchmark skill's deterministic core at its single seam:
# it feeds committed fixtures to the core and asserts the metrics, the
# Efficacy verdict, and the rendered report.
benchmark-core = import ./checks/benchmark-core.nix {
inherit pkgs;
};
};
# A working shell for developing skills in this repo.
# Python runs the benchmark core, while gitea-axi backs its project skill.
# Both project skills are placed into ./.agents/skills/ on entry, with
# ./.claude/skills as a compatibility symlink.
devShells.default = pkgs.mkShell {
packages = [
pkgs.python3
gitea-axi.packages.${system}.gitea-axi
];
shellHook = mkSkillsShellHook [
gitea-axi.packages.${system}.gitea-axi-skill
(skillPackages pkgs).benchmark-skill
];
};
}
);
}