(cwd: string)
| 60 | * project/local-scope plugins only when their recorded projectPath contains cwd. |
| 61 | */ |
| 62 | export async function relevantPluginPaths(cwd: string): Promise<Array<{ name: string; path: string }>> { |
| 63 | const file = path.join(claudeHome(), 'plugins', 'installed_plugins.json'); |
| 64 | let json: InstalledPluginsFile; |
| 65 | try { |
| 66 | json = JSON.parse(await fs.readFile(file, 'utf-8')); |
| 67 | } catch { |
| 68 | return []; |
| 69 | } |
| 70 | const out: Array<{ name: string; path: string }> = []; |
| 71 | for (const [key, entries] of Object.entries(json.plugins ?? {})) { |
| 72 | const name = key.split('@')[0] ?? key; |
| 73 | for (const e of entries ?? []) { |
| 74 | if (!e.installPath) continue; |
| 75 | const scope = e.scope ?? 'user'; |
| 76 | if (scope === 'user' || (e.projectPath && pathMatches(cwd, e.projectPath))) { |
| 77 | out.push({ name, path: e.installPath }); |
| 78 | } |
| 79 | } |
| 80 | } |
| 81 | return out; |
| 82 | } |
| 83 | |
| 84 | /** Extra skill roots contributed by Claude Code, lowest-precedence first. */ |
| 85 | export async function claudeCodeSkillDirs(cwd: string): Promise<ClaudeAssetDir[]> { |
no test coverage detected