fix(skills): use directory param instead of process.cwd() for project skill discovery

Project-level skills (.opencode/skills/ and .claude/skills/) were not
discovered in desktop app environments because the discover functions
hardcoded process.cwd() to resolve project paths. In desktop apps,
process.cwd() points to the app installation directory rather than the
user's project directory.

Add optional directory parameter to all project-level skill discovery
functions and thread ctx.directory from the plugin context through the
entire skill loading pipeline. Falls back to process.cwd() when
directory is not provided, preserving CLI compatibility.
This commit is contained in:
Willy
2026-02-13 10:49:15 +08:00
parent 4a991b5a83
commit 6914f2fd04
5 changed files with 23 additions and 20 deletions

View File

@@ -13,8 +13,8 @@ export async function loadUserSkills(): Promise<Record<string, CommandDefinition
return skillsToCommandDefinitionRecord(skills)
}
export async function loadProjectSkills(): Promise<Record<string, CommandDefinition>> {
const projectSkillsDir = join(process.cwd(), ".claude", "skills")
export async function loadProjectSkills(directory?: string): Promise<Record<string, CommandDefinition>> {
const projectSkillsDir = join(directory ?? process.cwd(), ".claude", "skills")
const skills = await loadSkillsFromDir({ skillsDir: projectSkillsDir, scope: "project" })
return skillsToCommandDefinitionRecord(skills)
}
@@ -26,21 +26,22 @@ export async function loadOpencodeGlobalSkills(): Promise<Record<string, Command
return skillsToCommandDefinitionRecord(skills)
}
export async function loadOpencodeProjectSkills(): Promise<Record<string, CommandDefinition>> {
const opencodeProjectDir = join(process.cwd(), ".opencode", "skills")
export async function loadOpencodeProjectSkills(directory?: string): Promise<Record<string, CommandDefinition>> {
const opencodeProjectDir = join(directory ?? process.cwd(), ".opencode", "skills")
const skills = await loadSkillsFromDir({ skillsDir: opencodeProjectDir, scope: "opencode-project" })
return skillsToCommandDefinitionRecord(skills)
}
export interface DiscoverSkillsOptions {
includeClaudeCodePaths?: boolean
directory?: string
}
export async function discoverAllSkills(): Promise<LoadedSkill[]> {
export async function discoverAllSkills(directory?: string): Promise<LoadedSkill[]> {
const [opencodeProjectSkills, opencodeGlobalSkills, projectSkills, userSkills] = await Promise.all([
discoverOpencodeProjectSkills(),
discoverOpencodeProjectSkills(directory),
discoverOpencodeGlobalSkills(),
discoverProjectClaudeSkills(),
discoverProjectClaudeSkills(directory),
discoverUserClaudeSkills(),
])
@@ -49,10 +50,10 @@ export async function discoverAllSkills(): Promise<LoadedSkill[]> {
}
export async function discoverSkills(options: DiscoverSkillsOptions = {}): Promise<LoadedSkill[]> {
const { includeClaudeCodePaths = true } = options
const { includeClaudeCodePaths = true, directory } = options
const [opencodeProjectSkills, opencodeGlobalSkills] = await Promise.all([
discoverOpencodeProjectSkills(),
discoverOpencodeProjectSkills(directory),
discoverOpencodeGlobalSkills(),
])
@@ -62,7 +63,7 @@ export async function discoverSkills(options: DiscoverSkillsOptions = {}): Promi
}
const [projectSkills, userSkills] = await Promise.all([
discoverProjectClaudeSkills(),
discoverProjectClaudeSkills(directory),
discoverUserClaudeSkills(),
])
@@ -80,8 +81,8 @@ export async function discoverUserClaudeSkills(): Promise<LoadedSkill[]> {
return loadSkillsFromDir({ skillsDir: userSkillsDir, scope: "user" })
}
export async function discoverProjectClaudeSkills(): Promise<LoadedSkill[]> {
const projectSkillsDir = join(process.cwd(), ".claude", "skills")
export async function discoverProjectClaudeSkills(directory?: string): Promise<LoadedSkill[]> {
const projectSkillsDir = join(directory ?? process.cwd(), ".claude", "skills")
return loadSkillsFromDir({ skillsDir: projectSkillsDir, scope: "project" })
}
@@ -91,7 +92,7 @@ export async function discoverOpencodeGlobalSkills(): Promise<LoadedSkill[]> {
return loadSkillsFromDir({ skillsDir: opencodeSkillsDir, scope: "opencode" })
}
export async function discoverOpencodeProjectSkills(): Promise<LoadedSkill[]> {
const opencodeProjectDir = join(process.cwd(), ".opencode", "skills")
export async function discoverOpencodeProjectSkills(directory?: string): Promise<LoadedSkill[]> {
const opencodeProjectDir = join(directory ?? process.cwd(), ".opencode", "skills")
return loadSkillsFromDir({ skillsDir: opencodeProjectDir, scope: "opencode-project" })
}

View File

@@ -20,7 +20,7 @@ export async function getAllSkills(options?: SkillResolutionOptions): Promise<Lo
}
const [discoveredSkills, builtinSkillDefinitions] = await Promise.all([
discoverSkills({ includeClaudeCodePaths: true }),
discoverSkills({ includeClaudeCodePaths: true, directory: options?.directory }),
Promise.resolve(
createBuiltinSkills({
browserProvider: options?.browserProvider,

View File

@@ -4,4 +4,6 @@ export interface SkillResolutionOptions {
gitMasterConfig?: GitMasterConfig
browserProvider?: BrowserAutomationProvider
disabledSkills?: Set<string>
/** Project directory to discover project-level skills from. Falls back to process.cwd() if not provided. */
directory?: string
}

View File

@@ -47,10 +47,10 @@ export async function applyAgentConfig(params: {
}),
includeClaudeSkillsForAwareness ? discoverUserClaudeSkills() : Promise.resolve([]),
includeClaudeSkillsForAwareness
? discoverProjectClaudeSkills()
: Promise.resolve([]),
? discoverProjectClaudeSkills(params.ctx.directory)
: Promise.resolve([]),
discoverOpencodeGlobalSkills(),
discoverOpencodeProjectSkills(),
discoverOpencodeProjectSkills(params.ctx.directory),
]);
const allDiscoveredSkills = [

View File

@@ -63,8 +63,8 @@ export async function createSkillContext(args: {
}),
includeClaudeSkills ? discoverUserClaudeSkills() : Promise.resolve([]),
discoverOpencodeGlobalSkills(),
includeClaudeSkills ? discoverProjectClaudeSkills() : Promise.resolve([]),
discoverOpencodeProjectSkills(),
includeClaudeSkills ? discoverProjectClaudeSkills(directory) : Promise.resolve([]),
discoverOpencodeProjectSkills(directory),
])
const mergedSkills = mergeSkills(