skilld 1.2.3 → 1.3.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 (57) hide show
  1. package/README.md +21 -20
  2. package/dist/_chunks/agent.mjs +471 -17
  3. package/dist/_chunks/agent.mjs.map +1 -1
  4. package/dist/_chunks/assemble.mjs +2 -2
  5. package/dist/_chunks/assemble.mjs.map +1 -1
  6. package/dist/_chunks/cache.mjs +8 -2
  7. package/dist/_chunks/cache.mjs.map +1 -1
  8. package/dist/_chunks/cache2.mjs +2 -2
  9. package/dist/_chunks/cache2.mjs.map +1 -1
  10. package/dist/_chunks/cli-helpers.mjs +421 -0
  11. package/dist/_chunks/cli-helpers.mjs.map +1 -0
  12. package/dist/_chunks/detect.mjs +51 -22
  13. package/dist/_chunks/detect.mjs.map +1 -1
  14. package/dist/_chunks/detect2.mjs +2 -0
  15. package/dist/_chunks/embedding-cache.mjs +13 -4
  16. package/dist/_chunks/embedding-cache.mjs.map +1 -1
  17. package/dist/_chunks/formatting.mjs +1 -286
  18. package/dist/_chunks/formatting.mjs.map +1 -1
  19. package/dist/_chunks/index.d.mts.map +1 -1
  20. package/dist/_chunks/install.mjs +4 -3
  21. package/dist/_chunks/install.mjs.map +1 -1
  22. package/dist/_chunks/list.mjs +3 -2
  23. package/dist/_chunks/list.mjs.map +1 -1
  24. package/dist/_chunks/pool.mjs +3 -2
  25. package/dist/_chunks/pool.mjs.map +1 -1
  26. package/dist/_chunks/prompts.mjs +38 -4
  27. package/dist/_chunks/prompts.mjs.map +1 -1
  28. package/dist/_chunks/search-interactive.mjs +3 -2
  29. package/dist/_chunks/search-interactive.mjs.map +1 -1
  30. package/dist/_chunks/search.mjs +4 -3
  31. package/dist/_chunks/search.mjs.map +1 -1
  32. package/dist/_chunks/setup.mjs +27 -0
  33. package/dist/_chunks/setup.mjs.map +1 -0
  34. package/dist/_chunks/shared.mjs +6 -2
  35. package/dist/_chunks/shared.mjs.map +1 -1
  36. package/dist/_chunks/skills.mjs +1 -1
  37. package/dist/_chunks/sources.mjs +1 -1
  38. package/dist/_chunks/sync.mjs +389 -108
  39. package/dist/_chunks/sync.mjs.map +1 -1
  40. package/dist/_chunks/uninstall.mjs +16 -2
  41. package/dist/_chunks/uninstall.mjs.map +1 -1
  42. package/dist/agent/index.d.mts +22 -4
  43. package/dist/agent/index.d.mts.map +1 -1
  44. package/dist/agent/index.mjs +3 -3
  45. package/dist/cli.mjs +619 -328
  46. package/dist/cli.mjs.map +1 -1
  47. package/dist/retriv/index.d.mts +18 -3
  48. package/dist/retriv/index.d.mts.map +1 -1
  49. package/dist/retriv/index.mjs +30 -1
  50. package/dist/retriv/index.mjs.map +1 -1
  51. package/dist/retriv/worker.d.mts +2 -0
  52. package/dist/retriv/worker.d.mts.map +1 -1
  53. package/dist/retriv/worker.mjs +1 -0
  54. package/dist/retriv/worker.mjs.map +1 -1
  55. package/dist/sources/index.mjs +1 -1
  56. package/package.json +3 -2
  57. package/dist/_chunks/chunk.mjs +0 -15
@@ -1,289 +1,4 @@
1
- import { n as yamlParseKV, r as yamlUnescape, t as yamlEscape } from "./yaml.mjs";
2
- import { a as targets, i as getAgentVersion, n as detectTargetAgent, t as detectInstalledAgents } from "./detect.mjs";
3
- import { o as getModelName } from "./agent.mjs";
4
- import { homedir } from "node:os";
5
- import { join } from "pathe";
6
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
7
- import { fileURLToPath } from "node:url";
8
1
  import * as p from "@clack/prompts";
9
- import { detectCurrentAgent } from "unagent/env";
10
- import { dirname as dirname$1, resolve as resolve$1 } from "node:path";
11
- //#region src/core/config.ts
12
- const defaultFeatures = {
13
- search: true,
14
- issues: true,
15
- discussions: true,
16
- releases: true
17
- };
18
- const CONFIG_DIR = join(homedir(), ".skilld");
19
- const CONFIG_PATH = join(CONFIG_DIR, "config.yaml");
20
- function hasConfig() {
21
- return existsSync(CONFIG_PATH);
22
- }
23
- /** Whether the first-run wizard has been completed (not just agent selection) */
24
- function hasCompletedWizard() {
25
- if (!existsSync(CONFIG_PATH)) return false;
26
- const config = readConfig();
27
- return config.features !== void 0 || config.model !== void 0 || config.skipLlm !== void 0;
28
- }
29
- function readConfig() {
30
- if (!existsSync(CONFIG_PATH)) return {};
31
- const content = readFileSync(CONFIG_PATH, "utf-8");
32
- const config = {};
33
- let inBlock = null;
34
- const projects = [];
35
- const features = {};
36
- for (const line of content.split("\n")) {
37
- if (line.startsWith("projects:")) {
38
- inBlock = "projects";
39
- continue;
40
- }
41
- if (line.startsWith("features:")) {
42
- inBlock = "features";
43
- continue;
44
- }
45
- if (inBlock === "projects") {
46
- if (line.startsWith(" - ")) {
47
- projects.push(yamlUnescape(line.slice(4)));
48
- continue;
49
- }
50
- inBlock = null;
51
- }
52
- if (inBlock === "features") {
53
- const m = line.match(/^ {2}(\w+):\s*(.+)/);
54
- if (m) {
55
- const key = m[1];
56
- if (key in defaultFeatures) features[key] = m[2] === "true";
57
- continue;
58
- }
59
- inBlock = null;
60
- }
61
- const kv = yamlParseKV(line);
62
- if (!kv) continue;
63
- const [key, value] = kv;
64
- if (key === "model" && value) config.model = value;
65
- if (key === "agent" && value) config.agent = value;
66
- if (key === "skipLlm") config.skipLlm = value === "true";
67
- }
68
- if (projects.length > 0) config.projects = projects;
69
- if (Object.keys(features).length > 0) config.features = {
70
- ...defaultFeatures,
71
- ...features
72
- };
73
- return config;
74
- }
75
- function writeConfig(config) {
76
- mkdirSync(CONFIG_DIR, {
77
- recursive: true,
78
- mode: 448
79
- });
80
- let yaml = "";
81
- if (config.model) yaml += `model: ${config.model}\n`;
82
- if (config.agent) yaml += `agent: ${config.agent}\n`;
83
- if (config.skipLlm) yaml += `skipLlm: true\n`;
84
- if (config.features) {
85
- yaml += "features:\n";
86
- for (const [k, v] of Object.entries(config.features)) yaml += ` ${k}: ${v}\n`;
87
- }
88
- if (config.projects?.length) {
89
- yaml += "projects:\n";
90
- for (const p of config.projects) yaml += ` - ${yamlEscape(p)}\n`;
91
- }
92
- writeFileSync(CONFIG_PATH, yaml, { mode: 384 });
93
- }
94
- function updateConfig(updates) {
95
- writeConfig({
96
- ...readConfig(),
97
- ...updates
98
- });
99
- }
100
- function registerProject(projectPath) {
101
- const config = readConfig();
102
- const projects = new Set(config.projects || []);
103
- projects.add(projectPath);
104
- writeConfig({
105
- ...config,
106
- projects: [...projects]
107
- });
108
- }
109
- function unregisterProject(projectPath) {
110
- const config = readConfig();
111
- const projects = (config.projects || []).filter((p) => p !== projectPath);
112
- writeConfig({
113
- ...config,
114
- projects
115
- });
116
- }
117
- function getRegisteredProjects() {
118
- return readConfig().projects || [];
119
- }
120
- //#endregion
121
- //#region src/version.ts
122
- function findPackageJson() {
123
- let dir = dirname$1(fileURLToPath(import.meta.url));
124
- for (let i = 0; i < 5; i++) {
125
- const candidate = resolve$1(dir, "package.json");
126
- try {
127
- const content = readFileSync(candidate, "utf8");
128
- if (content) return content;
129
- } catch {}
130
- dir = resolve$1(dir, "..");
131
- }
132
- return "{\"version\":\"0.0.0\"}";
133
- }
134
- const version = JSON.parse(findPackageJson()).version;
135
- //#endregion
136
- //#region src/cli-helpers.ts
137
- const sharedArgs = {
138
- global: {
139
- type: "boolean",
140
- alias: "g",
141
- description: "Install globally to ~/.skilld/skills",
142
- default: false
143
- },
144
- agent: {
145
- type: "enum",
146
- options: Object.keys(targets),
147
- alias: "a",
148
- description: "Agent where skills are installed"
149
- },
150
- model: {
151
- type: "string",
152
- alias: "m",
153
- description: "LLM model for skill generation",
154
- valueHint: "id"
155
- },
156
- yes: {
157
- type: "boolean",
158
- alias: "y",
159
- description: "Skip prompts, use defaults",
160
- default: false
161
- },
162
- force: {
163
- type: "boolean",
164
- alias: "f",
165
- description: "Ignore all caches, re-fetch docs and regenerate",
166
- default: false
167
- },
168
- debug: {
169
- type: "boolean",
170
- description: "Save raw LLM output to logs/ for each section",
171
- default: false
172
- }
173
- };
174
- /** Check if the current environment supports interactive prompts */
175
- function isInteractive() {
176
- if (detectCurrentAgent()) return false;
177
- if (process.env.CI) return false;
178
- if (!process.stdout.isTTY) return false;
179
- return true;
180
- }
181
- /** Exit with error if interactive terminal is required but unavailable */
182
- function requireInteractive(command) {
183
- if (!isInteractive()) {
184
- console.error(`Error: \`skilld ${command}\` requires an interactive terminal`);
185
- process.exit(1);
186
- }
187
- }
188
- /** Resolve agent from flags/cwd/config. cwd is source of truth over config. */
189
- function resolveAgent(agentFlag) {
190
- if (process.env.SKILLD_NO_AGENT) return null;
191
- return agentFlag ?? detectTargetAgent() ?? readConfig().agent ?? null;
192
- }
193
- let _warnedNoAgent = false;
194
- function warnNoAgent() {
195
- if (_warnedNoAgent) return;
196
- _warnedNoAgent = true;
197
- p.log.warn("No coding agent detected — falling back to prompt-only mode.\n Use --agent <name> to specify, or run `skilld config` to set a default.");
198
- }
199
- /** Prompt user to pick an agent when auto-detection fails */
200
- async function promptForAgent() {
201
- const installed = !!process.env.SKILLD_NO_AGENT ? [] : detectInstalledAgents();
202
- if (!isInteractive()) {
203
- if (installed.length === 1) {
204
- updateConfig({ agent: installed[0] });
205
- return installed[0];
206
- }
207
- warnNoAgent();
208
- return "none";
209
- }
210
- const options = (installed.length ? installed : Object.keys(targets)).map((id) => ({
211
- label: targets[id].displayName,
212
- value: id,
213
- hint: targets[id].skillsDir
214
- }));
215
- options.push({
216
- label: "No agent",
217
- value: "none",
218
- hint: "Export portable prompts for any LLM"
219
- });
220
- if (!_warnedNoAgent) {
221
- _warnedNoAgent = true;
222
- const hint = installed.length ? `Detected ${installed.map((t) => targets[t].displayName).join(", ")} but couldn't determine which to use` : "No agents auto-detected";
223
- p.log.warn(`Could not detect which coding agent to install skills for.\n ${hint}`);
224
- }
225
- const choice = await p.select({
226
- message: "Which coding agent should skills be installed for?",
227
- options
228
- });
229
- if (p.isCancel(choice)) return null;
230
- if (choice === "none") return "none";
231
- updateConfig({ agent: choice });
232
- p.log.success(`Default agent set to ${targets[choice].displayName}`);
233
- return choice;
234
- }
235
- /** Get installed LLM generators with working CLIs (verified via --version) */
236
- function getInstalledGenerators() {
237
- return detectInstalledAgents().filter((id) => targets[id].cli).map((id) => {
238
- const ver = getAgentVersion(id);
239
- return ver ? {
240
- name: targets[id].displayName,
241
- version: ver
242
- } : null;
243
- }).filter((a) => a !== null);
244
- }
245
- function relativeTime(date) {
246
- const diff = Date.now() - date.getTime();
247
- const mins = Math.floor(diff / 6e4);
248
- const hours = Math.floor(diff / 36e5);
249
- const days = Math.floor(diff / 864e5);
250
- if (mins < 1) return "just now";
251
- if (mins < 60) return `${mins}m ago`;
252
- if (hours < 24) return `${hours}h ago`;
253
- return `${days}d ago`;
254
- }
255
- function getLastSynced(state) {
256
- let latest = null;
257
- for (const skill of state.skills) if (skill.info?.syncedAt) {
258
- const d = new Date(skill.info.syncedAt);
259
- if (!latest || d > latest) latest = d;
260
- }
261
- return latest ? relativeTime(latest) : null;
262
- }
263
- function introLine({ state, generators, modelId }) {
264
- const name = "\x1B[1m\x1B[35mskilld\x1B[0m";
265
- const ver = `\x1B[90mv${version}\x1B[0m`;
266
- const lastSynced = getLastSynced(state);
267
- const synced = lastSynced ? ` · \x1B[90msynced ${lastSynced}\x1B[0m` : "";
268
- const modelStr = modelId ? ` · ${getModelName(modelId)}` : "";
269
- const genStr = generators?.length ? generators.map((g) => `${g.name} v${g.version}`).join(", ") : "";
270
- return `${name} ${ver}${synced}${genStr ? `\n\x1B[90m↳ ${genStr}${modelStr}\x1B[0m` : ""}`;
271
- }
272
- function formatStatus(synced, outdated) {
273
- const parts = [];
274
- if (synced > 0) parts.push(`\x1B[32m${synced} synced\x1B[0m`);
275
- if (outdated > 0) parts.push(`\x1B[33m${outdated} outdated\x1B[0m`);
276
- return `Skills: ${parts.join(" · ")}`;
277
- }
278
- function getRepoHint(name, cwd) {
279
- const pkgJsonPath = join(cwd, "node_modules", name, "package.json");
280
- if (!existsSync(pkgJsonPath)) return void 0;
281
- const pkg = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
282
- const url = typeof pkg.repository === "string" ? pkg.repository : pkg.repository?.url;
283
- if (!url) return void 0;
284
- return url.replace(/^git\+/, "").replace(/\.git$/, "").replace(/^git:\/\//, "https://").replace(/^ssh:\/\/git@github\.com/, "https://github.com").replace(/^https?:\/\/(www\.)?github\.com\//, "");
285
- }
286
- //#endregion
287
2
  //#region src/core/formatting.ts
288
3
  function timeAgo(iso) {
289
4
  if (!iso) return "";
@@ -368,6 +83,6 @@ function formatCompactSnippet(r, cols) {
368
83
  };
369
84
  }
370
85
  //#endregion
371
- export { hasCompletedWizard as C, unregisterProject as D, registerProject as E, updateConfig as O, getRegisteredProjects as S, readConfig as T, requireInteractive as _, highlightTerms as a, version as b, timeAgo as c, getInstalledGenerators as d, getRepoHint as f, relativeTime as g, promptForAgent as h, formatSource as i, timedSpinner as l, isInteractive as m, formatDuration as n, normalizeScores as o, introLine as p, formatSnippet as r, scoreLabel as s, formatCompactSnippet as t, formatStatus as u, resolveAgent as v, hasConfig as w, defaultFeatures as x, sharedArgs as y };
86
+ export { highlightTerms as a, timeAgo as c, formatSource as i, timedSpinner as l, formatDuration as n, normalizeScores as o, formatSnippet as r, scoreLabel as s, formatCompactSnippet as t };
372
87
 
373
88
  //# sourceMappingURL=formatting.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"formatting.mjs","names":["dirname","resolve","agents"],"sources":["../../src/core/config.ts","../../src/version.ts","../../src/cli-helpers.ts","../../src/core/formatting.ts"],"sourcesContent":["import type { OptimizeModel } from '../agent/index.ts'\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { yamlEscape, yamlParseKV, yamlUnescape } from './yaml.ts'\n\nexport interface FeaturesConfig {\n search: boolean\n issues: boolean\n discussions: boolean\n releases: boolean\n}\n\nexport const defaultFeatures: FeaturesConfig = {\n search: true,\n issues: true,\n discussions: true,\n releases: true,\n}\n\nexport interface SkilldConfig {\n model?: OptimizeModel\n agent?: string\n features?: FeaturesConfig\n projects?: string[]\n skipLlm?: boolean\n}\n\nconst CONFIG_DIR = join(homedir(), '.skilld')\nconst CONFIG_PATH = join(CONFIG_DIR, 'config.yaml')\n\nexport function hasConfig(): boolean {\n return existsSync(CONFIG_PATH)\n}\n\n/** Whether the first-run wizard has been completed (not just agent selection) */\nexport function hasCompletedWizard(): boolean {\n if (!existsSync(CONFIG_PATH))\n return false\n const config = readConfig()\n return config.features !== undefined || config.model !== undefined || config.skipLlm !== undefined\n}\n\nexport function readConfig(): SkilldConfig {\n if (!existsSync(CONFIG_PATH))\n return {}\n\n const content = readFileSync(CONFIG_PATH, 'utf-8')\n const config: SkilldConfig = {}\n let inBlock: 'projects' | 'features' | null = null\n const projects: string[] = []\n const features: Partial<FeaturesConfig> = {}\n\n for (const line of content.split('\\n')) {\n if (line.startsWith('projects:')) {\n inBlock = 'projects'\n continue\n }\n if (line.startsWith('features:')) {\n inBlock = 'features'\n continue\n }\n if (inBlock === 'projects') {\n if (line.startsWith(' - ')) {\n projects.push(yamlUnescape(line.slice(4)))\n continue\n }\n inBlock = null\n }\n if (inBlock === 'features') {\n const m = line.match(/^ {2}(\\w+):\\s*(.+)/)\n if (m) {\n const key = m[1] as keyof FeaturesConfig\n if (key in defaultFeatures)\n features[key] = m[2] === 'true'\n continue\n }\n inBlock = null\n }\n const kv = yamlParseKV(line)\n if (!kv)\n continue\n const [key, value] = kv\n if (key === 'model' && value)\n config.model = value as OptimizeModel\n if (key === 'agent' && value)\n config.agent = value\n if (key === 'skipLlm')\n config.skipLlm = value === 'true'\n }\n\n if (projects.length > 0)\n config.projects = projects\n if (Object.keys(features).length > 0)\n config.features = { ...defaultFeatures, ...features }\n return config\n}\n\nexport function writeConfig(config: SkilldConfig): void {\n mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 })\n\n let yaml = ''\n if (config.model)\n yaml += `model: ${config.model}\\n`\n if (config.agent)\n yaml += `agent: ${config.agent}\\n`\n if (config.skipLlm)\n yaml += `skipLlm: true\\n`\n if (config.features) {\n yaml += 'features:\\n'\n for (const [k, v] of Object.entries(config.features)) {\n yaml += ` ${k}: ${v}\\n`\n }\n }\n if (config.projects?.length) {\n yaml += 'projects:\\n'\n for (const p of config.projects) {\n yaml += ` - ${yamlEscape(p)}\\n`\n }\n }\n\n writeFileSync(CONFIG_PATH, yaml, { mode: 0o600 })\n}\n\nexport function updateConfig(updates: Partial<SkilldConfig>): void {\n const config = readConfig()\n writeConfig({ ...config, ...updates })\n}\n\nexport function registerProject(projectPath: string): void {\n const config = readConfig()\n const projects = new Set(config.projects || [])\n projects.add(projectPath)\n writeConfig({ ...config, projects: [...projects] })\n}\n\nexport function unregisterProject(projectPath: string): void {\n const config = readConfig()\n const projects = (config.projects || []).filter(p => p !== projectPath)\n writeConfig({ ...config, projects })\n}\n\nexport function getRegisteredProjects(): string[] {\n return readConfig().projects || []\n}\n","import { readFileSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\n// Walk up from current file to find package.json (works in both src/ and dist/_chunks/)\nfunction findPackageJson(): string {\n let dir = dirname(fileURLToPath(import.meta.url))\n for (let i = 0; i < 5; i++) {\n const candidate = resolve(dir, 'package.json')\n try {\n const content = readFileSync(candidate, 'utf8')\n if (content)\n return content\n }\n catch {}\n dir = resolve(dir, '..')\n }\n return '{\"version\":\"0.0.0\"}'\n}\n\nexport const version: string = JSON.parse(findPackageJson()).version\n","/**\n * Shared CLI helpers used by subcommand definitions and the main CLI entry.\n * Extracted to avoid circular deps between cli.ts and commands/*.ts.\n */\n\nimport type { AgentType, OptimizeModel } from './agent/index.ts'\nimport type { ProjectState } from './core/skills.ts'\nimport { existsSync, readFileSync } from 'node:fs'\nimport * as p from '@clack/prompts'\nimport { join } from 'pathe'\nimport { detectCurrentAgent } from 'unagent/env'\nimport { agents, detectInstalledAgents, detectTargetAgent, getAgentVersion, getModelName } from './agent/index.ts'\nimport { readConfig, updateConfig } from './core/config.ts'\nimport { version } from './version.ts'\n\nexport type { AgentType, OptimizeModel }\n\nexport interface IntroOptions {\n state: ProjectState\n generators?: Array<{ name: string, version: string }>\n modelId?: string\n}\n\nexport const sharedArgs = {\n global: {\n type: 'boolean' as const,\n alias: 'g',\n description: 'Install globally to ~/.skilld/skills',\n default: false,\n },\n agent: {\n type: 'enum' as const,\n options: Object.keys(agents),\n alias: 'a',\n description: 'Agent where skills are installed',\n },\n model: {\n type: 'string' as const,\n alias: 'm',\n description: 'LLM model for skill generation',\n valueHint: 'id',\n },\n yes: {\n type: 'boolean' as const,\n alias: 'y',\n description: 'Skip prompts, use defaults',\n default: false,\n },\n force: {\n type: 'boolean' as const,\n alias: 'f',\n description: 'Ignore all caches, re-fetch docs and regenerate',\n default: false,\n },\n debug: {\n type: 'boolean' as const,\n description: 'Save raw LLM output to logs/ for each section',\n default: false,\n },\n}\n\n/** Check if the current environment supports interactive prompts */\nexport function isInteractive(): boolean {\n if (detectCurrentAgent())\n return false\n if (process.env.CI)\n return false\n if (!process.stdout.isTTY)\n return false\n return true\n}\n\n/** Exit with error if interactive terminal is required but unavailable */\nexport function requireInteractive(command: string): void {\n if (!isInteractive()) {\n console.error(`Error: \\`skilld ${command}\\` requires an interactive terminal`)\n process.exit(1)\n }\n}\n\n/** Resolve agent from flags/cwd/config. cwd is source of truth over config. */\nexport function resolveAgent(agentFlag?: string): AgentType | 'none' | null {\n if (process.env.SKILLD_NO_AGENT)\n return null\n return (agentFlag as AgentType | undefined)\n ?? detectTargetAgent()\n ?? (readConfig().agent as AgentType | undefined)\n ?? null\n}\n\nlet _warnedNoAgent = false\nfunction warnNoAgent(): void {\n if (_warnedNoAgent)\n return\n _warnedNoAgent = true\n p.log.warn('No coding agent detected — falling back to prompt-only mode.\\n Use --agent <name> to specify, or run `skilld config` to set a default.')\n}\n\n/** Prompt user to pick an agent when auto-detection fails */\nexport async function promptForAgent(): Promise<AgentType | 'none' | null> {\n const noAgent = !!process.env.SKILLD_NO_AGENT\n const installed = noAgent ? [] : detectInstalledAgents()\n\n // Non-interactive: auto-select sole installed agent or fall back to prompt-only\n if (!isInteractive()) {\n if (installed.length === 1) {\n updateConfig({ agent: installed[0] })\n return installed[0]!\n }\n warnNoAgent()\n return 'none'\n }\n\n const options: Array<{ label: string, value: AgentType | 'none', hint?: string }> = (installed.length ? installed : Object.keys(agents) as AgentType[])\n .map(id => ({ label: agents[id].displayName, value: id as AgentType, hint: agents[id].skillsDir }))\n options.push({ label: 'No agent', value: 'none', hint: 'Export portable prompts for any LLM' })\n\n if (!_warnedNoAgent) {\n _warnedNoAgent = true\n const hint = installed.length\n ? `Detected ${installed.map(t => agents[t].displayName).join(', ')} but couldn't determine which to use`\n : 'No agents auto-detected'\n p.log.warn(`Could not detect which coding agent to install skills for.\\n ${hint}`)\n }\n\n const choice = await p.select({\n message: 'Which coding agent should skills be installed for?',\n options,\n })\n\n if (p.isCancel(choice))\n return null\n\n if (choice === 'none')\n return 'none'\n\n // Save as default so they don't get asked again\n updateConfig({ agent: choice })\n p.log.success(`Default agent set to ${agents[choice].displayName}`)\n return choice\n}\n\n/** Get installed LLM generators with working CLIs (verified via --version) */\nexport function getInstalledGenerators(): Array<{ name: string, version: string }> {\n const installed = detectInstalledAgents()\n return installed\n .filter(id => agents[id].cli)\n .map((id) => {\n const ver = getAgentVersion(id)\n return ver ? { name: agents[id].displayName, version: ver } : null\n })\n .filter((a): a is { name: string, version: string } => a !== null)\n}\n\nexport function relativeTime(date: Date): string {\n const now = Date.now()\n const diff = now - date.getTime()\n const mins = Math.floor(diff / 60000)\n const hours = Math.floor(diff / 3600000)\n const days = Math.floor(diff / 86400000)\n if (mins < 1)\n return 'just now'\n if (mins < 60)\n return `${mins}m ago`\n if (hours < 24)\n return `${hours}h ago`\n return `${days}d ago`\n}\n\nexport function getLastSynced(state: ProjectState): string | null {\n let latest: Date | null = null\n for (const skill of state.skills) {\n if (skill.info?.syncedAt) {\n const d = new Date(skill.info.syncedAt)\n if (!latest || d > latest)\n latest = d\n }\n }\n return latest ? relativeTime(latest) : null\n}\n\nexport function introLine({ state, generators, modelId }: IntroOptions): string {\n const name = '\\x1B[1m\\x1B[35mskilld\\x1B[0m'\n const ver = `\\x1B[90mv${version}\\x1B[0m`\n const lastSynced = getLastSynced(state)\n const synced = lastSynced ? ` · \\x1B[90msynced ${lastSynced}\\x1B[0m` : ''\n const modelStr = modelId ? ` · ${getModelName(modelId as any)}` : ''\n const genStr = generators?.length\n ? generators.map(g => `${g.name} v${g.version}`).join(', ')\n : ''\n const genLine = genStr ? `\\n\\x1B[90m↳ ${genStr}${modelStr}\\x1B[0m` : ''\n return `${name} ${ver}${synced}${genLine}`\n}\n\nexport function formatStatus(synced: number, outdated: number): string {\n const parts: string[] = []\n if (synced > 0)\n parts.push(`\\x1B[32m${synced} synced\\x1B[0m`)\n if (outdated > 0)\n parts.push(`\\x1B[33m${outdated} outdated\\x1B[0m`)\n return `Skills: ${parts.join(' · ')}`\n}\n\nexport function getRepoHint(name: string, cwd: string): string | undefined {\n const pkgJsonPath = join(cwd, 'node_modules', name, 'package.json')\n if (!existsSync(pkgJsonPath))\n return undefined\n const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'))\n const url = typeof pkg.repository === 'string'\n ? pkg.repository\n : pkg.repository?.url\n if (!url)\n return undefined\n return url\n .replace(/^git\\+/, '')\n .replace(/\\.git$/, '')\n .replace(/^git:\\/\\//, 'https://')\n .replace(/^ssh:\\/\\/git@github\\.com/, 'https://github.com')\n .replace(/^https?:\\/\\/(www\\.)?github\\.com\\//, '')\n}\n","import type { SearchSnippet } from '../retriv/index.ts'\nimport type { ProjectState } from './skills.ts'\nimport * as p from '@clack/prompts'\n\nexport function timeAgo(iso?: string): string {\n if (!iso)\n return ''\n const diff = Date.now() - new Date(iso).getTime()\n const days = Math.floor(diff / 86400000)\n if (days <= 0)\n return 'today'\n if (days === 1)\n return '1d ago'\n if (days < 7)\n return `${days}d ago`\n if (days < 30)\n return `${Math.floor(days / 7)}w ago`\n return `${Math.floor(days / 30)}mo ago`\n}\n\nexport function formatSource(source?: string): string {\n if (!source)\n return ''\n if (source === 'shipped')\n return 'shipped'\n if (source.includes('llms.txt'))\n return 'llms.txt'\n if (source.includes('github.com'))\n return source.replace(/https?:\\/\\/github\\.com\\//, '')\n return source\n}\n\nexport function formatDuration(ms: number): string {\n if (ms < 1000)\n return `${Math.round(ms)}ms`\n return `${(ms / 1000).toFixed(1)}s`\n}\n\n/** Spinner wrapper that shows elapsed time via built-in timer indicator */\nexport function timedSpinner() {\n const spin = p.spinner({ indicator: 'timer' })\n return {\n start(msg: string) {\n spin.start(msg)\n },\n message(msg: string) {\n spin.message(msg)\n },\n stop(msg: string) {\n spin.stop(msg)\n },\n }\n}\n\nexport function formatSkillStatus(state: ProjectState): void {\n const { missing, outdated, synced } = state\n\n if (synced.length > 0)\n p.log.success(`${synced.length} synced`)\n if (outdated.length > 0)\n p.log.warn(`${outdated.length} outdated: ${outdated.map(s => s.name).join(', ')}`)\n if (missing.length > 0)\n p.log.info(`${missing.length} missing: ${missing.slice(0, 5).join(', ')}${missing.length > 5 ? '...' : ''}`)\n}\n\nexport function highlightTerms(content: string, terms: string[]): string {\n if (terms.length === 0)\n return content\n // Sort by length desc to match longer terms first\n const sorted = terms.toSorted((a, b) => b.length - a.length)\n const pattern = new RegExp(`(${sorted.map(t => t.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('|')})`, 'gi')\n return content.replace(pattern, '\\x1B[33m$1\\x1B[0m')\n}\n\n/** Format a normalized score (0-100) with color */\nexport function scoreLabel(pct: number): string {\n const color = pct >= 70 ? '\\x1B[32m' : pct >= 40 ? '\\x1B[33m' : '\\x1B[90m'\n return `${color}${pct}%\\x1B[0m`\n}\n\n/** Normalize raw cosine similarity scores to 0-100 relative to the best match */\nexport function normalizeScores(results: SearchSnippet[]): Map<SearchSnippet, number> {\n const map = new Map<SearchSnippet, number>()\n const max = results.reduce((m, r) => Math.max(m, r.score), 0)\n for (const r of results)\n map.set(r, max > 0 ? Math.round((r.score / max) * 100) : 0)\n return map\n}\n\nexport function formatSnippet(r: SearchSnippet, versions?: Map<string, string>, pct?: number): string {\n const refPath = `.claude/skills/${r.package}/.skilld/${r.source}`\n const lineRange = r.lineStart === r.lineEnd ? `L${r.lineStart}` : `L${r.lineStart}-${r.lineEnd}`\n const score = pct != null ? scoreLabel(pct) : `\\x1B[90m${r.score.toFixed(2)}\\x1B[0m`\n const version = versions?.get(r.package)\n const pkgLabel = version ? `${r.package}@${version}` : r.package\n\n const scopeStr = r.scope?.length ? `${r.scope.map(e => e.name).join('.')} → ` : ''\n const entityStr = r.entities?.map(e => e.signature || `${e.type} ${e.name}`).join(', ')\n const highlighted = highlightTerms(r.content, r.highlights)\n\n return [\n `${pkgLabel} ${score}${entityStr ? ` \\x1B[36m${scopeStr}${entityStr}\\x1B[0m` : ''}`,\n `\\x1B[90m${refPath}:${lineRange}\\x1B[0m`,\n ` ${highlighted.replace(/\\n/g, '\\n ')}`,\n ].join('\\n')\n}\n\n/** Compact 2-line format for interactive search list */\nexport function formatCompactSnippet(r: SearchSnippet, cols: number): { title: string, path: string, preview: string } {\n const entityStr = r.entities?.length\n ? r.entities.map(e => e.signature || e.name).join(', ')\n : ''\n const scopeStr = r.scope?.length ? `${r.scope.map(e => e.name).join('.')} → ` : ''\n const title = entityStr ? `${scopeStr}${entityStr}` : r.source.split('/').pop() || r.source\n\n const refPath = `.claude/skills/${r.package}/.skilld/${r.source}`\n const lineRange = r.lineStart === r.lineEnd ? `L${r.lineStart}` : `L${r.lineStart}-${r.lineEnd}`\n const path = `${refPath}:${lineRange}`\n\n // First meaningful line as preview (skip empty, frontmatter delimiters, headings-only)\n const maxPreview = cols - 6\n const firstLine = r.content.split('\\n').find(l => l.trim() && l.trim() !== '---' && !/^#+\\s*$/.test(l.trim())) || ''\n const preview = firstLine.length > maxPreview ? `${firstLine.slice(0, maxPreview - 1)}…` : firstLine\n\n return { title, path, preview }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"formatting.mjs","names":[],"sources":["../../src/core/formatting.ts"],"sourcesContent":["import type { SearchSnippet } from '../retriv/index.ts'\nimport type { ProjectState } from './skills.ts'\nimport * as p from '@clack/prompts'\n\nexport function timeAgo(iso?: string): string {\n if (!iso)\n return ''\n const diff = Date.now() - new Date(iso).getTime()\n const days = Math.floor(diff / 86400000)\n if (days <= 0)\n return 'today'\n if (days === 1)\n return '1d ago'\n if (days < 7)\n return `${days}d ago`\n if (days < 30)\n return `${Math.floor(days / 7)}w ago`\n return `${Math.floor(days / 30)}mo ago`\n}\n\nexport function formatSource(source?: string): string {\n if (!source)\n return ''\n if (source === 'shipped')\n return 'shipped'\n if (source.includes('llms.txt'))\n return 'llms.txt'\n if (source.includes('github.com'))\n return source.replace(/https?:\\/\\/github\\.com\\//, '')\n return source\n}\n\nexport function formatDuration(ms: number): string {\n if (ms < 1000)\n return `${Math.round(ms)}ms`\n return `${(ms / 1000).toFixed(1)}s`\n}\n\n/** Spinner wrapper that shows elapsed time via built-in timer indicator */\nexport function timedSpinner() {\n const spin = p.spinner({ indicator: 'timer' })\n return {\n start(msg: string) {\n spin.start(msg)\n },\n message(msg: string) {\n spin.message(msg)\n },\n stop(msg: string) {\n spin.stop(msg)\n },\n }\n}\n\nexport function formatSkillStatus(state: ProjectState): void {\n const { missing, outdated, synced } = state\n\n if (synced.length > 0)\n p.log.success(`${synced.length} synced`)\n if (outdated.length > 0)\n p.log.warn(`${outdated.length} outdated: ${outdated.map(s => s.name).join(', ')}`)\n if (missing.length > 0)\n p.log.info(`${missing.length} missing: ${missing.slice(0, 5).join(', ')}${missing.length > 5 ? '...' : ''}`)\n}\n\nexport function highlightTerms(content: string, terms: string[]): string {\n if (terms.length === 0)\n return content\n // Sort by length desc to match longer terms first\n const sorted = terms.toSorted((a, b) => b.length - a.length)\n const pattern = new RegExp(`(${sorted.map(t => t.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('|')})`, 'gi')\n return content.replace(pattern, '\\x1B[33m$1\\x1B[0m')\n}\n\n/** Format a normalized score (0-100) with color */\nexport function scoreLabel(pct: number): string {\n const color = pct >= 70 ? '\\x1B[32m' : pct >= 40 ? '\\x1B[33m' : '\\x1B[90m'\n return `${color}${pct}%\\x1B[0m`\n}\n\n/** Normalize raw cosine similarity scores to 0-100 relative to the best match */\nexport function normalizeScores(results: SearchSnippet[]): Map<SearchSnippet, number> {\n const map = new Map<SearchSnippet, number>()\n const max = results.reduce((m, r) => Math.max(m, r.score), 0)\n for (const r of results)\n map.set(r, max > 0 ? Math.round((r.score / max) * 100) : 0)\n return map\n}\n\nexport function formatSnippet(r: SearchSnippet, versions?: Map<string, string>, pct?: number): string {\n const refPath = `.claude/skills/${r.package}/.skilld/${r.source}`\n const lineRange = r.lineStart === r.lineEnd ? `L${r.lineStart}` : `L${r.lineStart}-${r.lineEnd}`\n const score = pct != null ? scoreLabel(pct) : `\\x1B[90m${r.score.toFixed(2)}\\x1B[0m`\n const version = versions?.get(r.package)\n const pkgLabel = version ? `${r.package}@${version}` : r.package\n\n const scopeStr = r.scope?.length ? `${r.scope.map(e => e.name).join('.')} → ` : ''\n const entityStr = r.entities?.map(e => e.signature || `${e.type} ${e.name}`).join(', ')\n const highlighted = highlightTerms(r.content, r.highlights)\n\n return [\n `${pkgLabel} ${score}${entityStr ? ` \\x1B[36m${scopeStr}${entityStr}\\x1B[0m` : ''}`,\n `\\x1B[90m${refPath}:${lineRange}\\x1B[0m`,\n ` ${highlighted.replace(/\\n/g, '\\n ')}`,\n ].join('\\n')\n}\n\n/** Compact 2-line format for interactive search list */\nexport function formatCompactSnippet(r: SearchSnippet, cols: number): { title: string, path: string, preview: string } {\n const entityStr = r.entities?.length\n ? r.entities.map(e => e.signature || e.name).join(', ')\n : ''\n const scopeStr = r.scope?.length ? `${r.scope.map(e => e.name).join('.')} → ` : ''\n const title = entityStr ? `${scopeStr}${entityStr}` : r.source.split('/').pop() || r.source\n\n const refPath = `.claude/skills/${r.package}/.skilld/${r.source}`\n const lineRange = r.lineStart === r.lineEnd ? `L${r.lineStart}` : `L${r.lineStart}-${r.lineEnd}`\n const path = `${refPath}:${lineRange}`\n\n // First meaningful line as preview (skip empty, frontmatter delimiters, headings-only)\n const maxPreview = cols - 6\n const firstLine = r.content.split('\\n').find(l => l.trim() && l.trim() !== '---' && !/^#+\\s*$/.test(l.trim())) || ''\n const preview = firstLine.length > maxPreview ? `${firstLine.slice(0, maxPreview - 1)}…` : firstLine\n\n return { title, path, preview }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/cache/config.ts","../../src/cache/types.ts","../../src/cache/storage.ts","../../src/cache/version.ts"],"mappings":";;AASA;;;cAAa,SAAA;;cAGA,cAAA;;cAGA,SAAA;;iBAGG,eAAA,CAAgB,KAAA,UAAe,IAAA;AAH/C;AAAA,iBAUgB,gBAAA,CAAiB,IAAA,UAAc,OAAA;;;;AAhB/C;;UCLiB,WAAA;EDKkC;ECHjD,IAAA;EDMW;ECJX,OAAA;AAAA;AAAA,UAGe,aAAA;EACf,IAAA;EACA,OAAA;EACA,GAAA;AAAA;AAAA,UAGe,SAAA;EACf,IAAA;EACA,OAAA;AAAA;;;;;ADPF;iBEiBgB,QAAA,CAAS,IAAA,UAAc,OAAA;;;;iBAOvB,cAAA,CAAA;;;;iBAQA,YAAA,CACd,IAAA,UACA,OAAA,UACA,IAAA,EAAM,SAAA;AF7BR;;;AAAA,iBE8CgB,gBAAA,CACd,KAAA,UACA,IAAA,UACA,IAAA,EAAM,SAAA;;AF1CR;;;iBE4DgB,iBAAA,CAAkB,QAAA,UAAkB,KAAA,UAAe,IAAA,UAAc,MAAA;;;;;ADjFjF;;;;;iBCuGgB,aAAA,CAAc,QAAA,UAAkB,IAAA,UAAc,OAAA,UAAiB,MAAA;;;;;iBAiB/D,aAAA,CAAc,IAAA,UAAc,GAAA,UAAa,OAAA;;;;AD3GzD;;;;;iBCkIgB,OAAA,CAAQ,QAAA,UAAkB,IAAA,UAAc,GAAA,UAAa,OAAA;;;AAtHrE;;;;;iBA4IgB,YAAA,CAAa,QAAA,UAAkB,IAAA,UAAc,GAAA,UAAa,OAAA;;;;;iBAmB1D,cAAA,CAAe,IAAA,UAAc,GAAA,UAAa,OAAA;;;;UAmCzC,YAAA;EACf,SAAA;EACA,QAAA;AAAA;;;AAjKF;iBAuKgB,gBAAA,CAAiB,IAAA,UAAc,GAAA,UAAa,OAAA,YAAmB,YAAA;;;;;;;iBAoB/D,aAAA,CAAc,IAAA,UAAc,OAAA,UAAiB,QAAA,EAAU,KAAA;EAAQ,IAAA;EAAc,OAAA;AAAA;;;;iBAY7E,iBAAA,CAAkB,IAAA,UAAc,OAAA,UAAiB,IAAA;;;;iBAUjD,gBAAA,CAAiB,OAAA,UAAiB,SAAA,UAAmB,SAAA;AAAA,iBAWrD,cAAA,CAAe,IAAA,UAAc,GAAA,UAAa,OAAA;;;;iBAiB1C,UAAA,CAAA,GAAc,aAAA;;;;iBAed,cAAA,CAAe,IAAA,UAAc,OAAA,WAAkB,SAAA;;AAhM/D;;iBA+NgB,UAAA,CAAW,IAAA,UAAc,OAAA;;;;iBAYzB,aAAA,CAAA;;;AApNhB;;iBAmOgB,kBAAA,CAAmB,QAAA,UAAkB,QAAA;;;;AF7WrD;;;;;iBGOgB,aAAA,CAAc,OAAA;;;;iBAOd,WAAA,CAAY,IAAA,UAAc,OAAA;AHR1C;;;;AAAA,iBGgBgB,WAAA,CAAY,IAAA,UAAc,OAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/cache/config.ts","../../src/cache/types.ts","../../src/cache/storage.ts","../../src/cache/version.ts"],"mappings":";;AASA;;;cAAa,SAAA;;cAGA,cAAA;;cAGA,SAAA;;iBAGG,eAAA,CAAgB,KAAA,UAAe,IAAA;AAH/C;AAAA,iBAUgB,gBAAA,CAAiB,IAAA,UAAc,OAAA;;;;AAhB/C;;UCLiB,WAAA;EDKkC;ECHjD,IAAA;EDMW;ECJX,OAAA;AAAA;AAAA,UAGe,aAAA;EACf,IAAA;EACA,OAAA;EACA,GAAA;AAAA;AAAA,UAGe,SAAA;EACf,IAAA;EACA,OAAA;AAAA;;;;;ADPF;iBEiBgB,QAAA,CAAS,IAAA,UAAc,OAAA;;;;iBAOvB,cAAA,CAAA;;;;iBAQA,YAAA,CACd,IAAA,UACA,OAAA,UACA,IAAA,EAAM,SAAA;AF7BR;;;AAAA,iBE8CgB,gBAAA,CACd,KAAA,UACA,IAAA,UACA,IAAA,EAAM,SAAA;;AF1CR;;;iBE4DgB,iBAAA,CAAkB,QAAA,UAAkB,KAAA,UAAe,IAAA,UAAc,MAAA;;;;;ADjFjF;;;;;iBCuGgB,aAAA,CAAc,QAAA,UAAkB,IAAA,UAAc,OAAA,UAAiB,MAAA;;;;;iBAiB/D,aAAA,CAAc,IAAA,UAAc,GAAA,UAAa,OAAA;;;;AD3GzD;;;;;iBCkIgB,OAAA,CAAQ,QAAA,UAAkB,IAAA,UAAc,GAAA,UAAa,OAAA;;;AAtHrE;;;;;iBA8IgB,YAAA,CAAa,QAAA,UAAkB,IAAA,UAAc,GAAA,UAAa,OAAA;;;;;iBAsB1D,cAAA,CAAe,IAAA,UAAc,GAAA,UAAa,OAAA;;;;UAmCzC,YAAA;EACf,SAAA;EACA,QAAA;AAAA;;;AAtKF;iBA4KgB,gBAAA,CAAiB,IAAA,UAAc,GAAA,UAAa,OAAA,YAAmB,YAAA;;;;;;;iBAoB/D,aAAA,CAAc,IAAA,UAAc,OAAA,UAAiB,QAAA,EAAU,KAAA;EAAQ,IAAA;EAAc,OAAA;AAAA;;;;iBAY7E,iBAAA,CAAkB,IAAA,UAAc,OAAA,UAAiB,IAAA;;;;iBAUjD,gBAAA,CAAiB,OAAA,UAAiB,SAAA,UAAmB,SAAA;AAAA,iBAWrD,cAAA,CAAe,IAAA,UAAc,GAAA,UAAa,OAAA;;;;iBAiB1C,UAAA,CAAA,GAAc,aAAA;;;;iBAed,cAAA,CAAe,IAAA,UAAc,OAAA,WAAkB,SAAA;;AArM/D;;iBAoOgB,UAAA,CAAW,IAAA,UAAc,OAAA;;;;iBAYzB,aAAA,CAAA;;;AAzNhB;;iBAwOgB,kBAAA,CAAmB,QAAA,UAAkB,QAAA;;;;AFlXrD;;;;;iBGOgB,aAAA,CAAc,OAAA;;;;iBAOd,WAAA,CAAY,IAAA,UAAc,OAAA;AHR1C;;;;AAAA,iBGgBgB,WAAA,CAAY,IAAA,UAAc,OAAA"}
@@ -1,3 +1,4 @@
1
+ import { a as getModelLabel, r as createToolProgress, s as optimizeDocs } from "./agent.mjs";
1
2
  import { a as getRepoCacheDir, i as getPackageDbPath, o as getCacheDir } from "./config.mjs";
2
3
  import { n as sanitizeMarkdown } from "./sanitize.mjs";
3
4
  import { _ as resolvePkgDir, a as getShippedSkills, f as linkShippedSkill, h as readCachedDocs, i as getPkgKeyFiles, m as listReferenceFiles, o as hasShippedDocs, r as ensureCacheDir, s as isCached, u as linkPkgNamed, y as writeToCache } from "./cache.mjs";
@@ -8,9 +9,9 @@ import { n as getSharedSkillsDir } from "./shared.mjs";
8
9
  import { C as downloadLlmsDocs, D as normalizeLlmsLinks, M as resolveEntryFiles, T as fetchLlmsTxt, Z as fetchGitHubRaw, b as isShallowGitDocs, d as resolvePackageDocs, h as fetchGitDocs, k as fetchGitSkills, tt as parseGitHubUrl, v as fetchReadmeContent, y as filterFrameworkDocs } from "./sources.mjs";
9
10
  import { a as targets } from "./detect.mjs";
10
11
  import { i as linkSkillToAgents, t as generateSkillMd } from "./prompts.mjs";
11
- import { a as getModelLabel, r as createToolProgress, s as optimizeDocs } from "./agent.mjs";
12
- import { T as readConfig, h as promptForAgent, l as timedSpinner, v as resolveAgent, x as defaultFeatures, y as sharedArgs } from "./formatting.mjs";
12
+ import { S as readConfig, f as promptForAgent, g as sharedArgs, h as resolveAgent, v as defaultFeatures } from "./cli-helpers.mjs";
13
13
  import { a as mergeLocks, l as syncLockfilesToDirs, o as parsePackages, s as readLock, u as writeLock } from "./skills.mjs";
14
+ import { l as timedSpinner } from "./formatting.mjs";
14
15
  import { n as shutdownWorker } from "./pool.mjs";
15
16
  import { a as selectLlmConfig, i as indexResources, o as writePromptFiles, r as classifyCachedDoc } from "./sync.mjs";
16
17
  import { homedir } from "node:os";
@@ -472,7 +473,7 @@ async function enhanceRegenerated(pkgName, version, skillDir, model, sections, c
472
473
  features
473
474
  });
474
475
  writeFileSync(join(skillDir, "SKILL.md"), skillMd);
475
- } else llmLog.error("LLM optimization skipped");
476
+ } else llmLog.message("Enhancement skipped");
476
477
  }
477
478
  const installCommandDef = defineCommand({
478
479
  meta: {
@@ -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, readFileSync, 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 { 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}` })\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 let dependencies: Record<string, string> | undefined\n if (pkgPath) {\n const pkgJsonPath = join(pkgPath, 'package.json')\n if (existsSync(pkgJsonPath)) {\n const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'))\n description = pkg.description\n dependencies = pkg.dependencies\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 dependencies,\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.error('LLM optimization 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 let dependencies: Record<string, string> | undefined\n if (pkgPath) {\n const pkgJsonPath = join(pkgPath, 'package.json')\n if (existsSync(pkgJsonPath)) {\n const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'))\n description = pkg.description\n dependencies = pkg.dependencies\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 dependencies,\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","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, readFileSync, 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 { 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}` })\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 let dependencies: Record<string, string> | undefined\n if (pkgPath) {\n const pkgJsonPath = join(pkgPath, 'package.json')\n if (existsSync(pkgJsonPath)) {\n const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'))\n description = pkg.description\n dependencies = pkg.dependencies\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 dependencies,\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 let dependencies: Record<string, string> | undefined\n if (pkgPath) {\n const pkgJsonPath = join(pkgPath, 'package.json')\n if (existsSync(pkgJsonPath)) {\n const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'))\n description = pkg.description\n dependencies = pkg.dependencies\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 dependencies,\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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"}