feat: add per-project dev-shell skills placement (task 0003)

Expose lib.mkSkillsShellHook, which takes a list of selected skill derivations
and returns a dev-shell shellHook string. On shell entry the hook symlinks each
selected skill as a direct child of the project's .claude/skills/, pointing into
the store. It is stateless: each entry first removes only store-pointing symlinks
(deselected skills included), then relinks the current selection, leaving
hand-authored real directories untouched and regenerating a self-ignoring
.gitignore of the managed names. Add a nix flake check that sources the produced
hook against a fixture project and asserts placement, stale-removal, the
collision guard, non-store-symlink survival, and the .gitignore contents.
This commit was merged in pull request #3.
This commit is contained in:
2026-07-22 22:22:38 -04:00
parent b0a763e5ce
commit 49a73c30d1
4 changed files with 248 additions and 1 deletions

View File

@@ -17,6 +17,7 @@
{ self, nixpkgs, flake-utils, home-manager }:
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;
@@ -31,7 +32,7 @@
);
in
{
lib = { inherit mkSkill; };
lib = { inherit mkSkill mkSkillsShellHook; };
# Global placement: an operator selects skills into `~/.claude/skills/`
# via `programs.agents.skills`. Not per-system — it is a module function,
@@ -76,6 +77,13 @@
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;
};
};
}
);