skilld 1.6.2 → 1.7.0

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.
Files changed (73) hide show
  1. package/README.md +29 -20
  2. package/dist/_chunks/agent.mjs +2 -1
  3. package/dist/_chunks/agent.mjs.map +1 -1
  4. package/dist/_chunks/assemble.mjs +1 -1
  5. package/dist/_chunks/author-group.mjs +17 -0
  6. package/dist/_chunks/author-group.mjs.map +1 -0
  7. package/dist/_chunks/author.mjs +8 -6
  8. package/dist/_chunks/author.mjs.map +1 -1
  9. package/dist/_chunks/cache.mjs +1 -1
  10. package/dist/_chunks/cache2.mjs +1 -1
  11. package/dist/_chunks/cli-helpers.mjs +3 -119
  12. package/dist/_chunks/cli-helpers.mjs.map +1 -1
  13. package/dist/_chunks/config.mjs +119 -27
  14. package/dist/_chunks/config.mjs.map +1 -1
  15. package/dist/_chunks/core.mjs +1 -1
  16. package/dist/_chunks/embedding-cache2.mjs +1 -1
  17. package/dist/_chunks/index.d.mts.map +1 -1
  18. package/dist/_chunks/index3.d.mts +79 -78
  19. package/dist/_chunks/index3.d.mts.map +1 -1
  20. package/dist/_chunks/install.mjs +85 -535
  21. package/dist/_chunks/install.mjs.map +1 -1
  22. package/dist/_chunks/install2.mjs +554 -0
  23. package/dist/_chunks/install2.mjs.map +1 -0
  24. package/dist/_chunks/lockfile.mjs +1 -0
  25. package/dist/_chunks/lockfile.mjs.map +1 -1
  26. package/dist/_chunks/package-registry.mjs +465 -0
  27. package/dist/_chunks/package-registry.mjs.map +1 -0
  28. package/dist/_chunks/prefix.mjs +108 -0
  29. package/dist/_chunks/prefix.mjs.map +1 -0
  30. package/dist/_chunks/prepare.mjs +6 -2
  31. package/dist/_chunks/prepare.mjs.map +1 -1
  32. package/dist/_chunks/prepare2.mjs +1 -1
  33. package/dist/_chunks/prompts.mjs +5 -99
  34. package/dist/_chunks/prompts.mjs.map +1 -1
  35. package/dist/_chunks/search-helpers.mjs +99 -0
  36. package/dist/_chunks/search-helpers.mjs.map +1 -0
  37. package/dist/_chunks/search-interactive.mjs +1 -1
  38. package/dist/_chunks/search-interactive.mjs.map +1 -1
  39. package/dist/_chunks/search.mjs +219 -1
  40. package/dist/_chunks/search.mjs.map +1 -0
  41. package/dist/_chunks/shared.mjs +1 -463
  42. package/dist/_chunks/shared.mjs.map +1 -1
  43. package/dist/_chunks/skills.mjs +1 -1
  44. package/dist/_chunks/sources.mjs +1177 -988
  45. package/dist/_chunks/sources.mjs.map +1 -1
  46. package/dist/_chunks/sync-registry.mjs +59 -0
  47. package/dist/_chunks/sync-registry.mjs.map +1 -0
  48. package/dist/_chunks/sync-shared2.mjs +10 -7
  49. package/dist/_chunks/sync-shared2.mjs.map +1 -1
  50. package/dist/_chunks/sync.mjs +208 -99
  51. package/dist/_chunks/sync.mjs.map +1 -1
  52. package/dist/_chunks/sync2.mjs +1 -1
  53. package/dist/_chunks/uninstall.mjs +3 -2
  54. package/dist/_chunks/uninstall.mjs.map +1 -1
  55. package/dist/_chunks/upload.mjs +152 -0
  56. package/dist/_chunks/upload.mjs.map +1 -0
  57. package/dist/_chunks/validate.mjs +1 -1
  58. package/dist/_chunks/version.mjs +30 -0
  59. package/dist/_chunks/version.mjs.map +1 -0
  60. package/dist/_chunks/wizard.mjs +2 -1
  61. package/dist/_chunks/wizard.mjs.map +1 -1
  62. package/dist/agent/index.mjs +2 -1
  63. package/dist/cache/index.mjs +1 -1
  64. package/dist/cli.mjs +48 -20
  65. package/dist/cli.mjs.map +1 -1
  66. package/dist/index.d.mts +1 -1
  67. package/dist/index.mjs +2 -2
  68. package/dist/sources/index.d.mts +2 -2
  69. package/dist/sources/index.mjs +3 -3
  70. package/dist/types.d.mts +1 -1
  71. package/package.json +11 -12
  72. package/dist/_chunks/search2.mjs +0 -310
  73. package/dist/_chunks/search2.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"install.mjs","names":["agents","checkShippedDocs"],"sources":["../../src/commands/install.ts"],"sourcesContent":["/**\n * Install command - restore .skilld/ and SKILL.md from lockfile\n *\n * After cloning a repo, the .skilld/ symlinks are missing (gitignored).\n * If SKILL.md was deleted, a base version is regenerated from local metadata.\n * This command recreates them from the lockfile:\n * .claude/skills/<skill>/.skilld/pkg -> node_modules/<pkg> (always)\n * .claude/skills/<skill>/.skilld/docs -> ~/.skilld/references/<pkg>@<version>/docs (if external)\n * .claude/skills/<skill>/SKILL.md -> regenerated from package.json + cache state\n */\n\nimport type { AgentType, CustomPrompt, SkillSection } from '../agent/index.ts'\nimport type { FeaturesConfig } from '../core/config.ts'\nimport type { SkillInfo } from '../core/lockfile.ts'\nimport { copyFileSync, existsSync, lstatSync, mkdirSync, readdirSync, symlinkSync, unlinkSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { dirname, join } from 'pathe'\nimport { agents, createToolProgress, getModelLabel, linkSkillToAgents, optimizeDocs } from '../agent/index.ts'\nimport { generateSkillMd } from '../agent/prompts/skill.ts'\nimport {\n hasShippedDocs as checkShippedDocs,\n ensureCacheDir,\n getCacheDir,\n getPackageDbPath,\n getPkgKeyFiles,\n getRepoCacheDir,\n getShippedSkills,\n isCached,\n linkPkgNamed,\n linkShippedSkill,\n listReferenceFiles,\n readCachedDocs,\n resolvePkgDir,\n writeToCache,\n} from '../cache/index.ts'\nimport { promptForAgent, resolveAgent, sharedArgs } from '../cli-helpers.ts'\nimport { defaultFeatures, readConfig } from '../core/config.ts'\nimport { timedSpinner } from '../core/formatting.ts'\nimport { mergeLocks, parsePackages, readLock, syncLockfilesToDirs, writeLock } from '../core/lockfile.ts'\nimport { readPackageJsonSafe } from '../core/package-json.ts'\nimport { sanitizeMarkdown } from '../core/sanitize.ts'\nimport { getSharedSkillsDir } from '../core/shared.ts'\nimport { createIndex, SearchDepsUnavailableError } from '../retriv/index.ts'\nimport { shutdownWorker } from '../retriv/pool.ts'\nimport { fetchGitSkills } from '../sources/git-skills.ts'\nimport {\n downloadLlmsDocs,\n fetchGitDocs,\n fetchGitHubRaw,\n fetchLlmsTxt,\n fetchReadmeContent,\n filterFrameworkDocs,\n isShallowGitDocs,\n normalizeLlmsLinks,\n parseGitHubUrl,\n resolveEntryFiles,\n resolvePackageDocs,\n} from '../sources/index.ts'\nimport { classifyCachedDoc, indexResources } from './sync-shared.ts'\nimport { selectLlmConfig, writePromptFiles } from './sync.ts'\n\nexport interface InstallOptions {\n global: boolean\n agent: AgentType\n}\n\nexport async function installCommand(opts: InstallOptions): Promise<void> {\n const cwd = process.cwd()\n const agent = agents[opts.agent]\n const shared = !opts.global && getSharedSkillsDir(cwd)\n const skillsDir = opts.global\n ? join(homedir(), '.skilld', 'skills')\n : shared || join(cwd, agent.skillsDir)\n\n // Collect lockfiles from all agent skill dirs and merge\n // In shared mode, read from .skills/ only\n const allSkillsDirs = shared\n ? [shared]\n : Object.values(agents).map(t =>\n opts.global ? t.globalSkillsDir : join(cwd, t.skillsDir),\n )\n const allLocks = allSkillsDirs\n .map(dir => readLock(dir))\n .filter((l): l is NonNullable<typeof l> => !!l && Object.keys(l.skills).length > 0)\n\n if (allLocks.length === 0) {\n p.log.warn('No skilld-lock.yaml found. Run `skilld` to sync skills first.')\n return\n }\n\n const lock = mergeLocks(allLocks)\n\n const skills = Object.entries(lock.skills)\n const toRestore: Array<{ name: string, info: SkillInfo }> = []\n const features = readConfig().features ?? defaultFeatures\n\n // Find skills with missing/broken references symlinks\n for (const [name, info] of skills) {\n if (!info.version)\n continue\n\n // Shipped skills: the skill dir IS the symlink, no references/ subdir\n if (info.source === 'shipped') {\n const skillDir = join(skillsDir, name)\n if (!existsSync(skillDir)) {\n toRestore.push({ name, info })\n }\n continue\n }\n\n const skillDir = join(skillsDir, name)\n const referencesPath = join(skillDir, '.skilld')\n const skillMdPath = join(skillDir, 'SKILL.md')\n\n // Check skill dir, SKILL.md, and all internal .skilld/ references\n const needsRestore = !existsSync(skillDir)\n || !existsSync(skillMdPath)\n || !existsSync(referencesPath)\n || hasStaleReferences(referencesPath, info.packageName || name, info.version!, features)\n\n if (needsRestore) {\n toRestore.push({ name, info })\n }\n }\n\n if (toRestore.length === 0) {\n p.log.success('All up to date')\n return\n }\n\n p.log.info(`Restoring ${toRestore.length} references`)\n ensureCacheDir()\n\n const allSkillNames = skills.map(([, info]) => info.packageName || '').filter(Boolean)\n const regenerated: Array<{ name: string, pkgName: string, version: string, skillDir: string, packages?: string }> = []\n\n for (const { name, info } of toRestore) {\n const version = info.version!\n const pkgName = info.packageName || unsanitizeName(name, info.source)\n\n // Shipped skills: re-link from node_modules or cached dist\n if (info.source === 'shipped') {\n const shipped = getShippedSkills(pkgName, cwd, version)\n const match = shipped.find(s => s.skillName === name)\n if (match) {\n linkShippedSkill(skillsDir, name, match.skillDir)\n p.log.success(`Linked ${name}`)\n }\n else {\n p.log.warn(`${name}: package ${pkgName} no longer ships this skill`)\n }\n continue\n }\n\n // Git-sourced skills: re-fetch from remote\n if (info.source === 'github' || info.source === 'gitlab' || info.source === 'local') {\n const source = {\n type: info.source as 'github' | 'gitlab' | 'local',\n ...(info.repo?.includes('/') ? { owner: info.repo.split('/')[0], repo: info.repo.split('/')[1] } : {}),\n skillPath: info.path,\n ref: info.ref,\n ...(info.source === 'local' ? { localPath: info.repo } : {}),\n }\n const result = await fetchGitSkills(source)\n const match = result.skills.find(s => s.name === name)\n if (match) {\n const skillDir = join(skillsDir, name)\n mkdirSync(skillDir, { recursive: true })\n writeFileSync(join(skillDir, 'SKILL.md'), sanitizeMarkdown(match.content))\n for (const f of match.files) {\n const filePath = join(skillDir, f.path)\n mkdirSync(dirname(filePath), { recursive: true })\n writeFileSync(filePath, f.content)\n }\n p.log.success(`Restored ${name} from ${info.repo}`)\n }\n else {\n p.log.warn(`${name}: skill not found in ${info.repo}`)\n }\n continue\n }\n\n const skillDir = join(skillsDir, name)\n const referencesPath = join(skillDir, '.skilld')\n const globalCachePath = getCacheDir(pkgName, version)\n const spin = timedSpinner()\n\n // Check if already in global cache - just create symlinks\n if (isCached(pkgName, version)) {\n spin.start(`Linking ${name}`)\n mkdirSync(skillDir, { recursive: true })\n mkdirSync(referencesPath, { recursive: true })\n linkPkgSymlink(referencesPath, pkgName, cwd, version)\n // Restore named symlinks for all tracked packages\n for (const pkg of parsePackages(info.packages))\n linkPkgNamed(skillDir, pkg.name, cwd, pkg.version)\n // Only link external docs if package doesn't ship its own and has more than just README\n if (!pkgHasShippedDocs(pkgName, cwd, version) && !isReadmeOnly(globalCachePath)) {\n const docsLink = join(referencesPath, 'docs')\n const cachedDocs = join(globalCachePath, 'docs')\n if (existsSync(docsLink))\n unlinkSync(docsLink)\n if (existsSync(cachedDocs))\n symlinkSync(cachedDocs, docsLink, 'junction')\n }\n // Link issues, discussions, and releases (try repo cache first, fall back to package cache)\n const repoGh = info.repo ? parseGitHubUrl(`https://github.com/${info.repo}`) : null\n const repoCachePath = repoGh ? getRepoCacheDir(repoGh.owner, repoGh.repo) : null\n if (features.issues) {\n const issuesLink = join(referencesPath, 'issues')\n const repoIssues = repoCachePath ? join(repoCachePath, 'issues') : null\n const cachedIssues = (repoIssues && existsSync(repoIssues)) ? repoIssues : join(globalCachePath, 'issues')\n if (existsSync(issuesLink))\n unlinkSync(issuesLink)\n if (existsSync(cachedIssues))\n symlinkSync(cachedIssues, issuesLink, 'junction')\n }\n if (features.discussions) {\n const discussionsLink = join(referencesPath, 'discussions')\n const repoDiscussions = repoCachePath ? join(repoCachePath, 'discussions') : null\n const cachedDiscussions = (repoDiscussions && existsSync(repoDiscussions)) ? repoDiscussions : join(globalCachePath, 'discussions')\n if (existsSync(discussionsLink))\n unlinkSync(discussionsLink)\n if (existsSync(cachedDiscussions))\n symlinkSync(cachedDiscussions, discussionsLink, 'junction')\n }\n if (features.releases) {\n const releasesLink = join(referencesPath, 'releases')\n const repoReleases = repoCachePath ? join(repoCachePath, 'releases') : null\n const cachedReleases = (repoReleases && existsSync(repoReleases)) ? repoReleases : join(globalCachePath, 'releases')\n if (existsSync(releasesLink))\n unlinkSync(releasesLink)\n if (existsSync(cachedReleases))\n symlinkSync(cachedReleases, releasesLink, 'junction')\n }\n const sectionsLink = join(referencesPath, 'sections')\n const cachedSections = join(globalCachePath, 'sections')\n if (existsSync(sectionsLink))\n unlinkSync(sectionsLink)\n if (existsSync(cachedSections))\n symlinkSync(cachedSections, sectionsLink, 'junction')\n // Create search index from cached docs if missing\n if (features.search && !existsSync(getPackageDbPath(pkgName, version))) {\n spin.message(`Indexing ${name}`)\n const cached = readCachedDocs(pkgName, version)\n const docsToIndex = cached.map(d => ({\n id: d.path,\n content: d.content,\n metadata: { package: pkgName, source: d.path, type: classifyCachedDoc(d.path).type },\n }))\n await indexResources({ packageName: pkgName, version, cwd, docsToIndex, features, onProgress: msg => spin.message(msg) })\n }\n if (!copyFromExistingAgent(skillDir, name, allSkillsDirs)) {\n if (regenerateBaseSkillMd(skillDir, pkgName, version, cwd, allSkillNames, info.source, info.packages))\n regenerated.push({ name, pkgName, version, skillDir, packages: info.packages })\n }\n spin.stop(`Linked ${name}`)\n continue\n }\n\n // Need to download to global cache first\n spin.start(`Downloading ${name}@${version}`)\n\n const resolved = await resolvePackageDocs(pkgName, { version })\n\n if (!resolved) {\n spin.stop(`Could not resolve: ${name}`)\n continue\n }\n\n const cachedDocs: Array<{ path: string, content: string }> = []\n const docsToIndex: Array<{ id: string, content: string, metadata: Record<string, any> }> = []\n const isFrameworkDoc = (path: string) => filterFrameworkDocs([path], pkgName).length > 0\n\n // Try git docs first\n if (resolved.gitDocsUrl && resolved.repoUrl) {\n const gh = parseGitHubUrl(resolved.repoUrl)\n if (gh) {\n const gitDocs = await fetchGitDocs(gh.owner, gh.repo, version, pkgName)\n if (gitDocs?.files.length) {\n const BATCH_SIZE = 20\n for (let i = 0; i < gitDocs.files.length; i += BATCH_SIZE) {\n const batch = gitDocs.files.slice(i, i + BATCH_SIZE)\n const results = await Promise.all(\n batch.map(async (file) => {\n const url = `${gitDocs.baseUrl}/${file}`\n const content = await fetchGitHubRaw(url)\n if (!content)\n return null\n return { file, content }\n }),\n )\n for (const r of results) {\n if (r) {\n const stripped = gitDocs.docsPrefix ? r.file.replace(gitDocs.docsPrefix, '') : r.file\n const cachePath = stripped.startsWith('docs/') ? stripped : `docs/${stripped}`\n cachedDocs.push({ path: cachePath, content: r.content })\n docsToIndex.push({ id: cachePath, content: r.content, metadata: { package: pkgName, source: cachePath, type: 'doc' } })\n }\n }\n }\n\n // Shallow git-docs: if < threshold and llms.txt exists, discard and fall through\n if (isShallowGitDocs(cachedDocs.length) && resolved.llmsUrl) {\n cachedDocs.length = 0\n docsToIndex.length = 0\n }\n else if (cachedDocs.length > 0 && resolved.llmsUrl) {\n // Always cache llms.txt alongside good git-docs as supplementary reference\n const llmsContent = await fetchLlmsTxt(resolved.llmsUrl)\n if (llmsContent) {\n const baseUrl = resolved.docsUrl || new URL(resolved.llmsUrl).origin\n cachedDocs.push({ path: 'llms.txt', content: normalizeLlmsLinks(llmsContent.raw) })\n if (llmsContent.links.length > 0) {\n const docs = await downloadLlmsDocs(llmsContent, baseUrl)\n for (const doc of docs) {\n if (!isFrameworkDoc(doc.url))\n continue\n const localPath = doc.url.startsWith('/') ? doc.url.slice(1) : doc.url\n cachedDocs.push({ path: join('llms-docs', ...localPath.split('/')), content: doc.content })\n }\n }\n }\n }\n }\n }\n }\n\n // Try llms.txt\n if (resolved.llmsUrl && cachedDocs.length === 0) {\n const llmsContent = await fetchLlmsTxt(resolved.llmsUrl)\n if (llmsContent) {\n cachedDocs.push({ path: 'llms.txt', content: normalizeLlmsLinks(llmsContent.raw) })\n if (llmsContent.links.length > 0) {\n const baseUrl = resolved.docsUrl || new URL(resolved.llmsUrl).origin\n const docs = await downloadLlmsDocs(llmsContent, baseUrl)\n for (const doc of docs) {\n if (!isFrameworkDoc(doc.url))\n continue\n const localPath = doc.url.startsWith('/') ? doc.url.slice(1) : doc.url\n const cachePath = join('docs', ...localPath.split('/'))\n cachedDocs.push({ path: cachePath, content: doc.content })\n docsToIndex.push({ id: doc.url, content: doc.content, metadata: { package: pkgName, source: cachePath, type: 'doc' } })\n }\n }\n }\n }\n\n // Fallback to README\n if (resolved.readmeUrl && cachedDocs.length === 0) {\n const content = await fetchReadmeContent(resolved.readmeUrl)\n if (content) {\n cachedDocs.push({ path: 'docs/README.md', content })\n docsToIndex.push({ id: 'README.md', content, metadata: { package: pkgName, source: 'docs/README.md', type: 'doc' } })\n }\n }\n\n if (cachedDocs.length > 0) {\n writeToCache(pkgName, version, cachedDocs)\n\n mkdirSync(referencesPath, { recursive: true })\n linkPkgSymlink(referencesPath, pkgName, cwd, version)\n // Restore named symlinks for all tracked packages\n for (const pkg of parsePackages(info.packages))\n linkPkgNamed(skillDir, pkg.name, cwd, pkg.version)\n // Link fetched docs unless it's just a README (already in pkg/)\n if (!isReadmeOnly(globalCachePath)) {\n const docsLink = join(referencesPath, 'docs')\n const cachedDocsDir = join(globalCachePath, 'docs')\n if (existsSync(docsLink))\n unlinkSync(docsLink)\n if (existsSync(cachedDocsDir))\n symlinkSync(cachedDocsDir, docsLink, 'junction')\n }\n\n if (features.search) {\n try {\n if (docsToIndex.length > 0) {\n await createIndex(docsToIndex, { dbPath: getPackageDbPath(pkgName, version) })\n }\n\n // Index package entry files (.d.ts / .js)\n const pkgDir = resolvePkgDir(pkgName, cwd, version)\n const entryFiles = pkgDir ? await resolveEntryFiles(pkgDir) : []\n if (entryFiles.length > 0) {\n await createIndex(entryFiles.map(e => ({\n id: e.path,\n content: e.content,\n metadata: { package: pkgName, source: `pkg/${e.path}`, type: e.type },\n })), { dbPath: getPackageDbPath(pkgName, version) })\n }\n }\n catch (err) {\n if (!(err instanceof SearchDepsUnavailableError))\n throw err\n }\n }\n\n if (!copyFromExistingAgent(skillDir, name, allSkillsDirs)) {\n if (regenerateBaseSkillMd(skillDir, pkgName, version, cwd, allSkillNames, info.source, info.packages))\n regenerated.push({ name, pkgName, version, skillDir, packages: info.packages })\n }\n spin.stop(`Downloaded and linked ${name}`)\n }\n else {\n spin.stop(`No docs found for ${name}`)\n }\n }\n\n // Offer LLM enhancement for regenerated SKILL.md files\n if (regenerated.length > 0 && !readConfig().skipLlm) {\n const names = regenerated.map(r => r.name).join(', ')\n const llmConfig = await selectLlmConfig(undefined, `Enhance SKILL.md for ${names}`)\n if (llmConfig?.promptOnly) {\n const features = readConfig().features ?? defaultFeatures\n for (const { pkgName, version, skillDir } of regenerated) {\n const globalCachePath = getCacheDir(pkgName, version)\n writePromptFiles({\n packageName: pkgName,\n skillDir,\n version,\n hasIssues: existsSync(join(globalCachePath, 'issues')),\n hasDiscussions: existsSync(join(globalCachePath, 'discussions')),\n hasReleases: existsSync(join(globalCachePath, 'releases')),\n hasChangelog: false,\n docsType: 'docs',\n hasShippedDocs: false,\n pkgFiles: getPkgKeyFiles(pkgName, process.cwd(), version),\n sections: llmConfig.sections,\n customPrompt: llmConfig.customPrompt,\n features,\n })\n }\n }\n else if (llmConfig) {\n p.log.step(getModelLabel(llmConfig.model))\n for (const { pkgName, version, skillDir, packages: pkgPackages } of regenerated) {\n await enhanceRegenerated(pkgName, version, skillDir, llmConfig.model, llmConfig.sections, llmConfig.customPrompt, pkgPackages)\n }\n }\n }\n\n // Write merged lockfile to target dir and sync to all other existing lockfiles\n for (const [name, info] of Object.entries(lock.skills))\n writeLock(skillsDir, name, info)\n\n // In shared mode: recreate per-agent symlinks, skip per-agent lockfile sync\n if (shared) {\n for (const [name] of skills)\n linkSkillToAgents(name, shared, cwd, opts.agent)\n }\n else {\n syncLockfilesToDirs(lock, allSkillsDirs.filter(d => d !== skillsDir))\n }\n\n await shutdownWorker()\n\n p.outro('Install complete')\n}\n\n/** Copy SKILL.md from another agent's skill dir if one exists */\nfunction copyFromExistingAgent(skillDir: string, name: string, allSkillsDirs: string[]): boolean {\n const targetMd = join(skillDir, 'SKILL.md')\n if (existsSync(targetMd))\n return false\n for (const dir of allSkillsDirs) {\n if (dir === skillDir)\n continue\n const candidateMd = join(dir, name, 'SKILL.md')\n if (existsSync(candidateMd) && !lstatSync(candidateMd).isSymbolicLink()) {\n mkdirSync(skillDir, { recursive: true })\n copyFileSync(candidateMd, targetMd)\n return true\n }\n }\n return false\n}\n\n/** Try to recover original package name from sanitized name + source */\nfunction unsanitizeName(sanitized: string, source?: string): string {\n if (source?.includes('ungh://')) {\n const match = source.match(/ungh:\\/\\/([^/]+)\\/(.+)/)\n if (match)\n return `@${match[1]}/${match[2]}`\n }\n\n if (sanitized.startsWith('antfu-'))\n return `@antfu/${sanitized.slice(6)}`\n if (sanitized.startsWith('clack-'))\n return `@clack/${sanitized.slice(6)}`\n if (sanitized.startsWith('nuxt-'))\n return `@nuxt/${sanitized.slice(5)}`\n if (sanitized.startsWith('vue-'))\n return `@vue/${sanitized.slice(4)}`\n if (sanitized.startsWith('vueuse-'))\n return `@vueuse/${sanitized.slice(7)}`\n\n return sanitized\n}\n\n/** Create pkg symlink inside references dir (links to entire package or cached dist) */\nfunction linkPkgSymlink(referencesDir: string, name: string, cwd: string, version?: string): void {\n const pkgPath = resolvePkgDir(name, cwd, version)\n if (!pkgPath)\n return\n\n const pkgLink = join(referencesDir, 'pkg')\n if (existsSync(pkgLink))\n unlinkSync(pkgLink)\n symlinkSync(pkgPath, pkgLink, 'junction')\n}\n\n/** Check if cache only has docs/README.md (pkg/ already has this) */\nfunction isReadmeOnly(cacheDir: string): boolean {\n const docsDir = join(cacheDir, 'docs')\n if (!existsSync(docsDir))\n return false\n const files = readdirSync(docsDir)\n return files.length === 1 && files[0] === 'README.md'\n}\n\n/** Check if package ships its own docs folder */\nfunction pkgHasShippedDocs(name: string, cwd: string, version?: string): boolean {\n const pkgPath = resolvePkgDir(name, cwd, version)\n if (!pkgPath)\n return false\n\n const docsCandidates = ['docs', 'documentation', 'doc']\n for (const candidate of docsCandidates) {\n const docsPath = join(pkgPath, candidate)\n if (existsSync(docsPath))\n return true\n }\n return false\n}\n\n/** Run LLM enhancement on a regenerated SKILL.md */\nasync function enhanceRegenerated(\n pkgName: string,\n version: string,\n skillDir: string,\n model: Parameters<typeof optimizeDocs>[0]['model'],\n sections: SkillSection[],\n customPrompt?: CustomPrompt,\n packages?: string,\n): Promise<void> {\n const llmLog = p.taskLog({ title: `Agent exploring ${pkgName}`, limit: 3 })\n\n const docFiles = listReferenceFiles(skillDir)\n const globalCachePath = getCacheDir(pkgName, version)\n const hasIssues = existsSync(join(globalCachePath, 'issues'))\n const hasDiscussions = existsSync(join(globalCachePath, 'discussions'))\n const hasGithub = hasIssues || hasDiscussions\n const hasReleases = existsSync(join(globalCachePath, 'releases'))\n\n const features = readConfig().features ?? defaultFeatures\n const { optimized, wasOptimized } = await optimizeDocs({\n packageName: pkgName,\n skillDir,\n model,\n version,\n hasGithub,\n hasReleases,\n docFiles,\n sections,\n customPrompt,\n features,\n pkgFiles: getPkgKeyFiles(pkgName, process.cwd(), version),\n onProgress: createToolProgress(llmLog),\n })\n\n if (wasOptimized) {\n llmLog.success('Generated best practices')\n // Re-read local metadata for the enhanced version\n const cwd = process.cwd()\n const pkgPath = resolvePkgDir(pkgName, cwd, version)\n let description: string | undefined\n if (pkgPath) {\n const pkgJsonPath = join(pkgPath, 'package.json')\n const pkgJsonResult = readPackageJsonSafe(pkgJsonPath)\n if (pkgJsonResult) {\n description = pkgJsonResult.parsed.description as string | undefined\n }\n }\n\n let docsType: 'llms.txt' | 'readme' | 'docs' = 'docs'\n if (existsSync(join(globalCachePath, 'docs', 'llms.txt')))\n docsType = 'llms.txt'\n else if (isReadmeOnly(globalCachePath))\n docsType = 'readme'\n\n // Derive dirName from the skill directory name\n const dirName = skillDir.split('/').pop()\n\n const allPackages = parsePackages(packages).map(p => ({ name: p.name }))\n const skillMd = generateSkillMd({\n name: pkgName,\n version,\n description,\n body: optimized,\n relatedSkills: [],\n hasIssues,\n hasDiscussions,\n hasReleases,\n docsType,\n hasShippedDocs: checkShippedDocs(pkgName, cwd, version),\n pkgFiles: getPkgKeyFiles(pkgName, cwd, version),\n dirName,\n packages: allPackages.length > 1 ? allPackages : undefined,\n features,\n })\n writeFileSync(join(skillDir, 'SKILL.md'), skillMd)\n }\n else {\n llmLog.message('Enhancement skipped')\n }\n}\n\nexport const installCommandDef = defineCommand({\n meta: { name: 'install', description: 'Restore references from lockfile' },\n args: {\n global: sharedArgs.global,\n agent: sharedArgs.agent,\n },\n async run({ args }) {\n let agent = resolveAgent(args.agent)\n if (!agent || agent === 'none') {\n if (agent === 'none')\n return\n const picked = await promptForAgent()\n if (!picked || picked === 'none')\n return\n agent = picked\n }\n\n p.intro(`\\x1B[1m\\x1B[35mskilld\\x1B[0m install`)\n return installCommand({ global: args.global, agent })\n },\n})\n\n/** Regenerate base SKILL.md from local metadata if missing */\nfunction regenerateBaseSkillMd(\n skillDir: string,\n pkgName: string,\n version: string,\n cwd: string,\n allSkillNames: string[],\n source?: string,\n packages?: string,\n): boolean {\n const skillMdPath = join(skillDir, 'SKILL.md')\n if (existsSync(skillMdPath))\n return false\n\n // Read description + deps from local package.json\n const pkgPath = resolvePkgDir(pkgName, cwd, version)\n let description: string | undefined\n if (pkgPath) {\n const pkgResult = readPackageJsonSafe(join(pkgPath, 'package.json'))\n if (pkgResult) {\n description = pkgResult.parsed.description as string | undefined\n }\n }\n\n // Infer docsType from source or cache\n const globalCachePath = getCacheDir(pkgName, version)\n let docsType: 'llms.txt' | 'readme' | 'docs' = 'docs'\n if (source?.includes('llms.txt') || existsSync(join(globalCachePath, 'docs', 'llms.txt')))\n docsType = 'llms.txt'\n else if (isReadmeOnly(globalCachePath))\n docsType = 'readme'\n\n // Check cache dirs for issues/discussions/releases (only if feature enabled)\n const feat = readConfig().features ?? defaultFeatures\n const hasIssues = feat.issues && existsSync(join(globalCachePath, 'issues'))\n const hasDiscussions = feat.discussions && existsSync(join(globalCachePath, 'discussions'))\n const hasReleases = feat.releases && existsSync(join(globalCachePath, 'releases'))\n\n // Related skills from other lockfile entries\n const relatedSkills = allSkillNames.filter(n => n !== pkgName)\n\n // Derive dirName from the skill directory name (lockfile key)\n const dirName = skillDir.split('/').pop()\n\n // Build multi-package list from lockfile packages field\n const allPackages = parsePackages(packages).map(p => ({ name: p.name }))\n\n const content = generateSkillMd({\n name: pkgName,\n version,\n description,\n relatedSkills,\n hasIssues,\n hasDiscussions,\n hasReleases,\n docsType,\n hasShippedDocs: checkShippedDocs(pkgName, cwd, version),\n pkgFiles: getPkgKeyFiles(pkgName, cwd, version),\n dirName,\n packages: allPackages.length > 1 ? allPackages : undefined,\n features: readConfig().features ?? defaultFeatures,\n })\n\n mkdirSync(skillDir, { recursive: true })\n writeFileSync(skillMdPath, content)\n return true\n}\n\n/** Check if .skilld/ has broken symlinks or is missing expected references from global cache */\nfunction hasStaleReferences(referencesPath: string, pkgName: string, version: string, features: FeaturesConfig): boolean {\n // Scan existing entries for broken symlinks\n for (const entry of readdirSync(referencesPath)) {\n const entryPath = join(referencesPath, entry)\n if (lstatSync(entryPath).isSymbolicLink() && !existsSync(entryPath))\n return true\n }\n\n // Check pkg link always expected\n if (!existsSync(join(referencesPath, 'pkg')))\n return true\n\n // Check expected links against global cache\n const globalCachePath = getCacheDir(pkgName, version)\n const expected: Array<[string, boolean]> = [\n ['docs', existsSync(join(globalCachePath, 'docs'))],\n ['issues', features.issues && existsSync(join(globalCachePath, 'issues'))],\n ['discussions', features.discussions && existsSync(join(globalCachePath, 'discussions'))],\n ['releases', features.releases && existsSync(join(globalCachePath, 'releases'))],\n ['sections', existsSync(join(globalCachePath, 'sections'))],\n ]\n\n for (const [name, shouldExist] of expected) {\n if (shouldExist && !existsSync(join(referencesPath, name)))\n return true\n }\n\n return false\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"install.mjs","names":["agents"],"sources":["../../src/agent/install.ts"],"sourcesContent":["/**\n * Skill installation - write skills to agent directories\n */\n\nimport type { AgentType } from './types.ts'\nimport { existsSync, lstatSync, mkdirSync, symlinkSync, unlinkSync, writeFileSync } from 'node:fs'\nimport { join, relative } from 'pathe'\nimport { repairMarkdown, sanitizeMarkdown } from '../core/sanitize.ts'\nimport { detectInstalledAgents } from './detect.ts'\nimport { agents } from './registry.ts'\n\n/**\n * Sanitize skill name for filesystem\n */\nexport function sanitizeName(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9._]+/g, '-')\n .replace(/^[.\\-]+|[.\\-]+$/g, '')\n .slice(0, 255) || 'unnamed-skill'\n}\n\n/**\n * Compute skill directory name from package name with -skilld suffix.\n * No collisions for monorepo packages (each gets a unique name).\n *\n * Examples:\n * vue → vue-skilld\n * @unhead/vue → unhead-vue-skilld\n * @unhead/react → unhead-react-skilld\n */\nexport function computeSkillDirName(packageName: string): string {\n return `${sanitizeName(packageName)}-skilld`\n}\n\n/**\n * Install a skill directly to agent skill directories.\n * When agents are explicitly specified, creates directories as needed.\n * When falling back to auto-detection, only writes to agents whose skills dir already exists.\n */\nexport function installSkillForAgents(\n skillName: string,\n skillContent: string,\n options: {\n global?: boolean\n cwd?: string\n agents?: AgentType[]\n /** Additional files to write (filename -> content) */\n files?: Record<string, string>\n } = {},\n): { installed: AgentType[], skipped: Array<{ agent: AgentType, reason: string }>, paths: string[] } {\n const isGlobal = options.global ?? false\n const cwd = options.cwd || process.cwd()\n const sanitized = sanitizeName(skillName)\n const explicit = !!options.agents\n const targetAgents = options.agents || detectInstalledAgents()\n\n const installed: AgentType[] = []\n const skipped: Array<{ agent: AgentType, reason: string }> = []\n const paths: string[] = []\n // Track directories already written to, so agents that also scan those dirs\n // (via additionalSkillsDirs) don't get duplicate skills\n const writtenDirs = new Set<string>()\n\n for (const agentType of targetAgents) {\n const agent = agents[agentType]\n\n // Skip if agent doesn't support global installation\n if (isGlobal && !agent.globalSkillsDir) {\n skipped.push({ agent: agentType, reason: 'no global support' })\n continue\n }\n\n const baseDir = isGlobal ? agent.globalSkillsDir! : join(cwd, agent.skillsDir)\n\n // Auto-detected agents: only write if their skills dir already exists\n if (!explicit && !existsSync(baseDir)) {\n skipped.push({ agent: agentType, reason: 'skills dir not found' })\n continue\n }\n\n // Skip if this agent already reads a directory we've written to\n // (prevents duplicate skills in agents that scan multiple dirs)\n if (isGlobal && (writtenDirs.has(baseDir) || agent.additionalSkillsDirs.some(d => writtenDirs.has(d)))) {\n skipped.push({ agent: agentType, reason: 'already covered by another agent dir' })\n continue\n }\n\n const skillDir = join(baseDir, sanitized)\n const skilldDir = join(skillDir, '.skilld')\n mkdirSync(skilldDir, { recursive: true })\n writeFileSync(join(skilldDir, '_SKILL.md'), sanitizeMarkdown(repairMarkdown(skillContent)))\n\n if (options.files) {\n for (const [filename, content] of Object.entries(options.files)) {\n writeFileSync(join(skillDir, filename), filename.endsWith('.md') ? sanitizeMarkdown(repairMarkdown(content)) : content)\n }\n }\n\n installed.push(agentType)\n paths.push(skillDir)\n writtenDirs.add(baseDir)\n }\n\n return { installed, skipped, paths }\n}\n\n/**\n * Create a relative symlink from the target agent's skills dir to the shared .skills/ dir.\n * Only creates directories for the explicit target agent; other agents must already have\n * their skills dir present. This prevents skilld from polluting projects with dirs\n * for agents the user doesn't use (e.g. .gemini/, .agent/).\n */\nexport function linkSkillToAgents(skillName: string, sharedDir: string, cwd: string, agentType?: AgentType): void {\n const targetAgents = agentType ? [[agentType, agents[agentType]] as const] : Object.entries(agents)\n const linkedDirs = new Set<string>()\n\n for (const [type, agent] of targetAgents) {\n const agentSkillsDir = join(cwd, agent.skillsDir)\n const isTarget = agentType === type\n\n if (isTarget) {\n // Target agent: create skills dir if needed\n mkdirSync(agentSkillsDir, { recursive: true })\n }\n else {\n // Non-target agent: only link if skills dir already exists, never create\n if (!existsSync(agentSkillsDir))\n continue\n // Skip if this agent already reads a directory we've linked to\n const resolvedAdditional = agent.additionalSkillsDirs.map(d => join(cwd, d))\n if (resolvedAdditional.some(d => linkedDirs.has(d))) {\n // Clean stale symlinks before skipping\n const staleTarget = join(agentSkillsDir, skillName)\n try {\n if (lstatSync(staleTarget).isSymbolicLink() && !existsSync(staleTarget))\n unlinkSync(staleTarget)\n }\n catch {}\n continue\n }\n }\n\n const target = join(agentSkillsDir, skillName)\n\n // Check what's at the target path\n let isSymlink = false\n let targetExists = false\n try {\n const stat = lstatSync(target)\n targetExists = true\n isSymlink = stat.isSymbolicLink()\n }\n catch {}\n\n // Skip real directories (user's custom skills, not managed by us)\n if (targetExists && !isSymlink)\n continue\n\n // Remove existing symlink (including dangling)\n if (isSymlink)\n unlinkSync(target)\n\n const source = join(sharedDir, skillName)\n const rel = relative(agentSkillsDir, source)\n symlinkSync(rel, target)\n linkedDirs.add(agentSkillsDir)\n }\n}\n\n/**\n * Remove per-agent symlinks for a skill when removing from shared dir.\n */\nexport function unlinkSkillFromAgents(skillName: string, cwd: string, agentType?: AgentType): void {\n const targetAgents = agentType ? [[agentType, agents[agentType]] as const] : Object.entries(agents)\n\n for (const [, agent] of targetAgents) {\n const target = join(cwd, agent.skillsDir, skillName)\n try {\n if (lstatSync(target).isSymbolicLink())\n unlinkSync(target)\n }\n catch {}\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;CA+BA,MAAA,YAAgB,EAAA;CACd,MAAA,UAAU,EAAA;;;;;;;IAQZ,OAAgB;IAWd,QAAM;IACN,CAAA;AACA;;EAEA,MAAM,UAAA,WAAe,MAAQ,kBAAU,KAAA,KAAuB,MAAA,UAAA;AAE9D,MAAA,CAAM,YAAyB,CAAA,WAAE,QAAA,EAAA;AACjC,WAAM,KAAA;IACN,OAAM;IAGN,QAAM;IAEN,CAAA;AACE;;AAIE,MAAA,aAAa,YAAA,IAAA,QAAA,IAAA,MAAA,qBAAA,MAAA,MAAA,YAAA,IAAA,EAAA,CAAA,GAAA;WAAS,KAAA;IAAW,OAAA;IAA6B,QAAC;IAC/D,CAAA;;;EAMF,MAAK,WAAY,KAAC,SAAW,UAAU;EACrC,MAAA,YAAa,KAAA,UAAA,UAAA;YAAS,WAAA,EAAA,WAAA,MAAA,CAAA;gBAAmB,KAAA,WAAA,YAAA,EAAA,iBAAA,eAAA,aAAA,CAAA,CAAA;MAAyB,QAAA,MAAA,MAAA,MAAA,CAAA,UAAA,YAAA,OAAA,QAAA,QAAA,MAAA,CAAA,eAAA,KAAA,UAAA,SAAA,EAAA,SAAA,SAAA,MAAA,GAAA,iBAAA,eAAA,QAAA,CAAA,GAAA,QAAA;AAClE,YAAA,KAAA,UAAA;;AAKF,cAAI,IAAA,QAAa;;QACA;;;EACf;;;AAKF,SAAA,kBAAuB,WAAW,WAAO,KAAA,WAAA;CACzC,MAAA,eAAmB,YAAW,CAAA,CAAA,WAAc,QAAA,WAAiB,CAAA,GAAA,OAAA,QAAe,QAAe;CAE3F,MAAI,6BACU,IAAA,KAAU;AAKxB,MAAA,MAAU,CAAA,MAAK,UAAU,cAAA;EACzB,MAAM,iBAAc,KAAA,KAAA,MAAA,UAAA;AACpB,MAAA,cAAgB,KAAQ,WAAA,gBAAA,EAAA,WAAA,MAAA,CAAA;;AAG1B,OAAA,CAAO,WAAA,eAAA,CAAA;AAAE,OAAA,MAAA,qBAAA,KAAA,MAAA,KAAA,KAAA,EAAA,CAAA,CAAA,MAAA,MAAA,WAAA,IAAA,EAAA,CAAA,EAAA;IAAW,MAAA,cAAA,KAAA,gBAAA,UAAA;AAAS,QAAA;AAAO,SAAA,UAAA,YAAA,CAAA,gBAAA,IAAA,CAAA,WAAA,YAAA,CAAA,YAAA,YAAA;;;;;;;;AAStC,MAAA;GACE,MAAM,OAAA,UAAe,OAAA;AACrB,kBAAM;AAEN,eAAY,KAAM,gBAAU;UACpB;AAGN,MAFiB,gBAAc,CAAA,UAI7B;gBAEG,YAAA,OAAA;AAEH,cAAK,SAAW,gBACd,KAAA,WAAA,UAAA,CAAA,EAAA,OAAA;AAGF,aADiC,IAAA,eAAA;;;+BAQzB,WAAA,KAAA,WAAA;CACN,MAAA,eAAA,YAAA,CAAA,CAAA,WAAA,QAAA,WAAA,CAAA,GAAA,OAAA,QAAA,QAAA;;;AAIJ,MAAA;AAGA,OAAI,UAAA,OAAY,CAAA,gBAAA,CAAA,YAAA,OAAA;UACZ;;;AAIF,SAAA,yBAAiB,GAAgB,gBAAA,GAAA,yBAAA,GAAA,qBAAA,GAAA,uBAAA"}