skilld 1.7.4 → 2.0.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 (156) hide show
  1. package/dist/_chunks/add.mjs +66 -0
  2. package/dist/_chunks/add.mjs.map +1 -0
  3. package/dist/_chunks/agent-prompt.mjs +88 -0
  4. package/dist/_chunks/agent-prompt.mjs.map +1 -0
  5. package/dist/_chunks/agent.mjs +81 -57
  6. package/dist/_chunks/agent.mjs.map +1 -1
  7. package/dist/_chunks/args.mjs +42 -0
  8. package/dist/_chunks/args.mjs.map +1 -0
  9. package/dist/_chunks/assemble.mjs +10 -7
  10. package/dist/_chunks/assemble.mjs.map +1 -1
  11. package/dist/_chunks/author.mjs +33 -17
  12. package/dist/_chunks/author.mjs.map +1 -1
  13. package/dist/_chunks/cache.mjs +143 -183
  14. package/dist/_chunks/cache.mjs.map +1 -1
  15. package/dist/_chunks/cache2.mjs +7 -6
  16. package/dist/_chunks/cache2.mjs.map +1 -1
  17. package/dist/_chunks/client.mjs +117 -0
  18. package/dist/_chunks/client.mjs.map +1 -0
  19. package/dist/_chunks/core.mjs +5 -5
  20. package/dist/_chunks/detect.mjs +53 -43
  21. package/dist/_chunks/detect.mjs.map +1 -1
  22. package/dist/_chunks/eject.mjs +69 -0
  23. package/dist/_chunks/eject.mjs.map +1 -0
  24. package/dist/_chunks/embedding-cache2.mjs +1 -1
  25. package/dist/_chunks/env.mjs +19 -0
  26. package/dist/_chunks/env.mjs.map +1 -0
  27. package/dist/_chunks/install-many.mjs +376 -0
  28. package/dist/_chunks/install-many.mjs.map +1 -0
  29. package/dist/_chunks/install.mjs +81 -326
  30. package/dist/_chunks/install.mjs.map +1 -1
  31. package/dist/_chunks/intro.mjs +63 -0
  32. package/dist/_chunks/intro.mjs.map +1 -0
  33. package/dist/_chunks/list.mjs +2 -2
  34. package/dist/_chunks/list.mjs.map +1 -1
  35. package/dist/_chunks/lockfile.mjs +3 -2
  36. package/dist/_chunks/lockfile.mjs.map +1 -1
  37. package/dist/_chunks/login.mjs +233 -0
  38. package/dist/_chunks/login.mjs.map +1 -0
  39. package/dist/_chunks/logout.mjs +27 -0
  40. package/dist/_chunks/logout.mjs.map +1 -0
  41. package/dist/_chunks/map.mjs +11 -0
  42. package/dist/_chunks/map.mjs.map +1 -0
  43. package/dist/_chunks/markdown.mjs +79 -54
  44. package/dist/_chunks/markdown.mjs.map +1 -1
  45. package/dist/_chunks/menu.mjs +33 -0
  46. package/dist/_chunks/menu.mjs.map +1 -0
  47. package/dist/_chunks/model-picker.mjs +61 -0
  48. package/dist/_chunks/model-picker.mjs.map +1 -0
  49. package/dist/_chunks/monorepo.mjs +4 -2
  50. package/dist/_chunks/monorepo.mjs.map +1 -1
  51. package/dist/_chunks/package-json.mjs.map +1 -1
  52. package/dist/_chunks/paths.mjs +3 -5
  53. package/dist/_chunks/paths.mjs.map +1 -1
  54. package/dist/_chunks/{sync-pipeline.mjs → pipeline.mjs} +346 -313
  55. package/dist/_chunks/pipeline.mjs.map +1 -0
  56. package/dist/_chunks/pool2.mjs +1 -1
  57. package/dist/_chunks/portable.mjs +151 -0
  58. package/dist/_chunks/portable.mjs.map +1 -0
  59. package/dist/_chunks/prepare-hook.mjs +2 -0
  60. package/dist/_chunks/prepare-hook2.mjs +61 -0
  61. package/dist/_chunks/prepare-hook2.mjs.map +1 -0
  62. package/dist/_chunks/prepare.mjs +47 -3
  63. package/dist/_chunks/prepare.mjs.map +1 -1
  64. package/dist/_chunks/prepare2.mjs +7 -6
  65. package/dist/_chunks/prepare2.mjs.map +1 -1
  66. package/dist/_chunks/prompts.mjs +484 -74
  67. package/dist/_chunks/prompts.mjs.map +1 -1
  68. package/dist/_chunks/pull.mjs +219 -0
  69. package/dist/_chunks/pull.mjs.map +1 -0
  70. package/dist/_chunks/regex.mjs +19 -0
  71. package/dist/_chunks/regex.mjs.map +1 -0
  72. package/dist/_chunks/retriv.mjs +2 -171
  73. package/dist/_chunks/retriv2.mjs +159 -0
  74. package/dist/_chunks/retriv2.mjs.map +1 -0
  75. package/dist/_chunks/sanitize.mjs +12 -9
  76. package/dist/_chunks/sanitize.mjs.map +1 -1
  77. package/dist/_chunks/search-helpers.mjs +8 -6
  78. package/dist/_chunks/search-helpers.mjs.map +1 -1
  79. package/dist/_chunks/search-interactive.mjs +23 -20
  80. package/dist/_chunks/search-interactive.mjs.map +1 -1
  81. package/dist/_chunks/search.mjs +3 -3
  82. package/dist/_chunks/search.mjs.map +1 -1
  83. package/dist/_chunks/semver.mjs +2755 -1
  84. package/dist/_chunks/semver.mjs.map +1 -1
  85. package/dist/_chunks/skill-installer2.mjs +10 -11
  86. package/dist/_chunks/skill-installer2.mjs.map +1 -1
  87. package/dist/_chunks/skills.mjs +6 -7
  88. package/dist/_chunks/skills.mjs.map +1 -1
  89. package/dist/_chunks/store.mjs +107 -0
  90. package/dist/_chunks/store.mjs.map +1 -0
  91. package/dist/_chunks/sync.mjs +411 -910
  92. package/dist/_chunks/sync.mjs.map +1 -1
  93. package/dist/_chunks/sync2.mjs +2 -5
  94. package/dist/_chunks/telemetry.mjs +26 -0
  95. package/dist/_chunks/telemetry.mjs.map +1 -0
  96. package/dist/_chunks/uninstall.mjs +12 -9
  97. package/dist/_chunks/uninstall.mjs.map +1 -1
  98. package/dist/_chunks/update.mjs +171 -0
  99. package/dist/_chunks/update.mjs.map +1 -0
  100. package/dist/_chunks/upload.mjs +3 -3
  101. package/dist/_chunks/validate.mjs +1 -1
  102. package/dist/_chunks/version.mjs +16 -17
  103. package/dist/_chunks/version.mjs.map +1 -1
  104. package/dist/_chunks/whoami.mjs +21 -0
  105. package/dist/_chunks/whoami.mjs.map +1 -0
  106. package/dist/_chunks/wizard.mjs +2 -190
  107. package/dist/_chunks/wizard2.mjs +200 -0
  108. package/dist/_chunks/wizard2.mjs.map +1 -0
  109. package/dist/cli.mjs +72 -53
  110. package/dist/cli.mjs.map +1 -1
  111. package/dist/prepare.mjs +4 -3
  112. package/dist/prepare.mjs.map +1 -1
  113. package/dist/retriv/worker.d.mts +5 -1
  114. package/dist/retriv/worker.d.mts.map +1 -1
  115. package/dist/retriv/worker.mjs +1 -1
  116. package/package.json +19 -28
  117. package/dist/_chunks/author-group.mjs +0 -17
  118. package/dist/_chunks/author-group.mjs.map +0 -1
  119. package/dist/_chunks/cli-helpers.mjs +0 -335
  120. package/dist/_chunks/cli-helpers.mjs.map +0 -1
  121. package/dist/_chunks/cli-helpers2.mjs +0 -2
  122. package/dist/_chunks/index.d.mts +0 -344
  123. package/dist/_chunks/index.d.mts.map +0 -1
  124. package/dist/_chunks/index2.d.mts +0 -279
  125. package/dist/_chunks/index2.d.mts.map +0 -1
  126. package/dist/_chunks/index3.d.mts +0 -44
  127. package/dist/_chunks/index3.d.mts.map +0 -1
  128. package/dist/_chunks/index4.d.mts +0 -553
  129. package/dist/_chunks/index4.d.mts.map +0 -1
  130. package/dist/_chunks/package-registry.mjs +0 -465
  131. package/dist/_chunks/package-registry.mjs.map +0 -1
  132. package/dist/_chunks/retriv.mjs.map +0 -1
  133. package/dist/_chunks/setup.mjs +0 -17
  134. package/dist/_chunks/setup.mjs.map +0 -1
  135. package/dist/_chunks/sources.mjs +0 -2654
  136. package/dist/_chunks/sources.mjs.map +0 -1
  137. package/dist/_chunks/sync-pipeline.mjs.map +0 -1
  138. package/dist/_chunks/sync-registry.mjs +0 -65
  139. package/dist/_chunks/sync-registry.mjs.map +0 -1
  140. package/dist/_chunks/types.d.mts +0 -76
  141. package/dist/_chunks/types.d.mts.map +0 -1
  142. package/dist/_chunks/types2.d.mts +0 -88
  143. package/dist/_chunks/types2.d.mts.map +0 -1
  144. package/dist/_chunks/wizard.mjs.map +0 -1
  145. package/dist/agent/index.d.mts +0 -2
  146. package/dist/agent/index.mjs +0 -4
  147. package/dist/cache/index.d.mts +0 -2
  148. package/dist/cache/index.mjs +0 -5
  149. package/dist/index.d.mts +0 -6
  150. package/dist/index.mjs +0 -6
  151. package/dist/retriv/index.d.mts +0 -3
  152. package/dist/retriv/index.mjs +0 -2
  153. package/dist/sources/index.d.mts +0 -3
  154. package/dist/sources/index.mjs +0 -3
  155. package/dist/types.d.mts +0 -4
  156. package/dist/types.mjs +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"cache2.mjs","names":[],"sources":["../../src/commands/cache.ts"],"sourcesContent":["/**\n * Cache management commands\n */\n\nimport type { Dirent } from 'node:fs'\nimport { existsSync, readdirSync, readFileSync, rmSync, statSync } from 'node:fs'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { join } from 'pathe'\nimport { CACHE_DIR, REFERENCES_DIR, REPOS_DIR } from '../cache/index.ts'\nimport { clearEmbeddingCache } from '../retriv/embedding-cache.ts'\n\nconst LLM_CACHE_DIR = join(CACHE_DIR, 'llm-cache')\nconst LLM_CACHE_MAX_AGE = 7 * 24 * 60 * 60 * 1000\n\nfunction safeRemove(path: string): number {\n try {\n const size = statSync(path).size\n rmSync(path)\n return size\n }\n catch {\n try {\n rmSync(path)\n }\n catch {}\n return 0\n }\n}\n\nexport async function cacheCleanCommand(): Promise<void> {\n let expiredLlm = 0\n let freedBytes = 0\n\n // Clean expired LLM cache entries\n if (existsSync(LLM_CACHE_DIR)) {\n const now = Date.now()\n for (const entry of readdirSync(LLM_CACHE_DIR)) {\n const path = join(LLM_CACHE_DIR, entry)\n try {\n const { timestamp } = JSON.parse(readFileSync(path, 'utf-8'))\n if (now - timestamp > LLM_CACHE_MAX_AGE) {\n freedBytes += safeRemove(path)\n expiredLlm++\n }\n }\n catch {\n // Corrupt cache entry — remove it\n freedBytes += safeRemove(path)\n expiredLlm++\n }\n }\n }\n\n // Clear embedding cache\n const embeddingDbPath = join(CACHE_DIR, 'embeddings.db')\n let embeddingCleared = false\n if (existsSync(embeddingDbPath)) {\n const size = statSync(embeddingDbPath).size\n clearEmbeddingCache()\n freedBytes += size\n embeddingCleared = true\n }\n\n const freedKB = Math.round(freedBytes / 1024)\n if (expiredLlm > 0 || embeddingCleared) {\n const parts: string[] = []\n if (expiredLlm > 0)\n parts.push(`${expiredLlm} expired enhancement cache entries`)\n if (embeddingCleared)\n parts.push('embedding cache')\n p.log.success(`Removed ${parts.join(' + ')} (${freedKB}KB freed)`)\n }\n else {\n p.log.info('Cache is clean — no expired entries')\n }\n}\n\nfunction dirEntries(dir: string): Dirent[] {\n if (!existsSync(dir))\n return []\n return readdirSync(dir, { withFileTypes: true, recursive: true })\n}\n\nfunction sumFileBytes(entries: Dirent[]): number {\n return entries\n .filter(e => e.isFile())\n .reduce((sum, e) => {\n try {\n return sum + statSync(join(e.parentPath, e.name)).size\n }\n catch { return sum }\n }, 0)\n}\n\nfunction fmtBytes(n: number): string {\n const units = ['B', 'KB', 'MB', 'GB'] as const\n let i = 0\n while (n >= 1024 && i < units.length - 1) {\n n /= 1024\n i++\n }\n return i === 0 ? `${n}${units[i]}` : `${n.toFixed(1)}${units[i]}`\n}\n\nexport function cacheStatsCommand(): void {\n const dim = (s: string) => `\\x1B[90m${s}\\x1B[0m`\n\n const refs = dirEntries(REFERENCES_DIR)\n const repos = dirEntries(REPOS_DIR)\n const llm = dirEntries(LLM_CACHE_DIR)\n const embPath = join(CACHE_DIR, 'embeddings.db')\n const embSize = existsSync(embPath) ? statSync(embPath).size : 0\n\n // Count packages: top-level non-scoped dirs + dirs inside @scope/ dirs\n const packages = refs.filter(e =>\n e.isDirectory()\n && (e.parentPath === REFERENCES_DIR\n ? !e.name.startsWith('@')\n : e.parentPath.startsWith(REFERENCES_DIR)),\n ).length\n\n const llmFiles = llm.filter(e => e.isFile())\n const sizes = { refs: sumFileBytes(refs), repos: sumFileBytes(repos), llm: sumFileBytes(llmFiles), emb: embSize }\n const total = sizes.refs + sizes.repos + sizes.llm + sizes.emb\n\n const lines = [\n `References ${fmtBytes(sizes.refs)} ${dim(`${packages} packages`)}`,\n ...(sizes.repos > 0 ? [`Repos ${fmtBytes(sizes.repos)}`] : []),\n `LLM cache ${fmtBytes(sizes.llm)} ${dim(`${llmFiles.length} entries`)}`,\n ...(sizes.emb > 0 ? [`Embeddings ${fmtBytes(sizes.emb)}`] : []),\n '',\n `Total ${fmtBytes(total)} ${dim(CACHE_DIR)}`,\n ]\n p.log.message(lines.join('\\n'))\n}\n\nexport const cacheCommandDef = defineCommand({\n meta: { name: 'cache', description: 'Cache management', hidden: true },\n args: {\n clean: {\n type: 'boolean',\n alias: 'c',\n description: 'Remove expired enhancement cache entries',\n default: false,\n },\n stats: {\n type: 'boolean',\n alias: 's',\n description: 'Show cache disk usage',\n default: false,\n },\n },\n async run({ args }) {\n if (args.stats) {\n p.intro(`\\x1B[1m\\x1B[35mskilld\\x1B[0m cache stats`)\n cacheStatsCommand()\n return\n }\n if (args.clean) {\n p.intro(`\\x1B[1m\\x1B[35mskilld\\x1B[0m cache clean`)\n await cacheCleanCommand()\n return\n }\n // No flag: show usage\n p.intro(`\\x1B[1m\\x1B[35mskilld\\x1B[0m cache`)\n p.log.message('Usage:\\n skilld cache --clean Remove expired cache entries\\n skilld cache --stats Show cache disk usage')\n },\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"cache2.mjs","names":[],"sources":["../../src/commands/cache.ts"],"sourcesContent":["/**\n * Cache management commands\n */\n\nimport type { Dirent } from 'node:fs'\nimport { existsSync, readdirSync, readFileSync, rmSync, statSync } from 'node:fs'\nimport { styleText } from 'node:util'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { join } from 'pathe'\nimport { CACHE_DIR, REFERENCES_DIR, REPOS_DIR } from '../cache/index.ts'\nimport { clearEmbeddingCache } from '../retriv/embedding-cache.ts'\n\nconst LLM_CACHE_DIR = join(CACHE_DIR, 'llm-cache')\nconst LLM_CACHE_MAX_AGE = 7 * 24 * 60 * 60 * 1000\n\nfunction safeRemove(path: string): number {\n try {\n const size = statSync(path).size\n rmSync(path)\n return size\n }\n catch {\n try {\n rmSync(path)\n }\n catch {}\n return 0\n }\n}\n\nexport async function cacheCleanCommand(): Promise<void> {\n let expiredLlm = 0\n let freedBytes = 0\n\n // Clean expired LLM cache entries\n if (existsSync(LLM_CACHE_DIR)) {\n const now = Date.now()\n for (const entry of readdirSync(LLM_CACHE_DIR)) {\n const path = join(LLM_CACHE_DIR, entry)\n try {\n const { timestamp } = JSON.parse(readFileSync(path, 'utf-8'))\n if (now - timestamp > LLM_CACHE_MAX_AGE) {\n freedBytes += safeRemove(path)\n expiredLlm++\n }\n }\n catch {\n // Corrupt cache entry — remove it\n freedBytes += safeRemove(path)\n expiredLlm++\n }\n }\n }\n\n // Clear embedding cache\n const embeddingDbPath = join(CACHE_DIR, 'embeddings.db')\n let embeddingCleared = false\n if (existsSync(embeddingDbPath)) {\n const size = statSync(embeddingDbPath).size\n clearEmbeddingCache()\n freedBytes += size\n embeddingCleared = true\n }\n\n const freedKB = Math.round(freedBytes / 1024)\n if (expiredLlm > 0 || embeddingCleared) {\n const parts: string[] = []\n if (expiredLlm > 0)\n parts.push(`${expiredLlm} expired enhancement cache entries`)\n if (embeddingCleared)\n parts.push('embedding cache')\n p.log.success(`Removed ${parts.join(' + ')} (${freedKB}KB freed)`)\n }\n else {\n p.log.info('Cache is clean — no expired entries')\n }\n}\n\nfunction dirEntries(dir: string): Dirent[] {\n if (!existsSync(dir))\n return []\n return readdirSync(dir, { withFileTypes: true, recursive: true })\n}\n\nfunction sumFileBytes(entries: Dirent[]): number {\n return entries\n .filter(e => e.isFile())\n .reduce((sum, e) => {\n try {\n return sum + statSync(join(e.parentPath, e.name)).size\n }\n catch { return sum }\n }, 0)\n}\n\nfunction fmtBytes(n: number): string {\n const units = ['B', 'KB', 'MB', 'GB'] as const\n let i = 0\n while (n >= 1024 && i < units.length - 1) {\n n /= 1024\n i++\n }\n return i === 0 ? `${n}${units[i]}` : `${n.toFixed(1)}${units[i]}`\n}\n\nexport function cacheStatsCommand(): void {\n const dim = (s: string) => styleText('gray', s)\n\n const refs = dirEntries(REFERENCES_DIR)\n const repos = dirEntries(REPOS_DIR)\n const llm = dirEntries(LLM_CACHE_DIR)\n const embPath = join(CACHE_DIR, 'embeddings.db')\n const embSize = existsSync(embPath) ? statSync(embPath).size : 0\n\n // Count packages: top-level non-scoped dirs + dirs inside @scope/ dirs\n const packages = refs.filter(e =>\n e.isDirectory()\n && (e.parentPath === REFERENCES_DIR\n ? !e.name.startsWith('@')\n : e.parentPath.startsWith(REFERENCES_DIR)),\n ).length\n\n const llmFiles = llm.filter(e => e.isFile())\n const sizes = { refs: sumFileBytes(refs), repos: sumFileBytes(repos), llm: sumFileBytes(llmFiles), emb: embSize }\n const total = sizes.refs + sizes.repos + sizes.llm + sizes.emb\n\n const lines = [\n `References ${fmtBytes(sizes.refs)} ${dim(`${packages} packages`)}`,\n ...(sizes.repos > 0 ? [`Repos ${fmtBytes(sizes.repos)}`] : []),\n `LLM cache ${fmtBytes(sizes.llm)} ${dim(`${llmFiles.length} entries`)}`,\n ...(sizes.emb > 0 ? [`Embeddings ${fmtBytes(sizes.emb)}`] : []),\n '',\n `Total ${fmtBytes(total)} ${dim(CACHE_DIR)}`,\n ]\n p.log.message(lines.join('\\n'))\n}\n\nexport const cacheCommandDef = defineCommand({\n meta: { name: 'cache', description: 'Cache management', hidden: true },\n args: {\n clean: {\n type: 'boolean',\n alias: 'c',\n description: 'Remove expired enhancement cache entries',\n default: false,\n },\n stats: {\n type: 'boolean',\n alias: 's',\n description: 'Show cache disk usage',\n default: false,\n },\n },\n async run({ args }) {\n if (args.stats) {\n p.intro(`${styleText(['bold', 'magenta'], 'skilld')} cache stats`)\n cacheStatsCommand()\n return\n }\n if (args.clean) {\n p.intro(`${styleText(['bold', 'magenta'], 'skilld')} cache clean`)\n await cacheCleanCommand()\n return\n }\n // No flag: show usage\n p.intro(`${styleText(['bold', 'magenta'], 'skilld')} cache`)\n p.log.message('Usage:\\n skilld cache --clean Remove expired cache entries\\n skilld cache --stats Show cache disk usage')\n },\n})\n"],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ import { m as TRAILING_SLASH_RE } from "./regex.mjs";
2
+ import { ofetch } from "ofetch";
3
+ const DEFAULT_REGISTRY_URL = "https://skilld.dev/api";
4
+ function getRegistryBase() {
5
+ return (process.env.SKILLD_REGISTRY_URL || DEFAULT_REGISTRY_URL).replace(TRAILING_SLASH_RE, "");
6
+ }
7
+ function gateInstall(result, opts) {
8
+ switch (result.status) {
9
+ case "pass": return "install";
10
+ case "warn": return "install";
11
+ case "fail": return opts.allowUnsafe ? "install" : "skip";
12
+ case "unaudited":
13
+ if (opts.sourceKind !== "gh") return "install";
14
+ return opts.yes ? "install" : "prompt";
15
+ }
16
+ }
17
+ function aggregateAuditStatus(audits) {
18
+ if (audits.length === 0) return "unaudited";
19
+ if (audits.some((a) => a.status === "fail")) return "fail";
20
+ if (audits.some((a) => a.status === "warn")) return "warn";
21
+ return "pass";
22
+ }
23
+ function createRegistryClient(opts = {}) {
24
+ const base = (opts.baseUrl ?? getRegistryBase()).replace(TRAILING_SLASH_RE, "");
25
+ const headers = opts.session ? { Authorization: `Bearer ${opts.session.accessToken}` } : void 0;
26
+ const fetcher = (url, init) => {
27
+ if (!headers && !init) return ofetch(url);
28
+ if (!headers) return ofetch(url, init);
29
+ return ofetch(url, {
30
+ ...init,
31
+ headers: {
32
+ ...headers,
33
+ ...init?.headers
34
+ }
35
+ });
36
+ };
37
+ const requireSession = () => {
38
+ if (!opts.session) throw new Error("auth required");
39
+ };
40
+ return {
41
+ async resolveSkill(packageName, fetchOpts = {}) {
42
+ const hit = (await fetcher(`${base}/skills/resolve`, {
43
+ method: "POST",
44
+ body: { items: [{
45
+ packageName,
46
+ owner: fetchOpts.owner
47
+ }] }
48
+ }).catch(() => null))?.[packageName];
49
+ if (!hit) return null;
50
+ const detail = await fetcher(`${base}/skills/${hit.owner}/${hit.repo}/${packageName}`).catch(() => null);
51
+ if (!detail?.raw) return null;
52
+ return {
53
+ name: detail.name,
54
+ packageName,
55
+ content: detail.raw,
56
+ owner: detail.owner,
57
+ repo: `${detail.owner}/${detail.repo}`,
58
+ displayName: detail.displayName,
59
+ installs: detail.installs,
60
+ official: hit.official,
61
+ branch: detail.branch,
62
+ skillPath: detail.skillPath ?? void 0,
63
+ updatedAt: detail.pushedAt ?? void 0
64
+ };
65
+ },
66
+ async fetchSkillDetail(owner, repo, name) {
67
+ return fetcher(`${base}/skills/${owner}/${repo}/${name}`).catch(() => null);
68
+ },
69
+ async audit({ owner, repo, name }) {
70
+ const res = await fetcher(`${base}/skill-live/${owner}/${repo}/${name}`).catch(() => null);
71
+ if (!res) return {
72
+ status: "unaudited",
73
+ audits: []
74
+ };
75
+ const audits = res.audits ?? [];
76
+ return {
77
+ status: aggregateAuditStatus(audits),
78
+ riskLevel: res.riskLevel,
79
+ summary: res.summary,
80
+ audits
81
+ };
82
+ },
83
+ async fetchCollection(login, slug) {
84
+ return fetcher(`${base}/collections/by-author/${login}/${slug}/manifest`).catch(() => null);
85
+ },
86
+ async fetchCurator(login) {
87
+ return fetcher(`${base}/curators/${login}`).catch(() => null);
88
+ },
89
+ my: {
90
+ async collections() {
91
+ requireSession();
92
+ return fetcher(`${base}/me/collections`).catch(() => []);
93
+ },
94
+ async subscriptions() {
95
+ requireSession();
96
+ return fetcher(`${base}/me/subscriptions`).catch(() => []);
97
+ },
98
+ async changes({ since }) {
99
+ requireSession();
100
+ return fetcher(`${base}/cli/changes${since != null ? `?since=${since}` : ""}`).catch(() => null);
101
+ },
102
+ async installs(payload) {
103
+ requireSession();
104
+ await fetcher(`${base}/me/installs`, {
105
+ method: "POST",
106
+ body: payload
107
+ }).catch(() => {});
108
+ }
109
+ }
110
+ };
111
+ }
112
+ async function fetchRegistrySkill(packageName, opts = {}) {
113
+ return createRegistryClient().resolveSkill(packageName, opts);
114
+ }
115
+ export { getRegistryBase as i, fetchRegistrySkill as n, gateInstall as r, createRegistryClient as t };
116
+
117
+ //# sourceMappingURL=client.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.mjs","names":[],"sources":["../../src/registry/client.ts"],"sourcesContent":["/**\n * Registry client for skilld.dev\n *\n * Talks to the public skilld.dev JSON API: resolves an npm package name to a\n * curated skill's owner/repo, then fetches the detail payload which includes\n * the raw SKILL.md. For local development, set SKILLD_REGISTRY_URL (e.g.\n * http://localhost:3000/api) to point at a running Nuxt dev server.\n *\n * Returns null when a skill isn't curated, the API is unreachable, or the\n * skill has no resolvable SKILL.md, so callers fall through to the\n * doc-generation pipeline.\n */\n\nimport type { AuditStatus } from 'skilld-protocol/constants'\nimport type {\n AuditEntry,\n AuthSession,\n ChangeEntry,\n CollectionManifest,\n CollectionManifestItem,\n CollectionSummary,\n CuratorPayload,\n DigestResponse,\n InstallEventPayload,\n SkillDetailResponse,\n SkillsResolveEntry,\n SkillsResolveResponse,\n SubscriptionSummary,\n} from 'skilld-protocol/wire'\nimport { ofetch } from 'ofetch'\nimport { TRAILING_SLASH_RE } from '../core/regex.ts'\n\nexport type { AuditEntry, AuditStatus, AuthSession, ChangeEntry, CollectionManifest, CollectionManifestItem, CollectionSummary, CuratorPayload, DigestResponse, InstallEventPayload, SkillDetailResponse, SkillsResolveResponse, SubscriptionSummary }\n\nconst DEFAULT_REGISTRY_URL = 'https://skilld.dev/api'\n\nexport function getRegistryBase(): string {\n return (process.env.SKILLD_REGISTRY_URL || DEFAULT_REGISTRY_URL).replace(TRAILING_SLASH_RE, '')\n}\n\nexport interface RegistrySkill {\n name: string\n packageName: string\n content: string\n owner: string\n repo: string\n displayName?: string\n installs?: number\n official?: boolean\n branch?: string\n skillPath?: string\n updatedAt?: string\n}\n\nexport interface FetchRegistrySkillOptions {\n owner?: string\n}\n\n/**\n * CLI-internal computed shape. Built locally after fetching the wire\n * `SkillLiveResponse`; `status` is computed by `aggregateAuditStatus`.\n */\nexport interface AuditResult {\n status: AuditStatus\n riskLevel?: 'low' | 'medium' | 'high'\n summary?: string\n audits: AuditEntry[]\n}\n\ninterface AuditApiResponse {\n riskLevel?: 'low' | 'medium' | 'high'\n summary?: string\n audits?: AuditEntry[]\n}\n\nexport interface RegistryClient {\n resolveSkill: (packageName: string, opts?: FetchRegistrySkillOptions) => Promise<RegistrySkill | null>\n fetchSkillDetail: (owner: string, repo: string, name: string) => Promise<SkillDetailResponse | null>\n audit: (params: { owner: string, repo: string, name: string }) => Promise<AuditResult>\n fetchCollection: (login: string, slug: string) => Promise<CollectionManifest | null>\n fetchCurator: (login: string) => Promise<CuratorPayload | null>\n my: {\n collections: () => Promise<CollectionSummary[]>\n subscriptions: () => Promise<SubscriptionSummary[]>\n changes: (params: { since?: number }) => Promise<DigestResponse | null>\n installs: (payload: InstallEventPayload) => Promise<void>\n }\n}\n\nexport type GateDecision = 'install' | 'skip' | 'prompt'\n\nexport interface GateOptions {\n allowUnsafe?: boolean\n yes?: boolean\n /** Source kind drives unaudited behaviour: gh → prompt, npm/crate → silent install */\n sourceKind: 'npm' | 'gh' | 'crate' | 'collection'\n}\n\n/**\n * Pure gating rule from an audit result. Caller is responsible for the prompt\n * itself when the decision is `'prompt'`.\n */\nexport function gateInstall(result: AuditResult, opts: GateOptions): GateDecision {\n switch (result.status) {\n case 'pass':\n return 'install'\n case 'warn':\n return 'install'\n case 'fail':\n return opts.allowUnsafe ? 'install' : 'skip'\n case 'unaudited':\n if (opts.sourceKind !== 'gh')\n return 'install'\n return opts.yes ? 'install' : 'prompt'\n }\n}\n\nexport function aggregateAuditStatus(audits: AuditEntry[]): AuditStatus {\n if (audits.length === 0)\n return 'unaudited'\n if (audits.some(a => a.status === 'fail'))\n return 'fail'\n if (audits.some(a => a.status === 'warn'))\n return 'warn'\n return 'pass'\n}\n\nexport function createRegistryClient(opts: { session?: AuthSession, baseUrl?: string } = {}): RegistryClient {\n const base = (opts.baseUrl ?? getRegistryBase()).replace(TRAILING_SLASH_RE, '')\n const headers = opts.session ? { Authorization: `Bearer ${opts.session.accessToken}` } : undefined\n\n const fetcher = <T>(url: string, init?: Parameters<typeof ofetch<T>>[1]): Promise<T> => {\n if (!headers && !init)\n return ofetch<T>(url)\n if (!headers)\n return ofetch<T>(url, init)\n return ofetch<T>(url, { ...init, headers: { ...headers, ...(init?.headers as any) } })\n }\n\n const requireSession = (): void => {\n if (!opts.session)\n throw new Error('auth required')\n }\n\n return {\n async resolveSkill(packageName, fetchOpts = {}) {\n const resolved = await fetcher<Record<string, SkillsResolveEntry>>(`${base}/skills/resolve`, {\n method: 'POST',\n body: { items: [{ packageName, owner: fetchOpts.owner }] },\n }).catch(() => null)\n\n const hit = resolved?.[packageName]\n if (!hit)\n return null\n\n const detail = await fetcher<SkillDetailResponse>(`${base}/skills/${hit.owner}/${hit.repo}/${packageName}`).catch(() => null)\n if (!detail?.raw)\n return null\n\n return {\n name: detail.name,\n packageName,\n content: detail.raw,\n owner: detail.owner,\n repo: `${detail.owner}/${detail.repo}`,\n displayName: detail.displayName,\n installs: detail.installs,\n official: hit.official,\n branch: detail.branch,\n skillPath: detail.skillPath ?? undefined,\n updatedAt: detail.pushedAt ?? undefined,\n }\n },\n\n async fetchSkillDetail(owner, repo, name) {\n return fetcher<SkillDetailResponse>(`${base}/skills/${owner}/${repo}/${name}`).catch(() => null)\n },\n\n async audit({ owner, repo, name }) {\n const res = await fetcher<AuditApiResponse>(`${base}/skill-live/${owner}/${repo}/${name}`).catch(() => null)\n if (!res)\n return { status: 'unaudited', audits: [] }\n const audits = res.audits ?? []\n return {\n status: aggregateAuditStatus(audits),\n riskLevel: res.riskLevel,\n summary: res.summary,\n audits,\n }\n },\n\n async fetchCollection(login, slug) {\n return fetcher<CollectionManifest>(`${base}/collections/by-author/${login}/${slug}/manifest`).catch(() => null)\n },\n\n async fetchCurator(login) {\n return fetcher<CuratorPayload>(`${base}/curators/${login}`).catch(() => null)\n },\n\n my: {\n async collections() {\n requireSession()\n return fetcher<CollectionSummary[]>(`${base}/me/collections`).catch(() => [])\n },\n async subscriptions() {\n requireSession()\n return fetcher<SubscriptionSummary[]>(`${base}/me/subscriptions`).catch(() => [])\n },\n async changes({ since }) {\n requireSession()\n const qs = since != null ? `?since=${since}` : ''\n return fetcher<DigestResponse>(`${base}/cli/changes${qs}`).catch(() => null)\n },\n async installs(payload) {\n requireSession()\n await fetcher<void>(`${base}/me/installs`, { method: 'POST', body: payload }).catch(() => {})\n },\n },\n }\n}\n\n/**\n * Fetch a curated package skill from the registry.\n * Returns null if no curated skill exists, the SKILL.md can't be loaded, or the API is unreachable.\n *\n * Thin wrapper over `createRegistryClient().resolveSkill` for back-compat.\n */\nexport async function fetchRegistrySkill(\n packageName: string,\n opts: FetchRegistrySkillOptions = {},\n): Promise<RegistrySkill | null> {\n return createRegistryClient().resolveSkill(packageName, opts)\n}\n"],"mappings":";;AAkCA,MAAM,uBAAuB;AAE7B,SAAgB,kBAA0B;CACxC,QAAQ,QAAQ,IAAI,uBAAuB,sBAAsB,QAAQ,mBAAmB,GAAG;;;;;EAiEjG,KAAA,QAAgB,OAAY;EAC1B,KAAA,QAAQ,OAAO,KAAf,cAAA,YAAA;EACE,KAAK;GAEL,IAAK,KAAA,eACI,MAAA,OAAA;GACT,OAAK,KACH,MAAA,YAAY;;;SAIZ,qBAAkB,QAAY;;;CAIpC,IAAA,OAAgB,MAAA,MAAA,EAAA,WAAqB,OAAmC,EAAA,OAAA;CACtE,OAAI;;SAIA,qBAAmB,OAAW,EAAA,EAAA;CAElC,MAAA,QAAO,KAAA,WAAA,iBAAA,EAAA,QAAA,mBAAA,GAAA;;CAGT,MAAA,WAAgB,KAAA,SAAqB;EACnC,IAAA,CAAM,WAAQ,CAAA,MAAK,OAAW,OAAA,IAAA;EAC9B,IAAA,CAAM,SAAA,OAAe,OAAA,KAAY,KAAA;EAEjC,OAAM,OAAA,KAAc;GAClB,GAAI;GAEJ,SAAK;IAEL,GAAA;IAAwB,GAAG,MAAA;IAAM;IAAW;;OAAuC,uBAAA;MAAG,CAAA,KAAA,SAAA,MAAA,IAAA,MAAA,gBAAA;;CAGxF,OAAM;EACJ,MAAK,aACH,aAAU,YAAM,EAAA,EAAA;;IAGpB,QAAO;IACL,MAAM,EAAA,OAAA,CAAA;KAMJ;KAJE,OAAQ,UAAA;KACR,CAAA,EAAA;KAAkB,CAAA,YAAA,KAAA,IAAA;OAAa,CAAA,KAAO,OAAA;SAAoB,SAAA,MAAA,QAAA,GAAA,KAAA,UAAA,IAAA,MAAA,GAAA,IAAA,KAAA,GAAA,cAAA,CAAA,YAAA,KAAA;OACzD,CAAA,QAAA,KAAY,OAEQ;GACvB,OAAK;IAGL,MAAM,OAAA;IACN;IAGA,SAAO,OAAA;IACL,OAAM,OAAO;IACb,MAAA,GAAA,OAAA,MAAA,GAAA,OAAA;IACA,aAAS,OAAO;IAChB,UAAO,OAAO;IACd,UAAS,IAAA;IACT,QAAA,OAAa;IACb,WAAU,OAAO,aAAA,KAAA;IACjB,WAAU,OAAI,YAAA,KAAA;IACd;;QAEA,iBAAkB,OAAA,MAAY,MAAA;UAC/B,QAAA,GAAA,KAAA,UAAA,MAAA,GAAA,KAAA,GAAA,OAAA,CAAA,YAAA,KAAA;;EAGH,MAAM,MAAA,EAAA,OAAA,MAAiB,QAAO;GAC5B,MAAA,MAAO,MAAgC,QAAK,GAAA,KAAU,cAAc,MAAG,GAAO,KAAC,GAAA,OAAY,CAAA,YAAK,KAAA;;IAGlG,QAAM;IACJ,QAAM,EAAA;IACN;SACW,SAAQ,IAAA,UAAA,EAAA;UAAa;IAAY,QAAA,qBAAA,OAAA;IAC5C,WAAM,IAAS;IACf,SAAO,IAAA;IACL;IACA;;QAEA,gBAAA,OAAA,MAAA;UACD,QAAA,GAAA,KAAA,yBAAA,MAAA,GAAA,KAAA,WAAA,CAAA,YAAA,KAAA;;EAGH,MAAM,aAAA,OAAgB;GACpB,OAAO,QAA4B,GAAG,KAAK,YAAA,QAAA,CAAA,YAA+B,KAAG;;EAG/E,IAAA;GACE,MAAA,cAAkC;;IAGpC,OAAI,QAAA,GAAA,KAAA,iBAAA,CAAA,YAAA,EAAA,CAAA;;SAEA,gBAAgB;IAChB,gBAAoC;;;SAGpC,QAAA,EAAA,SAAgB;IAChB,gBAAsC;;;SAGtC,SAAA,SAAgB;IAEhB,gBAA+B;;KAEjC,QAAM;KACJ,MAAA;KACA,CAAA,CAAA,YAAoB,GAAG;;;;;eAG5B,mBAAA,aAAA,OAAA,EAAA,EAAA"}
@@ -1,13 +1,13 @@
1
+ import "./prompts.mjs";
1
2
  import "./paths.mjs";
3
+ import "./sanitize.mjs";
2
4
  import "./yaml.mjs";
3
- import "./cache.mjs";
4
5
  import "./package-json.mjs";
5
- import "./sanitize.mjs";
6
+ import "./cache.mjs";
7
+ import "./semver.mjs";
8
+ import "./map.mjs";
6
9
  import "./markdown.mjs";
7
- import "./sources.mjs";
8
- import "./prompts.mjs";
9
10
  import "./lockfile.mjs";
10
- import "./semver.mjs";
11
11
  import "./skills.mjs";
12
12
  import "./monorepo.mjs";
13
13
  export {};
@@ -1,8 +1,8 @@
1
1
  import { existsSync, readdirSync } from "node:fs";
2
- import { homedir } from "node:os";
3
2
  import { join } from "pathe";
4
3
  import { spawnSync } from "node:child_process";
5
4
  import { isWindows } from "std-env";
5
+ import { homedir } from "node:os";
6
6
  const SPEC_FRONTMATTER = {
7
7
  "name": {
8
8
  name: "name",
@@ -47,21 +47,29 @@ const BASE_DEFAULTS = {
47
47
  notes: []
48
48
  };
49
49
  function defineTarget(target) {
50
+ const { globalSkillsDir, additionalSkillsDirs, ...rest } = target;
51
+ const additional = additionalSkillsDirs ?? BASE_DEFAULTS.additionalSkillsDirs;
50
52
  return {
51
53
  ...BASE_DEFAULTS,
52
- ...target
54
+ ...rest,
55
+ get globalSkillsDir() {
56
+ return globalSkillsDir();
57
+ },
58
+ get additionalSkillsDirs() {
59
+ return typeof additional === "function" ? additional() : additional;
60
+ }
53
61
  };
54
62
  }
55
- const configHome$2 = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
63
+ const configHome$2 = () => process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
56
64
  const amp = defineTarget({
57
65
  agent: "amp",
58
66
  displayName: "Amp",
59
- detectInstalled: () => existsSync(join(configHome$2, "amp")),
67
+ detectInstalled: () => existsSync(join(configHome$2(), "amp")),
60
68
  detectEnv: () => !!process.env.AMP_SESSION,
61
69
  detectProject: (cwd) => existsSync(join(cwd, ".agents", "AGENTS.md")),
62
70
  instructionFile: "AGENTS.md",
63
71
  skillsDir: ".agents/skills",
64
- globalSkillsDir: join(configHome$2, "agents/skills"),
72
+ globalSkillsDir: () => join(configHome$2(), "agents/skills"),
65
73
  additionalSkillsDirs: [
66
74
  ".claude/skills",
67
75
  "~/.config/amp/skills",
@@ -86,16 +94,16 @@ const amp = defineTarget({
86
94
  "AGENTS.md files with globs frontmatter are conditionally included only when Amp reads matching files."
87
95
  ]
88
96
  });
89
- const home$6 = homedir();
97
+ const home$6 = () => homedir();
90
98
  const antigravity = defineTarget({
91
99
  agent: "antigravity",
92
100
  displayName: "Antigravity",
93
- detectInstalled: () => existsSync(join(home$6, ".gemini/antigravity")),
101
+ detectInstalled: () => existsSync(join(home$6(), ".gemini/antigravity")),
94
102
  detectEnv: () => !!process.env.ANTIGRAVITY_CLI_ALIAS,
95
103
  detectProject: (cwd) => existsSync(join(cwd, ".agent")),
96
104
  instructionFile: "GEMINI.md",
97
105
  skillsDir: ".agent/skills",
98
- globalSkillsDir: join(home$6, ".gemini/antigravity/skills"),
106
+ globalSkillsDir: () => join(home$6(), ".gemini/antigravity/skills"),
99
107
  frontmatter: [{
100
108
  ...SPEC_FRONTMATTER.name,
101
109
  description: "Skill identifier. Defaults to directory name if omitted."
@@ -113,11 +121,11 @@ const antigravity = defineTarget({
113
121
  "GEMINI.md instruction file is shared with Gemini CLI. .agent/rules/*.md for always-on workspace rules."
114
122
  ]
115
123
  });
116
- const claudeHome = process.env.CLAUDE_CONFIG_DIR || join(homedir(), ".claude");
124
+ const claudeHome = () => process.env.CLAUDE_CONFIG_DIR || join(homedir(), ".claude");
117
125
  const claudeCode = defineTarget({
118
126
  agent: "claude-code",
119
127
  displayName: "Claude Code",
120
- detectInstalled: () => existsSync(claudeHome),
128
+ detectInstalled: () => existsSync(claudeHome()),
121
129
  detectEnv: () => !!(process.env.CLAUDE_CODE || process.env.CLAUDECODE || process.env.CLAUDE_CODE_ENTRYPOINT || process.env.CLAUDE_CONFIG_DIR),
122
130
  detectProject: (cwd) => {
123
131
  if (existsSync(join(cwd, ".claude", "settings.json"))) return true;
@@ -128,7 +136,7 @@ const claudeCode = defineTarget({
128
136
  cli: "claude",
129
137
  instructionFile: "CLAUDE.md",
130
138
  skillsDir: ".claude/skills",
131
- globalSkillsDir: join(claudeHome, "skills"),
139
+ globalSkillsDir: () => join(claudeHome(), "skills"),
132
140
  frontmatter: [
133
141
  {
134
142
  ...SPEC_FRONTMATTER.name,
@@ -200,16 +208,16 @@ const claudeCode = defineTarget({
200
208
  "Project detection uses weighted signals: .claude/settings.json, .claude/settings.local.json, .claude/skills/ are strong; bare .claude/ is medium; CLAUDE.md alone is not checked (too many false positives from repo conventions)."
201
209
  ]
202
210
  });
203
- const home$5 = homedir();
211
+ const home$5 = () => homedir();
204
212
  const cline = defineTarget({
205
213
  agent: "cline",
206
214
  displayName: "Cline",
207
- detectInstalled: () => existsSync(join(home$5, ".cline")),
215
+ detectInstalled: () => existsSync(join(home$5(), ".cline")),
208
216
  detectEnv: () => !!(process.env.CLINE_TASK_ID || process.env.CLINE_ACTIVE),
209
217
  detectProject: (cwd) => existsSync(join(cwd, ".cline")),
210
218
  instructionFile: ".clinerules",
211
219
  skillsDir: ".cline/skills",
212
- globalSkillsDir: join(home$5, ".cline/skills"),
220
+ globalSkillsDir: () => join(home$5(), ".cline/skills"),
213
221
  additionalSkillsDirs: [".clinerules/skills", ".claude/skills"],
214
222
  frontmatter: [{
215
223
  ...SPEC_FRONTMATTER.name,
@@ -230,17 +238,17 @@ const cline = defineTarget({
230
238
  "Supporting dirs: docs/, scripts/, templates/ alongside SKILL.md."
231
239
  ]
232
240
  });
233
- const codexHome = process.env.CODEX_HOME || join(homedir(), ".codex");
241
+ const codexHome = () => process.env.CODEX_HOME || join(homedir(), ".codex");
234
242
  const codex = defineTarget({
235
243
  agent: "codex",
236
244
  displayName: "Codex",
237
- detectInstalled: () => existsSync(codexHome),
245
+ detectInstalled: () => existsSync(codexHome()),
238
246
  detectEnv: () => false,
239
247
  detectProject: (cwd) => existsSync(join(cwd, ".codex")) || existsSync(join(cwd, "AGENTS.md")) || existsSync(join(cwd, "AGENTS.override.md")) || existsSync(join(cwd, ".agents", "skills")),
240
248
  cli: "codex",
241
249
  instructionFile: "AGENTS.md",
242
250
  skillsDir: ".agents/skills",
243
- globalSkillsDir: join(homedir(), ".agents/skills"),
251
+ globalSkillsDir: () => join(homedir(), ".agents/skills"),
244
252
  additionalSkillsDirs: ["~/.codex/skills", "/etc/codex/skills"],
245
253
  frontmatter: [
246
254
  {
@@ -275,16 +283,16 @@ const codex = defineTarget({
275
283
  "Size limit: 32 KiB default (project_doc_max_bytes), configurable in ~/.codex/config.toml."
276
284
  ]
277
285
  });
278
- const home$4 = homedir();
286
+ const home$4 = () => homedir();
279
287
  const cursor = defineTarget({
280
288
  agent: "cursor",
281
289
  displayName: "Cursor",
282
- detectInstalled: () => existsSync(join(home$4, ".cursor")),
290
+ detectInstalled: () => existsSync(join(home$4(), ".cursor")),
283
291
  detectEnv: () => !!(process.env.CURSOR_SESSION || process.env.CURSOR_TRACE_ID),
284
292
  detectProject: (cwd) => existsSync(join(cwd, ".cursor")) || existsSync(join(cwd, ".cursorrules")),
285
293
  instructionFile: ".cursor/rules/skilld-activation.mdc",
286
294
  skillsDir: ".cursor/skills",
287
- globalSkillsDir: join(home$4, ".cursor/skills"),
295
+ globalSkillsDir: () => join(home$4(), ".cursor/skills"),
288
296
  additionalSkillsDirs: [
289
297
  ".claude/skills",
290
298
  ".codex/skills",
@@ -319,18 +327,18 @@ const cursor = defineTarget({
319
327
  "Supporting dirs: scripts/, references/, assets/ alongside SKILL.md."
320
328
  ]
321
329
  });
322
- const home$3 = homedir();
330
+ const home$3 = () => homedir();
323
331
  const geminiCli = defineTarget({
324
332
  agent: "gemini-cli",
325
333
  displayName: "Gemini CLI",
326
- detectInstalled: () => existsSync(join(home$3, ".gemini")),
334
+ detectInstalled: () => existsSync(join(home$3(), ".gemini")),
327
335
  detectEnv: () => !!process.env.GEMINI_CLI,
328
336
  detectProject: (cwd) => existsSync(join(cwd, ".gemini")),
329
337
  cli: "gemini",
330
338
  instructionFile: "GEMINI.md",
331
339
  skillsDir: ".gemini/skills",
332
- globalSkillsDir: join(home$3, ".gemini/skills"),
333
- additionalSkillsDirs: [".agents/skills", join(home$3, ".agents/skills")],
340
+ globalSkillsDir: () => join(home$3(), ".gemini/skills"),
341
+ additionalSkillsDirs: () => [".agents/skills", join(home$3(), ".agents/skills")],
334
342
  frontmatter: [
335
343
  SPEC_FRONTMATTER.name,
336
344
  {
@@ -355,12 +363,13 @@ const geminiCli = defineTarget({
355
363
  "Also scans .agents/skills/ (Agent Skills spec standard) - skilld deduplicates to avoid conflicts."
356
364
  ]
357
365
  });
358
- const home$2 = homedir();
366
+ const home$2 = () => homedir();
359
367
  function hasCopilotExtension() {
368
+ const h = home$2();
360
369
  const extDirs = [
361
- join(home$2, ".vscode", "extensions"),
362
- join(home$2, ".vscode-server", "extensions"),
363
- join(home$2, ".cursor", "extensions")
370
+ join(h, ".vscode", "extensions"),
371
+ join(h, ".vscode-server", "extensions"),
372
+ join(h, ".cursor", "extensions")
364
373
  ];
365
374
  for (const dir of extDirs) {
366
375
  if (!existsSync(dir)) continue;
@@ -373,12 +382,12 @@ function hasCopilotExtension() {
373
382
  const githubCopilot = defineTarget({
374
383
  agent: "github-copilot",
375
384
  displayName: "GitHub Copilot",
376
- detectInstalled: () => existsSync(join(home$2, ".copilot")) || hasCopilotExtension(),
385
+ detectInstalled: () => existsSync(join(home$2(), ".copilot")) || hasCopilotExtension(),
377
386
  detectEnv: () => !!process.env.COPILOT_RUN_APP,
378
387
  detectProject: (cwd) => existsSync(join(cwd, ".github", "copilot-instructions.md")) || existsSync(join(cwd, ".github", "skills")) || existsSync(join(cwd, "AGENTS.md")) || existsSync(join(cwd, ".github", "instructions")),
379
388
  instructionFile: ".github/copilot-instructions.md",
380
389
  skillsDir: ".github/skills",
381
- globalSkillsDir: join(home$2, ".copilot/skills"),
390
+ globalSkillsDir: () => join(home$2(), ".copilot/skills"),
382
391
  additionalSkillsDirs: [".claude/skills", "~/.claude/skills"],
383
392
  frontmatter: [
384
393
  SPEC_FRONTMATTER.name,
@@ -408,17 +417,17 @@ const githubCopilot = defineTarget({
408
417
  "Keep SKILL.md under 500 lines / 5000 tokens for optimal loading."
409
418
  ]
410
419
  });
411
- const configHome$1 = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
420
+ const configHome$1 = () => process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
412
421
  const goose = defineTarget({
413
422
  agent: "goose",
414
423
  displayName: "Goose",
415
- detectInstalled: () => existsSync(join(configHome$1, "goose")),
424
+ detectInstalled: () => existsSync(join(configHome$1(), "goose")),
416
425
  detectEnv: () => !!(process.env.GOOSE_SESSION || process.env.AGENT_SESSION_ID),
417
426
  detectProject: (cwd) => existsSync(join(cwd, ".goose")),
418
427
  cli: "goose",
419
428
  instructionFile: ".goosehints",
420
429
  skillsDir: ".goose/skills",
421
- globalSkillsDir: join(configHome$1, "goose/skills"),
430
+ globalSkillsDir: () => join(configHome$1(), "goose/skills"),
422
431
  additionalSkillsDirs: [
423
432
  ".claude/skills",
424
433
  ".agents/skills",
@@ -442,16 +451,16 @@ const goose = defineTarget({
442
451
  "Supporting files alongside SKILL.md (scripts, templates, configs) are accessible."
443
452
  ]
444
453
  });
445
- const configHome = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
454
+ const configHome = () => process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
446
455
  const opencode = defineTarget({
447
456
  agent: "opencode",
448
457
  displayName: "OpenCode",
449
- detectInstalled: () => existsSync(join(configHome, "opencode")),
458
+ detectInstalled: () => existsSync(join(configHome(), "opencode")),
450
459
  detectEnv: () => !!(process.env.OPENCODE_SESSION || process.env.OPENCODE_SESSION_ID),
451
460
  detectProject: (cwd) => existsSync(join(cwd, ".opencode")),
452
461
  instructionFile: "AGENTS.md",
453
462
  skillsDir: ".opencode/skills",
454
- globalSkillsDir: join(configHome, "opencode/skills"),
463
+ globalSkillsDir: () => join(configHome(), "opencode/skills"),
455
464
  additionalSkillsDirs: [
456
465
  ".claude/skills",
457
466
  ".agents/skills",
@@ -483,16 +492,16 @@ const opencode = defineTarget({
483
492
  "AGENTS.md (or CLAUDE.md fallback) for general instructions."
484
493
  ]
485
494
  });
486
- const home$1 = homedir();
495
+ const home$1 = () => homedir();
487
496
  const roo = defineTarget({
488
497
  agent: "roo",
489
498
  displayName: "Roo Code",
490
- detectInstalled: () => existsSync(join(home$1, ".roo")),
499
+ detectInstalled: () => existsSync(join(home$1(), ".roo")),
491
500
  detectEnv: () => !!process.env.ROO_SESSION,
492
501
  detectProject: (cwd) => existsSync(join(cwd, ".roo")),
493
502
  instructionFile: ".roorules",
494
503
  skillsDir: ".roo/skills",
495
- globalSkillsDir: join(home$1, ".roo/skills"),
504
+ globalSkillsDir: () => join(home$1(), ".roo/skills"),
496
505
  frontmatter: [{
497
506
  ...SPEC_FRONTMATTER.name,
498
507
  description: "Must exactly match the directory name."
@@ -515,19 +524,19 @@ const roo = defineTarget({
515
524
  "Skills manageable from Settings panel (v3.46.0+)."
516
525
  ]
517
526
  });
518
- const home = homedir();
527
+ const home = () => homedir();
519
528
  const targets = {
520
529
  "claude-code": claudeCode,
521
530
  "cursor": cursor,
522
531
  "windsurf": defineTarget({
523
532
  agent: "windsurf",
524
533
  displayName: "Windsurf",
525
- detectInstalled: () => existsSync(join(home, ".codeium/windsurf")),
534
+ detectInstalled: () => existsSync(join(home(), ".codeium/windsurf")),
526
535
  detectEnv: () => !!process.env.WINDSURF_SESSION,
527
536
  detectProject: (cwd) => existsSync(join(cwd, ".windsurf")) || existsSync(join(cwd, ".windsurfrules")),
528
537
  instructionFile: ".windsurfrules",
529
538
  skillsDir: ".windsurf/skills",
530
- globalSkillsDir: join(home, ".codeium/windsurf/skills"),
539
+ globalSkillsDir: () => join(home(), ".codeium/windsurf/skills"),
531
540
  frontmatter: [{
532
541
  ...SPEC_FRONTMATTER.name,
533
542
  description: "Skill identifier.",
@@ -558,6 +567,7 @@ const targets = {
558
567
  "roo": roo,
559
568
  "antigravity": antigravity
560
569
  };
570
+ const STATIC_REGEX_1 = /v?(\d+\.\d+\.\d+(?:-[a-z0-9.]+)?)/;
561
571
  function detectInstalledAgents() {
562
572
  return Object.entries(targets).filter(([_, config]) => config.detectInstalled()).map(([type]) => type);
563
573
  }
@@ -588,7 +598,7 @@ function getAgentVersion(agentType) {
588
598
  });
589
599
  if (result.status !== 0) return null;
590
600
  const output = (result.stdout || "").trim();
591
- const match = output.match(/v?(\d+\.\d+\.\d+(?:-[a-z0-9.]+)?)/);
601
+ const match = output.match(STATIC_REGEX_1);
592
602
  return match ? match[1] : output.split("\n")[0];
593
603
  } catch {
594
604
  return null;