import { test, expect } from "bun:test"import { Skill } from "../../src/skill"import { Instance } from "../../src/project/instance"import { tmpdir } from "../fixture/fixture"import path from "path"import fs from "fs/promises" async function createGlobalSkill(homeDir: string) { const skillDir = path.join(homeDir, ".claude", "skills", "global-test-skill") await fs.mkdir(skillDir, { recursive: true }) await Bun.write( path.join(skillDir, "SKILL.md"), `---name: global-test-skilldescription: A global skill from ~/.claude/skills for testing.--- # Global Test Skill This skill is loaded from the global home directory.`, )} test("discovers skills from .openscience/skill/ directory", async () => { await using tmp = await tmpdir({ git: true, init: async (dir) => { const skillDir = path.join(dir, ".openscience", "skill", "test-skill") await Bun.write( path.join(skillDir, "SKILL.md"), `---name: test-skilldescription: A test skill for verification.--- # Test Skill Instructions here.`, ) }, }) await Instance.provide({ directory: tmp.path, fn: async () => { const skills = await Skill.all() expect(skills.length).toBe(1) const testSkill = skills.find((s) => s.name === "test-skill") expect(testSkill).toBeDefined() expect(testSkill!.description).toBe("A test skill for verification.") expect(testSkill!.location).toContain("skill/test-skill/SKILL.md") }, })}) test("discovers multiple skills from .openscience/skill/ directory", async () => { await using tmp = await tmpdir({ git: true, init: async (dir) => { const skillDir1 = path.join(dir, ".openscience", "skill", "skill-one") const skillDir2 = path.join(dir, ".openscience", "skill", "skill-two") await Bun.write( path.join(skillDir1, "SKILL.md"), `---name: skill-onedescription: First test skill.--- # Skill One`, ) await Bun.write( path.join(skillDir2, "SKILL.md"), `---name: skill-twodescription: Second test skill.--- # Skill Two`, ) }, }) await Instance.provide({ directory: tmp.path, fn: async () => { const skills = await Skill.all() expect(skills.length).toBe(2) expect(skills.find((s) => s.name === "skill-one")).toBeDefined() expect(skills.find((s) => s.name === "skill-two")).toBeDefined() }, })}) test("skips skills with missing frontmatter", async () => { await using tmp = await tmpdir({ git: true, init: async (dir) => { const skillDir = path.join(dir, ".openscience", "skill", "no-frontmatter") await Bun.write( path.join(skillDir, "SKILL.md"), `# No Frontmatter Just some content without YAML frontmatter.`, ) }, }) await Instance.provide({ directory: tmp.path, fn: async () => { const skills = await Skill.all() expect(skills).toEqual([]) }, })}) test("discovers skills from .claude/skills/ directory", async () => { await using tmp = await tmpdir({ git: true, init: async (dir) => { const skillDir = path.join(dir, ".claude", "skills", "claude-skill") await Bun.write( path.join(skillDir, "SKILL.md"), `---name: claude-skilldescription: A skill in the .claude/skills directory.--- # Claude Skill`, ) }, }) await Instance.provide({ directory: tmp.path, fn: async () => { const skills = await Skill.all() expect(skills.length).toBe(1) const claudeSkill = skills.find((s) => s.name === "claude-skill") expect(claudeSkill).toBeDefined() expect(claudeSkill!.location).toContain(".claude/skills/claude-skill/SKILL.md") }, })}) test("discovers global skills from ~/.claude/skills/ directory", async () => { await using tmp = await tmpdir({ git: true }) const originalHome = process.env.OPENSCIENCE_TEST_HOME process.env.OPENSCIENCE_TEST_HOME = tmp.path try { await createGlobalSkill(tmp.path) await Instance.provide({ directory: tmp.path, fn: async () => { const skills = await Skill.all() expect(skills.length).toBe(1) expect(skills[0].name).toBe("global-test-skill") expect(skills[0].description).toBe("A global skill from ~/.claude/skills for testing.") expect(skills[0].location).toContain(".claude/skills/global-test-skill/SKILL.md") }, }) } finally { process.env.OPENSCIENCE_TEST_HOME = originalHome }}) test("returns empty array when no skills exist", async () => { await using tmp = await tmpdir({ git: true }) await Instance.provide({ directory: tmp.path, fn: async () => { const skills = await Skill.all() expect(skills).toEqual([]) }, })})
import { test, expect } from "bun:test"
import { Skill } from "../../src/skill"
import { Instance } from "../../src/project/instance"
import { tmpdir } from "../fixture/fixture"
import path from "path"
import fs from "fs/promises"
async function createGlobalSkill(homeDir: string) {
const skillDir = path.join(homeDir, ".claude", "skills", "global-test-skill")
await fs.mkdir(skillDir, { recursive: true })
await Bun.write(
path.join(skillDir, "SKILL.md"),
`---
name: global-test-skill
description: A global skill from ~/.claude/skills for testing.
---
# Global Test Skill
This skill is loaded from the global home directory.
`,
)
}
test("discovers skills from .openscience/skill/ directory", async () => {
await using tmp = await tmpdir({
git: true,
init: async (dir) => {
const skillDir = path.join(dir, ".openscience", "skill", "test-skill")
await Bun.write(
path.join(skillDir, "SKILL.md"),
`---
name: test-skill
description: A test skill for verification.
---
# Test Skill
Instructions here.
`,
)
},
})
await Instance.provide({
directory: tmp.path,
fn: async () => {
const skills = await Skill.all()
expect(skills.length).toBe(1)
const testSkill = skills.find((s) => s.name === "test-skill")
expect(testSkill).toBeDefined()
expect(testSkill!.description).toBe("A test skill for verification.")
expect(testSkill!.location).toContain("skill/test-skill/SKILL.md")
},
})
})
test("discovers multiple skills from .openscience/skill/ directory", async () => {
await using tmp = await tmpdir({
git: true,
init: async (dir) => {
const skillDir1 = path.join(dir, ".openscience", "skill", "skill-one")
const skillDir2 = path.join(dir, ".openscience", "skill", "skill-two")
await Bun.write(
path.join(skillDir1, "SKILL.md"),
`---
name: skill-one
description: First test skill.
---
# Skill One
`,
)
await Bun.write(
path.join(skillDir2, "SKILL.md"),
`---
name: skill-two
description: Second test skill.
---
# Skill Two
`,
)
},
})
await Instance.provide({
directory: tmp.path,
fn: async () => {
const skills = await Skill.all()
expect(skills.length).toBe(2)
expect(skills.find((s) => s.name === "skill-one")).toBeDefined()
expect(skills.find((s) => s.name === "skill-two")).toBeDefined()
},
})
})
test("skips skills with missing frontmatter", async () => {
await using tmp = await tmpdir({
git: true,
init: async (dir) => {
const skillDir = path.join(dir, ".openscience", "skill", "no-frontmatter")
await Bun.write(
path.join(skillDir, "SKILL.md"),
`# No Frontmatter
Just some content without YAML frontmatter.
`,
)
},
})
await Instance.provide({
directory: tmp.path,
fn: async () => {
const skills = await Skill.all()
expect(skills).toEqual([])
},
})
})
test("discovers skills from .claude/skills/ directory", async () => {
await using tmp = await tmpdir({
git: true,
init: async (dir) => {
const skillDir = path.join(dir, ".claude", "skills", "claude-skill")
await Bun.write(
path.join(skillDir, "SKILL.md"),
`---
name: claude-skill
description: A skill in the .claude/skills directory.
---
# Claude Skill
`,
)
},
})
await Instance.provide({
directory: tmp.path,
fn: async () => {
const skills = await Skill.all()
expect(skills.length).toBe(1)
const claudeSkill = skills.find((s) => s.name === "claude-skill")
expect(claudeSkill).toBeDefined()
expect(claudeSkill!.location).toContain(".claude/skills/claude-skill/SKILL.md")
},
})
})
test("discovers global skills from ~/.claude/skills/ directory", async () => {
await using tmp = await tmpdir({ git: true })
const originalHome = process.env.OPENSCIENCE_TEST_HOME
process.env.OPENSCIENCE_TEST_HOME = tmp.path
try {
await createGlobalSkill(tmp.path)
await Instance.provide({
directory: tmp.path,
fn: async () => {
const skills = await Skill.all()
expect(skills.length).toBe(1)
expect(skills[0].name).toBe("global-test-skill")
expect(skills[0].description).toBe("A global skill from ~/.claude/skills for testing.")
expect(skills[0].location).toContain(".claude/skills/global-test-skill/SKILL.md")
},
})
} finally {
process.env.OPENSCIENCE_TEST_HOME = originalHome
}
})
test("returns empty array when no skills exist", async () => {
await using tmp = await tmpdir({ git: true })
await Instance.provide({
directory: tmp.path,
fn: async () => {
const skills = await Skill.all()
expect(skills).toEqual([])
},
})
})