@@ -3,8 +3,10 @@ package commands
5 "path/filepath"
5 "path/filepath"
9+ "github.com/charmbracelet/crush/internal/skills"
8 "github.com/stretchr/testify/require"
10 "github.com/stretchr/testify/require"
@@ -51,3 +53,62 @@ func TestLoadAll_MixedSources(t *testing.T) {
51 require.Len(t, cmds, 1)
53 require.Len(t, cmds, 1)
52 require.Equal(t, "user:cmd", cmds[0].ID)
54 require.Equal(t, "user:cmd", cmds[0].ID)
57+func TestFromSkillCatalog_UserInvocableOnly(t *testing.T) {
60+ cmds := FromSkillCatalog([]skills.CatalogEntry{
62+ ID: "/skills/on/SKILL.md",
64+ Description: "Enabled.",
69+ ID: "/skills/off/SKILL.md",
71+ Description: "Not invocable.",
73+ UserInvocable: false,
77+ require.Len(t, cmds, 1)
78+ require.Equal(t, "user:on", cmds[0].ID)
79+ require.Equal(t, "user:on", cmds[0].Name)
80+ require.Equal(t, "on", cmds[0].Skill.Name)
81+ require.Equal(t, "Enabled.", cmds[0].Skill.Description)
82+ require.Equal(t, "/skills/on/SKILL.md", cmds[0].Skill.SkillFilePath)
85+func TestFromSkillCatalog_UsesDiscoveredSymlinkedSkills(t *testing.T) {
86+ if runtime.GOOS == "windows" {
87+ t.Skip("symlink creation requires special privileges on Windows")
92+ targetParent := t.TempDir()
93+ targetSkillDir := filepath.Join(targetParent, "linked-skill")
94+ require.NoError(t, os.MkdirAll(targetSkillDir, 0o755))
95+ require.NoError(t, os.WriteFile(
96+ filepath.Join(targetSkillDir, skills.SkillFileName),
97+ []byte("---\nname: linked-skill\ndescription: Symlinked.\nuser-invocable: true\n---\nUse me.\n"),
101+ link := filepath.Join(root, "linked-skill")
102+ require.NoError(t, os.Symlink(targetSkillDir, link))
104+ _, activeSkills, _ := skills.DiscoverFromConfig(skills.DiscoveryConfig{
105+ SkillsPaths: []string{root},
107+ entries := skills.Catalog(activeSkills, []string{root}, "")
108+ cmds := FromSkillCatalog(entries)
110+ require.Len(t, cmds, 1)
111+ require.Equal(t, "user:linked-skill", cmds[0].ID)
112+ require.Equal(t, "linked-skill", cmds[0].Skill.Name)
113+ require.Equal(t, filepath.Join(link, skills.SkillFileName), cmds[0].Skill.SkillFilePath)