Files
orcs-code/src/skills/loadSkillsDir.test.ts
Charlike Mike Reagent 63adb95e8d fix: support nested skill directories
Load nested SKILL.md files from .claude/skills and namespace them with colons so category-based skill layouts work in Claude Code clients.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 20:20:13 +03:00

65 lines
2.1 KiB
TypeScript

import assert from 'node:assert/strict'
import { mkdtempSync, rmSync, mkdirSync, writeFileSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import test from 'node:test'
import { getSkillDirCommands, clearSkillCaches } from './loadSkillsDir.ts'
function writeSkill(rootDir: string, skillPath: string): void {
const skillDir = join(rootDir, '.claude', 'skills', ...skillPath.split('/'))
mkdirSync(skillDir, { recursive: true })
writeFileSync(
join(skillDir, 'SKILL.md'),
`---\ndescription: ${skillPath}\n---\n# ${skillPath}\n`,
'utf8',
)
}
test('loads flat and nested skills with colon namespaces', async () => {
const configDir = mkdtempSync(join(tmpdir(), 'openclaude-skills-'))
const cwd = join(configDir, 'workspace')
const originalConfigDir = process.env.CLAUDE_CONFIG_DIR
try {
mkdirSync(cwd, { recursive: true })
writeSkill(configDir, 'flat-skill')
writeSkill(configDir, 'git/commit')
writeSkill(configDir, 'frontend/react/form')
process.env.CLAUDE_CONFIG_DIR = configDir
clearSkillCaches()
const skills = await getSkillDirCommands(cwd)
const promptSkills = skills.filter(skill => skill.type === 'prompt')
const skillNames = promptSkills.map(skill => skill.name).sort()
assert.deepEqual(skillNames, [
'flat-skill',
'frontend:react:form',
'git:commit',
])
const nestedSkill = promptSkills.find(skill => skill.name === 'git:commit')
assert.ok(nestedSkill)
assert.equal(nestedSkill.skillRoot, join(configDir, '.claude', 'skills', 'git', 'commit'))
const deepSkill = promptSkills.find(
skill => skill.name === 'frontend:react:form',
)
assert.ok(deepSkill)
assert.equal(
deepSkill.skillRoot,
join(configDir, '.claude', 'skills', 'frontend', 'react', 'form'),
)
} finally {
if (originalConfigDir === undefined) {
delete process.env.CLAUDE_CONFIG_DIR
} else {
process.env.CLAUDE_CONFIG_DIR = originalConfigDir
}
clearSkillCaches()
rmSync(configDir, { recursive: true, force: true })
}
})