diff --git a/src/resources/extensions/sf/preferences-skills.js b/src/resources/extensions/sf/preferences-skills.js index ae5c969ec..9ac4659d5 100644 --- a/src/resources/extensions/sf/preferences-skills.js +++ b/src/resources/extensions/sf/preferences-skills.js @@ -9,6 +9,7 @@ import { homedir } from "node:os"; import { isAbsolute, join } from "node:path"; import { validatePreferences } from "./preferences-validation.js"; import { sfHome } from "./sf-home.js"; +import { CLAUDE_SKILLS_DIR, SKILLS_DIR } from "./skill-discovery.js"; /** * Get skill search directories in priority order for resolution. * @@ -19,10 +20,10 @@ import { sfHome } from "./sf-home.js"; */ export function getSkillSearchDirs(cwd) { const dirs = [ - { dir: join(homedir(), ".agents", "skills"), method: "user-skill" }, + { dir: SKILLS_DIR, method: "user-skill" }, { dir: join(cwd, ".agents", "skills"), method: "project-skill" }, // Claude Code official skill directories - { dir: join(homedir(), ".claude", "skills"), method: "user-skill" }, + { dir: CLAUDE_SKILLS_DIR, method: "user-skill" }, { dir: join(cwd, ".claude", "skills"), method: "project-skill" }, ]; // Legacy fallback — read skills from old SF directory only if migration hasn't completed diff --git a/src/resources/extensions/sf/skill-catalog.js b/src/resources/extensions/sf/skill-catalog.js index 4346b38ed..8bffe836f 100644 --- a/src/resources/extensions/sf/skill-catalog.js +++ b/src/resources/extensions/sf/skill-catalog.js @@ -13,9 +13,9 @@ */ import { execFile } from "node:child_process"; import { existsSync } from "node:fs"; -import { homedir } from "node:os"; import { join } from "node:path"; import { showNextAction } from "../shared/tui.js"; +import { CLAUDE_SKILLS_DIR, SKILLS_DIR } from "./skill-discovery.js"; // ─── Curated Catalog ────────────────────────────────────────────────────────── export const SKILL_CATALOG = [ // ── Swift (language-level — any Swift project) ──────────────────────────── @@ -961,8 +961,8 @@ export async function installPacksBatched(packs, onProgress) { */ export function isPackInstalled(pack) { const skillsDirs = [ - join(homedir(), ".agents", "skills"), - join(homedir(), ".claude", "skills"), + SKILLS_DIR, + CLAUDE_SKILLS_DIR, ]; return pack.skills.every((name) => skillsDirs.some((dir) => existsSync(join(dir, name, "SKILL.md"))), diff --git a/src/resources/extensions/sf/skill-discovery.js b/src/resources/extensions/sf/skill-discovery.js index 358fc9199..7eb73805b 100644 --- a/src/resources/extensions/sf/skill-discovery.js +++ b/src/resources/extensions/sf/skill-discovery.js @@ -12,9 +12,9 @@ import { homedir } from "node:os"; import { join } from "node:path"; /** Skills directories — skills.sh ecosystem + Claude Code official + legacy Pi */ -const SKILLS_DIR = join(homedir(), ".agents", "skills"); -const CLAUDE_SKILLS_DIR = join(homedir(), ".claude", "skills"); -const PI_SKILLS_DIR = join(homedir(), ".pi", "agent", "skills"); +export const SKILLS_DIR = join(homedir(), ".agents", "skills"); +export const CLAUDE_SKILLS_DIR = join(homedir(), ".claude", "skills"); +export const PI_SKILLS_DIR = join(homedir(), ".pi", "agent", "skills"); /** Snapshot of skill names at autonomous mode start */ let baselineSkills = null; /** diff --git a/src/resources/extensions/sf/skill-health.js b/src/resources/extensions/sf/skill-health.js index 92179bdc1..1c84abaa3 100644 --- a/src/resources/extensions/sf/skill-health.js +++ b/src/resources/extensions/sf/skill-health.js @@ -13,10 +13,10 @@ * research identified as critical for skill quality. */ import { existsSync, statSync } from "node:fs"; -import { homedir } from "node:os"; import { join } from "node:path"; import { formatCost, formatTokenCount, loadLedgerFromDisk } from "./metrics.js"; import { detectStaleSkills } from "./skill-telemetry.js"; +import { CLAUDE_SKILLS_DIR, SKILLS_DIR } from "./skill-discovery.js"; // ─── Constants ──────────────────────────────────────────────────────────────── /** Default staleness threshold in days */ @@ -168,8 +168,8 @@ export function formatSkillDetail(basePath, skillName) { } // Check for SKILL.md existence — search both ecosystem and Claude Code directories const candidatePaths = [ - join(homedir(), ".agents", "skills", skillName, "SKILL.md"), - join(homedir(), ".claude", "skills", skillName, "SKILL.md"), + join(SKILLS_DIR, skillName, "SKILL.md"), + join(CLAUDE_SKILLS_DIR, skillName, "SKILL.md"), ]; const skillPath = candidatePaths.find((p) => existsSync(p)); if (skillPath) { diff --git a/src/resources/extensions/sf/skill-telemetry.js b/src/resources/extensions/sf/skill-telemetry.js index 8b077fcd4..a077fe0e3 100644 --- a/src/resources/extensions/sf/skill-telemetry.js +++ b/src/resources/extensions/sf/skill-telemetry.js @@ -11,9 +11,9 @@ * 3. At unit completion, getAndClearSkills() returns the loaded list for metrics */ import { existsSync, readdirSync } from "node:fs"; -import { homedir } from "node:os"; import { join } from "node:path"; import { sfHome } from "./sf-home.js"; +import { CLAUDE_SKILLS_DIR, SKILLS_DIR } from "./skill-discovery.js"; // ─── In-memory state ────────────────────────────────────────────────────────── /** Skills available in the system prompt for the current unit */ @@ -27,11 +27,9 @@ const activelyLoadedSkills = new Set(); * Called before each unit starts to establish the baseline for telemetry. */ export function captureAvailableSkills() { - const skillsDir = join(homedir(), ".agents", "skills"); - const claudeSkillsDir = join(homedir(), ".claude", "skills"); const legacyDir = join(sfHome(), "agent", "skills"); - const names = listSkillNames(skillsDir); - const claudeNames = listSkillNames(claudeSkillsDir); + const names = listSkillNames(SKILLS_DIR); + const claudeNames = listSkillNames(CLAUDE_SKILLS_DIR); // Include skills still in the legacy directory only if migration hasn't completed const legacyMigrated = existsSync(join(legacyDir, ".migrated-to-agents")); const legacyNames = legacyMigrated ? [] : listSkillNames(legacyDir); @@ -101,14 +99,12 @@ export function detectStaleSkills(units, thresholdDays) { const cutoff = Date.now() - thresholdDays * 24 * 60 * 60 * 1000; const stale = []; // Check all installed skills, not just those with usage data - const skillsDir = join(homedir(), ".agents", "skills"); - const claudeSkillsDir = join(homedir(), ".claude", "skills"); const legacyDir = join(sfHome(), "agent", "skills"); const legacyMigrated = existsSync(join(legacyDir, ".migrated-to-agents")); const legacyNames = legacyMigrated ? [] : listSkillNames(legacyDir); const installedSet = new Set([ - ...listSkillNames(skillsDir), - ...listSkillNames(claudeSkillsDir), + ...listSkillNames(SKILLS_DIR), + ...listSkillNames(CLAUDE_SKILLS_DIR), ...legacyNames, ]); const installed = [...installedSet];