import { existsSync, statSync } from "node:fs"; import { dirname, join, resolve } from "node:path"; import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"; function isDirectory(path: string): boolean { try { return statSync(path).isDirectory(); } catch { return false; } } function walkUpDirectories(startDir: string, stopDir?: string): string[] { const directories: string[] = []; const hasStopDir = stopDir !== undefined; let current = resolve(startDir); let parent = dirname(current); let reachedStopDir = hasStopDir && current === stopDir; let reachedFilesystemRoot = parent === current; directories.push(current); while (!reachedStopDir && !reachedFilesystemRoot) { current = parent; parent = dirname(current); reachedStopDir = hasStopDir && current === stopDir; reachedFilesystemRoot = parent === current; directories.push(current); } return directories; } function findNearestGitRoot(startDir: string): string | undefined { for (const directory of walkUpDirectories(startDir)) { if (existsSync(join(directory, ".git"))) { return directory; } } return undefined; } function findClaudeSkillDirs(cwd: string): string[] { const gitRoot = findNearestGitRoot(cwd); return walkUpDirectories(cwd, gitRoot) .map((directory) => join(directory, ".claude", "skills")) .filter(isDirectory); } export default function(pi: ExtensionAPI) { pi.on("resources_discover", (event) => { const skillPaths = findClaudeSkillDirs(event.cwd); if (skillPaths.length === 0) { return; } return { skillPaths }; }); }