skilld 1.5.1 → 1.5.2

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 (47) hide show
  1. package/dist/_chunks/assemble.mjs +1 -0
  2. package/dist/_chunks/assemble.mjs.map +1 -1
  3. package/dist/_chunks/author.mjs +10 -10
  4. package/dist/_chunks/author.mjs.map +1 -1
  5. package/dist/_chunks/cache.mjs +4 -3
  6. package/dist/_chunks/cache.mjs.map +1 -1
  7. package/dist/_chunks/cache2.mjs +1 -0
  8. package/dist/_chunks/cache2.mjs.map +1 -1
  9. package/dist/_chunks/cli-helpers.mjs +26 -75
  10. package/dist/_chunks/cli-helpers.mjs.map +1 -1
  11. package/dist/_chunks/cli-helpers2.mjs +2 -1
  12. package/dist/_chunks/embedding-cache.mjs +1 -0
  13. package/dist/_chunks/index.d.mts.map +1 -1
  14. package/dist/_chunks/index3.d.mts.map +1 -1
  15. package/dist/_chunks/install.mjs +7 -6
  16. package/dist/_chunks/install.mjs.map +1 -1
  17. package/dist/_chunks/list.mjs +2 -1
  18. package/dist/_chunks/list.mjs.map +1 -1
  19. package/dist/_chunks/lockfile.mjs +14 -1
  20. package/dist/_chunks/lockfile.mjs.map +1 -1
  21. package/dist/_chunks/package-json.mjs +107 -0
  22. package/dist/_chunks/package-json.mjs.map +1 -0
  23. package/dist/_chunks/prepare2.mjs +2 -1
  24. package/dist/_chunks/prepare2.mjs.map +1 -1
  25. package/dist/_chunks/search-interactive.mjs +1 -0
  26. package/dist/_chunks/search-interactive.mjs.map +1 -1
  27. package/dist/_chunks/search.mjs +1 -0
  28. package/dist/_chunks/search2.mjs +1 -1
  29. package/dist/_chunks/setup.mjs +2 -1
  30. package/dist/_chunks/setup.mjs.map +1 -1
  31. package/dist/_chunks/sources.mjs +15 -18
  32. package/dist/_chunks/sources.mjs.map +1 -1
  33. package/dist/_chunks/sync-shared.mjs +1 -0
  34. package/dist/_chunks/sync-shared2.mjs +5 -4
  35. package/dist/_chunks/sync-shared2.mjs.map +1 -1
  36. package/dist/_chunks/sync.mjs +1 -1
  37. package/dist/_chunks/sync2.mjs +1 -0
  38. package/dist/_chunks/uninstall.mjs +2 -1
  39. package/dist/_chunks/uninstall.mjs.map +1 -1
  40. package/dist/_chunks/wizard.mjs +1 -1
  41. package/dist/agent/index.mjs +1 -0
  42. package/dist/cache/index.mjs +1 -0
  43. package/dist/cli.mjs +16 -5
  44. package/dist/cli.mjs.map +1 -1
  45. package/dist/index.mjs +1 -0
  46. package/dist/sources/index.mjs +1 -0
  47. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"cli-helpers.mjs","names":["dirname","resolve","agents"],"sources":["../../src/core/config.ts","../../src/core/package-json.ts","../../src/version.ts","../../src/cli-helpers.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, writeFileSync } from 'node:fs'\nimport { applyEdits, modify, parseTree } from 'jsonc-parser'\n\nexport interface EditOptions {\n /** Formatting options for inserted content */\n tabSize?: number\n insertSpaces?: boolean\n}\n\nconst defaultEditOptions: EditOptions = { tabSize: 2, insertSpaces: true }\n\n/**\n * Set a value at a JSON path, preserving all surrounding formatting.\n * Returns the modified file content as a string.\n */\nexport function editJsonProperty(raw: string, path: (string | number)[], value: unknown, options?: EditOptions): string {\n const opts = { ...defaultEditOptions, ...options }\n const edits = modify(raw, path, value, {\n formattingOptions: { tabSize: opts.tabSize!, insertSpaces: opts.insertSpaces! },\n })\n return applyEdits(raw, edits)\n}\n\n/**\n * Remove a value at a JSON path, preserving all surrounding formatting.\n */\nexport function removeJsonProperty(raw: string, path: (string | number)[]): string {\n const edits = modify(raw, path, undefined, {})\n return applyEdits(raw, edits)\n}\n\n/**\n * Read a package.json, apply an edit function, and write it back.\n * The edit function receives the raw text and parsed object,\n * and returns the new raw text (or null to skip writing).\n */\nexport function patchPackageJson(\n pkgPath: string,\n editFn: (raw: string, pkg: Record<string, unknown>) => string | null,\n): boolean {\n const raw = readFileSync(pkgPath, 'utf-8')\n const pkg = JSON.parse(raw)\n const result = editFn(raw, pkg)\n if (result === null)\n return false\n writeFileSync(pkgPath, result)\n return true\n}\n\n/**\n * Append a value to a JSON array at the given path, preserving formatting.\n * Inserts in sorted order if the array contains strings.\n */\nexport function appendToJsonArray(raw: string, path: string[], value: string, options?: EditOptions): string {\n const opts = { ...defaultEditOptions, ...options }\n const tree = parseTree(raw)\n if (!tree)\n return editJsonProperty(raw, path, [value], opts)\n\n // Walk to the target array node\n let node = tree\n for (const key of path) {\n const child = node.children?.find(c =>\n c.type === 'property' && c.children?.[0]?.value === key,\n )\n if (!child?.children?.[1])\n return editJsonProperty(raw, path, [value], opts)\n node = child.children[1]\n }\n\n if (node.type !== 'array' || !node.children)\n return editJsonProperty(raw, path, [value], opts)\n\n // Find sorted insertion index (only for string-only arrays)\n const allStrings = node.children.every(c => typeof c.value === 'string')\n let idx = node.children.length\n if (allStrings) {\n const items = node.children.map(c => c.value as string)\n for (let i = 0; i < items.length; i++) {\n if (value.localeCompare(items[i]!) < 0) {\n idx = i\n break\n }\n }\n }\n\n const edits = modify(raw, [...path, idx], value, {\n formattingOptions: { tabSize: opts.tabSize!, insertSpaces: opts.insertSpaces! },\n isArrayInsertion: true,\n })\n return applyEdits(raw, edits)\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 { parseTree } from 'jsonc-parser'\nimport { join } from 'pathe'\nimport { detectCurrentAgent } from 'unagent/env'\nimport { agents, detectInstalledAgents, detectProjectAgents, detectTargetAgent, getAgentVersion, getModelName } from './agent/index.ts'\nimport { readConfig, updateConfig } from './core/config.ts'\nimport { editJsonProperty, patchPackageJson } from './core/package-json.ts'\nimport { version } from './version.ts'\n\nexport type { AgentType, OptimizeModel }\n\nexport interface IntroOptions {\n state: ProjectState\n /** Installed CLIs that can serve as enhancement models */\n generators?: Array<{ name: string, version: string }>\n /** Configured enhancement model ID */\n modelId?: string\n /** Resolved target agent ID */\n agentId?: string\n}\n\nexport const sharedArgs = {\n global: {\n type: 'boolean' as const,\n alias: 'g',\n description: 'Install globally to ~/<agent>/skills',\n default: false,\n },\n agent: {\n type: 'enum' as const,\n options: Object.keys(agents),\n alias: 'a',\n description: 'Target agent — where skills are installed',\n },\n model: {\n type: 'string' as const,\n alias: 'm',\n description: 'Enhancement model for SKILL.md 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 enhancement output to logs/ for each section',\n default: false,\n },\n}\n\n// ── Menu loop utility ─────────────────────────────────────────────────\n\n/** Thrown when a clack prompt is cancelled inside a menuLoop handler */\nexport class MenuCancel extends Error { override name = 'MenuCancel' }\n\n/** Assert a clack prompt result is not cancelled. Throws MenuCancel if cancelled. */\nexport function guard<T>(value: T | symbol): T {\n if (p.isCancel(value))\n throw new MenuCancel()\n return value as T\n}\n\nexport interface MenuOption {\n label: string\n value: string\n hint?: string\n}\n\n/**\n * Run a select menu in a loop with automatic back-navigation.\n *\n * - Cancel (Escape) at the menu itself → exits (returns)\n * - Cancel inside a handler (via guard()) → caught, loops back to menu\n * - Handler returns truthy → exits (returns)\n * - Handler returns void/false → loops back to menu\n *\n * Options are rebuilt each iteration so hints stay fresh after changes.\n */\nexport async function menuLoop(opts: {\n message: string\n options: () => MenuOption[] | Promise<MenuOption[]>\n onSelect: (value: string) => Promise<boolean | void>\n initialValue?: string | (() => string | undefined)\n /** Use fuzzy-searchable autocomplete instead of static select */\n searchable?: boolean\n}): Promise<void> {\n while (true) {\n const options = await opts.options()\n const initial = typeof opts.initialValue === 'function' ? opts.initialValue() : opts.initialValue\n const choice = opts.searchable\n ? await p.autocomplete({ message: opts.message, options, ...(initial != null ? { initialValue: initial } : {}) })\n : await p.select({ message: opts.message, options, ...(initial != null ? { initialValue: initial } : {}) })\n if (p.isCancel(choice))\n return\n try {\n if (await opts.onSelect(choice as string))\n return\n }\n catch (err) {\n if (err instanceof MenuCancel)\n continue\n throw err\n }\n }\n}\n\n/** Check if we're running inside an AI coding agent */\nexport function isRunningInsideAgent(): boolean {\n return !!detectCurrentAgent()\n}\n\n/** Check if the current environment supports interactive prompts */\nexport function isInteractive(): boolean {\n if (isRunningInsideAgent())\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 target 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 const projectMatches = noAgent ? [] : detectProjectAgents()\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 // Brief context before asking about agents\n p.log.info(\n `Skilld generates reference cards from package docs so your AI agent\\n`\n + ` always has accurate APIs for your exact dependency versions.`,\n )\n\n // Build options: prefer project-matched agents, then installed, then all\n const candidateIds = projectMatches.length > 0\n ? projectMatches\n : installed.length > 0\n ? installed\n : Object.keys(agents) as AgentType[]\n\n // Agents that also read .claude/skills/\n const sharedAgents = new Set(\n Object.entries(agents)\n .filter(([, a]) => a.additionalSkillsDirs.some(d => d.includes('.claude/skills')))\n .map(([id]) => id),\n )\n\n // Group: agents that share skills vs agents with their own directory\n const sharedIds = candidateIds.filter(id => id === 'claude-code' || sharedAgents.has(id))\n const isolatedIds = candidateIds.filter(id => id !== 'claude-code' && !sharedAgents.has(id))\n\n const options: Array<{ label: string, value: AgentType | 'none', hint?: string }> = []\n\n // Show shared-compatible agents first\n if (sharedIds.length > 0 && isolatedIds.length > 0) {\n for (const id of sharedIds) {\n const a = agents[id]\n const hint = id === 'claude-code'\n ? `skills shared with ${sharedIds.length - 1} other agents`\n : `skills shared with Claude Code and others`\n options.push({ label: a.displayName, value: id as AgentType, hint })\n }\n }\n\n // Agents with isolated skill dirs\n const isolatedAgentIds = new Set(\n Object.entries(agents)\n .filter(([, a]) => a.additionalSkillsDirs.length === 0)\n .map(([id]) => id),\n )\n\n for (const id of (sharedIds.length > 0 && isolatedIds.length > 0 ? isolatedIds : candidateIds)) {\n if (options.some(o => o.value === id))\n continue\n const a = agents[id]\n const hint = sharedAgents.has(id) && id !== 'claude-code'\n ? 'skills shared with Claude Code and others'\n : isolatedAgentIds.has(id)\n ? 'skills only visible to this agent'\n : undefined\n options.push({ label: a.displayName, value: id as AgentType, hint })\n }\n\n options.push({ label: 'No agent', value: 'none', hint: 'export as standalone files for any AI' })\n\n if (!_warnedNoAgent) {\n _warnedNoAgent = true\n const hint = projectMatches.length > 1\n ? `Multiple agent directories found: ${projectMatches.map(t => agents[t].displayName).join(', ')}`\n : installed.length > 0\n ? `Found ${installed.map(t => agents[t].displayName).join(', ')} but couldn't determine which to use`\n : 'No agents auto-detected'\n const crossNote = sharedIds.length > 1\n ? `\\n \\x1B[90mTip: Picking Claude Code shares skills with ${sharedIds.filter(id => id !== 'claude-code').map(id => agents[id].displayName).join(', ')} automatically.\\x1B[0m`\n : ''\n p.log.warn(`${hint}\\n Pick the agent you actively code with.${crossNote}`)\n }\n\n const choice = await p.select({\n message: 'Which AI coding agent do you use?',\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(`Target 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, agentId }: 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\n // Status line: enhancement model → target agent\n const parts: string[] = []\n if (modelId)\n parts.push(getModelName(modelId as any))\n else if (generators?.length)\n parts.push(generators.map(g => `${g.name} v${g.version}`).join(', '))\n if (agentId && agents[agentId as AgentType])\n parts.push(agents[agentId as AgentType].displayName)\n const statusLine = parts.length > 0\n ? `\\n\\x1B[90m↳ ${parts.join(' → ')}\\x1B[0m`\n : ''\n\n return `${name} ${ver}${synced}${statusLine}`\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\n// ── Shared UI constants ───────────────────────────────────────────────\n\nexport const OAUTH_NOTE\n = 'Use an existing subscription (Claude Pro, ChatGPT Plus, Gemini)\\n'\n + 'without an API key. You authenticate directly with the provider\\n'\n + 'in your browser - no data leaves your machine.\\n'\n + '\\n'\n + 'A refresh token is stored locally at ~/.skilld/pi-ai-auth.json\\n'\n + 'and used to call the provider API directly from your computer.\\n'\n + '\\x1B[90mOAuth handled by pi-ai, an open-source local client library:\\n'\n + 'https://github.com/badlogic/pi-mono\\x1B[0m'\n\nexport const NO_MODELS_MESSAGE = 'No enhancement models detected.\\n'\n + ' \\x1B[90mSkills work fine without this - you get raw docs, issues, and types.\\n'\n + ' Enhancement compresses them into a concise cheat sheet with gotchas.\\x1B[0m\\n'\n + '\\n'\n + ' To connect a model (optional):\\n'\n + ' 1. Connect a subscription via OAuth below (Claude Pro, ChatGPT Plus, Copilot, Gemini)\\n'\n + ' 2. Set an env var: ANTHROPIC_API_KEY, GEMINI_API_KEY, or OPENAI_API_KEY\\n'\n + ' 3. Install a CLI tool: \\x1B[36mclaude\\x1B[0m, \\x1B[36mgemini\\x1B[0m, or \\x1B[36mcodex\\x1B[0m (restart wizard after)'\n\n/** Group models by vendor for provider→model selection. Uses vendorGroup to merge CLI and API entries under one heading. */\nexport function groupModelsByProvider<T extends { provider: string, providerName: string, vendorGroup?: string }>(models: T[]): Map<string, { name: string, models: T[] }> {\n const byVendor = new Map<string, { name: string, models: T[] }>()\n for (const m of models) {\n const key = m.vendorGroup ?? m.provider\n if (!byVendor.has(key))\n byVendor.set(key, { name: key, models: [] })\n byVendor.get(key)!.models.push(m)\n }\n return byVendor\n}\n\nexport interface ModelPickerOptions {\n /** Extra options prepended (e.g. Auto, Connect OAuth) */\n before?: Array<{ label: string, value: string, hint?: string }>\n /** Extra options appended (e.g. Skip) */\n after?: Array<{ label: string, value: string, hint?: string }>\n}\n\n/**\n * Smart provider→model picker. Skips the provider step when there's only 1 provider.\n * Returns the selected model value, or a sentinel string from before/after options.\n */\nexport async function pickModel<T extends { provider: string, providerName: string, name: string, id: string, hint: string, recommended?: boolean }>(\n models: T[],\n opts: ModelPickerOptions = {},\n): Promise<string | null> {\n const byProvider = groupModelsByProvider(models)\n const before = opts.before ?? []\n const after = opts.after ?? []\n\n // Single provider → skip provider step, show models directly\n if (byProvider.size === 1 && before.length === 0) {\n const [, group] = [...byProvider.entries()][0]!\n const choice = await p.select({\n message: `${group.name}`,\n options: [\n ...group.models.map(m => ({\n label: m.recommended ? `${m.name} (recommended - fast and cheap)` : m.name,\n value: m.id,\n hint: m.hint,\n })),\n ...after,\n ],\n })\n return p.isCancel(choice) ? null : choice as string\n }\n\n // Multiple providers or has before options - two-step\n const providerChoice = await p.select({\n message: 'Select provider',\n options: [\n ...before,\n ...Array.from(byProvider.entries(), ([key, { name, models: ms }]) => ({\n label: name,\n value: key,\n hint: `${ms.length} models`,\n })),\n ...after,\n ],\n })\n\n if (p.isCancel(providerChoice))\n return null\n\n // Check if it's a sentinel from before/after\n const providerStr = providerChoice as string\n if (before.some(o => o.value === providerStr) || after.some(o => o.value === providerStr))\n return providerStr\n\n // Drill into provider's models\n const group = byProvider.get(providerStr)!\n const modelChoice = await p.select({\n message: `Select model (${group.name})`,\n options: group.models.map(m => ({\n label: m.recommended ? `${m.name} (recommended - fast and cheap)` : m.name,\n value: m.id,\n hint: m.hint,\n })),\n })\n\n return p.isCancel(modelChoice) ? null : modelChoice as string\n}\n\n/**\n * Prompt to add `skilld prepare` to package.json \"prepare\" script.\n * In non-interactive environments, falls back to an info log.\n * Returns true if the hook was added or already present.\n */\nexport async function suggestPrepareHook(cwd: string = process.cwd()): Promise<boolean> {\n const pkgJsonPath = join(cwd, 'package.json')\n if (!existsSync(pkgJsonPath))\n return false\n\n const raw = readFileSync(pkgJsonPath, 'utf-8')\n const pkgJson = JSON.parse(raw)\n const rawExisting = pkgJson.scripts?.prepare\n const existing: string | undefined = typeof rawExisting === 'string' ? rawExisting : undefined\n\n if (existing?.includes('skilld'))\n return true\n\n const prepareCmd = buildPrepareScript(existing)\n\n if (!isInteractive()) {\n p.log.info(\n `\\x1B[90mAdd to package.json scripts:\\n`\n + ` \\x1B[36m\"prepare\": \"${prepareCmd}\"\\x1B[0m\\n`\n + ` \\x1B[90mRestores references and shipped skills on install.\\x1B[0m`,\n )\n return false\n }\n\n const confirmed = await p.confirm({\n message: `Add \\x1B[36m\"prepare\": \"${prepareCmd}\"\\x1B[0m to package.json?`,\n initialValue: true,\n })\n if (p.isCancel(confirmed) || !confirmed)\n return false\n\n patchPackageJson(pkgJsonPath, (content) => {\n const tree = parseTree(content)\n const hasScripts = tree?.children?.some(c =>\n c.type === 'property' && c.children?.[0]?.value === 'scripts',\n )\n\n let patched = content\n if (!hasScripts)\n patched = editJsonProperty(patched, ['scripts'], {})\n\n return editJsonProperty(patched, ['scripts', 'prepare'], prepareCmd)\n })\n p.log.success('Added \\x1B[36mskilld prepare\\x1B[0m to package.json')\n return true\n}\n\n/**\n * Build the full prepare script value, safely appending to any existing command.\n */\nexport function buildPrepareScript(existing: string | undefined): string {\n const cmd = 'skilld prepare || true'\n if (!existing || !existing.trim())\n return cmd\n\n const trimmed = existing.trim()\n\n // Strip trailing && or ; that would leave a dangling operator\n const cleaned = trimmed.replace(/[&|;]+\\s*$/, '').trim()\n if (!cleaned)\n return cmd\n\n return `${cleaned} && (${cmd})`\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"],"mappings":"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"}
1
+ {"version":3,"file":"cli-helpers.mjs","names":["dirname","resolve","agents"],"sources":["../../src/core/config.ts","../../src/version.ts","../../src/cli-helpers.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\nlet configCache: SkilldConfig | undefined\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 (configCache) {\n return {\n ...configCache,\n features: configCache.features ? { ...configCache.features } : undefined,\n projects: configCache.projects ? [...configCache.projects] : undefined,\n }\n }\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 configCache = config\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 configCache = undefined\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 * as p from '@clack/prompts'\nimport { parseTree } from 'jsonc-parser'\nimport { join } from 'pathe'\nimport { detectCurrentAgent } from 'unagent/env'\nimport { agents, detectInstalledAgents, detectProjectAgents, detectTargetAgent, getAgentVersion, getModelName } from './agent/index.ts'\nimport { readConfig, updateConfig } from './core/config.ts'\nimport { editJsonProperty, patchPackageJson, readPackageJsonSafe } from './core/package-json.ts'\nimport { version } from './version.ts'\n\nexport type { AgentType, OptimizeModel }\n\nexport interface IntroOptions {\n state: ProjectState\n /** Installed CLIs that can serve as enhancement models */\n generators?: Array<{ name: string, version: string }>\n /** Configured enhancement model ID */\n modelId?: string\n /** Resolved target agent ID */\n agentId?: string\n}\n\nexport const sharedArgs = {\n global: {\n type: 'boolean' as const,\n alias: 'g',\n description: 'Install globally to ~/<agent>/skills',\n default: false,\n },\n agent: {\n type: 'enum' as const,\n options: Object.keys(agents),\n alias: 'a',\n description: 'Target agent — where skills are installed',\n },\n model: {\n type: 'string' as const,\n alias: 'm',\n description: 'Enhancement model for SKILL.md 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 enhancement output to logs/ for each section',\n default: false,\n },\n}\n\n// ── Menu loop utility ─────────────────────────────────────────────────\n\n/** Thrown when a clack prompt is cancelled inside a menuLoop handler */\nexport class MenuCancel extends Error { override name = 'MenuCancel' }\n\n/** Assert a clack prompt result is not cancelled. Throws MenuCancel if cancelled. */\nexport function guard<T>(value: T | symbol): T {\n if (p.isCancel(value))\n throw new MenuCancel()\n return value as T\n}\n\nexport interface MenuOption {\n label: string\n value: string\n hint?: string\n}\n\n/**\n * Run a select menu in a loop with automatic back-navigation.\n *\n * - Cancel (Escape) at the menu itself → exits (returns)\n * - Cancel inside a handler (via guard()) → caught, loops back to menu\n * - Handler returns truthy → exits (returns)\n * - Handler returns void/false → loops back to menu\n *\n * Options are rebuilt each iteration so hints stay fresh after changes.\n */\nexport async function menuLoop(opts: {\n message: string\n options: () => MenuOption[] | Promise<MenuOption[]>\n onSelect: (value: string) => Promise<boolean | void>\n initialValue?: string | (() => string | undefined)\n /** Use fuzzy-searchable autocomplete instead of static select */\n searchable?: boolean\n}): Promise<void> {\n while (true) {\n const options = await opts.options()\n const initial = typeof opts.initialValue === 'function' ? opts.initialValue() : opts.initialValue\n const choice = opts.searchable\n ? await p.autocomplete({ message: opts.message, options, ...(initial != null ? { initialValue: initial } : {}) })\n : await p.select({ message: opts.message, options, ...(initial != null ? { initialValue: initial } : {}) })\n if (p.isCancel(choice))\n return\n try {\n if (await opts.onSelect(choice as string))\n return\n }\n catch (err) {\n if (err instanceof MenuCancel)\n continue\n throw err\n }\n }\n}\n\n/** Check if we're running inside an AI coding agent */\nexport function isRunningInsideAgent(): boolean {\n return !!detectCurrentAgent()\n}\n\n/** Check if the current environment supports interactive prompts */\nexport function isInteractive(): boolean {\n if (isRunningInsideAgent())\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 target 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 const projectMatches = noAgent ? [] : detectProjectAgents()\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 // Brief context before asking about agents\n p.log.info(\n `Skilld generates reference cards from package docs so your AI agent\\n`\n + ` always has accurate APIs for your exact dependency versions.`,\n )\n\n // Build options: prefer project-matched agents, then installed, then all\n const candidateIds = projectMatches.length > 0\n ? projectMatches\n : installed.length > 0\n ? installed\n : Object.keys(agents) as AgentType[]\n\n // Agents that also read .claude/skills/\n const sharedAgents = new Set(\n Object.entries(agents)\n .filter(([, a]) => a.additionalSkillsDirs.some(d => d.includes('.claude/skills')))\n .map(([id]) => id),\n )\n\n // Group: agents that share skills vs agents with their own directory\n const sharedIds = candidateIds.filter(id => id === 'claude-code' || sharedAgents.has(id))\n const isolatedIds = candidateIds.filter(id => id !== 'claude-code' && !sharedAgents.has(id))\n\n const options: Array<{ label: string, value: AgentType | 'none', hint?: string }> = []\n\n // Show shared-compatible agents first\n if (sharedIds.length > 0 && isolatedIds.length > 0) {\n for (const id of sharedIds) {\n const a = agents[id]\n const hint = id === 'claude-code'\n ? `skills shared with ${sharedIds.length - 1} other agents`\n : `skills shared with Claude Code and others`\n options.push({ label: a.displayName, value: id as AgentType, hint })\n }\n }\n\n // Agents with isolated skill dirs\n const isolatedAgentIds = new Set(\n Object.entries(agents)\n .filter(([, a]) => a.additionalSkillsDirs.length === 0)\n .map(([id]) => id),\n )\n\n for (const id of (sharedIds.length > 0 && isolatedIds.length > 0 ? isolatedIds : candidateIds)) {\n if (options.some(o => o.value === id))\n continue\n const a = agents[id]\n const hint = sharedAgents.has(id) && id !== 'claude-code'\n ? 'skills shared with Claude Code and others'\n : isolatedAgentIds.has(id)\n ? 'skills only visible to this agent'\n : undefined\n options.push({ label: a.displayName, value: id as AgentType, hint })\n }\n\n options.push({ label: 'No agent', value: 'none', hint: 'export as standalone files for any AI' })\n\n if (!_warnedNoAgent) {\n _warnedNoAgent = true\n const hint = projectMatches.length > 1\n ? `Multiple agent directories found: ${projectMatches.map(t => agents[t].displayName).join(', ')}`\n : installed.length > 0\n ? `Found ${installed.map(t => agents[t].displayName).join(', ')} but couldn't determine which to use`\n : 'No agents auto-detected'\n const crossNote = sharedIds.length > 1\n ? `\\n \\x1B[90mTip: Picking Claude Code shares skills with ${sharedIds.filter(id => id !== 'claude-code').map(id => agents[id].displayName).join(', ')} automatically.\\x1B[0m`\n : ''\n p.log.warn(`${hint}\\n Pick the agent you actively code with.${crossNote}`)\n }\n\n const choice = await p.select({\n message: 'Which AI coding agent do you use?',\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(`Target 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, agentId }: 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\n // Status line: enhancement model → target agent\n const parts: string[] = []\n if (modelId)\n parts.push(getModelName(modelId as any))\n else if (generators?.length)\n parts.push(generators.map(g => `${g.name} v${g.version}`).join(', '))\n if (agentId && agents[agentId as AgentType])\n parts.push(agents[agentId as AgentType].displayName)\n const statusLine = parts.length > 0\n ? `\\n\\x1B[90m↳ ${parts.join(' → ')}\\x1B[0m`\n : ''\n\n return `${name} ${ver}${synced}${statusLine}`\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\n// ── Shared UI constants ───────────────────────────────────────────────\n\nexport const OAUTH_NOTE\n = 'Use an existing subscription (Claude Pro, ChatGPT Plus, Gemini)\\n'\n + 'without an API key. You authenticate directly with the provider\\n'\n + 'in your browser - no data leaves your machine.\\n'\n + '\\n'\n + 'A refresh token is stored locally at ~/.skilld/pi-ai-auth.json\\n'\n + 'and used to call the provider API directly from your computer.\\n'\n + '\\x1B[90mOAuth handled by pi-ai, an open-source local client library:\\n'\n + 'https://github.com/badlogic/pi-mono\\x1B[0m'\n\nexport const NO_MODELS_MESSAGE = 'No enhancement models detected.\\n'\n + ' \\x1B[90mSkills work fine without this - you get raw docs, issues, and types.\\n'\n + ' Enhancement compresses them into a concise cheat sheet with gotchas.\\x1B[0m\\n'\n + '\\n'\n + ' To connect a model (optional):\\n'\n + ' 1. Connect a subscription via OAuth below (Claude Pro, ChatGPT Plus, Copilot, Gemini)\\n'\n + ' 2. Set an env var: ANTHROPIC_API_KEY, GEMINI_API_KEY, or OPENAI_API_KEY\\n'\n + ' 3. Install a CLI tool: \\x1B[36mclaude\\x1B[0m, \\x1B[36mgemini\\x1B[0m, or \\x1B[36mcodex\\x1B[0m (restart wizard after)'\n\n/** Group models by vendor for provider→model selection. Uses vendorGroup to merge CLI and API entries under one heading. */\nexport function groupModelsByProvider<T extends { provider: string, providerName: string, vendorGroup?: string }>(models: T[]): Map<string, { name: string, models: T[] }> {\n const byVendor = new Map<string, { name: string, models: T[] }>()\n for (const m of models) {\n const key = m.vendorGroup ?? m.provider\n if (!byVendor.has(key))\n byVendor.set(key, { name: key, models: [] })\n byVendor.get(key)!.models.push(m)\n }\n return byVendor\n}\n\nexport interface ModelPickerOptions {\n /** Extra options prepended (e.g. Auto, Connect OAuth) */\n before?: Array<{ label: string, value: string, hint?: string }>\n /** Extra options appended (e.g. Skip) */\n after?: Array<{ label: string, value: string, hint?: string }>\n}\n\n/**\n * Smart provider→model picker. Skips the provider step when there's only 1 provider.\n * Returns the selected model value, or a sentinel string from before/after options.\n */\nexport async function pickModel<T extends { provider: string, providerName: string, name: string, id: string, hint: string, recommended?: boolean }>(\n models: T[],\n opts: ModelPickerOptions = {},\n): Promise<string | null> {\n const byProvider = groupModelsByProvider(models)\n const before = opts.before ?? []\n const after = opts.after ?? []\n\n // Single provider → skip provider step, show models directly\n if (byProvider.size === 1 && before.length === 0) {\n const [, group] = [...byProvider.entries()][0]!\n const choice = await p.select({\n message: `${group.name}`,\n options: [\n ...group.models.map(m => ({\n label: m.recommended ? `${m.name} (recommended - fast and cheap)` : m.name,\n value: m.id,\n hint: m.hint,\n })),\n ...after,\n ],\n })\n return p.isCancel(choice) ? null : choice as string\n }\n\n // Multiple providers or has before options - two-step\n const providerChoice = await p.select({\n message: 'Select provider',\n options: [\n ...before,\n ...Array.from(byProvider.entries(), ([key, { name, models: ms }]) => ({\n label: name,\n value: key,\n hint: `${ms.length} models`,\n })),\n ...after,\n ],\n })\n\n if (p.isCancel(providerChoice))\n return null\n\n // Check if it's a sentinel from before/after\n const providerStr = providerChoice as string\n if (before.some(o => o.value === providerStr) || after.some(o => o.value === providerStr))\n return providerStr\n\n // Drill into provider's models\n const group = byProvider.get(providerStr)!\n const modelChoice = await p.select({\n message: `Select model (${group.name})`,\n options: group.models.map(m => ({\n label: m.recommended ? `${m.name} (recommended - fast and cheap)` : m.name,\n value: m.id,\n hint: m.hint,\n })),\n })\n\n return p.isCancel(modelChoice) ? null : modelChoice as string\n}\n\n/**\n * Check if the prepare hook is already installed in package.json.\n */\nexport function hasPrepareHook(cwd: string = process.cwd()): boolean {\n const pkg = readPackageJsonSafe(join(cwd, 'package.json'))\n if (!pkg)\n return true // no package.json means nothing to suggest\n const existing = (pkg.parsed.scripts as Record<string, unknown> | undefined)?.prepare\n return typeof existing === 'string' && existing.includes('skilld')\n}\n\n/**\n * Prompt to add `skilld prepare` to package.json \"prepare\" script.\n * In non-interactive environments, falls back to an info log.\n * Returns true if the hook was added or already present.\n */\nexport async function suggestPrepareHook(cwd: string = process.cwd()): Promise<boolean> {\n const pkgJsonPath = join(cwd, 'package.json')\n const pkg = readPackageJsonSafe(pkgJsonPath)\n if (!pkg)\n return false\n\n const rawExisting = (pkg.parsed.scripts as Record<string, unknown> | undefined)?.prepare\n const existing: string | undefined = typeof rawExisting === 'string' ? rawExisting : undefined\n\n if (existing?.includes('skilld'))\n return true\n\n const prepareCmd = buildPrepareScript(existing)\n\n if (!isInteractive()) {\n p.log.info(\n `\\x1B[90mAdd to package.json scripts:\\n`\n + ` \\x1B[36m\"prepare\": \"${prepareCmd}\"\\x1B[0m\\n`\n + ` \\x1B[90mRestores references and shipped skills on install.\\x1B[0m`,\n )\n return false\n }\n\n const confirmed = await p.confirm({\n message: `Add \\x1B[36m\"prepare\": \"${prepareCmd}\"\\x1B[0m to package.json?`,\n initialValue: true,\n })\n if (p.isCancel(confirmed) || !confirmed)\n return false\n\n patchPackageJson(pkgJsonPath, (content) => {\n const tree = parseTree(content)\n const hasScripts = tree?.children?.some(c =>\n c.type === 'property' && c.children?.[0]?.value === 'scripts',\n )\n\n let patched = content\n if (!hasScripts)\n patched = editJsonProperty(patched, ['scripts'], {})\n\n return editJsonProperty(patched, ['scripts', 'prepare'], prepareCmd)\n })\n p.log.success('Added \\x1B[36mskilld prepare\\x1B[0m to package.json')\n return true\n}\n\n/**\n * Build the full prepare script value, safely appending to any existing command.\n */\nexport function buildPrepareScript(existing: string | undefined): string {\n const cmd = 'skilld prepare || true'\n if (!existing || !existing.trim())\n return cmd\n\n const trimmed = existing.trim()\n\n // Strip trailing && or ; that would leave a dangling operator\n const cleaned = trimmed.replace(/[&|;]+\\s*$/, '').trim()\n if (!cleaned)\n return cmd\n\n return `${cleaned} && (${cmd})`\n}\n\nexport function getRepoHint(name: string, cwd: string): string | undefined {\n const result = readPackageJsonSafe(join(cwd, 'node_modules', name, 'package.json'))\n if (!result)\n return undefined\n const pkg = result.parsed as Record<string, any>\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"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import "./agent.mjs";
2
2
  import "./config.mjs";
3
+ import "./package-json.mjs";
3
4
  import "./prepare.mjs";
4
5
  import "./sanitize.mjs";
5
6
  import "./cache.mjs";
@@ -7,5 +8,5 @@ import "./yaml.mjs";
7
8
  import "./shared.mjs";
8
9
  import "./detect.mjs";
9
10
  import "./prompts.mjs";
10
- import { x as suggestPrepareHook } from "./cli-helpers.mjs";
11
+ import { S as suggestPrepareHook } from "./cli-helpers.mjs";
11
12
  export { suggestPrepareHook };
@@ -1,4 +1,5 @@
1
1
  import "./config.mjs";
2
+ import "./package-json.mjs";
2
3
  import "./prepare.mjs";
3
4
  import "./sanitize.mjs";
4
5
  import "./cache.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/cache/config.ts","../../src/cache/types.ts","../../src/core/prepare.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;;;;iBCLc,aAAA,CAAc,IAAA,UAAc,GAAA,UAAa,OAAA;AAAA,UAkCxC,YAAA;EACf,SAAA;EACA,QAAA;AAAA;AFhCF;AAAA,iBEoCgB,gBAAA,CAAiB,IAAA,UAAc,GAAA,UAAa,OAAA,YAAmB,YAAA;;iBAe/D,gBAAA,CAAiB,OAAA,UAAiB,SAAA,UAAmB,SAAA;;;;;AFzDrE;iBGkBgB,QAAA,CAAS,IAAA,UAAc,OAAA;;;;iBAOvB,cAAA,CAAA;;;;iBAQA,YAAA,CACd,IAAA,UACA,OAAA,UACA,IAAA,EAAM,SAAA;AH9BR;;;AAAA,iBG+CgB,gBAAA,CACd,KAAA,UACA,IAAA,UACA,IAAA,EAAM,SAAA;;AH3CR;;;iBG6DgB,iBAAA,CAAkB,QAAA,UAAkB,KAAA,UAAe,IAAA,UAAc,MAAA;;;;;AFlFjF;;;;;iBEwGgB,aAAA,CAAc,QAAA,UAAkB,IAAA,UAAc,OAAA,UAAiB,MAAA;;AF3F/E;;;;;;;iBEwHgB,OAAA,CAAQ,QAAA,UAAkB,IAAA,UAAc,GAAA,UAAa,OAAA;AD3HrE;;;;;;;AAAA,iBCmJgB,YAAA,CAAa,QAAA,UAAkB,IAAA,UAAc,GAAA,UAAa,OAAA;;ADjH1E;;;iBCuIgB,cAAA,CAAe,IAAA,UAAc,GAAA,UAAa,OAAA;;ADjI1D;;;;;iBCuKgB,aAAA,CAAc,IAAA,UAAc,OAAA,UAAiB,QAAA,EAAU,KAAA;EAAQ,IAAA;EAAc,OAAA;AAAA;;ADxJ7F;;iBCoKgB,iBAAA,CAAkB,IAAA,UAAc,OAAA,UAAiB,IAAA;AAAA,iBAOjD,cAAA,CAAe,IAAA,UAAc,GAAA,UAAa,OAAA;;;;iBAiB1C,UAAA,CAAA,GAAc,aAAA;;;;iBAed,cAAA,CAAe,IAAA,UAAc,OAAA,WAAkB,SAAA;AAlP/D;;;AAAA,iBAiRgB,UAAA,CAAW,IAAA,UAAc,OAAA;;AA1QzC;;iBAsRgB,aAAA,CAAA;;;AA9QhB;;iBA6RgB,kBAAA,CAAmB,QAAA,UAAkB,QAAA;;;;AHjUrD;;;;;iBIOgB,aAAA,CAAc,OAAA;;;;iBAOd,WAAA,CAAY,IAAA,UAAc,OAAA;AJR1C;;;;AAAA,iBIgBgB,WAAA,CAAY,IAAA,UAAc,OAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/cache/config.ts","../../src/cache/types.ts","../../src/core/prepare.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;;;;iBCLc,aAAA,CAAc,IAAA,UAAc,GAAA,UAAa,OAAA;AAAA,UAkCxC,YAAA;EACf,SAAA;EACA,QAAA;AAAA;AFhCF;AAAA,iBEoCgB,gBAAA,CAAiB,IAAA,UAAc,GAAA,UAAa,OAAA,YAAmB,YAAA;;iBAe/D,gBAAA,CAAiB,OAAA,UAAiB,SAAA,UAAmB,SAAA;;;;;AFzDrE;iBGmBgB,QAAA,CAAS,IAAA,UAAc,OAAA;;;;iBAOvB,cAAA,CAAA;;;;iBAQA,YAAA,CACd,IAAA,UACA,OAAA,UACA,IAAA,EAAM,SAAA;AH/BR;;;AAAA,iBGgDgB,gBAAA,CACd,KAAA,UACA,IAAA,UACA,IAAA,EAAM,SAAA;;AH5CR;;;iBG8DgB,iBAAA,CAAkB,QAAA,UAAkB,KAAA,UAAe,IAAA,UAAc,MAAA;;;;;AFnFjF;;;;;iBEyGgB,aAAA,CAAc,QAAA,UAAkB,IAAA,UAAc,OAAA,UAAiB,MAAA;;AF5F/E;;;;;;;iBEyHgB,OAAA,CAAQ,QAAA,UAAkB,IAAA,UAAc,GAAA,UAAa,OAAA;AD5HrE;;;;;;;AAAA,iBCoJgB,YAAA,CAAa,QAAA,UAAkB,IAAA,UAAc,GAAA,UAAa,OAAA;;ADlH1E;;;iBCwIgB,cAAA,CAAe,IAAA,UAAc,GAAA,UAAa,OAAA;;ADlI1D;;;;;iBCyKgB,aAAA,CAAc,IAAA,UAAc,OAAA,UAAiB,QAAA,EAAU,KAAA;EAAQ,IAAA;EAAc,OAAA;AAAA;;AD1J7F;;iBCsKgB,iBAAA,CAAkB,IAAA,UAAc,OAAA,UAAiB,IAAA;AAAA,iBAOjD,cAAA,CAAe,IAAA,UAAc,GAAA,UAAa,OAAA;;;;iBAiB1C,UAAA,CAAA,GAAc,aAAA;;;;iBAed,cAAA,CAAe,IAAA,UAAc,OAAA,WAAkB,SAAA;AAnP/D;;;AAAA,iBAkRgB,UAAA,CAAW,IAAA,UAAc,OAAA;;AA3QzC;;iBAuRgB,aAAA,CAAA;;;AA/QhB;;iBA8RgB,kBAAA,CAAmB,QAAA,UAAkB,QAAA;;;;AHnUrD;;;;;iBIOgB,aAAA,CAAc,OAAA;;;;iBAOd,WAAA,CAAY,IAAA,UAAc,OAAA;AJR1C;;;;AAAA,iBIgBgB,WAAA,CAAY,IAAA,UAAc,OAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index3.d.mts","names":[],"sources":["../../src/sources/blog-releases.ts","../../src/sources/crawl.ts","../../src/sources/discussions.ts","../../src/sources/docs.ts","../../src/sources/entries.ts","../../src/sources/git-skills.ts","../../src/sources/types.ts","../../src/sources/github.ts","../../src/sources/issues.ts","../../src/sources/llms.ts","../../src/sources/npm.ts","../../src/sources/package-registry.ts","../../src/sources/releases.ts","../../src/sources/utils.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index3.d.mts","names":[],"sources":["../../src/sources/blog-releases.ts","../../src/sources/crawl.ts","../../src/sources/discussions.ts","../../src/sources/docs.ts","../../src/sources/entries.ts","../../src/sources/git-skills.ts","../../src/sources/types.ts","../../src/sources/github.ts","../../src/sources/issues.ts","../../src/sources/llms.ts","../../src/sources/npm.ts","../../src/sources/package-registry.ts","../../src/sources/releases.ts","../../src/sources/utils.ts"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { a as getModelLabel, r as createToolProgress, s as optimizeDocs } from "./agent.mjs";
2
2
  import { a as getRepoCacheDir, i as getPackageDbPath, o as getCacheDir } from "./config.mjs";
3
+ import { i as readPackageJsonSafe } from "./package-json.mjs";
3
4
  import { n as linkShippedSkill, r as resolvePkgDir, t as getShippedSkills } from "./prepare.mjs";
4
5
  import { n as sanitizeMarkdown } from "./sanitize.mjs";
5
6
  import { a as hasShippedDocs, f as listReferenceFiles, g as writeToCache, i as getPkgKeyFiles, l as linkPkgNamed, o as isCached, p as readCachedDocs, r as ensureCacheDir } from "./cache.mjs";
@@ -10,7 +11,7 @@ import { n as getSharedSkillsDir } from "./shared.mjs";
10
11
  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";
11
12
  import { a as targets } from "./detect.mjs";
12
13
  import { i as linkSkillToAgents, t as generateSkillMd } from "./prompts.mjs";
13
- import { T as defaultFeatures, b as sharedArgs, g as promptForAgent, k as readConfig, y as resolveAgent } from "./cli-helpers.mjs";
14
+ import { O as readConfig, _ as promptForAgent, b as resolveAgent, w as defaultFeatures, x as sharedArgs } from "./cli-helpers.mjs";
14
15
  import { i as readLock, n as parsePackages, o as syncLockfilesToDirs, s as writeLock, t as mergeLocks } from "./lockfile.mjs";
15
16
  import "./skills.mjs";
16
17
  import { l as timedSpinner } from "./formatting.mjs";
@@ -20,7 +21,7 @@ import { n as shutdownWorker } from "./pool2.mjs";
20
21
  import "./sync.mjs";
21
22
  import { homedir } from "node:os";
22
23
  import { dirname, join } from "pathe";
23
- import { copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
24
+ import { copyFileSync, existsSync, lstatSync, mkdirSync, readdirSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
24
25
  import * as p from "@clack/prompts";
25
26
  import { defineCommand } from "citty";
26
27
  //#region src/commands/install.ts
@@ -446,8 +447,8 @@ async function enhanceRegenerated(pkgName, version, skillDir, model, sections, c
446
447
  const pkgPath = resolvePkgDir(pkgName, cwd, version);
447
448
  let description;
448
449
  if (pkgPath) {
449
- const pkgJsonPath = join(pkgPath, "package.json");
450
- if (existsSync(pkgJsonPath)) description = JSON.parse(readFileSync(pkgJsonPath, "utf-8")).description;
450
+ const pkgJsonResult = readPackageJsonSafe(join(pkgPath, "package.json"));
451
+ if (pkgJsonResult) description = pkgJsonResult.parsed.description;
451
452
  }
452
453
  let docsType = "docs";
453
454
  if (existsSync(join(globalCachePath, "docs", "llms.txt"))) docsType = "llms.txt";
@@ -504,8 +505,8 @@ function regenerateBaseSkillMd(skillDir, pkgName, version, cwd, allSkillNames, s
504
505
  const pkgPath = resolvePkgDir(pkgName, cwd, version);
505
506
  let description;
506
507
  if (pkgPath) {
507
- const pkgJsonPath = join(pkgPath, "package.json");
508
- if (existsSync(pkgJsonPath)) description = JSON.parse(readFileSync(pkgJsonPath, "utf-8")).description;
508
+ const pkgResult = readPackageJsonSafe(join(pkgPath, "package.json"));
509
+ if (pkgResult) description = pkgResult.parsed.description;
509
510
  }
510
511
  const globalCachePath = getCacheDir(pkgName, version);
511
512
  let docsType = "docs";
@@ -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 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 }\n }\n\n let docsType: 'llms.txt' | 'readme' | 'docs' = 'docs'\n if (existsSync(join(globalCachePath, 'docs', 'llms.txt')))\n docsType = 'llms.txt'\n else if (isReadmeOnly(globalCachePath))\n docsType = 'readme'\n\n // Derive dirName from the skill directory name\n const dirName = skillDir.split('/').pop()\n\n const allPackages = parsePackages(packages).map(p => ({ name: p.name }))\n const skillMd = generateSkillMd({\n name: pkgName,\n version,\n description,\n body: optimized,\n relatedSkills: [],\n hasIssues,\n hasDiscussions,\n hasReleases,\n docsType,\n hasShippedDocs: checkShippedDocs(pkgName, cwd, version),\n pkgFiles: getPkgKeyFiles(pkgName, cwd, version),\n dirName,\n packages: allPackages.length > 1 ? allPackages : undefined,\n features,\n })\n writeFileSync(join(skillDir, 'SKILL.md'), skillMd)\n }\n else {\n llmLog.message('Enhancement skipped')\n }\n}\n\nexport const installCommandDef = defineCommand({\n meta: { name: 'install', description: 'Restore references from lockfile' },\n args: {\n global: sharedArgs.global,\n agent: sharedArgs.agent,\n },\n async run({ args }) {\n let agent = resolveAgent(args.agent)\n if (!agent || agent === 'none') {\n if (agent === 'none')\n return\n const picked = await promptForAgent()\n if (!picked || picked === 'none')\n return\n agent = picked\n }\n\n p.intro(`\\x1B[1m\\x1B[35mskilld\\x1B[0m install`)\n return installCommand({ global: args.global, agent })\n },\n})\n\n/** Regenerate base SKILL.md from local metadata if missing */\nfunction regenerateBaseSkillMd(\n skillDir: string,\n pkgName: string,\n version: string,\n cwd: string,\n allSkillNames: string[],\n source?: string,\n packages?: string,\n): boolean {\n const skillMdPath = join(skillDir, 'SKILL.md')\n if (existsSync(skillMdPath))\n return false\n\n // Read description + deps from local package.json\n const pkgPath = resolvePkgDir(pkgName, cwd, version)\n let description: string | undefined\n if (pkgPath) {\n const pkgJsonPath = join(pkgPath, 'package.json')\n if (existsSync(pkgJsonPath)) {\n const pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'))\n description = pkg.description\n }\n }\n\n // Infer docsType from source or cache\n const globalCachePath = getCacheDir(pkgName, version)\n let docsType: 'llms.txt' | 'readme' | 'docs' = 'docs'\n if (source?.includes('llms.txt') || existsSync(join(globalCachePath, 'docs', 'llms.txt')))\n docsType = 'llms.txt'\n else if (isReadmeOnly(globalCachePath))\n docsType = 'readme'\n\n // Check cache dirs for issues/discussions/releases (only if feature enabled)\n const feat = readConfig().features ?? defaultFeatures\n const hasIssues = feat.issues && existsSync(join(globalCachePath, 'issues'))\n const hasDiscussions = feat.discussions && existsSync(join(globalCachePath, 'discussions'))\n const hasReleases = feat.releases && existsSync(join(globalCachePath, 'releases'))\n\n // Related skills from other lockfile entries\n const relatedSkills = allSkillNames.filter(n => n !== pkgName)\n\n // Derive dirName from the skill directory name (lockfile key)\n const dirName = skillDir.split('/').pop()\n\n // Build multi-package list from lockfile packages field\n const allPackages = parsePackages(packages).map(p => ({ name: p.name }))\n\n const content = generateSkillMd({\n name: pkgName,\n version,\n description,\n relatedSkills,\n hasIssues,\n hasDiscussions,\n hasReleases,\n docsType,\n hasShippedDocs: checkShippedDocs(pkgName, cwd, version),\n pkgFiles: getPkgKeyFiles(pkgName, cwd, version),\n dirName,\n packages: allPackages.length > 1 ? allPackages : undefined,\n features: readConfig().features ?? defaultFeatures,\n })\n\n mkdirSync(skillDir, { recursive: true })\n writeFileSync(skillMdPath, content)\n return true\n}\n\n/** Check if .skilld/ has broken symlinks or is missing expected references from global cache */\nfunction hasStaleReferences(referencesPath: string, pkgName: string, version: string, features: FeaturesConfig): boolean {\n // Scan existing entries for broken symlinks\n for (const entry of readdirSync(referencesPath)) {\n const entryPath = join(referencesPath, entry)\n if (lstatSync(entryPath).isSymbolicLink() && !existsSync(entryPath))\n return true\n }\n\n // Check pkg link always expected\n if (!existsSync(join(referencesPath, 'pkg')))\n return true\n\n // Check expected links against global cache\n const globalCachePath = getCacheDir(pkgName, version)\n const expected: Array<[string, boolean]> = [\n ['docs', existsSync(join(globalCachePath, 'docs'))],\n ['issues', features.issues && existsSync(join(globalCachePath, 'issues'))],\n ['discussions', features.discussions && existsSync(join(globalCachePath, 'discussions'))],\n ['releases', features.releases && existsSync(join(globalCachePath, 'releases'))],\n ['sections', existsSync(join(globalCachePath, 'sections'))],\n ]\n\n for (const [name, shouldExist] of expected) {\n if (shouldExist && !existsSync(join(referencesPath, name)))\n return true\n }\n\n return false\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"install.mjs","names":["agents","checkShippedDocs"],"sources":["../../src/commands/install.ts"],"sourcesContent":["/**\n * Install command - restore .skilld/ and SKILL.md from lockfile\n *\n * After cloning a repo, the .skilld/ symlinks are missing (gitignored).\n * If SKILL.md was deleted, a base version is regenerated from local metadata.\n * This command recreates them from the lockfile:\n * .claude/skills/<skill>/.skilld/pkg -> node_modules/<pkg> (always)\n * .claude/skills/<skill>/.skilld/docs -> ~/.skilld/references/<pkg>@<version>/docs (if external)\n * .claude/skills/<skill>/SKILL.md -> regenerated from package.json + cache state\n */\n\nimport type { AgentType, CustomPrompt, SkillSection } from '../agent/index.ts'\nimport type { FeaturesConfig } from '../core/config.ts'\nimport type { SkillInfo } from '../core/lockfile.ts'\nimport { copyFileSync, existsSync, lstatSync, mkdirSync, readdirSync, symlinkSync, unlinkSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport * as p from '@clack/prompts'\nimport { defineCommand } from 'citty'\nimport { dirname, join } from 'pathe'\nimport { agents, createToolProgress, getModelLabel, linkSkillToAgents, optimizeDocs } from '../agent/index.ts'\nimport { generateSkillMd } from '../agent/prompts/skill.ts'\nimport {\n hasShippedDocs as checkShippedDocs,\n ensureCacheDir,\n getCacheDir,\n getPackageDbPath,\n getPkgKeyFiles,\n getRepoCacheDir,\n getShippedSkills,\n isCached,\n linkPkgNamed,\n linkShippedSkill,\n listReferenceFiles,\n readCachedDocs,\n resolvePkgDir,\n writeToCache,\n} from '../cache/index.ts'\nimport { promptForAgent, resolveAgent, sharedArgs } from '../cli-helpers.ts'\nimport { defaultFeatures, readConfig } from '../core/config.ts'\nimport { timedSpinner } from '../core/formatting.ts'\nimport { mergeLocks, parsePackages, readLock, syncLockfilesToDirs, writeLock } from '../core/lockfile.ts'\nimport { readPackageJsonSafe } from '../core/package-json.ts'\nimport { sanitizeMarkdown } from '../core/sanitize.ts'\nimport { getSharedSkillsDir } from '../core/shared.ts'\nimport { createIndex, SearchDepsUnavailableError } from '../retriv/index.ts'\nimport { shutdownWorker } from '../retriv/pool.ts'\nimport { fetchGitSkills } from '../sources/git-skills.ts'\nimport {\n downloadLlmsDocs,\n fetchGitDocs,\n fetchGitHubRaw,\n fetchLlmsTxt,\n fetchReadmeContent,\n filterFrameworkDocs,\n isShallowGitDocs,\n normalizeLlmsLinks,\n parseGitHubUrl,\n resolveEntryFiles,\n resolvePackageDocs,\n} from '../sources/index.ts'\nimport { classifyCachedDoc, indexResources } from './sync-shared.ts'\nimport { selectLlmConfig, writePromptFiles } from './sync.ts'\n\nexport interface InstallOptions {\n global: boolean\n agent: AgentType\n}\n\nexport async function installCommand(opts: InstallOptions): Promise<void> {\n const cwd = process.cwd()\n const agent = agents[opts.agent]\n const shared = !opts.global && getSharedSkillsDir(cwd)\n const skillsDir = opts.global\n ? join(homedir(), '.skilld', 'skills')\n : shared || join(cwd, agent.skillsDir)\n\n // Collect lockfiles from all agent skill dirs and merge\n // In shared mode, read from .skills/ only\n const allSkillsDirs = shared\n ? [shared]\n : Object.values(agents).map(t =>\n opts.global ? t.globalSkillsDir : join(cwd, t.skillsDir),\n )\n const allLocks = allSkillsDirs\n .map(dir => readLock(dir))\n .filter((l): l is NonNullable<typeof l> => !!l && Object.keys(l.skills).length > 0)\n\n if (allLocks.length === 0) {\n p.log.warn('No skilld-lock.yaml found. Run `skilld` to sync skills first.')\n return\n }\n\n const lock = mergeLocks(allLocks)\n\n const skills = Object.entries(lock.skills)\n const toRestore: Array<{ name: string, info: SkillInfo }> = []\n const features = readConfig().features ?? defaultFeatures\n\n // Find skills with missing/broken references symlinks\n for (const [name, info] of skills) {\n if (!info.version)\n continue\n\n // Shipped skills: the skill dir IS the symlink, no references/ subdir\n if (info.source === 'shipped') {\n const skillDir = join(skillsDir, name)\n if (!existsSync(skillDir)) {\n toRestore.push({ name, info })\n }\n continue\n }\n\n const skillDir = join(skillsDir, name)\n const referencesPath = join(skillDir, '.skilld')\n const skillMdPath = join(skillDir, 'SKILL.md')\n\n // Check skill dir, SKILL.md, and all internal .skilld/ references\n const needsRestore = !existsSync(skillDir)\n || !existsSync(skillMdPath)\n || !existsSync(referencesPath)\n || hasStaleReferences(referencesPath, info.packageName || name, info.version!, features)\n\n if (needsRestore) {\n toRestore.push({ name, info })\n }\n }\n\n if (toRestore.length === 0) {\n p.log.success('All up to date')\n return\n }\n\n p.log.info(`Restoring ${toRestore.length} references`)\n ensureCacheDir()\n\n const allSkillNames = skills.map(([, info]) => info.packageName || '').filter(Boolean)\n const regenerated: Array<{ name: string, pkgName: string, version: string, skillDir: string, packages?: string }> = []\n\n for (const { name, info } of toRestore) {\n const version = info.version!\n const pkgName = info.packageName || unsanitizeName(name, info.source)\n\n // Shipped skills: re-link from node_modules or cached dist\n if (info.source === 'shipped') {\n const shipped = getShippedSkills(pkgName, cwd, version)\n const match = shipped.find(s => s.skillName === name)\n if (match) {\n linkShippedSkill(skillsDir, name, match.skillDir)\n p.log.success(`Linked ${name}`)\n }\n else {\n p.log.warn(`${name}: package ${pkgName} no longer ships this skill`)\n }\n continue\n }\n\n // Git-sourced skills: re-fetch from remote\n if (info.source === 'github' || info.source === 'gitlab' || info.source === 'local') {\n const source = {\n type: info.source as 'github' | 'gitlab' | 'local',\n ...(info.repo?.includes('/') ? { owner: info.repo.split('/')[0], repo: info.repo.split('/')[1] } : {}),\n skillPath: info.path,\n ref: info.ref,\n ...(info.source === 'local' ? { localPath: info.repo } : {}),\n }\n const result = await fetchGitSkills(source)\n const match = result.skills.find(s => s.name === name)\n if (match) {\n const skillDir = join(skillsDir, name)\n mkdirSync(skillDir, { recursive: true })\n writeFileSync(join(skillDir, 'SKILL.md'), sanitizeMarkdown(match.content))\n for (const f of match.files) {\n const filePath = join(skillDir, f.path)\n mkdirSync(dirname(filePath), { recursive: true })\n writeFileSync(filePath, f.content)\n }\n p.log.success(`Restored ${name} from ${info.repo}`)\n }\n else {\n p.log.warn(`${name}: skill not found in ${info.repo}`)\n }\n continue\n }\n\n const skillDir = join(skillsDir, name)\n const referencesPath = join(skillDir, '.skilld')\n const globalCachePath = getCacheDir(pkgName, version)\n const spin = timedSpinner()\n\n // Check if already in global cache - just create symlinks\n if (isCached(pkgName, version)) {\n spin.start(`Linking ${name}`)\n mkdirSync(skillDir, { recursive: true })\n mkdirSync(referencesPath, { recursive: true })\n linkPkgSymlink(referencesPath, pkgName, cwd, version)\n // Restore named symlinks for all tracked packages\n for (const pkg of parsePackages(info.packages))\n linkPkgNamed(skillDir, pkg.name, cwd, pkg.version)\n // Only link external docs if package doesn't ship its own and has more than just README\n if (!pkgHasShippedDocs(pkgName, cwd, version) && !isReadmeOnly(globalCachePath)) {\n const docsLink = join(referencesPath, 'docs')\n const cachedDocs = join(globalCachePath, 'docs')\n if (existsSync(docsLink))\n unlinkSync(docsLink)\n if (existsSync(cachedDocs))\n symlinkSync(cachedDocs, docsLink, 'junction')\n }\n // Link issues, discussions, and releases (try repo cache first, fall back to package cache)\n const repoGh = info.repo ? parseGitHubUrl(`https://github.com/${info.repo}`) : null\n const repoCachePath = repoGh ? getRepoCacheDir(repoGh.owner, repoGh.repo) : null\n if (features.issues) {\n const issuesLink = join(referencesPath, 'issues')\n const repoIssues = repoCachePath ? join(repoCachePath, 'issues') : null\n const cachedIssues = (repoIssues && existsSync(repoIssues)) ? repoIssues : join(globalCachePath, 'issues')\n if (existsSync(issuesLink))\n unlinkSync(issuesLink)\n if (existsSync(cachedIssues))\n symlinkSync(cachedIssues, issuesLink, 'junction')\n }\n if (features.discussions) {\n const discussionsLink = join(referencesPath, 'discussions')\n const repoDiscussions = repoCachePath ? join(repoCachePath, 'discussions') : null\n const cachedDiscussions = (repoDiscussions && existsSync(repoDiscussions)) ? repoDiscussions : join(globalCachePath, 'discussions')\n if (existsSync(discussionsLink))\n unlinkSync(discussionsLink)\n if (existsSync(cachedDiscussions))\n symlinkSync(cachedDiscussions, discussionsLink, 'junction')\n }\n if (features.releases) {\n const releasesLink = join(referencesPath, 'releases')\n const repoReleases = repoCachePath ? join(repoCachePath, 'releases') : null\n const cachedReleases = (repoReleases && existsSync(repoReleases)) ? repoReleases : join(globalCachePath, 'releases')\n if (existsSync(releasesLink))\n unlinkSync(releasesLink)\n if (existsSync(cachedReleases))\n symlinkSync(cachedReleases, releasesLink, 'junction')\n }\n const sectionsLink = join(referencesPath, 'sections')\n const cachedSections = join(globalCachePath, 'sections')\n if (existsSync(sectionsLink))\n unlinkSync(sectionsLink)\n if (existsSync(cachedSections))\n symlinkSync(cachedSections, sectionsLink, 'junction')\n // Create search index from cached docs if missing\n if (features.search && !existsSync(getPackageDbPath(pkgName, version))) {\n spin.message(`Indexing ${name}`)\n const cached = readCachedDocs(pkgName, version)\n const docsToIndex = cached.map(d => ({\n id: d.path,\n content: d.content,\n metadata: { package: pkgName, source: d.path, type: classifyCachedDoc(d.path).type },\n }))\n await indexResources({ packageName: pkgName, version, cwd, docsToIndex, features, onProgress: msg => spin.message(msg) })\n }\n if (!copyFromExistingAgent(skillDir, name, allSkillsDirs)) {\n if (regenerateBaseSkillMd(skillDir, pkgName, version, cwd, allSkillNames, info.source, info.packages))\n regenerated.push({ name, pkgName, version, skillDir, packages: info.packages })\n }\n spin.stop(`Linked ${name}`)\n continue\n }\n\n // Need to download to global cache first\n spin.start(`Downloading ${name}@${version}`)\n\n const resolved = await resolvePackageDocs(pkgName, { version })\n\n if (!resolved) {\n spin.stop(`Could not resolve: ${name}`)\n continue\n }\n\n const cachedDocs: Array<{ path: string, content: string }> = []\n const docsToIndex: Array<{ id: string, content: string, metadata: Record<string, any> }> = []\n const isFrameworkDoc = (path: string) => filterFrameworkDocs([path], pkgName).length > 0\n\n // Try git docs first\n if (resolved.gitDocsUrl && resolved.repoUrl) {\n const gh = parseGitHubUrl(resolved.repoUrl)\n if (gh) {\n const gitDocs = await fetchGitDocs(gh.owner, gh.repo, version, pkgName)\n if (gitDocs?.files.length) {\n const BATCH_SIZE = 20\n for (let i = 0; i < gitDocs.files.length; i += BATCH_SIZE) {\n const batch = gitDocs.files.slice(i, i + BATCH_SIZE)\n const results = await Promise.all(\n batch.map(async (file) => {\n const url = `${gitDocs.baseUrl}/${file}`\n const content = await fetchGitHubRaw(url)\n if (!content)\n return null\n return { file, content }\n }),\n )\n for (const r of results) {\n if (r) {\n const stripped = gitDocs.docsPrefix ? r.file.replace(gitDocs.docsPrefix, '') : r.file\n const cachePath = stripped.startsWith('docs/') ? stripped : `docs/${stripped}`\n cachedDocs.push({ path: cachePath, content: r.content })\n docsToIndex.push({ id: cachePath, content: r.content, metadata: { package: pkgName, source: cachePath, type: 'doc' } })\n }\n }\n }\n\n // Shallow git-docs: if < threshold and llms.txt exists, discard and fall through\n if (isShallowGitDocs(cachedDocs.length) && resolved.llmsUrl) {\n cachedDocs.length = 0\n docsToIndex.length = 0\n }\n else if (cachedDocs.length > 0 && resolved.llmsUrl) {\n // Always cache llms.txt alongside good git-docs as supplementary reference\n const llmsContent = await fetchLlmsTxt(resolved.llmsUrl)\n if (llmsContent) {\n const baseUrl = resolved.docsUrl || new URL(resolved.llmsUrl).origin\n cachedDocs.push({ path: 'llms.txt', content: normalizeLlmsLinks(llmsContent.raw) })\n if (llmsContent.links.length > 0) {\n const docs = await downloadLlmsDocs(llmsContent, baseUrl)\n for (const doc of docs) {\n if (!isFrameworkDoc(doc.url))\n continue\n const localPath = doc.url.startsWith('/') ? doc.url.slice(1) : doc.url\n cachedDocs.push({ path: join('llms-docs', ...localPath.split('/')), content: doc.content })\n }\n }\n }\n }\n }\n }\n }\n\n // Try llms.txt\n if (resolved.llmsUrl && cachedDocs.length === 0) {\n const llmsContent = await fetchLlmsTxt(resolved.llmsUrl)\n if (llmsContent) {\n cachedDocs.push({ path: 'llms.txt', content: normalizeLlmsLinks(llmsContent.raw) })\n if (llmsContent.links.length > 0) {\n const baseUrl = resolved.docsUrl || new URL(resolved.llmsUrl).origin\n const docs = await downloadLlmsDocs(llmsContent, baseUrl)\n for (const doc of docs) {\n if (!isFrameworkDoc(doc.url))\n continue\n const localPath = doc.url.startsWith('/') ? doc.url.slice(1) : doc.url\n const cachePath = join('docs', ...localPath.split('/'))\n cachedDocs.push({ path: cachePath, content: doc.content })\n docsToIndex.push({ id: doc.url, content: doc.content, metadata: { package: pkgName, source: cachePath, type: 'doc' } })\n }\n }\n }\n }\n\n // Fallback to README\n if (resolved.readmeUrl && cachedDocs.length === 0) {\n const content = await fetchReadmeContent(resolved.readmeUrl)\n if (content) {\n cachedDocs.push({ path: 'docs/README.md', content })\n docsToIndex.push({ id: 'README.md', content, metadata: { package: pkgName, source: 'docs/README.md', type: 'doc' } })\n }\n }\n\n if (cachedDocs.length > 0) {\n writeToCache(pkgName, version, cachedDocs)\n\n mkdirSync(referencesPath, { recursive: true })\n linkPkgSymlink(referencesPath, pkgName, cwd, version)\n // Restore named symlinks for all tracked packages\n for (const pkg of parsePackages(info.packages))\n linkPkgNamed(skillDir, pkg.name, cwd, pkg.version)\n // Link fetched docs unless it's just a README (already in pkg/)\n if (!isReadmeOnly(globalCachePath)) {\n const docsLink = join(referencesPath, 'docs')\n const cachedDocsDir = join(globalCachePath, 'docs')\n if (existsSync(docsLink))\n unlinkSync(docsLink)\n if (existsSync(cachedDocsDir))\n symlinkSync(cachedDocsDir, docsLink, 'junction')\n }\n\n if (features.search) {\n try {\n if (docsToIndex.length > 0) {\n await createIndex(docsToIndex, { dbPath: getPackageDbPath(pkgName, version) })\n }\n\n // Index package entry files (.d.ts / .js)\n const pkgDir = resolvePkgDir(pkgName, cwd, version)\n const entryFiles = pkgDir ? await resolveEntryFiles(pkgDir) : []\n if (entryFiles.length > 0) {\n await createIndex(entryFiles.map(e => ({\n id: e.path,\n content: e.content,\n metadata: { package: pkgName, source: `pkg/${e.path}`, type: e.type },\n })), { dbPath: getPackageDbPath(pkgName, version) })\n }\n }\n catch (err) {\n if (!(err instanceof SearchDepsUnavailableError))\n throw err\n }\n }\n\n if (!copyFromExistingAgent(skillDir, name, allSkillsDirs)) {\n if (regenerateBaseSkillMd(skillDir, pkgName, version, cwd, allSkillNames, info.source, info.packages))\n regenerated.push({ name, pkgName, version, skillDir, packages: info.packages })\n }\n spin.stop(`Downloaded and linked ${name}`)\n }\n else {\n spin.stop(`No docs found for ${name}`)\n }\n }\n\n // Offer LLM enhancement for regenerated SKILL.md files\n if (regenerated.length > 0 && !readConfig().skipLlm) {\n const names = regenerated.map(r => r.name).join(', ')\n const llmConfig = await selectLlmConfig(undefined, `Enhance SKILL.md for ${names}`)\n if (llmConfig?.promptOnly) {\n const features = readConfig().features ?? defaultFeatures\n for (const { pkgName, version, skillDir } of regenerated) {\n const globalCachePath = getCacheDir(pkgName, version)\n writePromptFiles({\n packageName: pkgName,\n skillDir,\n version,\n hasIssues: existsSync(join(globalCachePath, 'issues')),\n hasDiscussions: existsSync(join(globalCachePath, 'discussions')),\n hasReleases: existsSync(join(globalCachePath, 'releases')),\n hasChangelog: false,\n docsType: 'docs',\n hasShippedDocs: false,\n pkgFiles: getPkgKeyFiles(pkgName, process.cwd(), version),\n sections: llmConfig.sections,\n customPrompt: llmConfig.customPrompt,\n features,\n })\n }\n }\n else if (llmConfig) {\n p.log.step(getModelLabel(llmConfig.model))\n for (const { pkgName, version, skillDir, packages: pkgPackages } of regenerated) {\n await enhanceRegenerated(pkgName, version, skillDir, llmConfig.model, llmConfig.sections, llmConfig.customPrompt, pkgPackages)\n }\n }\n }\n\n // Write merged lockfile to target dir and sync to all other existing lockfiles\n for (const [name, info] of Object.entries(lock.skills))\n writeLock(skillsDir, name, info)\n\n // In shared mode: recreate per-agent symlinks, skip per-agent lockfile sync\n if (shared) {\n for (const [name] of skills)\n linkSkillToAgents(name, shared, cwd, opts.agent)\n }\n else {\n syncLockfilesToDirs(lock, allSkillsDirs.filter(d => d !== skillsDir))\n }\n\n await shutdownWorker()\n\n p.outro('Install complete')\n}\n\n/** Copy SKILL.md from another agent's skill dir if one exists */\nfunction copyFromExistingAgent(skillDir: string, name: string, allSkillsDirs: string[]): boolean {\n const targetMd = join(skillDir, 'SKILL.md')\n if (existsSync(targetMd))\n return false\n for (const dir of allSkillsDirs) {\n if (dir === skillDir)\n continue\n const candidateMd = join(dir, name, 'SKILL.md')\n if (existsSync(candidateMd) && !lstatSync(candidateMd).isSymbolicLink()) {\n mkdirSync(skillDir, { recursive: true })\n copyFileSync(candidateMd, targetMd)\n return true\n }\n }\n return false\n}\n\n/** Try to recover original package name from sanitized name + source */\nfunction unsanitizeName(sanitized: string, source?: string): string {\n if (source?.includes('ungh://')) {\n const match = source.match(/ungh:\\/\\/([^/]+)\\/(.+)/)\n if (match)\n return `@${match[1]}/${match[2]}`\n }\n\n if (sanitized.startsWith('antfu-'))\n return `@antfu/${sanitized.slice(6)}`\n if (sanitized.startsWith('clack-'))\n return `@clack/${sanitized.slice(6)}`\n if (sanitized.startsWith('nuxt-'))\n return `@nuxt/${sanitized.slice(5)}`\n if (sanitized.startsWith('vue-'))\n return `@vue/${sanitized.slice(4)}`\n if (sanitized.startsWith('vueuse-'))\n return `@vueuse/${sanitized.slice(7)}`\n\n return sanitized\n}\n\n/** Create pkg symlink inside references dir (links to entire package or cached dist) */\nfunction linkPkgSymlink(referencesDir: string, name: string, cwd: string, version?: string): void {\n const pkgPath = resolvePkgDir(name, cwd, version)\n if (!pkgPath)\n return\n\n const pkgLink = join(referencesDir, 'pkg')\n if (existsSync(pkgLink))\n unlinkSync(pkgLink)\n symlinkSync(pkgPath, pkgLink, 'junction')\n}\n\n/** Check if cache only has docs/README.md (pkg/ already has this) */\nfunction isReadmeOnly(cacheDir: string): boolean {\n const docsDir = join(cacheDir, 'docs')\n if (!existsSync(docsDir))\n return false\n const files = readdirSync(docsDir)\n return files.length === 1 && files[0] === 'README.md'\n}\n\n/** Check if package ships its own docs folder */\nfunction pkgHasShippedDocs(name: string, cwd: string, version?: string): boolean {\n const pkgPath = resolvePkgDir(name, cwd, version)\n if (!pkgPath)\n return false\n\n const docsCandidates = ['docs', 'documentation', 'doc']\n for (const candidate of docsCandidates) {\n const docsPath = join(pkgPath, candidate)\n if (existsSync(docsPath))\n return true\n }\n return false\n}\n\n/** Run LLM enhancement on a regenerated SKILL.md */\nasync function enhanceRegenerated(\n pkgName: string,\n version: string,\n skillDir: string,\n model: Parameters<typeof optimizeDocs>[0]['model'],\n sections: SkillSection[],\n customPrompt?: CustomPrompt,\n packages?: string,\n): Promise<void> {\n const llmLog = p.taskLog({ title: `Agent exploring ${pkgName}` })\n\n const docFiles = listReferenceFiles(skillDir)\n const globalCachePath = getCacheDir(pkgName, version)\n const hasIssues = existsSync(join(globalCachePath, 'issues'))\n const hasDiscussions = existsSync(join(globalCachePath, 'discussions'))\n const hasGithub = hasIssues || hasDiscussions\n const hasReleases = existsSync(join(globalCachePath, 'releases'))\n\n const features = readConfig().features ?? defaultFeatures\n const { optimized, wasOptimized } = await optimizeDocs({\n packageName: pkgName,\n skillDir,\n model,\n version,\n hasGithub,\n hasReleases,\n docFiles,\n sections,\n customPrompt,\n features,\n pkgFiles: getPkgKeyFiles(pkgName, process.cwd(), version),\n onProgress: createToolProgress(llmLog),\n })\n\n if (wasOptimized) {\n llmLog.success('Generated best practices')\n // Re-read local metadata for the enhanced version\n const cwd = process.cwd()\n const pkgPath = resolvePkgDir(pkgName, cwd, version)\n let description: string | undefined\n if (pkgPath) {\n const pkgJsonPath = join(pkgPath, 'package.json')\n const pkgJsonResult = readPackageJsonSafe(pkgJsonPath)\n if (pkgJsonResult) {\n description = pkgJsonResult.parsed.description as string | undefined\n }\n }\n\n let docsType: 'llms.txt' | 'readme' | 'docs' = 'docs'\n if (existsSync(join(globalCachePath, 'docs', 'llms.txt')))\n docsType = 'llms.txt'\n else if (isReadmeOnly(globalCachePath))\n docsType = 'readme'\n\n // Derive dirName from the skill directory name\n const dirName = skillDir.split('/').pop()\n\n const allPackages = parsePackages(packages).map(p => ({ name: p.name }))\n const skillMd = generateSkillMd({\n name: pkgName,\n version,\n description,\n body: optimized,\n relatedSkills: [],\n hasIssues,\n hasDiscussions,\n hasReleases,\n docsType,\n hasShippedDocs: checkShippedDocs(pkgName, cwd, version),\n pkgFiles: getPkgKeyFiles(pkgName, cwd, version),\n dirName,\n packages: allPackages.length > 1 ? allPackages : undefined,\n features,\n })\n writeFileSync(join(skillDir, 'SKILL.md'), skillMd)\n }\n else {\n llmLog.message('Enhancement skipped')\n }\n}\n\nexport const installCommandDef = defineCommand({\n meta: { name: 'install', description: 'Restore references from lockfile' },\n args: {\n global: sharedArgs.global,\n agent: sharedArgs.agent,\n },\n async run({ args }) {\n let agent = resolveAgent(args.agent)\n if (!agent || agent === 'none') {\n if (agent === 'none')\n return\n const picked = await promptForAgent()\n if (!picked || picked === 'none')\n return\n agent = picked\n }\n\n p.intro(`\\x1B[1m\\x1B[35mskilld\\x1B[0m install`)\n return installCommand({ global: args.global, agent })\n },\n})\n\n/** Regenerate base SKILL.md from local metadata if missing */\nfunction regenerateBaseSkillMd(\n skillDir: string,\n pkgName: string,\n version: string,\n cwd: string,\n allSkillNames: string[],\n source?: string,\n packages?: string,\n): boolean {\n const skillMdPath = join(skillDir, 'SKILL.md')\n if (existsSync(skillMdPath))\n return false\n\n // Read description + deps from local package.json\n const pkgPath = resolvePkgDir(pkgName, cwd, version)\n let description: string | undefined\n if (pkgPath) {\n const pkgResult = readPackageJsonSafe(join(pkgPath, 'package.json'))\n if (pkgResult) {\n description = pkgResult.parsed.description as string | undefined\n }\n }\n\n // Infer docsType from source or cache\n const globalCachePath = getCacheDir(pkgName, version)\n let docsType: 'llms.txt' | 'readme' | 'docs' = 'docs'\n if (source?.includes('llms.txt') || existsSync(join(globalCachePath, 'docs', 'llms.txt')))\n docsType = 'llms.txt'\n else if (isReadmeOnly(globalCachePath))\n docsType = 'readme'\n\n // Check cache dirs for issues/discussions/releases (only if feature enabled)\n const feat = readConfig().features ?? defaultFeatures\n const hasIssues = feat.issues && existsSync(join(globalCachePath, 'issues'))\n const hasDiscussions = feat.discussions && existsSync(join(globalCachePath, 'discussions'))\n const hasReleases = feat.releases && existsSync(join(globalCachePath, 'releases'))\n\n // Related skills from other lockfile entries\n const relatedSkills = allSkillNames.filter(n => n !== pkgName)\n\n // Derive dirName from the skill directory name (lockfile key)\n const dirName = skillDir.split('/').pop()\n\n // Build multi-package list from lockfile packages field\n const allPackages = parsePackages(packages).map(p => ({ name: p.name }))\n\n const content = generateSkillMd({\n name: pkgName,\n version,\n description,\n relatedSkills,\n hasIssues,\n hasDiscussions,\n hasReleases,\n docsType,\n hasShippedDocs: checkShippedDocs(pkgName, cwd, version),\n pkgFiles: getPkgKeyFiles(pkgName, cwd, version),\n dirName,\n packages: allPackages.length > 1 ? allPackages : undefined,\n features: readConfig().features ?? defaultFeatures,\n })\n\n mkdirSync(skillDir, { recursive: true })\n writeFileSync(skillMdPath, content)\n return true\n}\n\n/** Check if .skilld/ has broken symlinks or is missing expected references from global cache */\nfunction hasStaleReferences(referencesPath: string, pkgName: string, version: string, features: FeaturesConfig): boolean {\n // Scan existing entries for broken symlinks\n for (const entry of readdirSync(referencesPath)) {\n const entryPath = join(referencesPath, entry)\n if (lstatSync(entryPath).isSymbolicLink() && !existsSync(entryPath))\n return true\n }\n\n // Check pkg link always expected\n if (!existsSync(join(referencesPath, 'pkg')))\n return true\n\n // Check expected links against global cache\n const globalCachePath = getCacheDir(pkgName, version)\n const expected: Array<[string, boolean]> = [\n ['docs', existsSync(join(globalCachePath, 'docs'))],\n ['issues', features.issues && existsSync(join(globalCachePath, 'issues'))],\n ['discussions', features.discussions && existsSync(join(globalCachePath, 'discussions'))],\n ['releases', features.releases && existsSync(join(globalCachePath, 'releases'))],\n ['sections', existsSync(join(globalCachePath, 'sections'))],\n ]\n\n for (const [name, shouldExist] of expected) {\n if (shouldExist && !existsSync(join(referencesPath, name)))\n return true\n }\n\n return false\n}\n"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import "./agent.mjs";
2
2
  import "./config.mjs";
3
+ import "./package-json.mjs";
3
4
  import "./prepare.mjs";
4
5
  import "./sanitize.mjs";
5
6
  import "./cache.mjs";
@@ -9,7 +10,7 @@ import "./shared.mjs";
9
10
  import "./sources.mjs";
10
11
  import "./detect.mjs";
11
12
  import "./prompts.mjs";
12
- import { b as sharedArgs } from "./cli-helpers.mjs";
13
+ import { x as sharedArgs } from "./cli-helpers.mjs";
13
14
  import "./lockfile.mjs";
14
15
  import { i as iterateSkills, t as getProjectState } from "./skills.mjs";
15
16
  import { c as timeAgo, i as formatSource } from "./formatting.mjs";
@@ -1 +1 @@
1
- {"version":3,"file":"list.mjs","names":[],"sources":["../../src/commands/list.ts"],"sourcesContent":["import { defineCommand } from 'citty'\nimport { sharedArgs } from '../cli-helpers.ts'\nimport { formatSource, timeAgo } from '../core/formatting.ts'\nimport { getProjectState, iterateSkills } from '../core/skills.ts'\n\nexport interface ListOptions {\n global?: boolean\n json?: boolean\n outdated?: boolean\n}\n\ninterface ListEntry {\n name: string\n version: string\n source: string\n synced: string\n latest?: string\n}\n\nexport async function listCommand(opts: ListOptions = {}): Promise<void> {\n if (opts.outdated) {\n const state = await getProjectState()\n const entries: ListEntry[] = state.outdated.map(skill => ({\n name: skill.name,\n version: skill.info?.version || '',\n latest: skill.latestVersion || '',\n source: formatSource(skill.info?.source),\n synced: timeAgo(skill.info?.syncedAt),\n }))\n\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(entries)}\\n`)\n return\n }\n\n if (entries.length === 0) {\n process.stdout.write('All skills are up to date\\n')\n return\n }\n\n const nameW = Math.max(...entries.map(e => e.name.length))\n const verW = Math.max(...entries.map(e => e.version.length))\n const latW = Math.max(...entries.map(e => (e.latest || '').length))\n const srcW = Math.max(...entries.map(e => e.source.length))\n\n for (const e of entries) {\n const line = [\n e.name.padEnd(nameW),\n `${e.version.padEnd(verW)} → ${(e.latest || '').padEnd(latW)}`,\n e.source.padEnd(srcW),\n e.synced,\n ].join(' ')\n process.stdout.write(`${line}\\n`)\n }\n return\n }\n\n const scope = opts.global ? 'global' : 'all'\n const skills = [...iterateSkills({ scope })]\n\n // Deduplicate by package identity\n const seen = new Set<string>()\n const entries: ListEntry[] = []\n\n for (const skill of skills) {\n const key = skill.info?.packageName || skill.name\n if (seen.has(key))\n continue\n seen.add(key)\n entries.push({\n name: skill.name,\n version: skill.info?.version || '',\n source: formatSource(skill.info?.source),\n synced: timeAgo(skill.info?.syncedAt),\n })\n }\n\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(entries)}\\n`)\n return\n }\n\n if (entries.length === 0) {\n process.stdout.write('No skills installed\\n')\n return\n }\n\n // Column widths\n const nameW = Math.max(...entries.map(e => e.name.length))\n const verW = Math.max(...entries.map(e => e.version.length))\n const srcW = Math.max(...entries.map(e => e.source.length))\n\n for (const e of entries) {\n const line = [\n e.name.padEnd(nameW),\n e.version.padEnd(verW),\n e.source.padEnd(srcW),\n e.synced,\n ].join(' ')\n process.stdout.write(`${line}\\n`)\n }\n}\n\nexport const listCommandDef = defineCommand({\n meta: { name: 'list', description: 'List installed skills' },\n args: {\n global: sharedArgs.global,\n json: {\n type: 'boolean' as const,\n description: 'Output as JSON',\n default: false,\n },\n outdated: {\n type: 'boolean' as const,\n alias: 'o',\n description: 'Show only outdated skills',\n default: false,\n },\n },\n run({ args }) {\n return listCommand({ global: args.global, json: args.json, outdated: args.outdated })\n },\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"list.mjs","names":[],"sources":["../../src/commands/list.ts"],"sourcesContent":["import { defineCommand } from 'citty'\nimport { sharedArgs } from '../cli-helpers.ts'\nimport { formatSource, timeAgo } from '../core/formatting.ts'\nimport { getProjectState, iterateSkills } from '../core/skills.ts'\n\nexport interface ListOptions {\n global?: boolean\n json?: boolean\n outdated?: boolean\n}\n\ninterface ListEntry {\n name: string\n version: string\n source: string\n synced: string\n latest?: string\n}\n\nexport async function listCommand(opts: ListOptions = {}): Promise<void> {\n if (opts.outdated) {\n const state = await getProjectState()\n const entries: ListEntry[] = state.outdated.map(skill => ({\n name: skill.name,\n version: skill.info?.version || '',\n latest: skill.latestVersion || '',\n source: formatSource(skill.info?.source),\n synced: timeAgo(skill.info?.syncedAt),\n }))\n\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(entries)}\\n`)\n return\n }\n\n if (entries.length === 0) {\n process.stdout.write('All skills are up to date\\n')\n return\n }\n\n const nameW = Math.max(...entries.map(e => e.name.length))\n const verW = Math.max(...entries.map(e => e.version.length))\n const latW = Math.max(...entries.map(e => (e.latest || '').length))\n const srcW = Math.max(...entries.map(e => e.source.length))\n\n for (const e of entries) {\n const line = [\n e.name.padEnd(nameW),\n `${e.version.padEnd(verW)} → ${(e.latest || '').padEnd(latW)}`,\n e.source.padEnd(srcW),\n e.synced,\n ].join(' ')\n process.stdout.write(`${line}\\n`)\n }\n return\n }\n\n const scope = opts.global ? 'global' : 'all'\n const skills = [...iterateSkills({ scope })]\n\n // Deduplicate by package identity\n const seen = new Set<string>()\n const entries: ListEntry[] = []\n\n for (const skill of skills) {\n const key = skill.info?.packageName || skill.name\n if (seen.has(key))\n continue\n seen.add(key)\n entries.push({\n name: skill.name,\n version: skill.info?.version || '',\n source: formatSource(skill.info?.source),\n synced: timeAgo(skill.info?.syncedAt),\n })\n }\n\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(entries)}\\n`)\n return\n }\n\n if (entries.length === 0) {\n process.stdout.write('No skills installed\\n')\n return\n }\n\n // Column widths\n const nameW = Math.max(...entries.map(e => e.name.length))\n const verW = Math.max(...entries.map(e => e.version.length))\n const srcW = Math.max(...entries.map(e => e.source.length))\n\n for (const e of entries) {\n const line = [\n e.name.padEnd(nameW),\n e.version.padEnd(verW),\n e.source.padEnd(srcW),\n e.synced,\n ].join(' ')\n process.stdout.write(`${line}\\n`)\n }\n}\n\nexport const listCommandDef = defineCommand({\n meta: { name: 'list', description: 'List installed skills' },\n args: {\n global: sharedArgs.global,\n json: {\n type: 'boolean' as const,\n description: 'Output as JSON',\n default: false,\n },\n outdated: {\n type: 'boolean' as const,\n alias: 'o',\n description: 'Show only outdated skills',\n default: false,\n },\n },\n run({ args }) {\n return listCommand({ global: args.global, json: args.json, outdated: args.outdated })\n },\n})\n"],"mappings":"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"}