# Builds a skill source directory into a derivation, `SKILL.md` at the `$out` root. { pkgs, src, name ? builtins.baseNameOf (toString src), commands ? [ ], }: let lib = pkgs.lib; patchEnvDefault = command: envName: value: let marker = "# mkSkill:${envName}"; replacement = '': "''${${envName}:=${value}}" ${marker}''; in '' if ! awk -v marker=${lib.escapeShellArg marker} -v replacement=${lib.escapeShellArg replacement} ' index($0, marker) { print replacement; found = 1; next } { print } END { if (!found) exit 42 } ' "$_mkskill_command" > "$_mkskill_command.tmp"; then rm -f "$_mkskill_command.tmp" echo "mkSkill: command '${command.path}' has no ${marker} marker" >&2 exit 1 fi mv "$_mkskill_command.tmp" "$_mkskill_command" chmod +x "$_mkskill_command" ''; patchCommand = command: let env = command.env or { }; in '' _mkskill_command="$out/${command.path}" test -f "$_mkskill_command" \ || { echo "mkSkill: command '${command.path}' does not exist" >&2; exit 1; } test -x "$_mkskill_command" \ || { echo "mkSkill: command '${command.path}' is not executable" >&2; exit 1; } ${lib.concatStringsSep "\n" (lib.mapAttrsToList (patchEnvDefault command) env)} ''; patchCommands = lib.concatStringsSep "\n" (map patchCommand commands); in pkgs.stdenvNoCC.mkDerivation { inherit name src; # A skill is just files to copy, with nothing to unpack, configure, or build. dontUnpack = true; dontConfigure = true; dontBuild = true; installPhase = '' runHook preInstall mkdir -p "$out" cp -R "$src"/. "$out/" test -f "$out/SKILL.md" \ || { echo "mkSkill: skill '${name}' has no SKILL.md at its root" >&2; exit 1; } ${patchCommands} runHook postInstall ''; # The name as an eval-time attribute, readable without building `$out` # (no import-from-derivation). passthru.skillName = name; }