import { join } from "path" import { getClaudeConfigDir } from "../../shared" import { getOpenCodeConfigDir } from "../../shared/opencode-config-dir" import type { CommandDefinition } from "../claude-code-command-loader/types" import type { LoadedSkill } from "./types" import { skillsToCommandDefinitionRecord } from "./skill-definition-record" import { deduplicateSkillsByName } from "./skill-deduplication" import { loadSkillsFromDir } from "./skill-directory-loader" export async function loadUserSkills(): Promise> { const userSkillsDir = join(getClaudeConfigDir(), "skills") const skills = await loadSkillsFromDir({ skillsDir: userSkillsDir, scope: "user" }) return skillsToCommandDefinitionRecord(skills) } export async function loadProjectSkills(): Promise> { const projectSkillsDir = join(process.cwd(), ".claude", "skills") const skills = await loadSkillsFromDir({ skillsDir: projectSkillsDir, scope: "project" }) return skillsToCommandDefinitionRecord(skills) } export async function loadOpencodeGlobalSkills(): Promise> { const configDir = getOpenCodeConfigDir({ binary: "opencode" }) const opencodeSkillsDir = join(configDir, "skills") const skills = await loadSkillsFromDir({ skillsDir: opencodeSkillsDir, scope: "opencode" }) return skillsToCommandDefinitionRecord(skills) } export async function loadOpencodeProjectSkills(): Promise> { const opencodeProjectDir = join(process.cwd(), ".opencode", "skills") const skills = await loadSkillsFromDir({ skillsDir: opencodeProjectDir, scope: "opencode-project" }) return skillsToCommandDefinitionRecord(skills) } export interface DiscoverSkillsOptions { includeClaudeCodePaths?: boolean } export async function discoverAllSkills(): Promise { const [opencodeProjectSkills, opencodeGlobalSkills, projectSkills, userSkills] = await Promise.all([ discoverOpencodeProjectSkills(), discoverOpencodeGlobalSkills(), discoverProjectClaudeSkills(), discoverUserClaudeSkills(), ]) // Priority: opencode-project > opencode > project > user return deduplicateSkillsByName([...opencodeProjectSkills, ...opencodeGlobalSkills, ...projectSkills, ...userSkills]) } export async function discoverSkills(options: DiscoverSkillsOptions = {}): Promise { const { includeClaudeCodePaths = true } = options const [opencodeProjectSkills, opencodeGlobalSkills] = await Promise.all([ discoverOpencodeProjectSkills(), discoverOpencodeGlobalSkills(), ]) if (!includeClaudeCodePaths) { // Priority: opencode-project > opencode return deduplicateSkillsByName([...opencodeProjectSkills, ...opencodeGlobalSkills]) } const [projectSkills, userSkills] = await Promise.all([ discoverProjectClaudeSkills(), discoverUserClaudeSkills(), ]) // Priority: opencode-project > opencode > project > user return deduplicateSkillsByName([...opencodeProjectSkills, ...opencodeGlobalSkills, ...projectSkills, ...userSkills]) } export async function getSkillByName(name: string, options: DiscoverSkillsOptions = {}): Promise { const skills = await discoverSkills(options) return skills.find(s => s.name === name) } export async function discoverUserClaudeSkills(): Promise { const userSkillsDir = join(getClaudeConfigDir(), "skills") return loadSkillsFromDir({ skillsDir: userSkillsDir, scope: "user" }) } export async function discoverProjectClaudeSkills(): Promise { const projectSkillsDir = join(process.cwd(), ".claude", "skills") return loadSkillsFromDir({ skillsDir: projectSkillsDir, scope: "project" }) } export async function discoverOpencodeGlobalSkills(): Promise { const configDir = getOpenCodeConfigDir({ binary: "opencode" }) const opencodeSkillsDir = join(configDir, "skills") return loadSkillsFromDir({ skillsDir: opencodeSkillsDir, scope: "opencode" }) } export async function discoverOpencodeProjectSkills(): Promise { const opencodeProjectDir = join(process.cwd(), ".opencode", "skills") return loadSkillsFromDir({ skillsDir: opencodeProjectDir, scope: "opencode-project" }) }