skilldex 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +89 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +39 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +38 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -9
package/dist/cli/index.js
CHANGED
|
@@ -330,13 +330,11 @@ async function listSkills(projectRoot) {
|
|
|
330
330
|
const skillMap = new Map(allSkills.map((s) => [s.relativePath, s]));
|
|
331
331
|
const indexed = config.skills.map((entry) => {
|
|
332
332
|
const discovered = skillMap.get(entry.path);
|
|
333
|
-
if (!discovered)
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
};
|
|
339
|
-
}).filter((s) => s !== void 0);
|
|
333
|
+
if (!discovered) {
|
|
334
|
+
return { name: entry.name, path: entry.path, description: "", missing: true };
|
|
335
|
+
}
|
|
336
|
+
return { name: entry.name, path: entry.path, description: discovered.description };
|
|
337
|
+
});
|
|
340
338
|
const available = allSkills.filter((s) => !indexedPaths.has(s.relativePath)).map((s) => ({
|
|
341
339
|
name: s.name,
|
|
342
340
|
description: s.description,
|
|
@@ -423,6 +421,38 @@ async function syncSkills(projectRoot) {
|
|
|
423
421
|
};
|
|
424
422
|
}
|
|
425
423
|
|
|
424
|
+
// src/lib/update.ts
|
|
425
|
+
import { access } from "fs/promises";
|
|
426
|
+
import { join as join6 } from "path";
|
|
427
|
+
async function updateSkill(projectRoot, skillPaths) {
|
|
428
|
+
const config = await readConfig(projectRoot);
|
|
429
|
+
const configPathMap = new Map(config.skills.map((s) => [s.path, s.name]));
|
|
430
|
+
for (const skillPath of skillPaths) {
|
|
431
|
+
if (!configPathMap.has(skillPath)) {
|
|
432
|
+
throw new Error(
|
|
433
|
+
`Skill "${skillPath}" is not indexed. Run 'skilldex add ${skillPath}' to index it.`
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
for (const skillPath of skillPaths) {
|
|
438
|
+
const absolutePath = join6(projectRoot, skillPath);
|
|
439
|
+
try {
|
|
440
|
+
await access(absolutePath);
|
|
441
|
+
} catch {
|
|
442
|
+
throw new Error(
|
|
443
|
+
`Skill "${skillPath}" not found on disk. Run 'skilldex sync' to remove stale entries.`
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
const updated = skillPaths.map((p3) => configPathMap.get(p3));
|
|
448
|
+
const result = await regenerateFromConfig(projectRoot);
|
|
449
|
+
return {
|
|
450
|
+
updated,
|
|
451
|
+
managedSize: result.managedSize,
|
|
452
|
+
targets: result.targets
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
|
|
426
456
|
// src/cli/format.ts
|
|
427
457
|
import * as p from "@clack/prompts";
|
|
428
458
|
import pc from "picocolors";
|
|
@@ -697,5 +727,57 @@ program.command("sync").description("Sync skills and regenerate target file").ac
|
|
|
697
727
|
handleCommandError(error, s);
|
|
698
728
|
}
|
|
699
729
|
});
|
|
730
|
+
program.command("update <skill>").description("Refresh the index for a specific skill").action(async (skillName) => {
|
|
731
|
+
p2.intro(pc2.bgCyan(pc2.black(" skilldex update ")));
|
|
732
|
+
const projectRoot = process.cwd();
|
|
733
|
+
const s = p2.spinner();
|
|
734
|
+
try {
|
|
735
|
+
let resolvedPaths;
|
|
736
|
+
if (!skillName.includes("/")) {
|
|
737
|
+
const config = await readConfig(projectRoot);
|
|
738
|
+
const matches = config.skills.filter((sk) => sk.name === skillName);
|
|
739
|
+
if (matches.length === 0) {
|
|
740
|
+
p2.outro(
|
|
741
|
+
pc2.yellow(
|
|
742
|
+
`Skill "${skillName}" is not indexed. Run 'skilldex add ${skillName}' to index it.`
|
|
743
|
+
)
|
|
744
|
+
);
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
if (matches.length === 1) {
|
|
748
|
+
resolvedPaths = [matches[0].path];
|
|
749
|
+
} else {
|
|
750
|
+
const selected = await p2.multiselect({
|
|
751
|
+
message: `Multiple skills named "${skillName}" are indexed. Which to update?`,
|
|
752
|
+
options: matches.map((sk) => {
|
|
753
|
+
const agent = getAgentDisplayName(sk.path);
|
|
754
|
+
return { value: sk.path, label: agent ?? sk.path, hint: sk.path };
|
|
755
|
+
}),
|
|
756
|
+
initialValues: matches.map((sk) => sk.path),
|
|
757
|
+
required: true
|
|
758
|
+
});
|
|
759
|
+
if (p2.isCancel(selected)) {
|
|
760
|
+
p2.cancel("Update cancelled.");
|
|
761
|
+
process.exit(0);
|
|
762
|
+
}
|
|
763
|
+
resolvedPaths = selected;
|
|
764
|
+
}
|
|
765
|
+
} else {
|
|
766
|
+
resolvedPaths = [skillName];
|
|
767
|
+
}
|
|
768
|
+
const count = resolvedPaths.length;
|
|
769
|
+
s.start(`Updating ${count} ${pluralize(count, "skill", "skills")}...`);
|
|
770
|
+
const result = await updateSkill(projectRoot, resolvedPaths);
|
|
771
|
+
s.stop(`\u2713 ${pluralize(count, "Skill", "Skills")} updated`);
|
|
772
|
+
logContextSize(result.managedSize, result.targets);
|
|
773
|
+
p2.outro(
|
|
774
|
+
pc2.green(
|
|
775
|
+
`Updated ${result.updated.map((n) => `"${n}"`).join(", ")} in ${result.targets.map((t) => t.file).join(", ")}`
|
|
776
|
+
)
|
|
777
|
+
);
|
|
778
|
+
} catch (error) {
|
|
779
|
+
handleCommandError(error, s);
|
|
780
|
+
}
|
|
781
|
+
});
|
|
700
782
|
program.parse();
|
|
701
783
|
//# sourceMappingURL=index.js.map
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/index.ts","../../src/lib/config.ts","../../src/lib/constants.ts","../../src/lib/scanner.ts","../../src/lib/agents.ts","../../src/lib/writer.ts","../../src/lib/indexer.ts","../../src/lib/add.ts","../../src/lib/init.ts","../../src/lib/list.ts","../../src/lib/remove.ts","../../src/lib/sync.ts","../../src/cli/format.ts"],"sourcesContent":["import * as p from \"@clack/prompts\";\nimport { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { addSkill } from \"../lib/add.js\";\nimport { getAgentDisplayName } from \"../lib/agents.js\";\nimport { readConfig } from \"../lib/config.js\";\nimport { TARGET_FILE } from \"../lib/constants.js\";\nimport { initWithSkills } from \"../lib/init.js\";\nimport { listSkills } from \"../lib/list.js\";\nimport { removeSkill } from \"../lib/remove.js\";\nimport { scanForSkills } from \"../lib/scanner.js\";\nimport { syncSkills } from \"../lib/sync.js\";\nimport { formatSkillPath, handleCommandError, logContextSize, pluralize } from \"./format.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"skilldex\")\n .description(\"Index AI agent skills into passive context (AGENTS.md)\")\n .version(\"0.1.0\");\n\nprogram\n .command(\"init\")\n .description(\"Initialize skilldex in the current project\")\n .option(\"-y, --yes\", \"Skip prompts and index all discovered skills\")\n .option(\"-t, --target <files...>\", \"Target file(s) to write index to\")\n .action(async (opts: { yes?: boolean; target?: string[] }) => {\n p.intro(pc.bgCyan(pc.black(\" skilldex init \")));\n\n const projectRoot = process.cwd();\n const skills = await scanForSkills(projectRoot);\n\n if (skills.length === 0) {\n p.outro(pc.yellow(\"No skills found in any agent skills directory.\"));\n return;\n }\n\n // Determine target files\n let targets: string[];\n if (opts.target) {\n targets = opts.target;\n } else if (opts.yes) {\n targets = [TARGET_FILE];\n } else {\n const selected = await p.multiselect({\n message: \"Select target file(s)\",\n options: [\n { value: \"AGENTS.md\", label: \"AGENTS.md\", hint: \"default\" },\n { value: \"CLAUDE.md\", label: \"CLAUDE.md\" },\n { value: \"__custom__\", label: \"Custom...\" },\n ],\n initialValues: [\"AGENTS.md\"],\n required: true,\n });\n\n if (p.isCancel(selected)) {\n p.cancel(\"Init cancelled.\");\n process.exit(0);\n }\n\n targets = selected.filter((v) => v !== \"__custom__\");\n\n if (selected.includes(\"__custom__\")) {\n const custom = await p.text({\n message: \"Enter target filename\",\n placeholder: \"AGENTS.md\",\n validate: (value) => {\n if (!value?.trim()) return \"Filename is required\";\n },\n });\n\n if (p.isCancel(custom)) {\n p.cancel(\"Init cancelled.\");\n process.exit(0);\n }\n\n targets.push(custom);\n }\n }\n\n // Detect name collisions for hint display\n const nameCount = new Map<string, number>();\n for (const s of skills) {\n nameCount.set(s.name, (nameCount.get(s.name) ?? 0) + 1);\n }\n\n let selectedSkillPaths: string[];\n\n if (opts.yes) {\n p.log.info(\n `Found ${skills.length} ${pluralize(skills.length, \"skill\", \"skills\")}, indexing all (--yes)`,\n );\n selectedSkillPaths = skills.map((s) => s.relativePath);\n } else {\n const selected = await p.multiselect({\n message: \"Select skills to index\",\n options: skills.map((s) => {\n const relPath = s.relativePath;\n const hasCollision = (nameCount.get(s.name) ?? 0) > 1;\n if (hasCollision) {\n const agent = getAgentDisplayName(relPath);\n const label = agent ? `${s.name} - ${agent}` : s.name;\n return { value: relPath, label, hint: relPath };\n }\n return { value: relPath, label: s.name, hint: s.description || undefined };\n }),\n initialValues: skills.map((s) => s.relativePath),\n required: true,\n });\n\n if (p.isCancel(selected)) {\n p.cancel(\"Init cancelled.\");\n process.exit(0);\n }\n\n selectedSkillPaths = selected;\n }\n\n const selectedSkills = skills.filter((s) => selectedSkillPaths.includes(s.relativePath));\n const result = await initWithSkills(projectRoot, selectedSkills, targets);\n\n logContextSize(result.managedSize, result.targets);\n p.outro(\n pc.green(\n `Indexed ${result.skillCount} ${pluralize(result.skillCount, \"skill\", \"skills\")} into ${result.targets.map((t) => t.file).join(\", \")}`,\n ),\n );\n });\n\nprogram\n .command(\"add <skill>\")\n .description(\"Add a skill to the project\")\n .action(async (skillName: string) => {\n p.intro(pc.bgCyan(pc.black(\" skilldex add \")));\n\n const projectRoot = process.cwd();\n const s = p.spinner();\n\n try {\n // Disambiguate name-based input before calling addSkill\n let resolvedName = skillName;\n\n if (!skillName.includes(\"/\")) {\n const allSkills = await scanForSkills(projectRoot);\n const matches = allSkills.filter((sk) => sk.name === skillName);\n\n if (matches.length > 1) {\n const config = await readConfig(projectRoot);\n const indexedPaths = new Set(config.skills.map((sk) => sk.path));\n const available = matches.filter((sk) => !indexedPaths.has(sk.relativePath));\n\n if (available.length === 0) {\n p.outro(pc.yellow(`All skills named \"${skillName}\" are already indexed.`));\n return;\n }\n\n const selected = await p.select({\n message: `Multiple skills named \"${skillName}\" found. Which one?`,\n options: matches\n .map((sk) => {\n const indexed = indexedPaths.has(sk.relativePath);\n const agent = getAgentDisplayName(sk.relativePath);\n return {\n value: sk.relativePath,\n label: agent ?? sk.relativePath,\n hint: indexed ? \"already indexed\" : sk.relativePath,\n disabled: indexed,\n };\n })\n .sort((a, b) => {\n if (a.disabled !== b.disabled) return a.disabled ? -1 : 1;\n return a.label.localeCompare(b.label);\n }),\n });\n\n if (p.isCancel(selected)) {\n p.cancel(\"Add cancelled.\");\n process.exit(0);\n }\n\n resolvedName = selected;\n }\n }\n\n s.start(\"Adding skill...\");\n const result = await addSkill(projectRoot, resolvedName);\n s.stop(\"✓ Skill added\");\n\n logContextSize(result.managedSize, result.targets);\n p.outro(\n pc.green(`Added \"${result.skillName}\" to ${result.targets.map((t) => t.file).join(\", \")}`),\n );\n } catch (error) {\n handleCommandError(error, s);\n }\n });\n\nprogram\n .command(\"remove <skill>\")\n .description(\"Remove a skill from the project\")\n .option(\"--delete-files\", \"Delete skill files from disk\")\n .action(async (skillName: string, opts: { deleteFiles?: boolean }) => {\n p.intro(pc.bgCyan(pc.black(\" skilldex remove \")));\n\n const projectRoot = process.cwd();\n const s = p.spinner();\n\n try {\n // Disambiguate name-based input before removing\n let resolvedName = skillName;\n\n if (!skillName.includes(\"/\")) {\n const config = await readConfig(projectRoot);\n const matches = config.skills.filter((sk) => sk.name === skillName);\n\n if (matches.length > 1) {\n const selected = await p.select({\n message: `Multiple skills named \"${skillName}\" indexed. Which one?`,\n options: matches.map((sk) => {\n const agent = getAgentDisplayName(sk.path);\n return { value: sk.path, label: agent ?? sk.path, hint: sk.path };\n }),\n });\n\n if (p.isCancel(selected)) {\n p.cancel(\"Remove cancelled.\");\n process.exit(0);\n }\n\n resolvedName = selected;\n }\n }\n\n let deleteFiles = opts.deleteFiles ?? false;\n\n if (!opts.deleteFiles) {\n const shouldDelete = await p.confirm({\n message: `Delete skill files from disk (${resolvedName})?`,\n initialValue: false,\n });\n\n if (p.isCancel(shouldDelete)) {\n p.cancel(\"Remove cancelled.\");\n process.exit(0);\n }\n\n deleteFiles = shouldDelete;\n }\n\n s.start(\"Removing skill...\");\n const result = await removeSkill(projectRoot, resolvedName, deleteFiles);\n s.stop(\"✓ Skill removed\");\n\n logContextSize(result.managedSize, result.targets);\n const suffix = result.wasDeleted ? \" (files deleted)\" : \" (files kept on disk)\";\n p.outro(pc.green(`Removed \"${result.skillName}\"${suffix}`));\n } catch (error) {\n handleCommandError(error, s);\n }\n });\n\nprogram\n .command(\"list\")\n .description(\"List indexed and available skills\")\n .action(async () => {\n p.intro(pc.bgCyan(pc.black(\" skilldex list \")));\n\n const projectRoot = process.cwd();\n\n try {\n const result = await listSkills(projectRoot);\n\n if (result.indexed.length > 0) {\n p.log.step(pc.bold(\"Indexed skills\"));\n const indexedLines = result.indexed.map(\n (skill) => ` ${pc.green(skill.name)} ${formatSkillPath(skill.path)}`,\n );\n p.log.info(indexedLines.join(\"\\n\"));\n } else {\n p.log.info(pc.dim(\"No indexed skills.\"));\n }\n\n if (result.available.length > 0) {\n p.log.step(pc.bold(\"Available skills (not indexed)\"));\n const availableLines = result.available.map(\n (skill) => ` ${pc.yellow(skill.name)} ${formatSkillPath(skill.path)}`,\n );\n p.log.info(availableLines.join(\"\\n\"));\n }\n\n p.outro(pc.green(\"Done\"));\n } catch (error) {\n handleCommandError(error);\n }\n });\n\nprogram\n .command(\"sync\")\n .description(\"Sync skills and regenerate target file\")\n .action(async () => {\n p.intro(pc.bgCyan(pc.black(\" skilldex sync \")));\n\n const projectRoot = process.cwd();\n const s = p.spinner();\n\n try {\n s.start(\"Syncing...\");\n const result = await syncSkills(projectRoot);\n s.stop(\"✓ Sync complete\");\n\n if (result.removed.length > 0) {\n for (const name of result.removed) {\n p.log.warn(pc.red(`Removed stale skill \"${name}\" (missing from disk)`));\n }\n }\n\n logContextSize(result.managedSize, result.targets);\n\n if (result.changed) {\n p.outro(pc.green(\"Index updated\"));\n } else {\n p.outro(pc.green(\"Everything up to date\"));\n }\n } catch (error) {\n handleCommandError(error, s);\n }\n });\n\nprogram.parse();\n","import { writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { CONFIG_FILENAME, compareByNameThenPath, TARGET_FILE } from \"./constants.js\";\nimport { safeReadFile } from \"./scanner.js\";\nimport type { Config } from \"./types.js\";\n\nfunction getDefaultConfig(): Config {\n return {\n version: 1,\n targets: [TARGET_FILE],\n skills: [],\n };\n}\n\nexport async function readConfig(projectRoot: string): Promise<Config> {\n const configPath = join(projectRoot, CONFIG_FILENAME);\n const content = await safeReadFile(configPath);\n\n if (content === undefined) {\n return getDefaultConfig();\n }\n\n try {\n const parsed = JSON.parse(content) as Config;\n // Validate structure\n if (\n typeof parsed.version !== \"number\" ||\n !Array.isArray(parsed.targets) ||\n !Array.isArray(parsed.skills)\n ) {\n return getDefaultConfig();\n }\n return parsed;\n } catch {\n return getDefaultConfig();\n }\n}\n\nexport async function writeConfig(projectRoot: string, config: Config): Promise<void> {\n const configPath = join(projectRoot, CONFIG_FILENAME);\n const sorted = {\n ...config,\n skills: [...config.skills].sort(compareByNameThenPath),\n };\n const content = JSON.stringify(sorted, null, 2);\n await writeFile(configPath, content, \"utf-8\");\n}\n","export const START_TAG = \"<!-- skilldex:start (auto-generated, do not edit) -->\";\nexport const END_TAG = \"<!-- skilldex:end -->\";\n\nexport const TARGET_FILE = \"AGENTS.md\";\nexport const CONFIG_FILENAME = \"skilldex.config.json\";\nexport const SKILL_META_FILE = \"SKILL.md\";\nexport const SKILLS_DIR_SEGMENTS = [\".agents\", \"skills\"] as const;\nexport const INDEX_HEADER = \"[Skills Index]\";\nexport const INDEX_INSTRUCTION =\n \"IMPORTANT: Prefer retrieval-led reasoning over pre-training-led reasoning for any tasks covered by indexed skills.\";\nexport const CONTEXT_BUDGET_WARN_KB = 20;\nexport const CONTEXT_BUDGET_DANGER_KB = 40;\n\nexport function compareByNameThenPath(\n a: { name: string; path: string },\n b: { name: string; path: string },\n): number {\n return a.name.localeCompare(b.name) || a.path.localeCompare(b.path);\n}\n","import type { Dirent } from \"node:fs\";\nimport { lstat, readdir, readFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { getUniqueSkillsDirs } from \"./agents.js\";\nimport { compareByNameThenPath, SKILL_META_FILE } from \"./constants.js\";\nimport type { DiscoveredSkill, SkillFile } from \"./types.js\";\n\n/** Extract key-value pairs from YAML frontmatter (between `---` fences). */\nexport function parseFrontmatter(content: string): Record<string, string> {\n const result: Record<string, string> = {};\n if (!content.startsWith(\"---\")) return result;\n\n const endIndex = content.indexOf(\"\\n---\", 3);\n if (endIndex === -1) return result;\n\n const block = content.slice(4, endIndex);\n for (const line of block.split(\"\\n\")) {\n const colonIndex = line.indexOf(\":\");\n if (colonIndex === -1) continue;\n const key = line.slice(0, colonIndex).trim();\n const value = line.slice(colonIndex + 1).trim();\n if (key) result[key] = value;\n }\n return result;\n}\n\nasync function safeReaddir(dir: string): Promise<Dirent[]> {\n try {\n return await readdir(dir, { withFileTypes: true });\n } catch {\n return [];\n }\n}\n\nexport async function safeReadFile(path: string): Promise<string | undefined> {\n try {\n return await readFile(path, \"utf-8\");\n } catch {\n return undefined;\n }\n}\n\nasync function collectMdFiles(dir: string, skillRoot: string): Promise<SkillFile[]> {\n const entries = await safeReaddir(dir);\n const files: SkillFile[] = [];\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n const nested = await collectMdFiles(fullPath, skillRoot);\n files.push(...nested);\n } else if (entry.isFile() && entry.name.endsWith(\".md\") && entry.name !== SKILL_META_FILE) {\n files.push({\n relativePath: relative(skillRoot, fullPath),\n name: entry.name.replace(/\\.md$/, \"\"),\n });\n }\n }\n return files;\n}\n\nasync function isSymlink(path: string): Promise<boolean> {\n try {\n const stats = await lstat(path);\n return stats.isSymbolicLink();\n } catch {\n return false;\n }\n}\n\n/** Scan a single skills directory and return discovered skills. */\nasync function scanDirectory(dir: string, projectRoot: string): Promise<DiscoveredSkill[]> {\n const entries = await safeReaddir(dir);\n const skills: DiscoveredSkill[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n\n const skillPath = join(dir, entry.name);\n\n if (await isSymlink(skillPath)) continue;\n\n let description = \"\";\n const skillMd = await safeReadFile(join(skillPath, SKILL_META_FILE));\n if (skillMd !== undefined) {\n const frontmatter = parseFrontmatter(skillMd);\n description = frontmatter.description ?? \"\";\n }\n\n const files = await collectMdFiles(skillPath, skillPath);\n skills.push({\n name: entry.name,\n description,\n path: skillPath,\n relativePath: relative(projectRoot, skillPath),\n files,\n });\n }\n return skills;\n}\n\n/** Scan all agent source directories for skills. Same-named skills in different directories are all included. */\nexport async function scanForSkills(projectRoot: string): Promise<DiscoveredSkill[]> {\n const results = await Promise.all(\n getUniqueSkillsDirs().map((d) => scanDirectory(join(projectRoot, d), projectRoot)),\n );\n return results.flat().sort(compareByNameThenPath);\n}\n","export interface AgentSource {\n /** Agent identifier, e.g. \"claude-code\" */\n name: string;\n /** Human-readable name, e.g. \"Claude Code\" */\n displayName: string;\n /** Skills directory relative to project root, e.g. \".claude/skills\" */\n skillsDir: string;\n}\n\n/**\n * Known agent source directories (project-scoped).\n * Sourced from the Vercel Skills CLI agent conventions.\n */\nexport const AGENT_SOURCES: AgentSource[] = [\n { name: \"universal\", displayName: \"Universal\", skillsDir: \".agents/skills\" },\n { name: \"antigravity\", displayName: \"Antigravity\", skillsDir: \".agent/skills\" },\n { name: \"claude-code\", displayName: \"Claude Code\", skillsDir: \".claude/skills\" },\n { name: \"codex\", displayName: \"Codex\", skillsDir: \".agents/skills\" },\n { name: \"cursor\", displayName: \"Cursor\", skillsDir: \".cursor/skills\" },\n { name: \"github-copilot\", displayName: \"GitHub Copilot\", skillsDir: \".agents/skills\" },\n { name: \"opencode\", displayName: \"OpenCode\", skillsDir: \".agents/skills\" },\n { name: \"openclaw\", displayName: \"OpenClaw\", skillsDir: \"skills\" },\n { name: \"windsurf\", displayName: \"Windsurf\", skillsDir: \".windsurf/skills\" },\n];\n\n/** Unique skills directories to scan (deduplicates agents sharing the same dir). */\nexport function getUniqueSkillsDirs(): string[] {\n return [...new Set(AGENT_SOURCES.map((a) => a.skillsDir))];\n}\n\n/** Maps a skill's relative path to the first matching agent's display name. */\nexport function getAgentDisplayName(relativePath: string): string | undefined {\n for (const agent of AGENT_SOURCES) {\n if (relativePath.startsWith(`${agent.skillsDir}/`) || relativePath === agent.skillsDir) {\n return agent.displayName;\n }\n }\n return undefined;\n}\n","import { stat, writeFile } from \"node:fs/promises\";\nimport { basename, join } from \"node:path\";\nimport { readConfig } from \"./config.js\";\nimport { END_TAG, START_TAG, TARGET_FILE } from \"./constants.js\";\nimport { generateIndex } from \"./indexer.js\";\nimport { safeReadFile, scanForSkills } from \"./scanner.js\";\nimport type { InitResult, TargetFileInfo } from \"./types.js\";\n\nexport async function getTargetInfos(\n projectRoot: string,\n targets: string[],\n): Promise<TargetFileInfo[]> {\n return Promise.all(\n targets.map(async (t) => {\n const p = join(projectRoot, t);\n const s = await stat(p);\n return { file: basename(t), path: p, totalSize: s.size };\n }),\n );\n}\n\nexport function buildManagedSection(indexContent: string): string {\n return `${START_TAG}\\n${indexContent}\\n${END_TAG}`;\n}\n\n/** Write or update the managed skilldex section in a target file. Creates, appends, or replaces as needed. Returns the written file content. */\nexport async function writeTargetFile(\n projectRoot: string,\n indexContent: string,\n targetFile: string = TARGET_FILE,\n): Promise<string> {\n const targetPath = join(projectRoot, targetFile);\n const section = buildManagedSection(indexContent);\n\n const existing = await safeReadFile(targetPath);\n\n let output: string;\n if (existing === undefined) {\n output = `${section}\\n`;\n } else if (existing.includes(START_TAG) && existing.includes(END_TAG)) {\n const startIdx = existing.indexOf(START_TAG);\n const endIdx = existing.indexOf(END_TAG) + END_TAG.length;\n output = existing.slice(0, startIdx) + section + existing.slice(endIdx);\n } else {\n output = `${existing.trimEnd()}\\n\\n${section}\\n`;\n }\n\n await writeFile(targetPath, output, \"utf-8\");\n return output;\n}\n\nexport interface RegenerateResult extends InitResult {\n /** Map of target file path → written content */\n writtenContent: Map<string, string>;\n}\n\n/** Regenerate all target files from config (reads config, scans indexed skills, writes targets). */\nexport async function regenerateFromConfig(projectRoot: string): Promise<RegenerateResult> {\n const config = await readConfig(projectRoot);\n const allSkills = await scanForSkills(projectRoot);\n\n // Map skill paths from config to DiscoveredSkill objects\n const skillMap = new Map(allSkills.map((s) => [s.relativePath, s]));\n const skills = config.skills\n .map((entry) => skillMap.get(entry.path))\n .filter((s) => s !== undefined);\n\n const index = generateIndex(skills);\n\n const writtenContent = new Map<string, string>();\n for (const target of config.targets) {\n const content = await writeTargetFile(projectRoot, index, target);\n writtenContent.set(join(projectRoot, target), content);\n }\n\n const managedSize = Buffer.byteLength(buildManagedSection(index));\n const targets = await getTargetInfos(projectRoot, config.targets);\n\n return {\n skillCount: skills.length,\n managedSize,\n targets,\n writtenContent,\n };\n}\n","import { dirname } from \"node:path\";\nimport { INDEX_HEADER, INDEX_INSTRUCTION } from \"./constants.js\";\nimport type { DiscoveredSkill } from \"./types.js\";\n\nfunction groupFilesBySubdir(\n files: { relativePath: string; name: string }[],\n): Map<string, string[]> {\n const groups = new Map<string, string[]>();\n for (const file of files) {\n const dir = dirname(file.relativePath);\n const key = dir === \".\" ? \"\" : dir;\n const existing = groups.get(key);\n if (existing) {\n existing.push(`${file.name}.md`);\n } else {\n groups.set(key, [`${file.name}.md`]);\n }\n }\n return groups;\n}\n\nexport function generateIndex(skills: DiscoveredSkill[]): string {\n const segments: string[] = [INDEX_HEADER, INDEX_INSTRUCTION];\n\n for (const skill of skills) {\n segments.push(`[${skill.name}]`);\n segments.push(`root:./${skill.relativePath}`);\n\n if (skill.description) {\n segments.push(`desc:${skill.description}`);\n }\n\n const groups = groupFilesBySubdir(skill.files);\n for (const [subdir, fileNames] of groups) {\n const fileList = `{${fileNames.join(\",\")}}`;\n if (subdir) {\n segments.push(`${subdir}:${fileList}`);\n } else {\n segments.push(fileList);\n }\n }\n }\n\n return segments.join(\"|\");\n}\n","import { readConfig, writeConfig } from \"./config.js\";\nimport { scanForSkills } from \"./scanner.js\";\nimport type { AddResult, DiscoveredSkill } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function addSkill(projectRoot: string, skillName: string): Promise<AddResult> {\n const config = await readConfig(projectRoot);\n const allSkills = await scanForSkills(projectRoot);\n\n const isPath = skillName.includes(\"/\");\n\n let targetSkill: DiscoveredSkill | undefined;\n\n if (isPath) {\n // Path-based lookup for disambiguation\n targetSkill = allSkills.find((s) => s.relativePath === skillName);\n if (!targetSkill) {\n throw new Error(`Skill \"${skillName}\" not found. Did you create the skill directory?`);\n }\n } else {\n // Name-based lookup\n const matches = allSkills.filter((s) => s.name === skillName);\n if (matches.length === 0) {\n throw new Error(`Skill \"${skillName}\" not found. Did you create the skill directory?`);\n }\n if (matches.length > 1) {\n const paths = matches.map((s) => ` ${s.relativePath}`).join(\"\\n\");\n throw new Error(`Multiple skills named \"${skillName}\" found. Specify the path:\\n${paths}`);\n }\n targetSkill = matches[0];\n }\n\n if (config.skills.some((s) => s.path === targetSkill.relativePath)) {\n throw new Error(`Skill \"${targetSkill.relativePath}\" is already indexed`);\n }\n\n config.skills.push({\n name: targetSkill.name,\n path: targetSkill.relativePath,\n });\n\n await writeConfig(projectRoot, config);\n\n const result = await regenerateFromConfig(projectRoot);\n\n return {\n skillName: targetSkill.name,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n","import { writeConfig } from \"./config.js\";\nimport { TARGET_FILE } from \"./constants.js\";\nimport { scanForSkills } from \"./scanner.js\";\nimport type { DiscoveredSkill, InitResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\n/** Scan for skills, filter by selection, and write the index to target files. */\nexport async function init(options: {\n projectRoot: string;\n selectedSkills?: string[];\n yes?: boolean;\n}): Promise<InitResult> {\n const { projectRoot, selectedSkills } = options;\n\n const discovered = await scanForSkills(projectRoot);\n\n let skills: DiscoveredSkill[];\n if (selectedSkills) {\n const selected = new Set(selectedSkills);\n skills = discovered.filter((s) => selected.has(s.name) || selected.has(s.relativePath));\n } else {\n skills = discovered;\n }\n\n return initWithSkills(projectRoot, skills);\n}\n\n/** Index a specific set of skills and write to target file(s). */\nexport async function initWithSkills(\n projectRoot: string,\n skills: DiscoveredSkill[],\n targets: string[] = [TARGET_FILE],\n): Promise<InitResult> {\n const config = {\n version: 1 as const,\n targets,\n skills: skills.map((skill) => ({\n name: skill.name,\n path: skill.relativePath,\n })),\n };\n await writeConfig(projectRoot, config);\n\n return regenerateFromConfig(projectRoot);\n}\n","import { readConfig } from \"./config.js\";\nimport { scanForSkills } from \"./scanner.js\";\nimport type { ListResult, SkillInfo } from \"./types.js\";\n\nexport async function listSkills(projectRoot: string): Promise<ListResult> {\n const config = await readConfig(projectRoot);\n const allSkills = await scanForSkills(projectRoot);\n\n const indexedPaths = new Set(config.skills.map((s) => s.path));\n const skillMap = new Map(allSkills.map((s) => [s.relativePath, s]));\n\n const indexed: SkillInfo[] = config.skills\n .map((entry) => {\n const discovered = skillMap.get(entry.path);\n if (!discovered) return undefined;\n return {\n name: entry.name,\n path: entry.path,\n description: discovered.description,\n };\n })\n .filter((s) => s !== undefined);\n\n const available: SkillInfo[] = allSkills\n .filter((s) => !indexedPaths.has(s.relativePath))\n .map((s) => ({\n name: s.name,\n description: s.description,\n path: s.relativePath,\n }));\n\n return { indexed, available };\n}\n","import { rm } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { readConfig, writeConfig } from \"./config.js\";\nimport type { RemoveResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function removeSkill(\n projectRoot: string,\n skillName: string,\n deleteFiles = false,\n): Promise<RemoveResult> {\n const config = await readConfig(projectRoot);\n\n const isPath = skillName.includes(\"/\");\n\n let skillIndex: number;\n\n if (isPath) {\n skillIndex = config.skills.findIndex((s) => s.path === skillName);\n if (skillIndex === -1) {\n throw new Error(`Skill \"${skillName}\" is not indexed`);\n }\n } else {\n const matches = config.skills\n .map((s, i) => ({ entry: s, index: i }))\n .filter(({ entry }) => entry.name === skillName);\n\n if (matches.length === 0) {\n throw new Error(`Skill \"${skillName}\" is not indexed`);\n }\n if (matches.length > 1) {\n const paths = matches.map(({ entry }) => ` ${entry.path}`).join(\"\\n\");\n throw new Error(`Multiple skills named \"${skillName}\" indexed. Specify the path:\\n${paths}`);\n }\n skillIndex = matches[0].index;\n }\n\n const entry = config.skills[skillIndex];\n const skillPath = join(projectRoot, entry.path);\n\n config.skills.splice(skillIndex, 1);\n await writeConfig(projectRoot, config);\n\n if (deleteFiles) {\n await rm(skillPath, { recursive: true, force: true });\n }\n\n const result = await regenerateFromConfig(projectRoot);\n\n return {\n skillName: entry.name,\n wasDeleted: deleteFiles,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n","import { join } from \"node:path\";\nimport { readConfig, writeConfig } from \"./config.js\";\nimport { safeReadFile, scanForSkills } from \"./scanner.js\";\nimport type { SyncResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function syncSkills(projectRoot: string): Promise<SyncResult> {\n const config = await readConfig(projectRoot);\n const onDisk = await scanForSkills(projectRoot);\n const diskPaths = new Set(onDisk.map((s) => s.relativePath));\n\n // Find stale entries: in config but not on disk\n const stale = config.skills.filter((s) => !diskPaths.has(s.path));\n const removed = stale.map((s) => s.name);\n\n if (stale.length > 0) {\n const stalePaths = new Set(stale.map((s) => s.path));\n config.skills = config.skills.filter((s) => !stalePaths.has(s.path));\n await writeConfig(projectRoot, config);\n }\n\n const targetPaths = config.targets.map((t) => join(projectRoot, t));\n\n // Read before-state for all targets\n const beforeMap = new Map<string, string | undefined>();\n for (const targetPath of targetPaths) {\n beforeMap.set(targetPath, await safeReadFile(targetPath));\n }\n\n // Nothing to do if no skills indexed and no target files exist\n if (config.skills.length === 0 && [...beforeMap.values()].every((v) => v === undefined)) {\n return { removed, changed: false, managedSize: 0, targets: [] };\n }\n\n const result = await regenerateFromConfig(projectRoot);\n\n // Check if ANY target changed using the written content from regeneration\n let changed = false;\n for (const targetPath of targetPaths) {\n const after = result.writtenContent.get(targetPath);\n if (beforeMap.get(targetPath) !== after) {\n changed = true;\n break;\n }\n }\n\n return {\n removed,\n changed,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n","import * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { getAgentDisplayName } from \"../lib/agents.js\";\nimport { CONTEXT_BUDGET_DANGER_KB, CONTEXT_BUDGET_WARN_KB } from \"../lib/constants.js\";\nimport type { TargetFileInfo } from \"../lib/types.js\";\n\nexport function pluralize(count: number, singular: string, plural: string): string {\n return count === 1 ? singular : plural;\n}\n\nfunction formatKb(bytes: number): string {\n return `${(bytes / 1024).toFixed(1)} KB`;\n}\n\nexport function logContextSize(managedSize: number, targets: TargetFileInfo[]): void {\n const sizeKb = managedSize / 1024;\n const sizeFormatted = formatKb(managedSize);\n let sizeLabel: string;\n if (sizeKb < CONTEXT_BUDGET_WARN_KB) {\n sizeLabel = pc.green(sizeFormatted);\n } else if (sizeKb < CONTEXT_BUDGET_DANGER_KB) {\n sizeLabel = pc.yellow(sizeFormatted);\n } else {\n sizeLabel = pc.red(`${sizeFormatted} — may degrade agent performance`);\n }\n\n const targetLines = targets.map(\n (t) => ` ${t.file} ${pc.dim(`${formatKb(t.totalSize)} total`)}`,\n );\n p.log.info(`Context: ${sizeLabel} (managed section)\\n${targetLines.join(\"\\n\")}`);\n}\n\nexport function formatSkillPath(relativePath: string): string {\n const agent = getAgentDisplayName(relativePath);\n if (agent) return `${pc.cyan(agent)} ${pc.dim(relativePath)}`;\n return pc.dim(relativePath);\n}\n\nexport function handleCommandError(error: unknown, spinner?: ReturnType<typeof p.spinner>): never {\n if (spinner) {\n spinner.stop(\"✗ Failed\");\n }\n const message = error instanceof Error ? error.message : String(error);\n p.outro(pc.red(message));\n process.exit(1);\n}\n"],"mappings":"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","names":["p","pc","join","join","writeFile","join","p","join","writeFile","join","entry","join","join","join","spinner","pc"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/index.ts","../../src/lib/config.ts","../../src/lib/constants.ts","../../src/lib/scanner.ts","../../src/lib/agents.ts","../../src/lib/writer.ts","../../src/lib/indexer.ts","../../src/lib/add.ts","../../src/lib/init.ts","../../src/lib/list.ts","../../src/lib/remove.ts","../../src/lib/sync.ts","../../src/lib/update.ts","../../src/cli/format.ts"],"sourcesContent":["import * as p from \"@clack/prompts\";\nimport { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { addSkill } from \"../lib/add.js\";\nimport { getAgentDisplayName } from \"../lib/agents.js\";\nimport { readConfig } from \"../lib/config.js\";\nimport { TARGET_FILE } from \"../lib/constants.js\";\nimport { initWithSkills } from \"../lib/init.js\";\nimport { listSkills } from \"../lib/list.js\";\nimport { removeSkill } from \"../lib/remove.js\";\nimport { scanForSkills } from \"../lib/scanner.js\";\nimport { syncSkills } from \"../lib/sync.js\";\nimport { updateSkill } from \"../lib/update.js\";\nimport { formatSkillPath, handleCommandError, logContextSize, pluralize } from \"./format.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"skilldex\")\n .description(\"Index AI agent skills into passive context (AGENTS.md)\")\n .version(\"0.1.0\");\n\nprogram\n .command(\"init\")\n .description(\"Initialize skilldex in the current project\")\n .option(\"-y, --yes\", \"Skip prompts and index all discovered skills\")\n .option(\"-t, --target <files...>\", \"Target file(s) to write index to\")\n .action(async (opts: { yes?: boolean; target?: string[] }) => {\n p.intro(pc.bgCyan(pc.black(\" skilldex init \")));\n\n const projectRoot = process.cwd();\n const skills = await scanForSkills(projectRoot);\n\n if (skills.length === 0) {\n p.outro(pc.yellow(\"No skills found in any agent skills directory.\"));\n return;\n }\n\n // Determine target files\n let targets: string[];\n if (opts.target) {\n targets = opts.target;\n } else if (opts.yes) {\n targets = [TARGET_FILE];\n } else {\n const selected = await p.multiselect({\n message: \"Select target file(s)\",\n options: [\n { value: \"AGENTS.md\", label: \"AGENTS.md\", hint: \"default\" },\n { value: \"CLAUDE.md\", label: \"CLAUDE.md\" },\n { value: \"__custom__\", label: \"Custom...\" },\n ],\n initialValues: [\"AGENTS.md\"],\n required: true,\n });\n\n if (p.isCancel(selected)) {\n p.cancel(\"Init cancelled.\");\n process.exit(0);\n }\n\n targets = selected.filter((v) => v !== \"__custom__\");\n\n if (selected.includes(\"__custom__\")) {\n const custom = await p.text({\n message: \"Enter target filename\",\n placeholder: \"AGENTS.md\",\n validate: (value) => {\n if (!value?.trim()) return \"Filename is required\";\n },\n });\n\n if (p.isCancel(custom)) {\n p.cancel(\"Init cancelled.\");\n process.exit(0);\n }\n\n targets.push(custom);\n }\n }\n\n // Detect name collisions for hint display\n const nameCount = new Map<string, number>();\n for (const s of skills) {\n nameCount.set(s.name, (nameCount.get(s.name) ?? 0) + 1);\n }\n\n let selectedSkillPaths: string[];\n\n if (opts.yes) {\n p.log.info(\n `Found ${skills.length} ${pluralize(skills.length, \"skill\", \"skills\")}, indexing all (--yes)`,\n );\n selectedSkillPaths = skills.map((s) => s.relativePath);\n } else {\n const selected = await p.multiselect({\n message: \"Select skills to index\",\n options: skills.map((s) => {\n const relPath = s.relativePath;\n const hasCollision = (nameCount.get(s.name) ?? 0) > 1;\n if (hasCollision) {\n const agent = getAgentDisplayName(relPath);\n const label = agent ? `${s.name} - ${agent}` : s.name;\n return { value: relPath, label, hint: relPath };\n }\n return { value: relPath, label: s.name, hint: s.description || undefined };\n }),\n initialValues: skills.map((s) => s.relativePath),\n required: true,\n });\n\n if (p.isCancel(selected)) {\n p.cancel(\"Init cancelled.\");\n process.exit(0);\n }\n\n selectedSkillPaths = selected;\n }\n\n const selectedSkills = skills.filter((s) => selectedSkillPaths.includes(s.relativePath));\n const result = await initWithSkills(projectRoot, selectedSkills, targets);\n\n logContextSize(result.managedSize, result.targets);\n p.outro(\n pc.green(\n `Indexed ${result.skillCount} ${pluralize(result.skillCount, \"skill\", \"skills\")} into ${result.targets.map((t) => t.file).join(\", \")}`,\n ),\n );\n });\n\nprogram\n .command(\"add <skill>\")\n .description(\"Add a skill to the project\")\n .action(async (skillName: string) => {\n p.intro(pc.bgCyan(pc.black(\" skilldex add \")));\n\n const projectRoot = process.cwd();\n const s = p.spinner();\n\n try {\n // Disambiguate name-based input before calling addSkill\n let resolvedName = skillName;\n\n if (!skillName.includes(\"/\")) {\n const allSkills = await scanForSkills(projectRoot);\n const matches = allSkills.filter((sk) => sk.name === skillName);\n\n if (matches.length > 1) {\n const config = await readConfig(projectRoot);\n const indexedPaths = new Set(config.skills.map((sk) => sk.path));\n const available = matches.filter((sk) => !indexedPaths.has(sk.relativePath));\n\n if (available.length === 0) {\n p.outro(pc.yellow(`All skills named \"${skillName}\" are already indexed.`));\n return;\n }\n\n const selected = await p.select({\n message: `Multiple skills named \"${skillName}\" found. Which one?`,\n options: matches\n .map((sk) => {\n const indexed = indexedPaths.has(sk.relativePath);\n const agent = getAgentDisplayName(sk.relativePath);\n return {\n value: sk.relativePath,\n label: agent ?? sk.relativePath,\n hint: indexed ? \"already indexed\" : sk.relativePath,\n disabled: indexed,\n };\n })\n .sort((a, b) => {\n if (a.disabled !== b.disabled) return a.disabled ? -1 : 1;\n return a.label.localeCompare(b.label);\n }),\n });\n\n if (p.isCancel(selected)) {\n p.cancel(\"Add cancelled.\");\n process.exit(0);\n }\n\n resolvedName = selected;\n }\n }\n\n s.start(\"Adding skill...\");\n const result = await addSkill(projectRoot, resolvedName);\n s.stop(\"✓ Skill added\");\n\n logContextSize(result.managedSize, result.targets);\n p.outro(\n pc.green(`Added \"${result.skillName}\" to ${result.targets.map((t) => t.file).join(\", \")}`),\n );\n } catch (error) {\n handleCommandError(error, s);\n }\n });\n\nprogram\n .command(\"remove <skill>\")\n .description(\"Remove a skill from the project\")\n .option(\"--delete-files\", \"Delete skill files from disk\")\n .action(async (skillName: string, opts: { deleteFiles?: boolean }) => {\n p.intro(pc.bgCyan(pc.black(\" skilldex remove \")));\n\n const projectRoot = process.cwd();\n const s = p.spinner();\n\n try {\n // Disambiguate name-based input before removing\n let resolvedName = skillName;\n\n if (!skillName.includes(\"/\")) {\n const config = await readConfig(projectRoot);\n const matches = config.skills.filter((sk) => sk.name === skillName);\n\n if (matches.length > 1) {\n const selected = await p.select({\n message: `Multiple skills named \"${skillName}\" indexed. Which one?`,\n options: matches.map((sk) => {\n const agent = getAgentDisplayName(sk.path);\n return { value: sk.path, label: agent ?? sk.path, hint: sk.path };\n }),\n });\n\n if (p.isCancel(selected)) {\n p.cancel(\"Remove cancelled.\");\n process.exit(0);\n }\n\n resolvedName = selected;\n }\n }\n\n let deleteFiles = opts.deleteFiles ?? false;\n\n if (!opts.deleteFiles) {\n const shouldDelete = await p.confirm({\n message: `Delete skill files from disk (${resolvedName})?`,\n initialValue: false,\n });\n\n if (p.isCancel(shouldDelete)) {\n p.cancel(\"Remove cancelled.\");\n process.exit(0);\n }\n\n deleteFiles = shouldDelete;\n }\n\n s.start(\"Removing skill...\");\n const result = await removeSkill(projectRoot, resolvedName, deleteFiles);\n s.stop(\"✓ Skill removed\");\n\n logContextSize(result.managedSize, result.targets);\n const suffix = result.wasDeleted ? \" (files deleted)\" : \" (files kept on disk)\";\n p.outro(pc.green(`Removed \"${result.skillName}\"${suffix}`));\n } catch (error) {\n handleCommandError(error, s);\n }\n });\n\nprogram\n .command(\"list\")\n .description(\"List indexed and available skills\")\n .action(async () => {\n p.intro(pc.bgCyan(pc.black(\" skilldex list \")));\n\n const projectRoot = process.cwd();\n\n try {\n const result = await listSkills(projectRoot);\n\n if (result.indexed.length > 0) {\n p.log.step(pc.bold(\"Indexed skills\"));\n const indexedLines = result.indexed.map(\n (skill) => ` ${pc.green(skill.name)} ${formatSkillPath(skill.path)}`,\n );\n p.log.info(indexedLines.join(\"\\n\"));\n } else {\n p.log.info(pc.dim(\"No indexed skills.\"));\n }\n\n if (result.available.length > 0) {\n p.log.step(pc.bold(\"Available skills (not indexed)\"));\n const availableLines = result.available.map(\n (skill) => ` ${pc.yellow(skill.name)} ${formatSkillPath(skill.path)}`,\n );\n p.log.info(availableLines.join(\"\\n\"));\n }\n\n p.outro(pc.green(\"Done\"));\n } catch (error) {\n handleCommandError(error);\n }\n });\n\nprogram\n .command(\"sync\")\n .description(\"Sync skills and regenerate target file\")\n .action(async () => {\n p.intro(pc.bgCyan(pc.black(\" skilldex sync \")));\n\n const projectRoot = process.cwd();\n const s = p.spinner();\n\n try {\n s.start(\"Syncing...\");\n const result = await syncSkills(projectRoot);\n s.stop(\"✓ Sync complete\");\n\n if (result.removed.length > 0) {\n for (const name of result.removed) {\n p.log.warn(pc.red(`Removed stale skill \"${name}\" (missing from disk)`));\n }\n }\n\n logContextSize(result.managedSize, result.targets);\n\n if (result.changed) {\n p.outro(pc.green(\"Index updated\"));\n } else {\n p.outro(pc.green(\"Everything up to date\"));\n }\n } catch (error) {\n handleCommandError(error, s);\n }\n });\n\nprogram\n .command(\"update <skill>\")\n .description(\"Refresh the index for a specific skill\")\n .action(async (skillName: string) => {\n p.intro(pc.bgCyan(pc.black(\" skilldex update \")));\n\n const projectRoot = process.cwd();\n const s = p.spinner();\n\n try {\n let resolvedPaths: string[];\n\n if (!skillName.includes(\"/\")) {\n const config = await readConfig(projectRoot);\n const matches = config.skills.filter((sk) => sk.name === skillName);\n\n if (matches.length === 0) {\n p.outro(\n pc.yellow(\n `Skill \"${skillName}\" is not indexed. Run 'skilldex add ${skillName}' to index it.`,\n ),\n );\n return;\n }\n\n if (matches.length === 1) {\n resolvedPaths = [matches[0].path];\n } else {\n // Multiple indexed skills with the same name — let the user pick one or more\n const selected = await p.multiselect({\n message: `Multiple skills named \"${skillName}\" are indexed. Which to update?`,\n options: matches.map((sk) => {\n const agent = getAgentDisplayName(sk.path);\n return { value: sk.path, label: agent ?? sk.path, hint: sk.path };\n }),\n initialValues: matches.map((sk) => sk.path),\n required: true,\n });\n\n if (p.isCancel(selected)) {\n p.cancel(\"Update cancelled.\");\n process.exit(0);\n }\n\n resolvedPaths = selected;\n }\n } else {\n resolvedPaths = [skillName];\n }\n\n const count = resolvedPaths.length;\n s.start(`Updating ${count} ${pluralize(count, \"skill\", \"skills\")}...`);\n const result = await updateSkill(projectRoot, resolvedPaths);\n s.stop(`✓ ${pluralize(count, \"Skill\", \"Skills\")} updated`);\n\n logContextSize(result.managedSize, result.targets);\n p.outro(\n pc.green(\n `Updated ${result.updated.map((n) => `\"${n}\"`).join(\", \")} in ${result.targets.map((t) => t.file).join(\", \")}`,\n ),\n );\n } catch (error) {\n handleCommandError(error, s);\n }\n });\n\nprogram.parse();\n","import { writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { CONFIG_FILENAME, compareByNameThenPath, TARGET_FILE } from \"./constants.js\";\nimport { safeReadFile } from \"./scanner.js\";\nimport type { Config } from \"./types.js\";\n\nfunction getDefaultConfig(): Config {\n return {\n version: 1,\n targets: [TARGET_FILE],\n skills: [],\n };\n}\n\nexport async function readConfig(projectRoot: string): Promise<Config> {\n const configPath = join(projectRoot, CONFIG_FILENAME);\n const content = await safeReadFile(configPath);\n\n if (content === undefined) {\n return getDefaultConfig();\n }\n\n try {\n const parsed = JSON.parse(content) as Config;\n // Validate structure\n if (\n typeof parsed.version !== \"number\" ||\n !Array.isArray(parsed.targets) ||\n !Array.isArray(parsed.skills)\n ) {\n return getDefaultConfig();\n }\n return parsed;\n } catch {\n return getDefaultConfig();\n }\n}\n\nexport async function writeConfig(projectRoot: string, config: Config): Promise<void> {\n const configPath = join(projectRoot, CONFIG_FILENAME);\n const sorted = {\n ...config,\n skills: [...config.skills].sort(compareByNameThenPath),\n };\n const content = JSON.stringify(sorted, null, 2);\n await writeFile(configPath, content, \"utf-8\");\n}\n","export const START_TAG = \"<!-- skilldex:start (auto-generated, do not edit) -->\";\nexport const END_TAG = \"<!-- skilldex:end -->\";\n\nexport const TARGET_FILE = \"AGENTS.md\";\nexport const CONFIG_FILENAME = \"skilldex.config.json\";\nexport const SKILL_META_FILE = \"SKILL.md\";\nexport const SKILLS_DIR_SEGMENTS = [\".agents\", \"skills\"] as const;\nexport const INDEX_HEADER = \"[Skills Index]\";\nexport const INDEX_INSTRUCTION =\n \"IMPORTANT: Prefer retrieval-led reasoning over pre-training-led reasoning for any tasks covered by indexed skills.\";\nexport const CONTEXT_BUDGET_WARN_KB = 20;\nexport const CONTEXT_BUDGET_DANGER_KB = 40;\n\nexport function compareByNameThenPath(\n a: { name: string; path: string },\n b: { name: string; path: string },\n): number {\n return a.name.localeCompare(b.name) || a.path.localeCompare(b.path);\n}\n","import type { Dirent } from \"node:fs\";\nimport { lstat, readdir, readFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { getUniqueSkillsDirs } from \"./agents.js\";\nimport { compareByNameThenPath, SKILL_META_FILE } from \"./constants.js\";\nimport type { DiscoveredSkill, SkillFile } from \"./types.js\";\n\n/** Extract key-value pairs from YAML frontmatter (between `---` fences). */\nexport function parseFrontmatter(content: string): Record<string, string> {\n const result: Record<string, string> = {};\n if (!content.startsWith(\"---\")) return result;\n\n const endIndex = content.indexOf(\"\\n---\", 3);\n if (endIndex === -1) return result;\n\n const block = content.slice(4, endIndex);\n for (const line of block.split(\"\\n\")) {\n const colonIndex = line.indexOf(\":\");\n if (colonIndex === -1) continue;\n const key = line.slice(0, colonIndex).trim();\n const value = line.slice(colonIndex + 1).trim();\n if (key) result[key] = value;\n }\n return result;\n}\n\nasync function safeReaddir(dir: string): Promise<Dirent[]> {\n try {\n return await readdir(dir, { withFileTypes: true });\n } catch {\n return [];\n }\n}\n\nexport async function safeReadFile(path: string): Promise<string | undefined> {\n try {\n return await readFile(path, \"utf-8\");\n } catch {\n return undefined;\n }\n}\n\nasync function collectMdFiles(dir: string, skillRoot: string): Promise<SkillFile[]> {\n const entries = await safeReaddir(dir);\n const files: SkillFile[] = [];\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n const nested = await collectMdFiles(fullPath, skillRoot);\n files.push(...nested);\n } else if (entry.isFile() && entry.name.endsWith(\".md\") && entry.name !== SKILL_META_FILE) {\n files.push({\n relativePath: relative(skillRoot, fullPath),\n name: entry.name.replace(/\\.md$/, \"\"),\n });\n }\n }\n return files;\n}\n\nasync function isSymlink(path: string): Promise<boolean> {\n try {\n const stats = await lstat(path);\n return stats.isSymbolicLink();\n } catch {\n return false;\n }\n}\n\n/** Scan a single skills directory and return discovered skills. */\nasync function scanDirectory(dir: string, projectRoot: string): Promise<DiscoveredSkill[]> {\n const entries = await safeReaddir(dir);\n const skills: DiscoveredSkill[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n\n const skillPath = join(dir, entry.name);\n\n if (await isSymlink(skillPath)) continue;\n\n let description = \"\";\n const skillMd = await safeReadFile(join(skillPath, SKILL_META_FILE));\n if (skillMd !== undefined) {\n const frontmatter = parseFrontmatter(skillMd);\n description = frontmatter.description ?? \"\";\n }\n\n const files = await collectMdFiles(skillPath, skillPath);\n skills.push({\n name: entry.name,\n description,\n path: skillPath,\n relativePath: relative(projectRoot, skillPath),\n files,\n });\n }\n return skills;\n}\n\n/** Scan all agent source directories for skills. Same-named skills in different directories are all included. */\nexport async function scanForSkills(projectRoot: string): Promise<DiscoveredSkill[]> {\n const results = await Promise.all(\n getUniqueSkillsDirs().map((d) => scanDirectory(join(projectRoot, d), projectRoot)),\n );\n return results.flat().sort(compareByNameThenPath);\n}\n","export interface AgentSource {\n /** Agent identifier, e.g. \"claude-code\" */\n name: string;\n /** Human-readable name, e.g. \"Claude Code\" */\n displayName: string;\n /** Skills directory relative to project root, e.g. \".claude/skills\" */\n skillsDir: string;\n}\n\n/**\n * Known agent source directories (project-scoped).\n * Sourced from the Vercel Skills CLI agent conventions.\n */\nexport const AGENT_SOURCES: AgentSource[] = [\n { name: \"universal\", displayName: \"Universal\", skillsDir: \".agents/skills\" },\n { name: \"antigravity\", displayName: \"Antigravity\", skillsDir: \".agent/skills\" },\n { name: \"claude-code\", displayName: \"Claude Code\", skillsDir: \".claude/skills\" },\n { name: \"codex\", displayName: \"Codex\", skillsDir: \".agents/skills\" },\n { name: \"cursor\", displayName: \"Cursor\", skillsDir: \".cursor/skills\" },\n { name: \"github-copilot\", displayName: \"GitHub Copilot\", skillsDir: \".agents/skills\" },\n { name: \"opencode\", displayName: \"OpenCode\", skillsDir: \".agents/skills\" },\n { name: \"openclaw\", displayName: \"OpenClaw\", skillsDir: \"skills\" },\n { name: \"windsurf\", displayName: \"Windsurf\", skillsDir: \".windsurf/skills\" },\n];\n\n/** Unique skills directories to scan (deduplicates agents sharing the same dir). */\nexport function getUniqueSkillsDirs(): string[] {\n return [...new Set(AGENT_SOURCES.map((a) => a.skillsDir))];\n}\n\n/** Maps a skill's relative path to the first matching agent's display name. */\nexport function getAgentDisplayName(relativePath: string): string | undefined {\n for (const agent of AGENT_SOURCES) {\n if (relativePath.startsWith(`${agent.skillsDir}/`) || relativePath === agent.skillsDir) {\n return agent.displayName;\n }\n }\n return undefined;\n}\n","import { stat, writeFile } from \"node:fs/promises\";\nimport { basename, join } from \"node:path\";\nimport { readConfig } from \"./config.js\";\nimport { END_TAG, START_TAG, TARGET_FILE } from \"./constants.js\";\nimport { generateIndex } from \"./indexer.js\";\nimport { safeReadFile, scanForSkills } from \"./scanner.js\";\nimport type { InitResult, TargetFileInfo } from \"./types.js\";\n\nexport async function getTargetInfos(\n projectRoot: string,\n targets: string[],\n): Promise<TargetFileInfo[]> {\n return Promise.all(\n targets.map(async (t) => {\n const p = join(projectRoot, t);\n const s = await stat(p);\n return { file: basename(t), path: p, totalSize: s.size };\n }),\n );\n}\n\nexport function buildManagedSection(indexContent: string): string {\n return `${START_TAG}\\n${indexContent}\\n${END_TAG}`;\n}\n\n/** Write or update the managed skilldex section in a target file. Creates, appends, or replaces as needed. Returns the written file content. */\nexport async function writeTargetFile(\n projectRoot: string,\n indexContent: string,\n targetFile: string = TARGET_FILE,\n): Promise<string> {\n const targetPath = join(projectRoot, targetFile);\n const section = buildManagedSection(indexContent);\n\n const existing = await safeReadFile(targetPath);\n\n let output: string;\n if (existing === undefined) {\n output = `${section}\\n`;\n } else if (existing.includes(START_TAG) && existing.includes(END_TAG)) {\n const startIdx = existing.indexOf(START_TAG);\n const endIdx = existing.indexOf(END_TAG) + END_TAG.length;\n output = existing.slice(0, startIdx) + section + existing.slice(endIdx);\n } else {\n output = `${existing.trimEnd()}\\n\\n${section}\\n`;\n }\n\n await writeFile(targetPath, output, \"utf-8\");\n return output;\n}\n\nexport interface RegenerateResult extends InitResult {\n /** Map of target file path → written content */\n writtenContent: Map<string, string>;\n}\n\n/** Regenerate all target files from config (reads config, scans indexed skills, writes targets). */\nexport async function regenerateFromConfig(projectRoot: string): Promise<RegenerateResult> {\n const config = await readConfig(projectRoot);\n const allSkills = await scanForSkills(projectRoot);\n\n // Map skill paths from config to DiscoveredSkill objects\n const skillMap = new Map(allSkills.map((s) => [s.relativePath, s]));\n const skills = config.skills\n .map((entry) => skillMap.get(entry.path))\n .filter((s) => s !== undefined);\n\n const index = generateIndex(skills);\n\n const writtenContent = new Map<string, string>();\n for (const target of config.targets) {\n const content = await writeTargetFile(projectRoot, index, target);\n writtenContent.set(join(projectRoot, target), content);\n }\n\n const managedSize = Buffer.byteLength(buildManagedSection(index));\n const targets = await getTargetInfos(projectRoot, config.targets);\n\n return {\n skillCount: skills.length,\n managedSize,\n targets,\n writtenContent,\n };\n}\n","import { dirname } from \"node:path\";\nimport { INDEX_HEADER, INDEX_INSTRUCTION } from \"./constants.js\";\nimport type { DiscoveredSkill } from \"./types.js\";\n\nfunction groupFilesBySubdir(\n files: { relativePath: string; name: string }[],\n): Map<string, string[]> {\n const groups = new Map<string, string[]>();\n for (const file of files) {\n const dir = dirname(file.relativePath);\n const key = dir === \".\" ? \"\" : dir;\n const existing = groups.get(key);\n if (existing) {\n existing.push(`${file.name}.md`);\n } else {\n groups.set(key, [`${file.name}.md`]);\n }\n }\n return groups;\n}\n\nexport function generateIndex(skills: DiscoveredSkill[]): string {\n const segments: string[] = [INDEX_HEADER, INDEX_INSTRUCTION];\n\n for (const skill of skills) {\n segments.push(`[${skill.name}]`);\n segments.push(`root:./${skill.relativePath}`);\n\n if (skill.description) {\n segments.push(`desc:${skill.description}`);\n }\n\n const groups = groupFilesBySubdir(skill.files);\n for (const [subdir, fileNames] of groups) {\n const fileList = `{${fileNames.join(\",\")}}`;\n if (subdir) {\n segments.push(`${subdir}:${fileList}`);\n } else {\n segments.push(fileList);\n }\n }\n }\n\n return segments.join(\"|\");\n}\n","import { readConfig, writeConfig } from \"./config.js\";\nimport { scanForSkills } from \"./scanner.js\";\nimport type { AddResult, DiscoveredSkill } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function addSkill(projectRoot: string, skillName: string): Promise<AddResult> {\n const config = await readConfig(projectRoot);\n const allSkills = await scanForSkills(projectRoot);\n\n const isPath = skillName.includes(\"/\");\n\n let targetSkill: DiscoveredSkill | undefined;\n\n if (isPath) {\n // Path-based lookup for disambiguation\n targetSkill = allSkills.find((s) => s.relativePath === skillName);\n if (!targetSkill) {\n throw new Error(`Skill \"${skillName}\" not found. Did you create the skill directory?`);\n }\n } else {\n // Name-based lookup\n const matches = allSkills.filter((s) => s.name === skillName);\n if (matches.length === 0) {\n throw new Error(`Skill \"${skillName}\" not found. Did you create the skill directory?`);\n }\n if (matches.length > 1) {\n const paths = matches.map((s) => ` ${s.relativePath}`).join(\"\\n\");\n throw new Error(`Multiple skills named \"${skillName}\" found. Specify the path:\\n${paths}`);\n }\n targetSkill = matches[0];\n }\n\n if (config.skills.some((s) => s.path === targetSkill.relativePath)) {\n throw new Error(`Skill \"${targetSkill.relativePath}\" is already indexed`);\n }\n\n config.skills.push({\n name: targetSkill.name,\n path: targetSkill.relativePath,\n });\n\n await writeConfig(projectRoot, config);\n\n const result = await regenerateFromConfig(projectRoot);\n\n return {\n skillName: targetSkill.name,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n","import { writeConfig } from \"./config.js\";\nimport { TARGET_FILE } from \"./constants.js\";\nimport { scanForSkills } from \"./scanner.js\";\nimport type { DiscoveredSkill, InitResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\n/** Scan for skills, filter by selection, and write the index to target files. */\nexport async function init(options: {\n projectRoot: string;\n selectedSkills?: string[];\n yes?: boolean;\n}): Promise<InitResult> {\n const { projectRoot, selectedSkills } = options;\n\n const discovered = await scanForSkills(projectRoot);\n\n let skills: DiscoveredSkill[];\n if (selectedSkills) {\n const selected = new Set(selectedSkills);\n skills = discovered.filter((s) => selected.has(s.name) || selected.has(s.relativePath));\n } else {\n skills = discovered;\n }\n\n return initWithSkills(projectRoot, skills);\n}\n\n/** Index a specific set of skills and write to target file(s). */\nexport async function initWithSkills(\n projectRoot: string,\n skills: DiscoveredSkill[],\n targets: string[] = [TARGET_FILE],\n): Promise<InitResult> {\n const config = {\n version: 1 as const,\n targets,\n skills: skills.map((skill) => ({\n name: skill.name,\n path: skill.relativePath,\n })),\n };\n await writeConfig(projectRoot, config);\n\n return regenerateFromConfig(projectRoot);\n}\n","import { readConfig } from \"./config.js\";\nimport { scanForSkills } from \"./scanner.js\";\nimport type { ListResult, SkillInfo } from \"./types.js\";\n\nexport async function listSkills(projectRoot: string): Promise<ListResult> {\n const config = await readConfig(projectRoot);\n const allSkills = await scanForSkills(projectRoot);\n\n const indexedPaths = new Set(config.skills.map((s) => s.path));\n const skillMap = new Map(allSkills.map((s) => [s.relativePath, s]));\n\n const indexed: SkillInfo[] = config.skills.map((entry) => {\n const discovered = skillMap.get(entry.path);\n if (!discovered) {\n return { name: entry.name, path: entry.path, description: \"\", missing: true };\n }\n return { name: entry.name, path: entry.path, description: discovered.description };\n });\n\n const available: SkillInfo[] = allSkills\n .filter((s) => !indexedPaths.has(s.relativePath))\n .map((s) => ({\n name: s.name,\n description: s.description,\n path: s.relativePath,\n }));\n\n return { indexed, available };\n}\n","import { rm } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { readConfig, writeConfig } from \"./config.js\";\nimport type { RemoveResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function removeSkill(\n projectRoot: string,\n skillName: string,\n deleteFiles = false,\n): Promise<RemoveResult> {\n const config = await readConfig(projectRoot);\n\n const isPath = skillName.includes(\"/\");\n\n let skillIndex: number;\n\n if (isPath) {\n skillIndex = config.skills.findIndex((s) => s.path === skillName);\n if (skillIndex === -1) {\n throw new Error(`Skill \"${skillName}\" is not indexed`);\n }\n } else {\n const matches = config.skills\n .map((s, i) => ({ entry: s, index: i }))\n .filter(({ entry }) => entry.name === skillName);\n\n if (matches.length === 0) {\n throw new Error(`Skill \"${skillName}\" is not indexed`);\n }\n if (matches.length > 1) {\n const paths = matches.map(({ entry }) => ` ${entry.path}`).join(\"\\n\");\n throw new Error(`Multiple skills named \"${skillName}\" indexed. Specify the path:\\n${paths}`);\n }\n skillIndex = matches[0].index;\n }\n\n const entry = config.skills[skillIndex];\n const skillPath = join(projectRoot, entry.path);\n\n config.skills.splice(skillIndex, 1);\n await writeConfig(projectRoot, config);\n\n if (deleteFiles) {\n await rm(skillPath, { recursive: true, force: true });\n }\n\n const result = await regenerateFromConfig(projectRoot);\n\n return {\n skillName: entry.name,\n wasDeleted: deleteFiles,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n","import { join } from \"node:path\";\nimport { readConfig, writeConfig } from \"./config.js\";\nimport { safeReadFile, scanForSkills } from \"./scanner.js\";\nimport type { SyncResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function syncSkills(projectRoot: string): Promise<SyncResult> {\n const config = await readConfig(projectRoot);\n const onDisk = await scanForSkills(projectRoot);\n const diskPaths = new Set(onDisk.map((s) => s.relativePath));\n\n // Find stale entries: in config but not on disk\n const stale = config.skills.filter((s) => !diskPaths.has(s.path));\n const removed = stale.map((s) => s.name);\n\n if (stale.length > 0) {\n const stalePaths = new Set(stale.map((s) => s.path));\n config.skills = config.skills.filter((s) => !stalePaths.has(s.path));\n await writeConfig(projectRoot, config);\n }\n\n const targetPaths = config.targets.map((t) => join(projectRoot, t));\n\n // Read before-state for all targets\n const beforeMap = new Map<string, string | undefined>();\n for (const targetPath of targetPaths) {\n beforeMap.set(targetPath, await safeReadFile(targetPath));\n }\n\n // Nothing to do if no skills indexed and no target files exist\n if (config.skills.length === 0 && [...beforeMap.values()].every((v) => v === undefined)) {\n return { removed, changed: false, managedSize: 0, targets: [] };\n }\n\n const result = await regenerateFromConfig(projectRoot);\n\n // Check if ANY target changed using the written content from regeneration\n let changed = false;\n for (const targetPath of targetPaths) {\n const after = result.writtenContent.get(targetPath);\n if (beforeMap.get(targetPath) !== after) {\n changed = true;\n break;\n }\n }\n\n return {\n removed,\n changed,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n","import { access } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { readConfig } from \"./config.js\";\nimport type { UpdateResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function updateSkill(\n projectRoot: string,\n skillPaths: string[],\n): Promise<UpdateResult> {\n const config = await readConfig(projectRoot);\n const configPathMap = new Map(config.skills.map((s) => [s.path, s.name]));\n\n // Validate all requested paths are indexed\n for (const skillPath of skillPaths) {\n if (!configPathMap.has(skillPath)) {\n throw new Error(\n `Skill \"${skillPath}\" is not indexed. Run 'skilldex add ${skillPath}' to index it.`,\n );\n }\n }\n\n // Validate all exist on disk\n for (const skillPath of skillPaths) {\n const absolutePath = join(projectRoot, skillPath);\n try {\n await access(absolutePath);\n } catch {\n throw new Error(\n `Skill \"${skillPath}\" not found on disk. Run 'skilldex sync' to remove stale entries.`,\n );\n }\n }\n\n const updated = skillPaths.map((p) => configPathMap.get(p) as string);\n\n const result = await regenerateFromConfig(projectRoot);\n\n return {\n updated,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n","import * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { getAgentDisplayName } from \"../lib/agents.js\";\nimport { CONTEXT_BUDGET_DANGER_KB, CONTEXT_BUDGET_WARN_KB } from \"../lib/constants.js\";\nimport type { TargetFileInfo } from \"../lib/types.js\";\n\nexport function pluralize(count: number, singular: string, plural: string): string {\n return count === 1 ? singular : plural;\n}\n\nfunction formatKb(bytes: number): string {\n return `${(bytes / 1024).toFixed(1)} KB`;\n}\n\nexport function logContextSize(managedSize: number, targets: TargetFileInfo[]): void {\n const sizeKb = managedSize / 1024;\n const sizeFormatted = formatKb(managedSize);\n let sizeLabel: string;\n if (sizeKb < CONTEXT_BUDGET_WARN_KB) {\n sizeLabel = pc.green(sizeFormatted);\n } else if (sizeKb < CONTEXT_BUDGET_DANGER_KB) {\n sizeLabel = pc.yellow(sizeFormatted);\n } else {\n sizeLabel = pc.red(`${sizeFormatted} — may degrade agent performance`);\n }\n\n const targetLines = targets.map(\n (t) => ` ${t.file} ${pc.dim(`${formatKb(t.totalSize)} total`)}`,\n );\n p.log.info(`Context: ${sizeLabel} (managed section)\\n${targetLines.join(\"\\n\")}`);\n}\n\nexport function formatSkillPath(relativePath: string): string {\n const agent = getAgentDisplayName(relativePath);\n if (agent) return `${pc.cyan(agent)} ${pc.dim(relativePath)}`;\n return pc.dim(relativePath);\n}\n\nexport function handleCommandError(error: unknown, spinner?: ReturnType<typeof p.spinner>): never {\n if (spinner) {\n spinner.stop(\"✗ Failed\");\n }\n const message = error instanceof Error ? error.message : String(error);\n p.outro(pc.red(message));\n process.exit(1);\n}\n"],"mappings":"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","names":["p","pc","join","join","writeFile","join","p","join","writeFile","join","entry","join","join","join","join","join","p","spinner","pc"]}
|
package/dist/index.cjs
CHANGED
|
@@ -44,6 +44,7 @@ __export(index_exports, {
|
|
|
44
44
|
removeSkill: () => removeSkill,
|
|
45
45
|
scanForSkills: () => scanForSkills,
|
|
46
46
|
syncSkills: () => syncSkills,
|
|
47
|
+
updateSkill: () => updateSkill,
|
|
47
48
|
writeConfig: () => writeConfig,
|
|
48
49
|
writeTargetFile: () => writeTargetFile
|
|
49
50
|
});
|
|
@@ -386,13 +387,11 @@ async function listSkills(projectRoot) {
|
|
|
386
387
|
const skillMap = new Map(allSkills.map((s) => [s.relativePath, s]));
|
|
387
388
|
const indexed = config.skills.map((entry) => {
|
|
388
389
|
const discovered = skillMap.get(entry.path);
|
|
389
|
-
if (!discovered)
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
};
|
|
395
|
-
}).filter((s) => s !== void 0);
|
|
390
|
+
if (!discovered) {
|
|
391
|
+
return { name: entry.name, path: entry.path, description: "", missing: true };
|
|
392
|
+
}
|
|
393
|
+
return { name: entry.name, path: entry.path, description: discovered.description };
|
|
394
|
+
});
|
|
396
395
|
const available = allSkills.filter((s) => !indexedPaths.has(s.relativePath)).map((s) => ({
|
|
397
396
|
name: s.name,
|
|
398
397
|
description: s.description,
|
|
@@ -478,6 +477,38 @@ async function syncSkills(projectRoot) {
|
|
|
478
477
|
targets: result.targets
|
|
479
478
|
};
|
|
480
479
|
}
|
|
480
|
+
|
|
481
|
+
// src/lib/update.ts
|
|
482
|
+
var import_promises5 = require("fs/promises");
|
|
483
|
+
var import_node_path7 = require("path");
|
|
484
|
+
async function updateSkill(projectRoot, skillPaths) {
|
|
485
|
+
const config = await readConfig(projectRoot);
|
|
486
|
+
const configPathMap = new Map(config.skills.map((s) => [s.path, s.name]));
|
|
487
|
+
for (const skillPath of skillPaths) {
|
|
488
|
+
if (!configPathMap.has(skillPath)) {
|
|
489
|
+
throw new Error(
|
|
490
|
+
`Skill "${skillPath}" is not indexed. Run 'skilldex add ${skillPath}' to index it.`
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
for (const skillPath of skillPaths) {
|
|
495
|
+
const absolutePath = (0, import_node_path7.join)(projectRoot, skillPath);
|
|
496
|
+
try {
|
|
497
|
+
await (0, import_promises5.access)(absolutePath);
|
|
498
|
+
} catch {
|
|
499
|
+
throw new Error(
|
|
500
|
+
`Skill "${skillPath}" not found on disk. Run 'skilldex sync' to remove stale entries.`
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
const updated = skillPaths.map((p) => configPathMap.get(p));
|
|
505
|
+
const result = await regenerateFromConfig(projectRoot);
|
|
506
|
+
return {
|
|
507
|
+
updated,
|
|
508
|
+
managedSize: result.managedSize,
|
|
509
|
+
targets: result.targets
|
|
510
|
+
};
|
|
511
|
+
}
|
|
481
512
|
// Annotate the CommonJS export names for ESM import in node:
|
|
482
513
|
0 && (module.exports = {
|
|
483
514
|
AGENT_SOURCES,
|
|
@@ -504,6 +535,7 @@ async function syncSkills(projectRoot) {
|
|
|
504
535
|
removeSkill,
|
|
505
536
|
scanForSkills,
|
|
506
537
|
syncSkills,
|
|
538
|
+
updateSkill,
|
|
507
539
|
writeConfig,
|
|
508
540
|
writeTargetFile
|
|
509
541
|
});
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/lib/config.ts","../src/lib/constants.ts","../src/lib/scanner.ts","../src/lib/agents.ts","../src/lib/writer.ts","../src/lib/indexer.ts","../src/lib/add.ts","../src/lib/init.ts","../src/lib/list.ts","../src/lib/remove.ts","../src/lib/sync.ts"],"sourcesContent":["// skilldex library entry point\n\nexport { addSkill } from \"./lib/add.js\";\nexport type { AgentSource } from \"./lib/agents.js\";\nexport { AGENT_SOURCES, getAgentDisplayName, getUniqueSkillsDirs } from \"./lib/agents.js\";\nexport { readConfig, writeConfig } from \"./lib/config.js\";\nexport {\n CONFIG_FILENAME,\n CONTEXT_BUDGET_DANGER_KB,\n CONTEXT_BUDGET_WARN_KB,\n compareByNameThenPath,\n END_TAG,\n INDEX_HEADER,\n INDEX_INSTRUCTION,\n SKILL_META_FILE,\n START_TAG,\n TARGET_FILE,\n} from \"./lib/constants.js\";\nexport { generateIndex } from \"./lib/indexer.js\";\nexport { init, initWithSkills } from \"./lib/init.js\";\nexport { listSkills } from \"./lib/list.js\";\nexport { removeSkill } from \"./lib/remove.js\";\nexport { scanForSkills } from \"./lib/scanner.js\";\nexport { syncSkills } from \"./lib/sync.js\";\nexport type {\n AddResult,\n Config,\n DiscoveredSkill,\n InitResult,\n ListResult,\n RemoveResult,\n SkillEntry,\n SkillFile,\n SkillInfo,\n SyncResult,\n TargetFileInfo,\n} from \"./lib/types.js\";\nexport type { RegenerateResult } from \"./lib/writer.js\";\nexport { buildManagedSection, regenerateFromConfig, writeTargetFile } from \"./lib/writer.js\";\n","import { writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { CONFIG_FILENAME, compareByNameThenPath, TARGET_FILE } from \"./constants.js\";\nimport { safeReadFile } from \"./scanner.js\";\nimport type { Config } from \"./types.js\";\n\nfunction getDefaultConfig(): Config {\n return {\n version: 1,\n targets: [TARGET_FILE],\n skills: [],\n };\n}\n\nexport async function readConfig(projectRoot: string): Promise<Config> {\n const configPath = join(projectRoot, CONFIG_FILENAME);\n const content = await safeReadFile(configPath);\n\n if (content === undefined) {\n return getDefaultConfig();\n }\n\n try {\n const parsed = JSON.parse(content) as Config;\n // Validate structure\n if (\n typeof parsed.version !== \"number\" ||\n !Array.isArray(parsed.targets) ||\n !Array.isArray(parsed.skills)\n ) {\n return getDefaultConfig();\n }\n return parsed;\n } catch {\n return getDefaultConfig();\n }\n}\n\nexport async function writeConfig(projectRoot: string, config: Config): Promise<void> {\n const configPath = join(projectRoot, CONFIG_FILENAME);\n const sorted = {\n ...config,\n skills: [...config.skills].sort(compareByNameThenPath),\n };\n const content = JSON.stringify(sorted, null, 2);\n await writeFile(configPath, content, \"utf-8\");\n}\n","export const START_TAG = \"<!-- skilldex:start (auto-generated, do not edit) -->\";\nexport const END_TAG = \"<!-- skilldex:end -->\";\n\nexport const TARGET_FILE = \"AGENTS.md\";\nexport const CONFIG_FILENAME = \"skilldex.config.json\";\nexport const SKILL_META_FILE = \"SKILL.md\";\nexport const SKILLS_DIR_SEGMENTS = [\".agents\", \"skills\"] as const;\nexport const INDEX_HEADER = \"[Skills Index]\";\nexport const INDEX_INSTRUCTION =\n \"IMPORTANT: Prefer retrieval-led reasoning over pre-training-led reasoning for any tasks covered by indexed skills.\";\nexport const CONTEXT_BUDGET_WARN_KB = 20;\nexport const CONTEXT_BUDGET_DANGER_KB = 40;\n\nexport function compareByNameThenPath(\n a: { name: string; path: string },\n b: { name: string; path: string },\n): number {\n return a.name.localeCompare(b.name) || a.path.localeCompare(b.path);\n}\n","import type { Dirent } from \"node:fs\";\nimport { lstat, readdir, readFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { getUniqueSkillsDirs } from \"./agents.js\";\nimport { compareByNameThenPath, SKILL_META_FILE } from \"./constants.js\";\nimport type { DiscoveredSkill, SkillFile } from \"./types.js\";\n\n/** Extract key-value pairs from YAML frontmatter (between `---` fences). */\nexport function parseFrontmatter(content: string): Record<string, string> {\n const result: Record<string, string> = {};\n if (!content.startsWith(\"---\")) return result;\n\n const endIndex = content.indexOf(\"\\n---\", 3);\n if (endIndex === -1) return result;\n\n const block = content.slice(4, endIndex);\n for (const line of block.split(\"\\n\")) {\n const colonIndex = line.indexOf(\":\");\n if (colonIndex === -1) continue;\n const key = line.slice(0, colonIndex).trim();\n const value = line.slice(colonIndex + 1).trim();\n if (key) result[key] = value;\n }\n return result;\n}\n\nasync function safeReaddir(dir: string): Promise<Dirent[]> {\n try {\n return await readdir(dir, { withFileTypes: true });\n } catch {\n return [];\n }\n}\n\nexport async function safeReadFile(path: string): Promise<string | undefined> {\n try {\n return await readFile(path, \"utf-8\");\n } catch {\n return undefined;\n }\n}\n\nasync function collectMdFiles(dir: string, skillRoot: string): Promise<SkillFile[]> {\n const entries = await safeReaddir(dir);\n const files: SkillFile[] = [];\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n const nested = await collectMdFiles(fullPath, skillRoot);\n files.push(...nested);\n } else if (entry.isFile() && entry.name.endsWith(\".md\") && entry.name !== SKILL_META_FILE) {\n files.push({\n relativePath: relative(skillRoot, fullPath),\n name: entry.name.replace(/\\.md$/, \"\"),\n });\n }\n }\n return files;\n}\n\nasync function isSymlink(path: string): Promise<boolean> {\n try {\n const stats = await lstat(path);\n return stats.isSymbolicLink();\n } catch {\n return false;\n }\n}\n\n/** Scan a single skills directory and return discovered skills. */\nasync function scanDirectory(dir: string, projectRoot: string): Promise<DiscoveredSkill[]> {\n const entries = await safeReaddir(dir);\n const skills: DiscoveredSkill[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n\n const skillPath = join(dir, entry.name);\n\n if (await isSymlink(skillPath)) continue;\n\n let description = \"\";\n const skillMd = await safeReadFile(join(skillPath, SKILL_META_FILE));\n if (skillMd !== undefined) {\n const frontmatter = parseFrontmatter(skillMd);\n description = frontmatter.description ?? \"\";\n }\n\n const files = await collectMdFiles(skillPath, skillPath);\n skills.push({\n name: entry.name,\n description,\n path: skillPath,\n relativePath: relative(projectRoot, skillPath),\n files,\n });\n }\n return skills;\n}\n\n/** Scan all agent source directories for skills. Same-named skills in different directories are all included. */\nexport async function scanForSkills(projectRoot: string): Promise<DiscoveredSkill[]> {\n const results = await Promise.all(\n getUniqueSkillsDirs().map((d) => scanDirectory(join(projectRoot, d), projectRoot)),\n );\n return results.flat().sort(compareByNameThenPath);\n}\n","export interface AgentSource {\n /** Agent identifier, e.g. \"claude-code\" */\n name: string;\n /** Human-readable name, e.g. \"Claude Code\" */\n displayName: string;\n /** Skills directory relative to project root, e.g. \".claude/skills\" */\n skillsDir: string;\n}\n\n/**\n * Known agent source directories (project-scoped).\n * Sourced from the Vercel Skills CLI agent conventions.\n */\nexport const AGENT_SOURCES: AgentSource[] = [\n { name: \"universal\", displayName: \"Universal\", skillsDir: \".agents/skills\" },\n { name: \"antigravity\", displayName: \"Antigravity\", skillsDir: \".agent/skills\" },\n { name: \"claude-code\", displayName: \"Claude Code\", skillsDir: \".claude/skills\" },\n { name: \"codex\", displayName: \"Codex\", skillsDir: \".agents/skills\" },\n { name: \"cursor\", displayName: \"Cursor\", skillsDir: \".cursor/skills\" },\n { name: \"github-copilot\", displayName: \"GitHub Copilot\", skillsDir: \".agents/skills\" },\n { name: \"opencode\", displayName: \"OpenCode\", skillsDir: \".agents/skills\" },\n { name: \"openclaw\", displayName: \"OpenClaw\", skillsDir: \"skills\" },\n { name: \"windsurf\", displayName: \"Windsurf\", skillsDir: \".windsurf/skills\" },\n];\n\n/** Unique skills directories to scan (deduplicates agents sharing the same dir). */\nexport function getUniqueSkillsDirs(): string[] {\n return [...new Set(AGENT_SOURCES.map((a) => a.skillsDir))];\n}\n\n/** Maps a skill's relative path to the first matching agent's display name. */\nexport function getAgentDisplayName(relativePath: string): string | undefined {\n for (const agent of AGENT_SOURCES) {\n if (relativePath.startsWith(`${agent.skillsDir}/`) || relativePath === agent.skillsDir) {\n return agent.displayName;\n }\n }\n return undefined;\n}\n","import { stat, writeFile } from \"node:fs/promises\";\nimport { basename, join } from \"node:path\";\nimport { readConfig } from \"./config.js\";\nimport { END_TAG, START_TAG, TARGET_FILE } from \"./constants.js\";\nimport { generateIndex } from \"./indexer.js\";\nimport { safeReadFile, scanForSkills } from \"./scanner.js\";\nimport type { InitResult, TargetFileInfo } from \"./types.js\";\n\nexport async function getTargetInfos(\n projectRoot: string,\n targets: string[],\n): Promise<TargetFileInfo[]> {\n return Promise.all(\n targets.map(async (t) => {\n const p = join(projectRoot, t);\n const s = await stat(p);\n return { file: basename(t), path: p, totalSize: s.size };\n }),\n );\n}\n\nexport function buildManagedSection(indexContent: string): string {\n return `${START_TAG}\\n${indexContent}\\n${END_TAG}`;\n}\n\n/** Write or update the managed skilldex section in a target file. Creates, appends, or replaces as needed. Returns the written file content. */\nexport async function writeTargetFile(\n projectRoot: string,\n indexContent: string,\n targetFile: string = TARGET_FILE,\n): Promise<string> {\n const targetPath = join(projectRoot, targetFile);\n const section = buildManagedSection(indexContent);\n\n const existing = await safeReadFile(targetPath);\n\n let output: string;\n if (existing === undefined) {\n output = `${section}\\n`;\n } else if (existing.includes(START_TAG) && existing.includes(END_TAG)) {\n const startIdx = existing.indexOf(START_TAG);\n const endIdx = existing.indexOf(END_TAG) + END_TAG.length;\n output = existing.slice(0, startIdx) + section + existing.slice(endIdx);\n } else {\n output = `${existing.trimEnd()}\\n\\n${section}\\n`;\n }\n\n await writeFile(targetPath, output, \"utf-8\");\n return output;\n}\n\nexport interface RegenerateResult extends InitResult {\n /** Map of target file path → written content */\n writtenContent: Map<string, string>;\n}\n\n/** Regenerate all target files from config (reads config, scans indexed skills, writes targets). */\nexport async function regenerateFromConfig(projectRoot: string): Promise<RegenerateResult> {\n const config = await readConfig(projectRoot);\n const allSkills = await scanForSkills(projectRoot);\n\n // Map skill paths from config to DiscoveredSkill objects\n const skillMap = new Map(allSkills.map((s) => [s.relativePath, s]));\n const skills = config.skills\n .map((entry) => skillMap.get(entry.path))\n .filter((s) => s !== undefined);\n\n const index = generateIndex(skills);\n\n const writtenContent = new Map<string, string>();\n for (const target of config.targets) {\n const content = await writeTargetFile(projectRoot, index, target);\n writtenContent.set(join(projectRoot, target), content);\n }\n\n const managedSize = Buffer.byteLength(buildManagedSection(index));\n const targets = await getTargetInfos(projectRoot, config.targets);\n\n return {\n skillCount: skills.length,\n managedSize,\n targets,\n writtenContent,\n };\n}\n","import { dirname } from \"node:path\";\nimport { INDEX_HEADER, INDEX_INSTRUCTION } from \"./constants.js\";\nimport type { DiscoveredSkill } from \"./types.js\";\n\nfunction groupFilesBySubdir(\n files: { relativePath: string; name: string }[],\n): Map<string, string[]> {\n const groups = new Map<string, string[]>();\n for (const file of files) {\n const dir = dirname(file.relativePath);\n const key = dir === \".\" ? \"\" : dir;\n const existing = groups.get(key);\n if (existing) {\n existing.push(`${file.name}.md`);\n } else {\n groups.set(key, [`${file.name}.md`]);\n }\n }\n return groups;\n}\n\nexport function generateIndex(skills: DiscoveredSkill[]): string {\n const segments: string[] = [INDEX_HEADER, INDEX_INSTRUCTION];\n\n for (const skill of skills) {\n segments.push(`[${skill.name}]`);\n segments.push(`root:./${skill.relativePath}`);\n\n if (skill.description) {\n segments.push(`desc:${skill.description}`);\n }\n\n const groups = groupFilesBySubdir(skill.files);\n for (const [subdir, fileNames] of groups) {\n const fileList = `{${fileNames.join(\",\")}}`;\n if (subdir) {\n segments.push(`${subdir}:${fileList}`);\n } else {\n segments.push(fileList);\n }\n }\n }\n\n return segments.join(\"|\");\n}\n","import { readConfig, writeConfig } from \"./config.js\";\nimport { scanForSkills } from \"./scanner.js\";\nimport type { AddResult, DiscoveredSkill } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function addSkill(projectRoot: string, skillName: string): Promise<AddResult> {\n const config = await readConfig(projectRoot);\n const allSkills = await scanForSkills(projectRoot);\n\n const isPath = skillName.includes(\"/\");\n\n let targetSkill: DiscoveredSkill | undefined;\n\n if (isPath) {\n // Path-based lookup for disambiguation\n targetSkill = allSkills.find((s) => s.relativePath === skillName);\n if (!targetSkill) {\n throw new Error(`Skill \"${skillName}\" not found. Did you create the skill directory?`);\n }\n } else {\n // Name-based lookup\n const matches = allSkills.filter((s) => s.name === skillName);\n if (matches.length === 0) {\n throw new Error(`Skill \"${skillName}\" not found. Did you create the skill directory?`);\n }\n if (matches.length > 1) {\n const paths = matches.map((s) => ` ${s.relativePath}`).join(\"\\n\");\n throw new Error(`Multiple skills named \"${skillName}\" found. Specify the path:\\n${paths}`);\n }\n targetSkill = matches[0];\n }\n\n if (config.skills.some((s) => s.path === targetSkill.relativePath)) {\n throw new Error(`Skill \"${targetSkill.relativePath}\" is already indexed`);\n }\n\n config.skills.push({\n name: targetSkill.name,\n path: targetSkill.relativePath,\n });\n\n await writeConfig(projectRoot, config);\n\n const result = await regenerateFromConfig(projectRoot);\n\n return {\n skillName: targetSkill.name,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n","import { writeConfig } from \"./config.js\";\nimport { TARGET_FILE } from \"./constants.js\";\nimport { scanForSkills } from \"./scanner.js\";\nimport type { DiscoveredSkill, InitResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\n/** Scan for skills, filter by selection, and write the index to target files. */\nexport async function init(options: {\n projectRoot: string;\n selectedSkills?: string[];\n yes?: boolean;\n}): Promise<InitResult> {\n const { projectRoot, selectedSkills } = options;\n\n const discovered = await scanForSkills(projectRoot);\n\n let skills: DiscoveredSkill[];\n if (selectedSkills) {\n const selected = new Set(selectedSkills);\n skills = discovered.filter((s) => selected.has(s.name) || selected.has(s.relativePath));\n } else {\n skills = discovered;\n }\n\n return initWithSkills(projectRoot, skills);\n}\n\n/** Index a specific set of skills and write to target file(s). */\nexport async function initWithSkills(\n projectRoot: string,\n skills: DiscoveredSkill[],\n targets: string[] = [TARGET_FILE],\n): Promise<InitResult> {\n const config = {\n version: 1 as const,\n targets,\n skills: skills.map((skill) => ({\n name: skill.name,\n path: skill.relativePath,\n })),\n };\n await writeConfig(projectRoot, config);\n\n return regenerateFromConfig(projectRoot);\n}\n","import { readConfig } from \"./config.js\";\nimport { scanForSkills } from \"./scanner.js\";\nimport type { ListResult, SkillInfo } from \"./types.js\";\n\nexport async function listSkills(projectRoot: string): Promise<ListResult> {\n const config = await readConfig(projectRoot);\n const allSkills = await scanForSkills(projectRoot);\n\n const indexedPaths = new Set(config.skills.map((s) => s.path));\n const skillMap = new Map(allSkills.map((s) => [s.relativePath, s]));\n\n const indexed: SkillInfo[] = config.skills\n .map((entry) => {\n const discovered = skillMap.get(entry.path);\n if (!discovered) return undefined;\n return {\n name: entry.name,\n path: entry.path,\n description: discovered.description,\n };\n })\n .filter((s) => s !== undefined);\n\n const available: SkillInfo[] = allSkills\n .filter((s) => !indexedPaths.has(s.relativePath))\n .map((s) => ({\n name: s.name,\n description: s.description,\n path: s.relativePath,\n }));\n\n return { indexed, available };\n}\n","import { rm } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { readConfig, writeConfig } from \"./config.js\";\nimport type { RemoveResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function removeSkill(\n projectRoot: string,\n skillName: string,\n deleteFiles = false,\n): Promise<RemoveResult> {\n const config = await readConfig(projectRoot);\n\n const isPath = skillName.includes(\"/\");\n\n let skillIndex: number;\n\n if (isPath) {\n skillIndex = config.skills.findIndex((s) => s.path === skillName);\n if (skillIndex === -1) {\n throw new Error(`Skill \"${skillName}\" is not indexed`);\n }\n } else {\n const matches = config.skills\n .map((s, i) => ({ entry: s, index: i }))\n .filter(({ entry }) => entry.name === skillName);\n\n if (matches.length === 0) {\n throw new Error(`Skill \"${skillName}\" is not indexed`);\n }\n if (matches.length > 1) {\n const paths = matches.map(({ entry }) => ` ${entry.path}`).join(\"\\n\");\n throw new Error(`Multiple skills named \"${skillName}\" indexed. Specify the path:\\n${paths}`);\n }\n skillIndex = matches[0].index;\n }\n\n const entry = config.skills[skillIndex];\n const skillPath = join(projectRoot, entry.path);\n\n config.skills.splice(skillIndex, 1);\n await writeConfig(projectRoot, config);\n\n if (deleteFiles) {\n await rm(skillPath, { recursive: true, force: true });\n }\n\n const result = await regenerateFromConfig(projectRoot);\n\n return {\n skillName: entry.name,\n wasDeleted: deleteFiles,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n","import { join } from \"node:path\";\nimport { readConfig, writeConfig } from \"./config.js\";\nimport { safeReadFile, scanForSkills } from \"./scanner.js\";\nimport type { SyncResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function syncSkills(projectRoot: string): Promise<SyncResult> {\n const config = await readConfig(projectRoot);\n const onDisk = await scanForSkills(projectRoot);\n const diskPaths = new Set(onDisk.map((s) => s.relativePath));\n\n // Find stale entries: in config but not on disk\n const stale = config.skills.filter((s) => !diskPaths.has(s.path));\n const removed = stale.map((s) => s.name);\n\n if (stale.length > 0) {\n const stalePaths = new Set(stale.map((s) => s.path));\n config.skills = config.skills.filter((s) => !stalePaths.has(s.path));\n await writeConfig(projectRoot, config);\n }\n\n const targetPaths = config.targets.map((t) => join(projectRoot, t));\n\n // Read before-state for all targets\n const beforeMap = new Map<string, string | undefined>();\n for (const targetPath of targetPaths) {\n beforeMap.set(targetPath, await safeReadFile(targetPath));\n }\n\n // Nothing to do if no skills indexed and no target files exist\n if (config.skills.length === 0 && [...beforeMap.values()].every((v) => v === undefined)) {\n return { removed, changed: false, managedSize: 0, targets: [] };\n }\n\n const result = await regenerateFromConfig(projectRoot);\n\n // Check if ANY target changed using the written content from regeneration\n let changed = false;\n for (const targetPath of targetPaths) {\n const after = result.writtenContent.get(targetPath);\n if (beforeMap.get(targetPath) !== after) {\n changed = true;\n break;\n }\n }\n\n return {\n removed,\n changed,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n"],"mappings":"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","names":["import_promises","import_node_path","import_promises","import_node_path","import_node_path","import_promises","import_node_path","entry","import_node_path"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/lib/config.ts","../src/lib/constants.ts","../src/lib/scanner.ts","../src/lib/agents.ts","../src/lib/writer.ts","../src/lib/indexer.ts","../src/lib/add.ts","../src/lib/init.ts","../src/lib/list.ts","../src/lib/remove.ts","../src/lib/sync.ts","../src/lib/update.ts"],"sourcesContent":["// skilldex library entry point\n\nexport { addSkill } from \"./lib/add.js\";\nexport type { AgentSource } from \"./lib/agents.js\";\nexport { AGENT_SOURCES, getAgentDisplayName, getUniqueSkillsDirs } from \"./lib/agents.js\";\nexport { readConfig, writeConfig } from \"./lib/config.js\";\nexport {\n CONFIG_FILENAME,\n CONTEXT_BUDGET_DANGER_KB,\n CONTEXT_BUDGET_WARN_KB,\n compareByNameThenPath,\n END_TAG,\n INDEX_HEADER,\n INDEX_INSTRUCTION,\n SKILL_META_FILE,\n START_TAG,\n TARGET_FILE,\n} from \"./lib/constants.js\";\nexport { generateIndex } from \"./lib/indexer.js\";\nexport { init, initWithSkills } from \"./lib/init.js\";\nexport { listSkills } from \"./lib/list.js\";\nexport { removeSkill } from \"./lib/remove.js\";\nexport { scanForSkills } from \"./lib/scanner.js\";\nexport { syncSkills } from \"./lib/sync.js\";\nexport type {\n AddResult,\n Config,\n DiscoveredSkill,\n InitResult,\n ListResult,\n RemoveResult,\n SkillEntry,\n SkillFile,\n SkillInfo,\n SyncResult,\n TargetFileInfo,\n UpdateResult,\n} from \"./lib/types.js\";\nexport { updateSkill } from \"./lib/update.js\";\nexport type { RegenerateResult } from \"./lib/writer.js\";\nexport { buildManagedSection, regenerateFromConfig, writeTargetFile } from \"./lib/writer.js\";\n","import { writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { CONFIG_FILENAME, compareByNameThenPath, TARGET_FILE } from \"./constants.js\";\nimport { safeReadFile } from \"./scanner.js\";\nimport type { Config } from \"./types.js\";\n\nfunction getDefaultConfig(): Config {\n return {\n version: 1,\n targets: [TARGET_FILE],\n skills: [],\n };\n}\n\nexport async function readConfig(projectRoot: string): Promise<Config> {\n const configPath = join(projectRoot, CONFIG_FILENAME);\n const content = await safeReadFile(configPath);\n\n if (content === undefined) {\n return getDefaultConfig();\n }\n\n try {\n const parsed = JSON.parse(content) as Config;\n // Validate structure\n if (\n typeof parsed.version !== \"number\" ||\n !Array.isArray(parsed.targets) ||\n !Array.isArray(parsed.skills)\n ) {\n return getDefaultConfig();\n }\n return parsed;\n } catch {\n return getDefaultConfig();\n }\n}\n\nexport async function writeConfig(projectRoot: string, config: Config): Promise<void> {\n const configPath = join(projectRoot, CONFIG_FILENAME);\n const sorted = {\n ...config,\n skills: [...config.skills].sort(compareByNameThenPath),\n };\n const content = JSON.stringify(sorted, null, 2);\n await writeFile(configPath, content, \"utf-8\");\n}\n","export const START_TAG = \"<!-- skilldex:start (auto-generated, do not edit) -->\";\nexport const END_TAG = \"<!-- skilldex:end -->\";\n\nexport const TARGET_FILE = \"AGENTS.md\";\nexport const CONFIG_FILENAME = \"skilldex.config.json\";\nexport const SKILL_META_FILE = \"SKILL.md\";\nexport const SKILLS_DIR_SEGMENTS = [\".agents\", \"skills\"] as const;\nexport const INDEX_HEADER = \"[Skills Index]\";\nexport const INDEX_INSTRUCTION =\n \"IMPORTANT: Prefer retrieval-led reasoning over pre-training-led reasoning for any tasks covered by indexed skills.\";\nexport const CONTEXT_BUDGET_WARN_KB = 20;\nexport const CONTEXT_BUDGET_DANGER_KB = 40;\n\nexport function compareByNameThenPath(\n a: { name: string; path: string },\n b: { name: string; path: string },\n): number {\n return a.name.localeCompare(b.name) || a.path.localeCompare(b.path);\n}\n","import type { Dirent } from \"node:fs\";\nimport { lstat, readdir, readFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { getUniqueSkillsDirs } from \"./agents.js\";\nimport { compareByNameThenPath, SKILL_META_FILE } from \"./constants.js\";\nimport type { DiscoveredSkill, SkillFile } from \"./types.js\";\n\n/** Extract key-value pairs from YAML frontmatter (between `---` fences). */\nexport function parseFrontmatter(content: string): Record<string, string> {\n const result: Record<string, string> = {};\n if (!content.startsWith(\"---\")) return result;\n\n const endIndex = content.indexOf(\"\\n---\", 3);\n if (endIndex === -1) return result;\n\n const block = content.slice(4, endIndex);\n for (const line of block.split(\"\\n\")) {\n const colonIndex = line.indexOf(\":\");\n if (colonIndex === -1) continue;\n const key = line.slice(0, colonIndex).trim();\n const value = line.slice(colonIndex + 1).trim();\n if (key) result[key] = value;\n }\n return result;\n}\n\nasync function safeReaddir(dir: string): Promise<Dirent[]> {\n try {\n return await readdir(dir, { withFileTypes: true });\n } catch {\n return [];\n }\n}\n\nexport async function safeReadFile(path: string): Promise<string | undefined> {\n try {\n return await readFile(path, \"utf-8\");\n } catch {\n return undefined;\n }\n}\n\nasync function collectMdFiles(dir: string, skillRoot: string): Promise<SkillFile[]> {\n const entries = await safeReaddir(dir);\n const files: SkillFile[] = [];\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n const nested = await collectMdFiles(fullPath, skillRoot);\n files.push(...nested);\n } else if (entry.isFile() && entry.name.endsWith(\".md\") && entry.name !== SKILL_META_FILE) {\n files.push({\n relativePath: relative(skillRoot, fullPath),\n name: entry.name.replace(/\\.md$/, \"\"),\n });\n }\n }\n return files;\n}\n\nasync function isSymlink(path: string): Promise<boolean> {\n try {\n const stats = await lstat(path);\n return stats.isSymbolicLink();\n } catch {\n return false;\n }\n}\n\n/** Scan a single skills directory and return discovered skills. */\nasync function scanDirectory(dir: string, projectRoot: string): Promise<DiscoveredSkill[]> {\n const entries = await safeReaddir(dir);\n const skills: DiscoveredSkill[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n\n const skillPath = join(dir, entry.name);\n\n if (await isSymlink(skillPath)) continue;\n\n let description = \"\";\n const skillMd = await safeReadFile(join(skillPath, SKILL_META_FILE));\n if (skillMd !== undefined) {\n const frontmatter = parseFrontmatter(skillMd);\n description = frontmatter.description ?? \"\";\n }\n\n const files = await collectMdFiles(skillPath, skillPath);\n skills.push({\n name: entry.name,\n description,\n path: skillPath,\n relativePath: relative(projectRoot, skillPath),\n files,\n });\n }\n return skills;\n}\n\n/** Scan all agent source directories for skills. Same-named skills in different directories are all included. */\nexport async function scanForSkills(projectRoot: string): Promise<DiscoveredSkill[]> {\n const results = await Promise.all(\n getUniqueSkillsDirs().map((d) => scanDirectory(join(projectRoot, d), projectRoot)),\n );\n return results.flat().sort(compareByNameThenPath);\n}\n","export interface AgentSource {\n /** Agent identifier, e.g. \"claude-code\" */\n name: string;\n /** Human-readable name, e.g. \"Claude Code\" */\n displayName: string;\n /** Skills directory relative to project root, e.g. \".claude/skills\" */\n skillsDir: string;\n}\n\n/**\n * Known agent source directories (project-scoped).\n * Sourced from the Vercel Skills CLI agent conventions.\n */\nexport const AGENT_SOURCES: AgentSource[] = [\n { name: \"universal\", displayName: \"Universal\", skillsDir: \".agents/skills\" },\n { name: \"antigravity\", displayName: \"Antigravity\", skillsDir: \".agent/skills\" },\n { name: \"claude-code\", displayName: \"Claude Code\", skillsDir: \".claude/skills\" },\n { name: \"codex\", displayName: \"Codex\", skillsDir: \".agents/skills\" },\n { name: \"cursor\", displayName: \"Cursor\", skillsDir: \".cursor/skills\" },\n { name: \"github-copilot\", displayName: \"GitHub Copilot\", skillsDir: \".agents/skills\" },\n { name: \"opencode\", displayName: \"OpenCode\", skillsDir: \".agents/skills\" },\n { name: \"openclaw\", displayName: \"OpenClaw\", skillsDir: \"skills\" },\n { name: \"windsurf\", displayName: \"Windsurf\", skillsDir: \".windsurf/skills\" },\n];\n\n/** Unique skills directories to scan (deduplicates agents sharing the same dir). */\nexport function getUniqueSkillsDirs(): string[] {\n return [...new Set(AGENT_SOURCES.map((a) => a.skillsDir))];\n}\n\n/** Maps a skill's relative path to the first matching agent's display name. */\nexport function getAgentDisplayName(relativePath: string): string | undefined {\n for (const agent of AGENT_SOURCES) {\n if (relativePath.startsWith(`${agent.skillsDir}/`) || relativePath === agent.skillsDir) {\n return agent.displayName;\n }\n }\n return undefined;\n}\n","import { stat, writeFile } from \"node:fs/promises\";\nimport { basename, join } from \"node:path\";\nimport { readConfig } from \"./config.js\";\nimport { END_TAG, START_TAG, TARGET_FILE } from \"./constants.js\";\nimport { generateIndex } from \"./indexer.js\";\nimport { safeReadFile, scanForSkills } from \"./scanner.js\";\nimport type { InitResult, TargetFileInfo } from \"./types.js\";\n\nexport async function getTargetInfos(\n projectRoot: string,\n targets: string[],\n): Promise<TargetFileInfo[]> {\n return Promise.all(\n targets.map(async (t) => {\n const p = join(projectRoot, t);\n const s = await stat(p);\n return { file: basename(t), path: p, totalSize: s.size };\n }),\n );\n}\n\nexport function buildManagedSection(indexContent: string): string {\n return `${START_TAG}\\n${indexContent}\\n${END_TAG}`;\n}\n\n/** Write or update the managed skilldex section in a target file. Creates, appends, or replaces as needed. Returns the written file content. */\nexport async function writeTargetFile(\n projectRoot: string,\n indexContent: string,\n targetFile: string = TARGET_FILE,\n): Promise<string> {\n const targetPath = join(projectRoot, targetFile);\n const section = buildManagedSection(indexContent);\n\n const existing = await safeReadFile(targetPath);\n\n let output: string;\n if (existing === undefined) {\n output = `${section}\\n`;\n } else if (existing.includes(START_TAG) && existing.includes(END_TAG)) {\n const startIdx = existing.indexOf(START_TAG);\n const endIdx = existing.indexOf(END_TAG) + END_TAG.length;\n output = existing.slice(0, startIdx) + section + existing.slice(endIdx);\n } else {\n output = `${existing.trimEnd()}\\n\\n${section}\\n`;\n }\n\n await writeFile(targetPath, output, \"utf-8\");\n return output;\n}\n\nexport interface RegenerateResult extends InitResult {\n /** Map of target file path → written content */\n writtenContent: Map<string, string>;\n}\n\n/** Regenerate all target files from config (reads config, scans indexed skills, writes targets). */\nexport async function regenerateFromConfig(projectRoot: string): Promise<RegenerateResult> {\n const config = await readConfig(projectRoot);\n const allSkills = await scanForSkills(projectRoot);\n\n // Map skill paths from config to DiscoveredSkill objects\n const skillMap = new Map(allSkills.map((s) => [s.relativePath, s]));\n const skills = config.skills\n .map((entry) => skillMap.get(entry.path))\n .filter((s) => s !== undefined);\n\n const index = generateIndex(skills);\n\n const writtenContent = new Map<string, string>();\n for (const target of config.targets) {\n const content = await writeTargetFile(projectRoot, index, target);\n writtenContent.set(join(projectRoot, target), content);\n }\n\n const managedSize = Buffer.byteLength(buildManagedSection(index));\n const targets = await getTargetInfos(projectRoot, config.targets);\n\n return {\n skillCount: skills.length,\n managedSize,\n targets,\n writtenContent,\n };\n}\n","import { dirname } from \"node:path\";\nimport { INDEX_HEADER, INDEX_INSTRUCTION } from \"./constants.js\";\nimport type { DiscoveredSkill } from \"./types.js\";\n\nfunction groupFilesBySubdir(\n files: { relativePath: string; name: string }[],\n): Map<string, string[]> {\n const groups = new Map<string, string[]>();\n for (const file of files) {\n const dir = dirname(file.relativePath);\n const key = dir === \".\" ? \"\" : dir;\n const existing = groups.get(key);\n if (existing) {\n existing.push(`${file.name}.md`);\n } else {\n groups.set(key, [`${file.name}.md`]);\n }\n }\n return groups;\n}\n\nexport function generateIndex(skills: DiscoveredSkill[]): string {\n const segments: string[] = [INDEX_HEADER, INDEX_INSTRUCTION];\n\n for (const skill of skills) {\n segments.push(`[${skill.name}]`);\n segments.push(`root:./${skill.relativePath}`);\n\n if (skill.description) {\n segments.push(`desc:${skill.description}`);\n }\n\n const groups = groupFilesBySubdir(skill.files);\n for (const [subdir, fileNames] of groups) {\n const fileList = `{${fileNames.join(\",\")}}`;\n if (subdir) {\n segments.push(`${subdir}:${fileList}`);\n } else {\n segments.push(fileList);\n }\n }\n }\n\n return segments.join(\"|\");\n}\n","import { readConfig, writeConfig } from \"./config.js\";\nimport { scanForSkills } from \"./scanner.js\";\nimport type { AddResult, DiscoveredSkill } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function addSkill(projectRoot: string, skillName: string): Promise<AddResult> {\n const config = await readConfig(projectRoot);\n const allSkills = await scanForSkills(projectRoot);\n\n const isPath = skillName.includes(\"/\");\n\n let targetSkill: DiscoveredSkill | undefined;\n\n if (isPath) {\n // Path-based lookup for disambiguation\n targetSkill = allSkills.find((s) => s.relativePath === skillName);\n if (!targetSkill) {\n throw new Error(`Skill \"${skillName}\" not found. Did you create the skill directory?`);\n }\n } else {\n // Name-based lookup\n const matches = allSkills.filter((s) => s.name === skillName);\n if (matches.length === 0) {\n throw new Error(`Skill \"${skillName}\" not found. Did you create the skill directory?`);\n }\n if (matches.length > 1) {\n const paths = matches.map((s) => ` ${s.relativePath}`).join(\"\\n\");\n throw new Error(`Multiple skills named \"${skillName}\" found. Specify the path:\\n${paths}`);\n }\n targetSkill = matches[0];\n }\n\n if (config.skills.some((s) => s.path === targetSkill.relativePath)) {\n throw new Error(`Skill \"${targetSkill.relativePath}\" is already indexed`);\n }\n\n config.skills.push({\n name: targetSkill.name,\n path: targetSkill.relativePath,\n });\n\n await writeConfig(projectRoot, config);\n\n const result = await regenerateFromConfig(projectRoot);\n\n return {\n skillName: targetSkill.name,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n","import { writeConfig } from \"./config.js\";\nimport { TARGET_FILE } from \"./constants.js\";\nimport { scanForSkills } from \"./scanner.js\";\nimport type { DiscoveredSkill, InitResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\n/** Scan for skills, filter by selection, and write the index to target files. */\nexport async function init(options: {\n projectRoot: string;\n selectedSkills?: string[];\n yes?: boolean;\n}): Promise<InitResult> {\n const { projectRoot, selectedSkills } = options;\n\n const discovered = await scanForSkills(projectRoot);\n\n let skills: DiscoveredSkill[];\n if (selectedSkills) {\n const selected = new Set(selectedSkills);\n skills = discovered.filter((s) => selected.has(s.name) || selected.has(s.relativePath));\n } else {\n skills = discovered;\n }\n\n return initWithSkills(projectRoot, skills);\n}\n\n/** Index a specific set of skills and write to target file(s). */\nexport async function initWithSkills(\n projectRoot: string,\n skills: DiscoveredSkill[],\n targets: string[] = [TARGET_FILE],\n): Promise<InitResult> {\n const config = {\n version: 1 as const,\n targets,\n skills: skills.map((skill) => ({\n name: skill.name,\n path: skill.relativePath,\n })),\n };\n await writeConfig(projectRoot, config);\n\n return regenerateFromConfig(projectRoot);\n}\n","import { readConfig } from \"./config.js\";\nimport { scanForSkills } from \"./scanner.js\";\nimport type { ListResult, SkillInfo } from \"./types.js\";\n\nexport async function listSkills(projectRoot: string): Promise<ListResult> {\n const config = await readConfig(projectRoot);\n const allSkills = await scanForSkills(projectRoot);\n\n const indexedPaths = new Set(config.skills.map((s) => s.path));\n const skillMap = new Map(allSkills.map((s) => [s.relativePath, s]));\n\n const indexed: SkillInfo[] = config.skills.map((entry) => {\n const discovered = skillMap.get(entry.path);\n if (!discovered) {\n return { name: entry.name, path: entry.path, description: \"\", missing: true };\n }\n return { name: entry.name, path: entry.path, description: discovered.description };\n });\n\n const available: SkillInfo[] = allSkills\n .filter((s) => !indexedPaths.has(s.relativePath))\n .map((s) => ({\n name: s.name,\n description: s.description,\n path: s.relativePath,\n }));\n\n return { indexed, available };\n}\n","import { rm } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { readConfig, writeConfig } from \"./config.js\";\nimport type { RemoveResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function removeSkill(\n projectRoot: string,\n skillName: string,\n deleteFiles = false,\n): Promise<RemoveResult> {\n const config = await readConfig(projectRoot);\n\n const isPath = skillName.includes(\"/\");\n\n let skillIndex: number;\n\n if (isPath) {\n skillIndex = config.skills.findIndex((s) => s.path === skillName);\n if (skillIndex === -1) {\n throw new Error(`Skill \"${skillName}\" is not indexed`);\n }\n } else {\n const matches = config.skills\n .map((s, i) => ({ entry: s, index: i }))\n .filter(({ entry }) => entry.name === skillName);\n\n if (matches.length === 0) {\n throw new Error(`Skill \"${skillName}\" is not indexed`);\n }\n if (matches.length > 1) {\n const paths = matches.map(({ entry }) => ` ${entry.path}`).join(\"\\n\");\n throw new Error(`Multiple skills named \"${skillName}\" indexed. Specify the path:\\n${paths}`);\n }\n skillIndex = matches[0].index;\n }\n\n const entry = config.skills[skillIndex];\n const skillPath = join(projectRoot, entry.path);\n\n config.skills.splice(skillIndex, 1);\n await writeConfig(projectRoot, config);\n\n if (deleteFiles) {\n await rm(skillPath, { recursive: true, force: true });\n }\n\n const result = await regenerateFromConfig(projectRoot);\n\n return {\n skillName: entry.name,\n wasDeleted: deleteFiles,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n","import { join } from \"node:path\";\nimport { readConfig, writeConfig } from \"./config.js\";\nimport { safeReadFile, scanForSkills } from \"./scanner.js\";\nimport type { SyncResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function syncSkills(projectRoot: string): Promise<SyncResult> {\n const config = await readConfig(projectRoot);\n const onDisk = await scanForSkills(projectRoot);\n const diskPaths = new Set(onDisk.map((s) => s.relativePath));\n\n // Find stale entries: in config but not on disk\n const stale = config.skills.filter((s) => !diskPaths.has(s.path));\n const removed = stale.map((s) => s.name);\n\n if (stale.length > 0) {\n const stalePaths = new Set(stale.map((s) => s.path));\n config.skills = config.skills.filter((s) => !stalePaths.has(s.path));\n await writeConfig(projectRoot, config);\n }\n\n const targetPaths = config.targets.map((t) => join(projectRoot, t));\n\n // Read before-state for all targets\n const beforeMap = new Map<string, string | undefined>();\n for (const targetPath of targetPaths) {\n beforeMap.set(targetPath, await safeReadFile(targetPath));\n }\n\n // Nothing to do if no skills indexed and no target files exist\n if (config.skills.length === 0 && [...beforeMap.values()].every((v) => v === undefined)) {\n return { removed, changed: false, managedSize: 0, targets: [] };\n }\n\n const result = await regenerateFromConfig(projectRoot);\n\n // Check if ANY target changed using the written content from regeneration\n let changed = false;\n for (const targetPath of targetPaths) {\n const after = result.writtenContent.get(targetPath);\n if (beforeMap.get(targetPath) !== after) {\n changed = true;\n break;\n }\n }\n\n return {\n removed,\n changed,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n","import { access } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { readConfig } from \"./config.js\";\nimport type { UpdateResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function updateSkill(\n projectRoot: string,\n skillPaths: string[],\n): Promise<UpdateResult> {\n const config = await readConfig(projectRoot);\n const configPathMap = new Map(config.skills.map((s) => [s.path, s.name]));\n\n // Validate all requested paths are indexed\n for (const skillPath of skillPaths) {\n if (!configPathMap.has(skillPath)) {\n throw new Error(\n `Skill \"${skillPath}\" is not indexed. Run 'skilldex add ${skillPath}' to index it.`,\n );\n }\n }\n\n // Validate all exist on disk\n for (const skillPath of skillPaths) {\n const absolutePath = join(projectRoot, skillPath);\n try {\n await access(absolutePath);\n } catch {\n throw new Error(\n `Skill \"${skillPath}\" not found on disk. Run 'skilldex sync' to remove stale entries.`,\n );\n }\n }\n\n const updated = skillPaths.map((p) => configPathMap.get(p) as string);\n\n const result = await regenerateFromConfig(projectRoot);\n\n return {\n updated,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n"],"mappings":"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","names":["import_promises","import_node_path","import_promises","import_node_path","import_node_path","import_promises","import_node_path","entry","import_node_path","import_promises","import_node_path"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -61,6 +61,8 @@ interface SkillInfo {
|
|
|
61
61
|
/** Relative path from project root */
|
|
62
62
|
path: string;
|
|
63
63
|
description: string;
|
|
64
|
+
/** true when the skill is indexed but its directory no longer exists on disk */
|
|
65
|
+
missing?: boolean;
|
|
64
66
|
}
|
|
65
67
|
interface ListResult {
|
|
66
68
|
indexed: SkillInfo[];
|
|
@@ -74,6 +76,12 @@ interface SyncResult {
|
|
|
74
76
|
managedSize: number;
|
|
75
77
|
targets: TargetFileInfo[];
|
|
76
78
|
}
|
|
79
|
+
interface UpdateResult {
|
|
80
|
+
/** Display names of the skills that were updated */
|
|
81
|
+
updated: string[];
|
|
82
|
+
managedSize: number;
|
|
83
|
+
targets: TargetFileInfo[];
|
|
84
|
+
}
|
|
77
85
|
|
|
78
86
|
declare function addSkill(projectRoot: string, skillName: string): Promise<AddResult>;
|
|
79
87
|
|
|
@@ -135,6 +143,8 @@ declare function scanForSkills(projectRoot: string): Promise<DiscoveredSkill[]>;
|
|
|
135
143
|
|
|
136
144
|
declare function syncSkills(projectRoot: string): Promise<SyncResult>;
|
|
137
145
|
|
|
146
|
+
declare function updateSkill(projectRoot: string, skillPaths: string[]): Promise<UpdateResult>;
|
|
147
|
+
|
|
138
148
|
declare function buildManagedSection(indexContent: string): string;
|
|
139
149
|
/** Write or update the managed skilldex section in a target file. Creates, appends, or replaces as needed. Returns the written file content. */
|
|
140
150
|
declare function writeTargetFile(projectRoot: string, indexContent: string, targetFile?: string): Promise<string>;
|
|
@@ -145,4 +155,4 @@ interface RegenerateResult extends InitResult {
|
|
|
145
155
|
/** Regenerate all target files from config (reads config, scans indexed skills, writes targets). */
|
|
146
156
|
declare function regenerateFromConfig(projectRoot: string): Promise<RegenerateResult>;
|
|
147
157
|
|
|
148
|
-
export { AGENT_SOURCES, type AddResult, type AgentSource, CONFIG_FILENAME, CONTEXT_BUDGET_DANGER_KB, CONTEXT_BUDGET_WARN_KB, type Config, type DiscoveredSkill, END_TAG, INDEX_HEADER, INDEX_INSTRUCTION, type InitResult, type ListResult, type RegenerateResult, type RemoveResult, SKILL_META_FILE, START_TAG, type SkillEntry, type SkillFile, type SkillInfo, type SyncResult, TARGET_FILE, type TargetFileInfo, addSkill, buildManagedSection, compareByNameThenPath, generateIndex, getAgentDisplayName, getUniqueSkillsDirs, init, initWithSkills, listSkills, readConfig, regenerateFromConfig, removeSkill, scanForSkills, syncSkills, writeConfig, writeTargetFile };
|
|
158
|
+
export { AGENT_SOURCES, type AddResult, type AgentSource, CONFIG_FILENAME, CONTEXT_BUDGET_DANGER_KB, CONTEXT_BUDGET_WARN_KB, type Config, type DiscoveredSkill, END_TAG, INDEX_HEADER, INDEX_INSTRUCTION, type InitResult, type ListResult, type RegenerateResult, type RemoveResult, SKILL_META_FILE, START_TAG, type SkillEntry, type SkillFile, type SkillInfo, type SyncResult, TARGET_FILE, type TargetFileInfo, type UpdateResult, addSkill, buildManagedSection, compareByNameThenPath, generateIndex, getAgentDisplayName, getUniqueSkillsDirs, init, initWithSkills, listSkills, readConfig, regenerateFromConfig, removeSkill, scanForSkills, syncSkills, updateSkill, writeConfig, writeTargetFile };
|
package/dist/index.d.ts
CHANGED
|
@@ -61,6 +61,8 @@ interface SkillInfo {
|
|
|
61
61
|
/** Relative path from project root */
|
|
62
62
|
path: string;
|
|
63
63
|
description: string;
|
|
64
|
+
/** true when the skill is indexed but its directory no longer exists on disk */
|
|
65
|
+
missing?: boolean;
|
|
64
66
|
}
|
|
65
67
|
interface ListResult {
|
|
66
68
|
indexed: SkillInfo[];
|
|
@@ -74,6 +76,12 @@ interface SyncResult {
|
|
|
74
76
|
managedSize: number;
|
|
75
77
|
targets: TargetFileInfo[];
|
|
76
78
|
}
|
|
79
|
+
interface UpdateResult {
|
|
80
|
+
/** Display names of the skills that were updated */
|
|
81
|
+
updated: string[];
|
|
82
|
+
managedSize: number;
|
|
83
|
+
targets: TargetFileInfo[];
|
|
84
|
+
}
|
|
77
85
|
|
|
78
86
|
declare function addSkill(projectRoot: string, skillName: string): Promise<AddResult>;
|
|
79
87
|
|
|
@@ -135,6 +143,8 @@ declare function scanForSkills(projectRoot: string): Promise<DiscoveredSkill[]>;
|
|
|
135
143
|
|
|
136
144
|
declare function syncSkills(projectRoot: string): Promise<SyncResult>;
|
|
137
145
|
|
|
146
|
+
declare function updateSkill(projectRoot: string, skillPaths: string[]): Promise<UpdateResult>;
|
|
147
|
+
|
|
138
148
|
declare function buildManagedSection(indexContent: string): string;
|
|
139
149
|
/** Write or update the managed skilldex section in a target file. Creates, appends, or replaces as needed. Returns the written file content. */
|
|
140
150
|
declare function writeTargetFile(projectRoot: string, indexContent: string, targetFile?: string): Promise<string>;
|
|
@@ -145,4 +155,4 @@ interface RegenerateResult extends InitResult {
|
|
|
145
155
|
/** Regenerate all target files from config (reads config, scans indexed skills, writes targets). */
|
|
146
156
|
declare function regenerateFromConfig(projectRoot: string): Promise<RegenerateResult>;
|
|
147
157
|
|
|
148
|
-
export { AGENT_SOURCES, type AddResult, type AgentSource, CONFIG_FILENAME, CONTEXT_BUDGET_DANGER_KB, CONTEXT_BUDGET_WARN_KB, type Config, type DiscoveredSkill, END_TAG, INDEX_HEADER, INDEX_INSTRUCTION, type InitResult, type ListResult, type RegenerateResult, type RemoveResult, SKILL_META_FILE, START_TAG, type SkillEntry, type SkillFile, type SkillInfo, type SyncResult, TARGET_FILE, type TargetFileInfo, addSkill, buildManagedSection, compareByNameThenPath, generateIndex, getAgentDisplayName, getUniqueSkillsDirs, init, initWithSkills, listSkills, readConfig, regenerateFromConfig, removeSkill, scanForSkills, syncSkills, writeConfig, writeTargetFile };
|
|
158
|
+
export { AGENT_SOURCES, type AddResult, type AgentSource, CONFIG_FILENAME, CONTEXT_BUDGET_DANGER_KB, CONTEXT_BUDGET_WARN_KB, type Config, type DiscoveredSkill, END_TAG, INDEX_HEADER, INDEX_INSTRUCTION, type InitResult, type ListResult, type RegenerateResult, type RemoveResult, SKILL_META_FILE, START_TAG, type SkillEntry, type SkillFile, type SkillInfo, type SyncResult, TARGET_FILE, type TargetFileInfo, type UpdateResult, addSkill, buildManagedSection, compareByNameThenPath, generateIndex, getAgentDisplayName, getUniqueSkillsDirs, init, initWithSkills, listSkills, readConfig, regenerateFromConfig, removeSkill, scanForSkills, syncSkills, updateSkill, writeConfig, writeTargetFile };
|
package/dist/index.js
CHANGED
|
@@ -335,13 +335,11 @@ async function listSkills(projectRoot) {
|
|
|
335
335
|
const skillMap = new Map(allSkills.map((s) => [s.relativePath, s]));
|
|
336
336
|
const indexed = config.skills.map((entry) => {
|
|
337
337
|
const discovered = skillMap.get(entry.path);
|
|
338
|
-
if (!discovered)
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
};
|
|
344
|
-
}).filter((s) => s !== void 0);
|
|
338
|
+
if (!discovered) {
|
|
339
|
+
return { name: entry.name, path: entry.path, description: "", missing: true };
|
|
340
|
+
}
|
|
341
|
+
return { name: entry.name, path: entry.path, description: discovered.description };
|
|
342
|
+
});
|
|
345
343
|
const available = allSkills.filter((s) => !indexedPaths.has(s.relativePath)).map((s) => ({
|
|
346
344
|
name: s.name,
|
|
347
345
|
description: s.description,
|
|
@@ -427,6 +425,38 @@ async function syncSkills(projectRoot) {
|
|
|
427
425
|
targets: result.targets
|
|
428
426
|
};
|
|
429
427
|
}
|
|
428
|
+
|
|
429
|
+
// src/lib/update.ts
|
|
430
|
+
import { access } from "fs/promises";
|
|
431
|
+
import { join as join6 } from "path";
|
|
432
|
+
async function updateSkill(projectRoot, skillPaths) {
|
|
433
|
+
const config = await readConfig(projectRoot);
|
|
434
|
+
const configPathMap = new Map(config.skills.map((s) => [s.path, s.name]));
|
|
435
|
+
for (const skillPath of skillPaths) {
|
|
436
|
+
if (!configPathMap.has(skillPath)) {
|
|
437
|
+
throw new Error(
|
|
438
|
+
`Skill "${skillPath}" is not indexed. Run 'skilldex add ${skillPath}' to index it.`
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
for (const skillPath of skillPaths) {
|
|
443
|
+
const absolutePath = join6(projectRoot, skillPath);
|
|
444
|
+
try {
|
|
445
|
+
await access(absolutePath);
|
|
446
|
+
} catch {
|
|
447
|
+
throw new Error(
|
|
448
|
+
`Skill "${skillPath}" not found on disk. Run 'skilldex sync' to remove stale entries.`
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
const updated = skillPaths.map((p) => configPathMap.get(p));
|
|
453
|
+
const result = await regenerateFromConfig(projectRoot);
|
|
454
|
+
return {
|
|
455
|
+
updated,
|
|
456
|
+
managedSize: result.managedSize,
|
|
457
|
+
targets: result.targets
|
|
458
|
+
};
|
|
459
|
+
}
|
|
430
460
|
export {
|
|
431
461
|
AGENT_SOURCES,
|
|
432
462
|
CONFIG_FILENAME,
|
|
@@ -452,6 +482,7 @@ export {
|
|
|
452
482
|
removeSkill,
|
|
453
483
|
scanForSkills,
|
|
454
484
|
syncSkills,
|
|
485
|
+
updateSkill,
|
|
455
486
|
writeConfig,
|
|
456
487
|
writeTargetFile
|
|
457
488
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/config.ts","../src/lib/constants.ts","../src/lib/scanner.ts","../src/lib/agents.ts","../src/lib/writer.ts","../src/lib/indexer.ts","../src/lib/add.ts","../src/lib/init.ts","../src/lib/list.ts","../src/lib/remove.ts","../src/lib/sync.ts"],"sourcesContent":["import { writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { CONFIG_FILENAME, compareByNameThenPath, TARGET_FILE } from \"./constants.js\";\nimport { safeReadFile } from \"./scanner.js\";\nimport type { Config } from \"./types.js\";\n\nfunction getDefaultConfig(): Config {\n return {\n version: 1,\n targets: [TARGET_FILE],\n skills: [],\n };\n}\n\nexport async function readConfig(projectRoot: string): Promise<Config> {\n const configPath = join(projectRoot, CONFIG_FILENAME);\n const content = await safeReadFile(configPath);\n\n if (content === undefined) {\n return getDefaultConfig();\n }\n\n try {\n const parsed = JSON.parse(content) as Config;\n // Validate structure\n if (\n typeof parsed.version !== \"number\" ||\n !Array.isArray(parsed.targets) ||\n !Array.isArray(parsed.skills)\n ) {\n return getDefaultConfig();\n }\n return parsed;\n } catch {\n return getDefaultConfig();\n }\n}\n\nexport async function writeConfig(projectRoot: string, config: Config): Promise<void> {\n const configPath = join(projectRoot, CONFIG_FILENAME);\n const sorted = {\n ...config,\n skills: [...config.skills].sort(compareByNameThenPath),\n };\n const content = JSON.stringify(sorted, null, 2);\n await writeFile(configPath, content, \"utf-8\");\n}\n","export const START_TAG = \"<!-- skilldex:start (auto-generated, do not edit) -->\";\nexport const END_TAG = \"<!-- skilldex:end -->\";\n\nexport const TARGET_FILE = \"AGENTS.md\";\nexport const CONFIG_FILENAME = \"skilldex.config.json\";\nexport const SKILL_META_FILE = \"SKILL.md\";\nexport const SKILLS_DIR_SEGMENTS = [\".agents\", \"skills\"] as const;\nexport const INDEX_HEADER = \"[Skills Index]\";\nexport const INDEX_INSTRUCTION =\n \"IMPORTANT: Prefer retrieval-led reasoning over pre-training-led reasoning for any tasks covered by indexed skills.\";\nexport const CONTEXT_BUDGET_WARN_KB = 20;\nexport const CONTEXT_BUDGET_DANGER_KB = 40;\n\nexport function compareByNameThenPath(\n a: { name: string; path: string },\n b: { name: string; path: string },\n): number {\n return a.name.localeCompare(b.name) || a.path.localeCompare(b.path);\n}\n","import type { Dirent } from \"node:fs\";\nimport { lstat, readdir, readFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { getUniqueSkillsDirs } from \"./agents.js\";\nimport { compareByNameThenPath, SKILL_META_FILE } from \"./constants.js\";\nimport type { DiscoveredSkill, SkillFile } from \"./types.js\";\n\n/** Extract key-value pairs from YAML frontmatter (between `---` fences). */\nexport function parseFrontmatter(content: string): Record<string, string> {\n const result: Record<string, string> = {};\n if (!content.startsWith(\"---\")) return result;\n\n const endIndex = content.indexOf(\"\\n---\", 3);\n if (endIndex === -1) return result;\n\n const block = content.slice(4, endIndex);\n for (const line of block.split(\"\\n\")) {\n const colonIndex = line.indexOf(\":\");\n if (colonIndex === -1) continue;\n const key = line.slice(0, colonIndex).trim();\n const value = line.slice(colonIndex + 1).trim();\n if (key) result[key] = value;\n }\n return result;\n}\n\nasync function safeReaddir(dir: string): Promise<Dirent[]> {\n try {\n return await readdir(dir, { withFileTypes: true });\n } catch {\n return [];\n }\n}\n\nexport async function safeReadFile(path: string): Promise<string | undefined> {\n try {\n return await readFile(path, \"utf-8\");\n } catch {\n return undefined;\n }\n}\n\nasync function collectMdFiles(dir: string, skillRoot: string): Promise<SkillFile[]> {\n const entries = await safeReaddir(dir);\n const files: SkillFile[] = [];\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n const nested = await collectMdFiles(fullPath, skillRoot);\n files.push(...nested);\n } else if (entry.isFile() && entry.name.endsWith(\".md\") && entry.name !== SKILL_META_FILE) {\n files.push({\n relativePath: relative(skillRoot, fullPath),\n name: entry.name.replace(/\\.md$/, \"\"),\n });\n }\n }\n return files;\n}\n\nasync function isSymlink(path: string): Promise<boolean> {\n try {\n const stats = await lstat(path);\n return stats.isSymbolicLink();\n } catch {\n return false;\n }\n}\n\n/** Scan a single skills directory and return discovered skills. */\nasync function scanDirectory(dir: string, projectRoot: string): Promise<DiscoveredSkill[]> {\n const entries = await safeReaddir(dir);\n const skills: DiscoveredSkill[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n\n const skillPath = join(dir, entry.name);\n\n if (await isSymlink(skillPath)) continue;\n\n let description = \"\";\n const skillMd = await safeReadFile(join(skillPath, SKILL_META_FILE));\n if (skillMd !== undefined) {\n const frontmatter = parseFrontmatter(skillMd);\n description = frontmatter.description ?? \"\";\n }\n\n const files = await collectMdFiles(skillPath, skillPath);\n skills.push({\n name: entry.name,\n description,\n path: skillPath,\n relativePath: relative(projectRoot, skillPath),\n files,\n });\n }\n return skills;\n}\n\n/** Scan all agent source directories for skills. Same-named skills in different directories are all included. */\nexport async function scanForSkills(projectRoot: string): Promise<DiscoveredSkill[]> {\n const results = await Promise.all(\n getUniqueSkillsDirs().map((d) => scanDirectory(join(projectRoot, d), projectRoot)),\n );\n return results.flat().sort(compareByNameThenPath);\n}\n","export interface AgentSource {\n /** Agent identifier, e.g. \"claude-code\" */\n name: string;\n /** Human-readable name, e.g. \"Claude Code\" */\n displayName: string;\n /** Skills directory relative to project root, e.g. \".claude/skills\" */\n skillsDir: string;\n}\n\n/**\n * Known agent source directories (project-scoped).\n * Sourced from the Vercel Skills CLI agent conventions.\n */\nexport const AGENT_SOURCES: AgentSource[] = [\n { name: \"universal\", displayName: \"Universal\", skillsDir: \".agents/skills\" },\n { name: \"antigravity\", displayName: \"Antigravity\", skillsDir: \".agent/skills\" },\n { name: \"claude-code\", displayName: \"Claude Code\", skillsDir: \".claude/skills\" },\n { name: \"codex\", displayName: \"Codex\", skillsDir: \".agents/skills\" },\n { name: \"cursor\", displayName: \"Cursor\", skillsDir: \".cursor/skills\" },\n { name: \"github-copilot\", displayName: \"GitHub Copilot\", skillsDir: \".agents/skills\" },\n { name: \"opencode\", displayName: \"OpenCode\", skillsDir: \".agents/skills\" },\n { name: \"openclaw\", displayName: \"OpenClaw\", skillsDir: \"skills\" },\n { name: \"windsurf\", displayName: \"Windsurf\", skillsDir: \".windsurf/skills\" },\n];\n\n/** Unique skills directories to scan (deduplicates agents sharing the same dir). */\nexport function getUniqueSkillsDirs(): string[] {\n return [...new Set(AGENT_SOURCES.map((a) => a.skillsDir))];\n}\n\n/** Maps a skill's relative path to the first matching agent's display name. */\nexport function getAgentDisplayName(relativePath: string): string | undefined {\n for (const agent of AGENT_SOURCES) {\n if (relativePath.startsWith(`${agent.skillsDir}/`) || relativePath === agent.skillsDir) {\n return agent.displayName;\n }\n }\n return undefined;\n}\n","import { stat, writeFile } from \"node:fs/promises\";\nimport { basename, join } from \"node:path\";\nimport { readConfig } from \"./config.js\";\nimport { END_TAG, START_TAG, TARGET_FILE } from \"./constants.js\";\nimport { generateIndex } from \"./indexer.js\";\nimport { safeReadFile, scanForSkills } from \"./scanner.js\";\nimport type { InitResult, TargetFileInfo } from \"./types.js\";\n\nexport async function getTargetInfos(\n projectRoot: string,\n targets: string[],\n): Promise<TargetFileInfo[]> {\n return Promise.all(\n targets.map(async (t) => {\n const p = join(projectRoot, t);\n const s = await stat(p);\n return { file: basename(t), path: p, totalSize: s.size };\n }),\n );\n}\n\nexport function buildManagedSection(indexContent: string): string {\n return `${START_TAG}\\n${indexContent}\\n${END_TAG}`;\n}\n\n/** Write or update the managed skilldex section in a target file. Creates, appends, or replaces as needed. Returns the written file content. */\nexport async function writeTargetFile(\n projectRoot: string,\n indexContent: string,\n targetFile: string = TARGET_FILE,\n): Promise<string> {\n const targetPath = join(projectRoot, targetFile);\n const section = buildManagedSection(indexContent);\n\n const existing = await safeReadFile(targetPath);\n\n let output: string;\n if (existing === undefined) {\n output = `${section}\\n`;\n } else if (existing.includes(START_TAG) && existing.includes(END_TAG)) {\n const startIdx = existing.indexOf(START_TAG);\n const endIdx = existing.indexOf(END_TAG) + END_TAG.length;\n output = existing.slice(0, startIdx) + section + existing.slice(endIdx);\n } else {\n output = `${existing.trimEnd()}\\n\\n${section}\\n`;\n }\n\n await writeFile(targetPath, output, \"utf-8\");\n return output;\n}\n\nexport interface RegenerateResult extends InitResult {\n /** Map of target file path → written content */\n writtenContent: Map<string, string>;\n}\n\n/** Regenerate all target files from config (reads config, scans indexed skills, writes targets). */\nexport async function regenerateFromConfig(projectRoot: string): Promise<RegenerateResult> {\n const config = await readConfig(projectRoot);\n const allSkills = await scanForSkills(projectRoot);\n\n // Map skill paths from config to DiscoveredSkill objects\n const skillMap = new Map(allSkills.map((s) => [s.relativePath, s]));\n const skills = config.skills\n .map((entry) => skillMap.get(entry.path))\n .filter((s) => s !== undefined);\n\n const index = generateIndex(skills);\n\n const writtenContent = new Map<string, string>();\n for (const target of config.targets) {\n const content = await writeTargetFile(projectRoot, index, target);\n writtenContent.set(join(projectRoot, target), content);\n }\n\n const managedSize = Buffer.byteLength(buildManagedSection(index));\n const targets = await getTargetInfos(projectRoot, config.targets);\n\n return {\n skillCount: skills.length,\n managedSize,\n targets,\n writtenContent,\n };\n}\n","import { dirname } from \"node:path\";\nimport { INDEX_HEADER, INDEX_INSTRUCTION } from \"./constants.js\";\nimport type { DiscoveredSkill } from \"./types.js\";\n\nfunction groupFilesBySubdir(\n files: { relativePath: string; name: string }[],\n): Map<string, string[]> {\n const groups = new Map<string, string[]>();\n for (const file of files) {\n const dir = dirname(file.relativePath);\n const key = dir === \".\" ? \"\" : dir;\n const existing = groups.get(key);\n if (existing) {\n existing.push(`${file.name}.md`);\n } else {\n groups.set(key, [`${file.name}.md`]);\n }\n }\n return groups;\n}\n\nexport function generateIndex(skills: DiscoveredSkill[]): string {\n const segments: string[] = [INDEX_HEADER, INDEX_INSTRUCTION];\n\n for (const skill of skills) {\n segments.push(`[${skill.name}]`);\n segments.push(`root:./${skill.relativePath}`);\n\n if (skill.description) {\n segments.push(`desc:${skill.description}`);\n }\n\n const groups = groupFilesBySubdir(skill.files);\n for (const [subdir, fileNames] of groups) {\n const fileList = `{${fileNames.join(\",\")}}`;\n if (subdir) {\n segments.push(`${subdir}:${fileList}`);\n } else {\n segments.push(fileList);\n }\n }\n }\n\n return segments.join(\"|\");\n}\n","import { readConfig, writeConfig } from \"./config.js\";\nimport { scanForSkills } from \"./scanner.js\";\nimport type { AddResult, DiscoveredSkill } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function addSkill(projectRoot: string, skillName: string): Promise<AddResult> {\n const config = await readConfig(projectRoot);\n const allSkills = await scanForSkills(projectRoot);\n\n const isPath = skillName.includes(\"/\");\n\n let targetSkill: DiscoveredSkill | undefined;\n\n if (isPath) {\n // Path-based lookup for disambiguation\n targetSkill = allSkills.find((s) => s.relativePath === skillName);\n if (!targetSkill) {\n throw new Error(`Skill \"${skillName}\" not found. Did you create the skill directory?`);\n }\n } else {\n // Name-based lookup\n const matches = allSkills.filter((s) => s.name === skillName);\n if (matches.length === 0) {\n throw new Error(`Skill \"${skillName}\" not found. Did you create the skill directory?`);\n }\n if (matches.length > 1) {\n const paths = matches.map((s) => ` ${s.relativePath}`).join(\"\\n\");\n throw new Error(`Multiple skills named \"${skillName}\" found. Specify the path:\\n${paths}`);\n }\n targetSkill = matches[0];\n }\n\n if (config.skills.some((s) => s.path === targetSkill.relativePath)) {\n throw new Error(`Skill \"${targetSkill.relativePath}\" is already indexed`);\n }\n\n config.skills.push({\n name: targetSkill.name,\n path: targetSkill.relativePath,\n });\n\n await writeConfig(projectRoot, config);\n\n const result = await regenerateFromConfig(projectRoot);\n\n return {\n skillName: targetSkill.name,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n","import { writeConfig } from \"./config.js\";\nimport { TARGET_FILE } from \"./constants.js\";\nimport { scanForSkills } from \"./scanner.js\";\nimport type { DiscoveredSkill, InitResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\n/** Scan for skills, filter by selection, and write the index to target files. */\nexport async function init(options: {\n projectRoot: string;\n selectedSkills?: string[];\n yes?: boolean;\n}): Promise<InitResult> {\n const { projectRoot, selectedSkills } = options;\n\n const discovered = await scanForSkills(projectRoot);\n\n let skills: DiscoveredSkill[];\n if (selectedSkills) {\n const selected = new Set(selectedSkills);\n skills = discovered.filter((s) => selected.has(s.name) || selected.has(s.relativePath));\n } else {\n skills = discovered;\n }\n\n return initWithSkills(projectRoot, skills);\n}\n\n/** Index a specific set of skills and write to target file(s). */\nexport async function initWithSkills(\n projectRoot: string,\n skills: DiscoveredSkill[],\n targets: string[] = [TARGET_FILE],\n): Promise<InitResult> {\n const config = {\n version: 1 as const,\n targets,\n skills: skills.map((skill) => ({\n name: skill.name,\n path: skill.relativePath,\n })),\n };\n await writeConfig(projectRoot, config);\n\n return regenerateFromConfig(projectRoot);\n}\n","import { readConfig } from \"./config.js\";\nimport { scanForSkills } from \"./scanner.js\";\nimport type { ListResult, SkillInfo } from \"./types.js\";\n\nexport async function listSkills(projectRoot: string): Promise<ListResult> {\n const config = await readConfig(projectRoot);\n const allSkills = await scanForSkills(projectRoot);\n\n const indexedPaths = new Set(config.skills.map((s) => s.path));\n const skillMap = new Map(allSkills.map((s) => [s.relativePath, s]));\n\n const indexed: SkillInfo[] = config.skills\n .map((entry) => {\n const discovered = skillMap.get(entry.path);\n if (!discovered) return undefined;\n return {\n name: entry.name,\n path: entry.path,\n description: discovered.description,\n };\n })\n .filter((s) => s !== undefined);\n\n const available: SkillInfo[] = allSkills\n .filter((s) => !indexedPaths.has(s.relativePath))\n .map((s) => ({\n name: s.name,\n description: s.description,\n path: s.relativePath,\n }));\n\n return { indexed, available };\n}\n","import { rm } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { readConfig, writeConfig } from \"./config.js\";\nimport type { RemoveResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function removeSkill(\n projectRoot: string,\n skillName: string,\n deleteFiles = false,\n): Promise<RemoveResult> {\n const config = await readConfig(projectRoot);\n\n const isPath = skillName.includes(\"/\");\n\n let skillIndex: number;\n\n if (isPath) {\n skillIndex = config.skills.findIndex((s) => s.path === skillName);\n if (skillIndex === -1) {\n throw new Error(`Skill \"${skillName}\" is not indexed`);\n }\n } else {\n const matches = config.skills\n .map((s, i) => ({ entry: s, index: i }))\n .filter(({ entry }) => entry.name === skillName);\n\n if (matches.length === 0) {\n throw new Error(`Skill \"${skillName}\" is not indexed`);\n }\n if (matches.length > 1) {\n const paths = matches.map(({ entry }) => ` ${entry.path}`).join(\"\\n\");\n throw new Error(`Multiple skills named \"${skillName}\" indexed. Specify the path:\\n${paths}`);\n }\n skillIndex = matches[0].index;\n }\n\n const entry = config.skills[skillIndex];\n const skillPath = join(projectRoot, entry.path);\n\n config.skills.splice(skillIndex, 1);\n await writeConfig(projectRoot, config);\n\n if (deleteFiles) {\n await rm(skillPath, { recursive: true, force: true });\n }\n\n const result = await regenerateFromConfig(projectRoot);\n\n return {\n skillName: entry.name,\n wasDeleted: deleteFiles,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n","import { join } from \"node:path\";\nimport { readConfig, writeConfig } from \"./config.js\";\nimport { safeReadFile, scanForSkills } from \"./scanner.js\";\nimport type { SyncResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function syncSkills(projectRoot: string): Promise<SyncResult> {\n const config = await readConfig(projectRoot);\n const onDisk = await scanForSkills(projectRoot);\n const diskPaths = new Set(onDisk.map((s) => s.relativePath));\n\n // Find stale entries: in config but not on disk\n const stale = config.skills.filter((s) => !diskPaths.has(s.path));\n const removed = stale.map((s) => s.name);\n\n if (stale.length > 0) {\n const stalePaths = new Set(stale.map((s) => s.path));\n config.skills = config.skills.filter((s) => !stalePaths.has(s.path));\n await writeConfig(projectRoot, config);\n }\n\n const targetPaths = config.targets.map((t) => join(projectRoot, t));\n\n // Read before-state for all targets\n const beforeMap = new Map<string, string | undefined>();\n for (const targetPath of targetPaths) {\n beforeMap.set(targetPath, await safeReadFile(targetPath));\n }\n\n // Nothing to do if no skills indexed and no target files exist\n if (config.skills.length === 0 && [...beforeMap.values()].every((v) => v === undefined)) {\n return { removed, changed: false, managedSize: 0, targets: [] };\n }\n\n const result = await regenerateFromConfig(projectRoot);\n\n // Check if ANY target changed using the written content from regeneration\n let changed = false;\n for (const targetPath of targetPaths) {\n const after = result.writtenContent.get(targetPath);\n if (beforeMap.get(targetPath) !== after) {\n changed = true;\n break;\n }\n }\n\n return {\n removed,\n changed,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n"],"mappings":"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","names":["join","join","writeFile","join","join","writeFile","join","entry","join","join","join"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/config.ts","../src/lib/constants.ts","../src/lib/scanner.ts","../src/lib/agents.ts","../src/lib/writer.ts","../src/lib/indexer.ts","../src/lib/add.ts","../src/lib/init.ts","../src/lib/list.ts","../src/lib/remove.ts","../src/lib/sync.ts","../src/lib/update.ts"],"sourcesContent":["import { writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { CONFIG_FILENAME, compareByNameThenPath, TARGET_FILE } from \"./constants.js\";\nimport { safeReadFile } from \"./scanner.js\";\nimport type { Config } from \"./types.js\";\n\nfunction getDefaultConfig(): Config {\n return {\n version: 1,\n targets: [TARGET_FILE],\n skills: [],\n };\n}\n\nexport async function readConfig(projectRoot: string): Promise<Config> {\n const configPath = join(projectRoot, CONFIG_FILENAME);\n const content = await safeReadFile(configPath);\n\n if (content === undefined) {\n return getDefaultConfig();\n }\n\n try {\n const parsed = JSON.parse(content) as Config;\n // Validate structure\n if (\n typeof parsed.version !== \"number\" ||\n !Array.isArray(parsed.targets) ||\n !Array.isArray(parsed.skills)\n ) {\n return getDefaultConfig();\n }\n return parsed;\n } catch {\n return getDefaultConfig();\n }\n}\n\nexport async function writeConfig(projectRoot: string, config: Config): Promise<void> {\n const configPath = join(projectRoot, CONFIG_FILENAME);\n const sorted = {\n ...config,\n skills: [...config.skills].sort(compareByNameThenPath),\n };\n const content = JSON.stringify(sorted, null, 2);\n await writeFile(configPath, content, \"utf-8\");\n}\n","export const START_TAG = \"<!-- skilldex:start (auto-generated, do not edit) -->\";\nexport const END_TAG = \"<!-- skilldex:end -->\";\n\nexport const TARGET_FILE = \"AGENTS.md\";\nexport const CONFIG_FILENAME = \"skilldex.config.json\";\nexport const SKILL_META_FILE = \"SKILL.md\";\nexport const SKILLS_DIR_SEGMENTS = [\".agents\", \"skills\"] as const;\nexport const INDEX_HEADER = \"[Skills Index]\";\nexport const INDEX_INSTRUCTION =\n \"IMPORTANT: Prefer retrieval-led reasoning over pre-training-led reasoning for any tasks covered by indexed skills.\";\nexport const CONTEXT_BUDGET_WARN_KB = 20;\nexport const CONTEXT_BUDGET_DANGER_KB = 40;\n\nexport function compareByNameThenPath(\n a: { name: string; path: string },\n b: { name: string; path: string },\n): number {\n return a.name.localeCompare(b.name) || a.path.localeCompare(b.path);\n}\n","import type { Dirent } from \"node:fs\";\nimport { lstat, readdir, readFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { getUniqueSkillsDirs } from \"./agents.js\";\nimport { compareByNameThenPath, SKILL_META_FILE } from \"./constants.js\";\nimport type { DiscoveredSkill, SkillFile } from \"./types.js\";\n\n/** Extract key-value pairs from YAML frontmatter (between `---` fences). */\nexport function parseFrontmatter(content: string): Record<string, string> {\n const result: Record<string, string> = {};\n if (!content.startsWith(\"---\")) return result;\n\n const endIndex = content.indexOf(\"\\n---\", 3);\n if (endIndex === -1) return result;\n\n const block = content.slice(4, endIndex);\n for (const line of block.split(\"\\n\")) {\n const colonIndex = line.indexOf(\":\");\n if (colonIndex === -1) continue;\n const key = line.slice(0, colonIndex).trim();\n const value = line.slice(colonIndex + 1).trim();\n if (key) result[key] = value;\n }\n return result;\n}\n\nasync function safeReaddir(dir: string): Promise<Dirent[]> {\n try {\n return await readdir(dir, { withFileTypes: true });\n } catch {\n return [];\n }\n}\n\nexport async function safeReadFile(path: string): Promise<string | undefined> {\n try {\n return await readFile(path, \"utf-8\");\n } catch {\n return undefined;\n }\n}\n\nasync function collectMdFiles(dir: string, skillRoot: string): Promise<SkillFile[]> {\n const entries = await safeReaddir(dir);\n const files: SkillFile[] = [];\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n const nested = await collectMdFiles(fullPath, skillRoot);\n files.push(...nested);\n } else if (entry.isFile() && entry.name.endsWith(\".md\") && entry.name !== SKILL_META_FILE) {\n files.push({\n relativePath: relative(skillRoot, fullPath),\n name: entry.name.replace(/\\.md$/, \"\"),\n });\n }\n }\n return files;\n}\n\nasync function isSymlink(path: string): Promise<boolean> {\n try {\n const stats = await lstat(path);\n return stats.isSymbolicLink();\n } catch {\n return false;\n }\n}\n\n/** Scan a single skills directory and return discovered skills. */\nasync function scanDirectory(dir: string, projectRoot: string): Promise<DiscoveredSkill[]> {\n const entries = await safeReaddir(dir);\n const skills: DiscoveredSkill[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n\n const skillPath = join(dir, entry.name);\n\n if (await isSymlink(skillPath)) continue;\n\n let description = \"\";\n const skillMd = await safeReadFile(join(skillPath, SKILL_META_FILE));\n if (skillMd !== undefined) {\n const frontmatter = parseFrontmatter(skillMd);\n description = frontmatter.description ?? \"\";\n }\n\n const files = await collectMdFiles(skillPath, skillPath);\n skills.push({\n name: entry.name,\n description,\n path: skillPath,\n relativePath: relative(projectRoot, skillPath),\n files,\n });\n }\n return skills;\n}\n\n/** Scan all agent source directories for skills. Same-named skills in different directories are all included. */\nexport async function scanForSkills(projectRoot: string): Promise<DiscoveredSkill[]> {\n const results = await Promise.all(\n getUniqueSkillsDirs().map((d) => scanDirectory(join(projectRoot, d), projectRoot)),\n );\n return results.flat().sort(compareByNameThenPath);\n}\n","export interface AgentSource {\n /** Agent identifier, e.g. \"claude-code\" */\n name: string;\n /** Human-readable name, e.g. \"Claude Code\" */\n displayName: string;\n /** Skills directory relative to project root, e.g. \".claude/skills\" */\n skillsDir: string;\n}\n\n/**\n * Known agent source directories (project-scoped).\n * Sourced from the Vercel Skills CLI agent conventions.\n */\nexport const AGENT_SOURCES: AgentSource[] = [\n { name: \"universal\", displayName: \"Universal\", skillsDir: \".agents/skills\" },\n { name: \"antigravity\", displayName: \"Antigravity\", skillsDir: \".agent/skills\" },\n { name: \"claude-code\", displayName: \"Claude Code\", skillsDir: \".claude/skills\" },\n { name: \"codex\", displayName: \"Codex\", skillsDir: \".agents/skills\" },\n { name: \"cursor\", displayName: \"Cursor\", skillsDir: \".cursor/skills\" },\n { name: \"github-copilot\", displayName: \"GitHub Copilot\", skillsDir: \".agents/skills\" },\n { name: \"opencode\", displayName: \"OpenCode\", skillsDir: \".agents/skills\" },\n { name: \"openclaw\", displayName: \"OpenClaw\", skillsDir: \"skills\" },\n { name: \"windsurf\", displayName: \"Windsurf\", skillsDir: \".windsurf/skills\" },\n];\n\n/** Unique skills directories to scan (deduplicates agents sharing the same dir). */\nexport function getUniqueSkillsDirs(): string[] {\n return [...new Set(AGENT_SOURCES.map((a) => a.skillsDir))];\n}\n\n/** Maps a skill's relative path to the first matching agent's display name. */\nexport function getAgentDisplayName(relativePath: string): string | undefined {\n for (const agent of AGENT_SOURCES) {\n if (relativePath.startsWith(`${agent.skillsDir}/`) || relativePath === agent.skillsDir) {\n return agent.displayName;\n }\n }\n return undefined;\n}\n","import { stat, writeFile } from \"node:fs/promises\";\nimport { basename, join } from \"node:path\";\nimport { readConfig } from \"./config.js\";\nimport { END_TAG, START_TAG, TARGET_FILE } from \"./constants.js\";\nimport { generateIndex } from \"./indexer.js\";\nimport { safeReadFile, scanForSkills } from \"./scanner.js\";\nimport type { InitResult, TargetFileInfo } from \"./types.js\";\n\nexport async function getTargetInfos(\n projectRoot: string,\n targets: string[],\n): Promise<TargetFileInfo[]> {\n return Promise.all(\n targets.map(async (t) => {\n const p = join(projectRoot, t);\n const s = await stat(p);\n return { file: basename(t), path: p, totalSize: s.size };\n }),\n );\n}\n\nexport function buildManagedSection(indexContent: string): string {\n return `${START_TAG}\\n${indexContent}\\n${END_TAG}`;\n}\n\n/** Write or update the managed skilldex section in a target file. Creates, appends, or replaces as needed. Returns the written file content. */\nexport async function writeTargetFile(\n projectRoot: string,\n indexContent: string,\n targetFile: string = TARGET_FILE,\n): Promise<string> {\n const targetPath = join(projectRoot, targetFile);\n const section = buildManagedSection(indexContent);\n\n const existing = await safeReadFile(targetPath);\n\n let output: string;\n if (existing === undefined) {\n output = `${section}\\n`;\n } else if (existing.includes(START_TAG) && existing.includes(END_TAG)) {\n const startIdx = existing.indexOf(START_TAG);\n const endIdx = existing.indexOf(END_TAG) + END_TAG.length;\n output = existing.slice(0, startIdx) + section + existing.slice(endIdx);\n } else {\n output = `${existing.trimEnd()}\\n\\n${section}\\n`;\n }\n\n await writeFile(targetPath, output, \"utf-8\");\n return output;\n}\n\nexport interface RegenerateResult extends InitResult {\n /** Map of target file path → written content */\n writtenContent: Map<string, string>;\n}\n\n/** Regenerate all target files from config (reads config, scans indexed skills, writes targets). */\nexport async function regenerateFromConfig(projectRoot: string): Promise<RegenerateResult> {\n const config = await readConfig(projectRoot);\n const allSkills = await scanForSkills(projectRoot);\n\n // Map skill paths from config to DiscoveredSkill objects\n const skillMap = new Map(allSkills.map((s) => [s.relativePath, s]));\n const skills = config.skills\n .map((entry) => skillMap.get(entry.path))\n .filter((s) => s !== undefined);\n\n const index = generateIndex(skills);\n\n const writtenContent = new Map<string, string>();\n for (const target of config.targets) {\n const content = await writeTargetFile(projectRoot, index, target);\n writtenContent.set(join(projectRoot, target), content);\n }\n\n const managedSize = Buffer.byteLength(buildManagedSection(index));\n const targets = await getTargetInfos(projectRoot, config.targets);\n\n return {\n skillCount: skills.length,\n managedSize,\n targets,\n writtenContent,\n };\n}\n","import { dirname } from \"node:path\";\nimport { INDEX_HEADER, INDEX_INSTRUCTION } from \"./constants.js\";\nimport type { DiscoveredSkill } from \"./types.js\";\n\nfunction groupFilesBySubdir(\n files: { relativePath: string; name: string }[],\n): Map<string, string[]> {\n const groups = new Map<string, string[]>();\n for (const file of files) {\n const dir = dirname(file.relativePath);\n const key = dir === \".\" ? \"\" : dir;\n const existing = groups.get(key);\n if (existing) {\n existing.push(`${file.name}.md`);\n } else {\n groups.set(key, [`${file.name}.md`]);\n }\n }\n return groups;\n}\n\nexport function generateIndex(skills: DiscoveredSkill[]): string {\n const segments: string[] = [INDEX_HEADER, INDEX_INSTRUCTION];\n\n for (const skill of skills) {\n segments.push(`[${skill.name}]`);\n segments.push(`root:./${skill.relativePath}`);\n\n if (skill.description) {\n segments.push(`desc:${skill.description}`);\n }\n\n const groups = groupFilesBySubdir(skill.files);\n for (const [subdir, fileNames] of groups) {\n const fileList = `{${fileNames.join(\",\")}}`;\n if (subdir) {\n segments.push(`${subdir}:${fileList}`);\n } else {\n segments.push(fileList);\n }\n }\n }\n\n return segments.join(\"|\");\n}\n","import { readConfig, writeConfig } from \"./config.js\";\nimport { scanForSkills } from \"./scanner.js\";\nimport type { AddResult, DiscoveredSkill } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function addSkill(projectRoot: string, skillName: string): Promise<AddResult> {\n const config = await readConfig(projectRoot);\n const allSkills = await scanForSkills(projectRoot);\n\n const isPath = skillName.includes(\"/\");\n\n let targetSkill: DiscoveredSkill | undefined;\n\n if (isPath) {\n // Path-based lookup for disambiguation\n targetSkill = allSkills.find((s) => s.relativePath === skillName);\n if (!targetSkill) {\n throw new Error(`Skill \"${skillName}\" not found. Did you create the skill directory?`);\n }\n } else {\n // Name-based lookup\n const matches = allSkills.filter((s) => s.name === skillName);\n if (matches.length === 0) {\n throw new Error(`Skill \"${skillName}\" not found. Did you create the skill directory?`);\n }\n if (matches.length > 1) {\n const paths = matches.map((s) => ` ${s.relativePath}`).join(\"\\n\");\n throw new Error(`Multiple skills named \"${skillName}\" found. Specify the path:\\n${paths}`);\n }\n targetSkill = matches[0];\n }\n\n if (config.skills.some((s) => s.path === targetSkill.relativePath)) {\n throw new Error(`Skill \"${targetSkill.relativePath}\" is already indexed`);\n }\n\n config.skills.push({\n name: targetSkill.name,\n path: targetSkill.relativePath,\n });\n\n await writeConfig(projectRoot, config);\n\n const result = await regenerateFromConfig(projectRoot);\n\n return {\n skillName: targetSkill.name,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n","import { writeConfig } from \"./config.js\";\nimport { TARGET_FILE } from \"./constants.js\";\nimport { scanForSkills } from \"./scanner.js\";\nimport type { DiscoveredSkill, InitResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\n/** Scan for skills, filter by selection, and write the index to target files. */\nexport async function init(options: {\n projectRoot: string;\n selectedSkills?: string[];\n yes?: boolean;\n}): Promise<InitResult> {\n const { projectRoot, selectedSkills } = options;\n\n const discovered = await scanForSkills(projectRoot);\n\n let skills: DiscoveredSkill[];\n if (selectedSkills) {\n const selected = new Set(selectedSkills);\n skills = discovered.filter((s) => selected.has(s.name) || selected.has(s.relativePath));\n } else {\n skills = discovered;\n }\n\n return initWithSkills(projectRoot, skills);\n}\n\n/** Index a specific set of skills and write to target file(s). */\nexport async function initWithSkills(\n projectRoot: string,\n skills: DiscoveredSkill[],\n targets: string[] = [TARGET_FILE],\n): Promise<InitResult> {\n const config = {\n version: 1 as const,\n targets,\n skills: skills.map((skill) => ({\n name: skill.name,\n path: skill.relativePath,\n })),\n };\n await writeConfig(projectRoot, config);\n\n return regenerateFromConfig(projectRoot);\n}\n","import { readConfig } from \"./config.js\";\nimport { scanForSkills } from \"./scanner.js\";\nimport type { ListResult, SkillInfo } from \"./types.js\";\n\nexport async function listSkills(projectRoot: string): Promise<ListResult> {\n const config = await readConfig(projectRoot);\n const allSkills = await scanForSkills(projectRoot);\n\n const indexedPaths = new Set(config.skills.map((s) => s.path));\n const skillMap = new Map(allSkills.map((s) => [s.relativePath, s]));\n\n const indexed: SkillInfo[] = config.skills.map((entry) => {\n const discovered = skillMap.get(entry.path);\n if (!discovered) {\n return { name: entry.name, path: entry.path, description: \"\", missing: true };\n }\n return { name: entry.name, path: entry.path, description: discovered.description };\n });\n\n const available: SkillInfo[] = allSkills\n .filter((s) => !indexedPaths.has(s.relativePath))\n .map((s) => ({\n name: s.name,\n description: s.description,\n path: s.relativePath,\n }));\n\n return { indexed, available };\n}\n","import { rm } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { readConfig, writeConfig } from \"./config.js\";\nimport type { RemoveResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function removeSkill(\n projectRoot: string,\n skillName: string,\n deleteFiles = false,\n): Promise<RemoveResult> {\n const config = await readConfig(projectRoot);\n\n const isPath = skillName.includes(\"/\");\n\n let skillIndex: number;\n\n if (isPath) {\n skillIndex = config.skills.findIndex((s) => s.path === skillName);\n if (skillIndex === -1) {\n throw new Error(`Skill \"${skillName}\" is not indexed`);\n }\n } else {\n const matches = config.skills\n .map((s, i) => ({ entry: s, index: i }))\n .filter(({ entry }) => entry.name === skillName);\n\n if (matches.length === 0) {\n throw new Error(`Skill \"${skillName}\" is not indexed`);\n }\n if (matches.length > 1) {\n const paths = matches.map(({ entry }) => ` ${entry.path}`).join(\"\\n\");\n throw new Error(`Multiple skills named \"${skillName}\" indexed. Specify the path:\\n${paths}`);\n }\n skillIndex = matches[0].index;\n }\n\n const entry = config.skills[skillIndex];\n const skillPath = join(projectRoot, entry.path);\n\n config.skills.splice(skillIndex, 1);\n await writeConfig(projectRoot, config);\n\n if (deleteFiles) {\n await rm(skillPath, { recursive: true, force: true });\n }\n\n const result = await regenerateFromConfig(projectRoot);\n\n return {\n skillName: entry.name,\n wasDeleted: deleteFiles,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n","import { join } from \"node:path\";\nimport { readConfig, writeConfig } from \"./config.js\";\nimport { safeReadFile, scanForSkills } from \"./scanner.js\";\nimport type { SyncResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function syncSkills(projectRoot: string): Promise<SyncResult> {\n const config = await readConfig(projectRoot);\n const onDisk = await scanForSkills(projectRoot);\n const diskPaths = new Set(onDisk.map((s) => s.relativePath));\n\n // Find stale entries: in config but not on disk\n const stale = config.skills.filter((s) => !diskPaths.has(s.path));\n const removed = stale.map((s) => s.name);\n\n if (stale.length > 0) {\n const stalePaths = new Set(stale.map((s) => s.path));\n config.skills = config.skills.filter((s) => !stalePaths.has(s.path));\n await writeConfig(projectRoot, config);\n }\n\n const targetPaths = config.targets.map((t) => join(projectRoot, t));\n\n // Read before-state for all targets\n const beforeMap = new Map<string, string | undefined>();\n for (const targetPath of targetPaths) {\n beforeMap.set(targetPath, await safeReadFile(targetPath));\n }\n\n // Nothing to do if no skills indexed and no target files exist\n if (config.skills.length === 0 && [...beforeMap.values()].every((v) => v === undefined)) {\n return { removed, changed: false, managedSize: 0, targets: [] };\n }\n\n const result = await regenerateFromConfig(projectRoot);\n\n // Check if ANY target changed using the written content from regeneration\n let changed = false;\n for (const targetPath of targetPaths) {\n const after = result.writtenContent.get(targetPath);\n if (beforeMap.get(targetPath) !== after) {\n changed = true;\n break;\n }\n }\n\n return {\n removed,\n changed,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n","import { access } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { readConfig } from \"./config.js\";\nimport type { UpdateResult } from \"./types.js\";\nimport { regenerateFromConfig } from \"./writer.js\";\n\nexport async function updateSkill(\n projectRoot: string,\n skillPaths: string[],\n): Promise<UpdateResult> {\n const config = await readConfig(projectRoot);\n const configPathMap = new Map(config.skills.map((s) => [s.path, s.name]));\n\n // Validate all requested paths are indexed\n for (const skillPath of skillPaths) {\n if (!configPathMap.has(skillPath)) {\n throw new Error(\n `Skill \"${skillPath}\" is not indexed. Run 'skilldex add ${skillPath}' to index it.`,\n );\n }\n }\n\n // Validate all exist on disk\n for (const skillPath of skillPaths) {\n const absolutePath = join(projectRoot, skillPath);\n try {\n await access(absolutePath);\n } catch {\n throw new Error(\n `Skill \"${skillPath}\" not found on disk. Run 'skilldex sync' to remove stale entries.`,\n );\n }\n }\n\n const updated = skillPaths.map((p) => configPathMap.get(p) as string);\n\n const result = await regenerateFromConfig(projectRoot);\n\n return {\n updated,\n managedSize: result.managedSize,\n targets: result.targets,\n };\n}\n"],"mappings":"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","names":["join","join","writeFile","join","join","writeFile","join","entry","join","join","join","join","join"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skilldex",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "CLI tool that indexes AI agent skills into passive context (AGENTS.md)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -58,17 +58,9 @@
|
|
|
58
58
|
"commander": "^14.0.3",
|
|
59
59
|
"picocolors": "^1.1.1"
|
|
60
60
|
},
|
|
61
|
-
"pnpm": {
|
|
62
|
-
"onlyBuiltDependencies": [
|
|
63
|
-
"esbuild",
|
|
64
|
-
"@biomejs/biome"
|
|
65
|
-
]
|
|
66
|
-
},
|
|
67
61
|
"devDependencies": {
|
|
68
|
-
"@biomejs/biome": "^2.3.15",
|
|
69
62
|
"@types/node": "^25.2.3",
|
|
70
63
|
"tsup": "^8.5.1",
|
|
71
|
-
"typescript": "^5.9.3",
|
|
72
64
|
"vitest": "^4.0.18"
|
|
73
65
|
}
|
|
74
66
|
}
|