skilld 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +45 -21
  2. package/dist/_chunks/agent.mjs +8 -7
  3. package/dist/_chunks/agent.mjs.map +1 -1
  4. package/dist/_chunks/assemble.mjs +134 -0
  5. package/dist/_chunks/assemble.mjs.map +1 -0
  6. package/dist/_chunks/detect.mjs +737 -0
  7. package/dist/_chunks/detect.mjs.map +1 -0
  8. package/dist/_chunks/formatting.mjs +25 -294
  9. package/dist/_chunks/formatting.mjs.map +1 -1
  10. package/dist/_chunks/install.mjs +34 -10
  11. package/dist/_chunks/install.mjs.map +1 -1
  12. package/dist/_chunks/list.mjs +3 -1
  13. package/dist/_chunks/list.mjs.map +1 -1
  14. package/dist/_chunks/pool.mjs +113 -176
  15. package/dist/_chunks/pool.mjs.map +1 -1
  16. package/dist/_chunks/prompts.mjs +64 -735
  17. package/dist/_chunks/prompts.mjs.map +1 -1
  18. package/dist/_chunks/sanitize.mjs +2 -2
  19. package/dist/_chunks/sanitize.mjs.map +1 -1
  20. package/dist/_chunks/search-interactive.mjs +3 -1
  21. package/dist/_chunks/search-interactive.mjs.map +1 -1
  22. package/dist/_chunks/search.mjs +3 -1
  23. package/dist/_chunks/search2.mjs +180 -0
  24. package/dist/_chunks/search2.mjs.map +1 -0
  25. package/dist/_chunks/skills.mjs +292 -0
  26. package/dist/_chunks/skills.mjs.map +1 -0
  27. package/dist/_chunks/sync.mjs +298 -25
  28. package/dist/_chunks/sync.mjs.map +1 -1
  29. package/dist/_chunks/sync2.mjs +4 -2
  30. package/dist/_chunks/uninstall.mjs +6 -4
  31. package/dist/_chunks/uninstall.mjs.map +1 -1
  32. package/dist/_chunks/validate.mjs +2 -1
  33. package/dist/_chunks/validate.mjs.map +1 -1
  34. package/dist/agent/index.d.mts +29 -6
  35. package/dist/agent/index.d.mts.map +1 -1
  36. package/dist/agent/index.mjs +4 -3
  37. package/dist/cli.mjs +24 -13
  38. package/dist/cli.mjs.map +1 -1
  39. package/dist/retriv/index.mjs +1 -1
  40. package/dist/retriv/index.mjs.map +1 -1
  41. package/package.json +1 -1
  42. package/dist/_chunks/pool2.mjs +0 -115
  43. package/dist/_chunks/pool2.mjs.map +0 -1
@@ -5,11 +5,13 @@ import { i as parseFrontmatter } from "./markdown.mjs";
5
5
  import { SearchDepsUnavailableError, createIndex } from "../retriv/index.mjs";
6
6
  import { d as getPrereleaseChangelogRef, n as getSharedSkillsDir, o as getBlogPreset, t as SHARED_SKILLS_DIR } from "./shared.mjs";
7
7
  import { $ as fetchGitHubIssues, A as parseGitSkillInput, C as downloadLlmsDocs, D as normalizeLlmsLinks, F as formatDiscussionAsMarkdown, G as $fetch, H as generateReleaseIndex, I as generateDiscussionIndex, L as fetchCrawledDocs, M as resolveEntryFiles, N as generateDocsIndex, P as fetchGitHubDiscussions, R as toCrawlPattern, T as fetchLlmsTxt, U as isPrerelease, V as fetchReleaseNotes, X as parseGitHubUrl, Z as parsePackageSpec, b as isShallowGitDocs, et as formatIssueAsMarkdown, f as resolvePackageDocsWithAttempts, h as fetchGitDocs, i as fetchPkgDist, k as fetchGitSkills, n as fetchNpmPackage, nt as isGhAvailable, p as searchNpmPackages, s as readLocalDependencies, tt as generateIssueIndex, u as resolveLocalPackageDocs, v as fetchReadmeContent, x as resolveGitHubRepo, y as filterFrameworkDocs, z as fetchBlogReleases } from "./sources.mjs";
8
- import { _ as targets, a as sanitizeName, f as maxItems, i as linkSkillToAgents, n as computeSkillDirName, p as maxLines, t as generateSkillMd } from "./prompts.mjs";
9
- import { a as getModelName, i as getModelLabel, n as createToolProgress, o as optimizeDocs, r as getAvailableModels, t as detectImportedPackages } from "./agent.mjs";
10
- import { C as introLine, F as readConfig, I as registerProject, N as hasCompletedWizard, O as resolveAgent, R as updateConfig, T as promptForAgent, g as readLock, h as parsePackages, j as defaultFeatures, k as sharedArgs, l as timedSpinner, n as formatDuration, u as getProjectState, w as isInteractive, x as getInstalledGenerators, y as writeLock } from "./formatting.mjs";
8
+ import { a as targets } from "./detect.mjs";
9
+ import { a as sanitizeName, c as SECTION_OUTPUT_FILES, g as maxLines, h as maxItems, i as linkSkillToAgents, l as buildAllSectionPrompts, n as computeSkillDirName, p as portabilizePrompt, t as generateSkillMd } from "./prompts.mjs";
10
+ import { a as getModelLabel, i as getAvailableModels, o as getModelName, r as createToolProgress, s as optimizeDocs, t as detectImportedPackages } from "./agent.mjs";
11
+ import { C as hasCompletedWizard, E as registerProject, O as updateConfig, T as readConfig, d as getInstalledGenerators, h as promptForAgent, l as timedSpinner, m as isInteractive, n as formatDuration, p as introLine, v as resolveAgent, x as defaultFeatures, y as sharedArgs } from "./formatting.mjs";
12
+ import { o as parsePackages, s as readLock, t as getProjectState, u as writeLock } from "./skills.mjs";
11
13
  import { t as runWizard } from "../cli.mjs";
12
- import { n as shutdownWorker } from "./pool2.mjs";
14
+ import { n as shutdownWorker } from "./pool.mjs";
13
15
  import { dirname, join, relative, resolve } from "pathe";
14
16
  import { appendFileSync, copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
15
17
  import { isCI } from "std-env";
@@ -17,6 +19,8 @@ import pLimit from "p-limit";
17
19
  import * as p from "@clack/prompts";
18
20
  import { defineCommand } from "citty";
19
21
  import logUpdate from "log-update";
22
+ /** Max docs sent to the embedding pipeline to prevent oversized indexes */
23
+ const MAX_INDEX_DOCS = 250;
20
24
  const RESOLVE_STEP_LABELS = {
21
25
  "npm": "npm registry",
22
26
  "github-docs": "GitHub docs",
@@ -322,7 +326,7 @@ async function fetchAndCacheResources(opts) {
322
326
  if (resolved.docsUrl && !cachedDocs.some((d) => d.path.startsWith("docs/"))) {
323
327
  const crawlPattern = resolved.crawlUrl || toCrawlPattern(resolved.docsUrl);
324
328
  onProgress("Crawling docs site");
325
- const crawledDocs = await fetchCrawledDocs(crawlPattern, onProgress).catch((err) => {
329
+ const crawledDocs = await fetchCrawledDocs(crawlPattern, onProgress, resolved.crawlUrl ? 200 : 400).catch((err) => {
326
330
  warnings.push(`Crawl failed for ${crawlPattern}: ${err?.message || err}`);
327
331
  return [];
328
332
  });
@@ -558,6 +562,24 @@ async function indexResources(opts) {
558
562
  });
559
563
  }
560
564
  if (allDocs.length === 0) return;
565
+ if (allDocs.length > MAX_INDEX_DOCS) {
566
+ const TYPE_PRIORITY = {
567
+ doc: 0,
568
+ issue: 1,
569
+ discussion: 2,
570
+ release: 3,
571
+ source: 4,
572
+ types: 5
573
+ };
574
+ allDocs.sort((a, b) => {
575
+ const ta = TYPE_PRIORITY[a.metadata?.type || "doc"] ?? 3;
576
+ const tb = TYPE_PRIORITY[b.metadata?.type || "doc"] ?? 3;
577
+ if (ta !== tb) return ta - tb;
578
+ return a.id.localeCompare(b.id);
579
+ });
580
+ onProgress(`Indexing capped at ${MAX_INDEX_DOCS}/${allDocs.length} docs (prioritized by type)`);
581
+ allDocs.length = MAX_INDEX_DOCS;
582
+ }
561
583
  onProgress(`Building search index (${allDocs.length} docs)`);
562
584
  try {
563
585
  await createIndex(allDocs, {
@@ -804,6 +826,11 @@ async function selectLlmConfig(presetModel, message) {
804
826
  value: "pick",
805
827
  hint: "choose another model"
806
828
  },
829
+ {
830
+ label: "Prompt only",
831
+ value: "prompt",
832
+ hint: "write prompts for manual use"
833
+ },
807
834
  {
808
835
  label: "Skip",
809
836
  value: "skip",
@@ -813,6 +840,16 @@ async function selectLlmConfig(presetModel, message) {
813
840
  });
814
841
  if (p.isCancel(choice)) return null;
815
842
  if (choice === "skip") return null;
843
+ if (choice === "prompt") {
844
+ const { sections, customPrompt, cancelled } = await selectSkillSections(message ? `${message} (prompt only)` : "Select sections for prompt generation");
845
+ if (cancelled || sections.length === 0) return null;
846
+ return {
847
+ model: defaultModel,
848
+ sections,
849
+ customPrompt,
850
+ promptOnly: true
851
+ };
852
+ }
816
853
  const model = choice === "pick" ? await selectModel(false) : defaultModel;
817
854
  if (!model) return null;
818
855
  const modelName = getModelName(model);
@@ -886,6 +923,41 @@ async function enhanceSkillWithLLM(opts) {
886
923
  } else llmLog.error(`LLM optimization failed${error ? `: ${error}` : ""}`);
887
924
  }
888
925
  /**
926
+ * Build and write PROMPT_*.md files for manual LLM use.
927
+ * Returns the list of sections that had prompts written.
928
+ */
929
+ function writePromptFiles(opts) {
930
+ const { skillDir, sections, customPrompt, features } = opts;
931
+ const docFiles = listReferenceFiles(skillDir);
932
+ const prompts = buildAllSectionPrompts({
933
+ packageName: opts.packageName,
934
+ skillDir,
935
+ version: opts.version,
936
+ hasIssues: opts.hasIssues,
937
+ hasDiscussions: opts.hasDiscussions,
938
+ hasReleases: opts.hasReleases,
939
+ hasChangelog: opts.hasChangelog,
940
+ docFiles,
941
+ docsType: opts.docsType,
942
+ hasShippedDocs: opts.hasShippedDocs,
943
+ pkgFiles: opts.pkgFiles,
944
+ customPrompt,
945
+ features,
946
+ sections
947
+ });
948
+ const skilldDir = join(skillDir, ".skilld");
949
+ mkdirSync(skilldDir, { recursive: true });
950
+ for (const [section, prompt] of prompts) writeFileSync(join(skilldDir, `PROMPT_${section}.md`), prompt);
951
+ const written = [...prompts.keys()];
952
+ if (written.length > 0) {
953
+ const relDir = relative(process.cwd(), skillDir);
954
+ const promptFiles = written.map((s) => `PROMPT_${s}.md`).join(", ");
955
+ const outputFileList = written.map((s) => SECTION_OUTPUT_FILES[s]).join(", ");
956
+ p.log.info(`Prompt files written to ${relDir}/.skilld/\n\x1B[2m\x1B[3m Read each prompt file (${promptFiles}) in ${relDir}/.skilld/, read the\n referenced files, then write your output to the matching file (${outputFileList}).\n When done, run: skilld assemble\x1B[0m`);
957
+ }
958
+ return written;
959
+ }
960
+ /**
889
961
  * Anonymous telemetry — fire-and-forget GET to add-skill.vercel.sh/t
890
962
  *
891
963
  * Opt-out: set DISABLE_TELEMETRY=1 or DO_NOT_TRACK=1
@@ -1076,7 +1148,22 @@ async function syncGitHubRepo(opts) {
1076
1148
  p.log.success(`Created base skill: ${relative(cwd, skillDir)}`);
1077
1149
  if (!readConfig().skipLlm && (!yes || opts.model)) {
1078
1150
  const llmConfig = await selectLlmConfig(opts.model);
1079
- if (llmConfig) {
1151
+ if (llmConfig?.promptOnly) writePromptFiles({
1152
+ packageName,
1153
+ skillDir,
1154
+ version,
1155
+ hasIssues: resources.hasIssues,
1156
+ hasDiscussions: resources.hasDiscussions,
1157
+ hasReleases: resources.hasReleases,
1158
+ hasChangelog,
1159
+ docsType: resources.docsType,
1160
+ hasShippedDocs: shippedDocs,
1161
+ pkgFiles,
1162
+ sections: llmConfig.sections,
1163
+ customPrompt: llmConfig.customPrompt,
1164
+ features
1165
+ });
1166
+ else if (llmConfig) {
1080
1167
  p.log.step(getModelLabel(llmConfig.model));
1081
1168
  await enhanceSkillWithLLM({
1082
1169
  packageName,
@@ -1102,7 +1189,7 @@ async function syncGitHubRepo(opts) {
1102
1189
  }
1103
1190
  }
1104
1191
  const shared = !isGlobal && getSharedSkillsDir(cwd);
1105
- if (shared) linkSkillToAgents(skillDirName, shared, cwd);
1192
+ if (shared) linkSkillToAgents(skillDirName, shared, cwd, agent);
1106
1193
  if (!isGlobal) {
1107
1194
  registerProject(cwd);
1108
1195
  await ensureGitignore(shared || targets[agent].skillsDir, cwd, isGlobal);
@@ -1210,7 +1297,25 @@ async function syncPackagesParallel(config) {
1210
1297
  const globalConfig = readConfig();
1211
1298
  if (successfulPkgs.length > 0 && !globalConfig.skipLlm && !(config.yes && !config.model)) {
1212
1299
  const llmConfig = await selectLlmConfig(config.model);
1213
- if (llmConfig) {
1300
+ if (llmConfig?.promptOnly) for (const pkg of successfulPkgs) {
1301
+ const data = skillData.get(pkg);
1302
+ writePromptFiles({
1303
+ packageName: pkg,
1304
+ skillDir: join(resolveBaseDir(cwd, config.agent, config.global), data.skillDirName),
1305
+ version: data.version,
1306
+ hasIssues: data.hasIssues,
1307
+ hasDiscussions: data.hasDiscussions,
1308
+ hasReleases: data.hasReleases,
1309
+ hasChangelog: data.hasChangelog,
1310
+ docsType: data.docsType,
1311
+ hasShippedDocs: data.shippedDocs,
1312
+ pkgFiles: data.pkgFiles,
1313
+ sections: llmConfig.sections,
1314
+ customPrompt: llmConfig.customPrompt,
1315
+ features: data.features
1316
+ });
1317
+ }
1318
+ else if (llmConfig) {
1214
1319
  p.log.step(getModelLabel(llmConfig.model));
1215
1320
  for (const pkg of successfulPkgs) states.set(pkg, {
1216
1321
  name: pkg,
@@ -1266,7 +1371,7 @@ async function syncBaseSkill(packageSpec, config, cwd, update) {
1266
1371
  const shippedResult = handleShippedSkills(packageName, version, cwd, config.agent, config.global);
1267
1372
  if (shippedResult) {
1268
1373
  const shared = !config.global && getSharedSkillsDir(cwd);
1269
- if (shared) for (const shipped of shippedResult.shipped) linkSkillToAgents(shipped.skillName, shared, cwd);
1374
+ if (shared) for (const shipped of shippedResult.shipped) linkSkillToAgents(shipped.skillName, shared, cwd, config.agent);
1270
1375
  update(packageName, "done", "Published SKILL.md", versionKey);
1271
1376
  return "shipped";
1272
1377
  }
@@ -1338,7 +1443,7 @@ async function syncBaseSkill(packageSpec, config, cwd, update) {
1338
1443
  });
1339
1444
  writeFileSync(join(skillDir, "SKILL.md"), skillMd);
1340
1445
  const shared = !config.global && getSharedSkillsDir(cwd);
1341
- if (shared) linkSkillToAgents(skillDirName, shared, cwd);
1446
+ if (shared) linkSkillToAgents(skillDirName, shared, cwd, config.agent);
1342
1447
  if (!config.global) registerProject(cwd);
1343
1448
  update(packageName, "done", config.mode === "update" ? "Skill updated" : "Base skill created", versionKey);
1344
1449
  return {
@@ -1568,7 +1673,7 @@ async function syncSinglePackage(packageSpec, config) {
1568
1673
  if (shippedResult) {
1569
1674
  const shared = !config.global && getSharedSkillsDir(cwd);
1570
1675
  for (const shipped of shippedResult.shipped) {
1571
- if (shared) linkSkillToAgents(shipped.skillName, shared, cwd);
1676
+ if (shared) linkSkillToAgents(shipped.skillName, shared, cwd, config.agent);
1572
1677
  p.log.success(`Using published SKILL.md: ${shipped.skillName} → ${relative(cwd, shipped.skillDir)}`);
1573
1678
  }
1574
1679
  spin.stop(`Using published SKILL.md(s) from ${packageName}`);
@@ -1577,7 +1682,7 @@ async function syncSinglePackage(packageSpec, config) {
1577
1682
  spin.stop(`Resolved ${packageName}@${useCache ? versionKey : version}${config.force ? " (force)" : useCache ? " (cached)" : ""}`);
1578
1683
  if (!localVersion && !requestedTag && !isPrerelease(version)) {
1579
1684
  const nextTag = resolved.distTags?.next ?? resolved.distTags?.beta ?? resolved.distTags?.alpha;
1580
- if (nextTag) p.log.warn(`\x1B[33mNo local dependency found — using latest stable (${version}). Prerelease ${nextTag.version} available: skilld add ${packageName}@beta\x1B[0m`);
1685
+ if (nextTag && (!resolved.releasedAt || !nextTag.releasedAt || nextTag.releasedAt > resolved.releasedAt)) p.log.warn(`\x1B[33mNo local dependency found — using latest stable (${version}). Prerelease ${nextTag.version} available: skilld add ${packageName}@beta\x1B[0m`);
1581
1686
  }
1582
1687
  ensureCacheDir();
1583
1688
  const baseDir = resolveBaseDir(cwd, config.agent, config.global);
@@ -1619,12 +1724,13 @@ async function syncSinglePackage(packageSpec, config) {
1619
1724
  });
1620
1725
  writeFileSync(join(skillDir, "SKILL.md"), skillMd);
1621
1726
  const mergeShared = !config.global && getSharedSkillsDir(cwd);
1622
- if (mergeShared) linkSkillToAgents(skillDirName, mergeShared, cwd);
1727
+ if (mergeShared) linkSkillToAgents(skillDirName, mergeShared, cwd, config.agent);
1623
1728
  if (!config.global) registerProject(cwd);
1624
1729
  p.outro(`Merged ${packageName} into ${skillDirName}`);
1625
1730
  return;
1626
1731
  }
1627
- const features = readConfig().features ?? defaultFeatures;
1732
+ const features = { ...readConfig().features ?? defaultFeatures };
1733
+ if (config.noSearch) features.search = false;
1628
1734
  const resSpin = timedSpinner();
1629
1735
  resSpin.start("Finding resources");
1630
1736
  const resources = await fetchAndCacheResources({
@@ -1701,7 +1807,22 @@ async function syncSinglePackage(packageSpec, config) {
1701
1807
  p.log.success(config.mode === "update" ? `Updated skill: ${relative(cwd, skillDir)}` : `Created base skill: ${relative(cwd, skillDir)}`);
1702
1808
  if (!readConfig().skipLlm && (!config.yes || config.model)) {
1703
1809
  const llmConfig = await selectLlmConfig(config.model);
1704
- if (llmConfig) {
1810
+ if (llmConfig?.promptOnly) writePromptFiles({
1811
+ packageName,
1812
+ skillDir,
1813
+ version,
1814
+ hasIssues: resources.hasIssues,
1815
+ hasDiscussions: resources.hasDiscussions,
1816
+ hasReleases: resources.hasReleases,
1817
+ hasChangelog,
1818
+ docsType: resources.docsType,
1819
+ hasShippedDocs: shippedDocs,
1820
+ pkgFiles,
1821
+ sections: llmConfig.sections,
1822
+ customPrompt: llmConfig.customPrompt,
1823
+ features
1824
+ });
1825
+ else if (llmConfig) {
1705
1826
  p.log.step(getModelLabel(llmConfig.model));
1706
1827
  await enhanceSkillWithLLM({
1707
1828
  packageName,
@@ -1738,7 +1859,7 @@ async function syncSinglePackage(packageSpec, config) {
1738
1859
  }
1739
1860
  if (!isEject) {
1740
1861
  const shared = !config.global && getSharedSkillsDir(cwd);
1741
- if (shared) linkSkillToAgents(skillDirName, shared, cwd);
1862
+ if (shared) linkSkillToAgents(skillDirName, shared, cwd, config.agent);
1742
1863
  if (!config.global) registerProject(cwd);
1743
1864
  await ensureGitignore(shared ? SHARED_SKILLS_DIR : targets[config.agent].skillsDir, cwd, config.global);
1744
1865
  await ensureAgentInstructions(config.agent, cwd, config.global);
@@ -1773,8 +1894,16 @@ const addCommandDef = defineCommand({
1773
1894
  agent = await promptForAgent();
1774
1895
  if (!agent) return;
1775
1896
  }
1776
- if (!hasCompletedWizard()) await runWizard();
1777
1897
  const rawInputs = [...new Set([args.package, ...args._ || []].map((s) => s.trim()).filter(Boolean))];
1898
+ if (agent === "none") {
1899
+ const packages = [...new Set(rawInputs.flatMap((s) => s.split(/[,\s]+/)).map((s) => s.trim()).filter(Boolean))];
1900
+ for (const pkg of packages) await exportPortablePrompts(pkg, {
1901
+ force: args.force,
1902
+ agent: "none"
1903
+ });
1904
+ return;
1905
+ }
1906
+ if (!hasCompletedWizard()) await runWizard();
1778
1907
  const gitSources = [];
1779
1908
  const npmTokens = [];
1780
1909
  for (const input of rawInputs) {
@@ -1817,30 +1946,36 @@ const ejectCommandDef = defineCommand({
1817
1946
  description: "Eject skill with references as real files (portable, no symlinks)"
1818
1947
  },
1819
1948
  args: {
1820
- package: {
1949
+ "package": {
1821
1950
  type: "positional",
1822
1951
  description: "Package to eject",
1823
1952
  required: true
1824
1953
  },
1825
- name: {
1954
+ "name": {
1826
1955
  type: "string",
1827
1956
  alias: "n",
1828
1957
  description: "Custom skill directory name (default: derived from package)"
1829
1958
  },
1830
- out: {
1959
+ "out": {
1831
1960
  type: "string",
1832
1961
  alias: "o",
1833
1962
  description: "Output directory path override"
1834
1963
  },
1835
- from: {
1964
+ "from": {
1836
1965
  type: "string",
1837
1966
  description: "Collect releases/issues/discussions from this date onward (YYYY-MM-DD)"
1838
1967
  },
1968
+ "no-search": {
1969
+ type: "boolean",
1970
+ description: "Skip search index / embeddings generation",
1971
+ default: false
1972
+ },
1839
1973
  ...sharedArgs
1840
1974
  },
1841
1975
  async run({ args }) {
1842
1976
  const cwd = process.cwd();
1843
- const agent = resolveAgent(args.agent) || "claude-code";
1977
+ const resolved = resolveAgent(args.agent);
1978
+ const agent = resolved && resolved !== "none" ? resolved : "claude-code";
1844
1979
  if (!hasCompletedWizard()) await runWizard();
1845
1980
  const state = await getProjectState(cwd);
1846
1981
  p.intro(introLine({ state }));
@@ -1854,7 +1989,8 @@ const ejectCommandDef = defineCommand({
1854
1989
  debug: args.debug,
1855
1990
  eject: args.out || true,
1856
1991
  name: args.name,
1857
- from: args.from
1992
+ from: args.from,
1993
+ noSearch: args["no-search"]
1858
1994
  });
1859
1995
  }
1860
1996
  });
@@ -1897,10 +2033,22 @@ const updateCommandDef = defineCommand({
1897
2033
  const silent = !isInteractive();
1898
2034
  let agent = resolveAgent(args.agent);
1899
2035
  if (!agent) {
1900
- if (silent) return;
1901
2036
  agent = await promptForAgent();
1902
2037
  if (!agent) return;
1903
2038
  }
2039
+ if (agent === "none") {
2040
+ const state = await getProjectState(cwd);
2041
+ const packages = args.package ? [...new Set([args.package, ...args._ || []].flatMap((s) => s.split(/[,\s]+/)).map((s) => s.trim()).filter(Boolean))] : state.outdated.map((s) => s.packageName || s.name);
2042
+ if (packages.length === 0) {
2043
+ if (!silent) p.log.success("All skills up to date");
2044
+ return;
2045
+ }
2046
+ for (const pkg of packages) await exportPortablePrompts(pkg, {
2047
+ force: args.force,
2048
+ agent: "none"
2049
+ });
2050
+ return;
2051
+ }
1904
2052
  const config = readConfig();
1905
2053
  const state = await getProjectState(cwd);
1906
2054
  if (!silent) {
@@ -1937,6 +2085,131 @@ const updateCommandDef = defineCommand({
1937
2085
  });
1938
2086
  }
1939
2087
  });
1940
- export { DEFAULT_SECTIONS as a, classifyCachedDoc as c, ensureGitignore as d, indexResources as f, selectSkillSections as h, updateCommandDef as i, enhanceSkillWithLLM as l, selectModel as m, ejectCommandDef as n, SKILLD_MARKER_END as o, selectLlmConfig as p, syncCommand as r, SKILLD_MARKER_START as s, addCommandDef as t, ensureAgentInstructions as u };
2088
+ async function exportPortablePrompts(packageSpec, opts) {
2089
+ const { name: packageName } = parsePackageSpec(packageSpec);
2090
+ const sections = opts.sections ?? DEFAULT_SECTIONS;
2091
+ const spin = timedSpinner();
2092
+ spin.start(`Resolving ${packageSpec}`);
2093
+ const cwd = process.cwd();
2094
+ const localVersion = (await readLocalDependencies(cwd).catch(() => [])).find((d) => d.name === packageName)?.version;
2095
+ let resolved = (await resolvePackageDocsWithAttempts(packageName, {
2096
+ version: localVersion,
2097
+ cwd,
2098
+ onProgress: (step) => spin.message(`${packageName}: ${RESOLVE_STEP_LABELS[step]}`)
2099
+ })).package;
2100
+ if (!resolved) {
2101
+ spin.message(`Resolving local package: ${packageName}`);
2102
+ resolved = await resolveLocalDep(packageName, cwd);
2103
+ }
2104
+ if (!resolved) {
2105
+ spin.stop(`Could not find docs for: ${packageName}`);
2106
+ return;
2107
+ }
2108
+ const version = localVersion || resolved.version || "latest";
2109
+ const versionKey = getVersionKey(version);
2110
+ const useCache = !opts.force && isCached(packageName, version);
2111
+ if (!existsSync(join(cwd, "node_modules", packageName))) {
2112
+ spin.message(`Downloading ${packageName}@${version} dist`);
2113
+ await fetchPkgDist(packageName, version);
2114
+ }
2115
+ spin.stop(`Resolved ${packageName}@${useCache ? versionKey : version}`);
2116
+ ensureCacheDir();
2117
+ const skillDirName = computeSkillDirName(packageName);
2118
+ const features = readConfig().features ?? defaultFeatures;
2119
+ const agent = opts.agent === "none" ? null : opts.agent ?? await import("./detect.mjs").then((n) => n.r).then((m) => m.detectTargetAgent());
2120
+ const baseDir = agent ? resolveBaseDir(cwd, agent, false) : join(cwd, ".claude", "skills");
2121
+ const skillDir = opts.out ? resolve(cwd, opts.out) : join(baseDir, skillDirName);
2122
+ if (existsSync(skillDir) && !opts.force) {
2123
+ const existing = Object.values(SECTION_OUTPUT_FILES).filter((f) => existsSync(join(skillDir, f)));
2124
+ if (existing.length > 0) p.log.warn(`Overwriting existing output files in ${relative(cwd, skillDir)}: ${existing.join(", ")}`);
2125
+ }
2126
+ mkdirSync(skillDir, { recursive: true });
2127
+ const resSpin = timedSpinner();
2128
+ resSpin.start("Fetching resources");
2129
+ const resources = await fetchAndCacheResources({
2130
+ packageName,
2131
+ resolved,
2132
+ version,
2133
+ useCache,
2134
+ features,
2135
+ onProgress: (msg) => resSpin.message(msg)
2136
+ });
2137
+ resSpin.stop("Resources ready");
2138
+ for (const w of resources.warnings) p.log.warn(`\x1B[33m${w}\x1B[0m`);
2139
+ linkAllReferences(skillDir, packageName, cwd, version, resources.docsType, void 0, features, resources.repoInfo);
2140
+ const hasChangelog = detectChangelog(resolvePkgDir(packageName, cwd, version), getCacheDir(packageName, version));
2141
+ const shippedDocs = hasShippedDocs(packageName, cwd, version);
2142
+ const pkgFiles = getPkgKeyFiles(packageName, cwd, version);
2143
+ const docFiles = listReferenceFiles(skillDir);
2144
+ const prompts = buildAllSectionPrompts({
2145
+ packageName,
2146
+ skillDir,
2147
+ version,
2148
+ hasIssues: resources.hasIssues,
2149
+ hasDiscussions: resources.hasDiscussions,
2150
+ hasReleases: resources.hasReleases,
2151
+ hasChangelog,
2152
+ docFiles,
2153
+ docsType: resources.docsType,
2154
+ hasShippedDocs: shippedDocs,
2155
+ pkgFiles,
2156
+ features,
2157
+ sections
2158
+ });
2159
+ ejectReferences(skillDir, packageName, cwd, version, resources.docsType, features, resources.repoInfo);
2160
+ const skilldDir = join(skillDir, ".skilld");
2161
+ if (existsSync(skilldDir)) rmSync(skilldDir, {
2162
+ recursive: true,
2163
+ force: true
2164
+ });
2165
+ for (const [section, prompt] of prompts) {
2166
+ const portable = portabilizePrompt(prompt, section);
2167
+ writeFileSync(join(skillDir, `PROMPT_${section}.md`), portable);
2168
+ }
2169
+ const relatedSkills = await findRelatedSkills(packageName, join(skillDir, ".."));
2170
+ const skillMd = generateSkillMd({
2171
+ name: packageName,
2172
+ version,
2173
+ releasedAt: resolved.releasedAt,
2174
+ description: resolved.description,
2175
+ dependencies: resolved.dependencies,
2176
+ distTags: resolved.distTags,
2177
+ relatedSkills,
2178
+ hasIssues: resources.hasIssues,
2179
+ hasDiscussions: resources.hasDiscussions,
2180
+ hasReleases: resources.hasReleases,
2181
+ hasChangelog,
2182
+ docsType: resources.docsType,
2183
+ hasShippedDocs: shippedDocs,
2184
+ pkgFiles,
2185
+ repoUrl: resolved.repoUrl,
2186
+ features,
2187
+ eject: true
2188
+ });
2189
+ writeFileSync(join(skillDir, "SKILL.md"), skillMd);
2190
+ const repoSlug = resolved.repoUrl?.match(/github\.com\/([^/]+\/[^/]+?)(?:\.git)?(?:[/#]|$)/)?.[1];
2191
+ writeLock(baseDir, skillDirName, {
2192
+ packageName,
2193
+ version,
2194
+ repo: repoSlug,
2195
+ source: resources.docSource,
2196
+ syncedAt: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
2197
+ generator: "skilld"
2198
+ });
2199
+ if (agent) {
2200
+ const shared = getSharedSkillsDir(cwd);
2201
+ if (shared) linkSkillToAgents(skillDirName, shared, cwd, agent);
2202
+ await ensureGitignore(shared ? SHARED_SKILLS_DIR : targets[agent].skillsDir, cwd, false);
2203
+ await ensureAgentInstructions(agent, cwd, false);
2204
+ registerProject(cwd);
2205
+ } else await ensureGitignore(".claude/skills", cwd, false);
2206
+ const relDir = relative(cwd, skillDir);
2207
+ const sectionList = [...prompts.keys()];
2208
+ p.log.success(`Skill installed to ${relDir}`);
2209
+ const promptFiles = sectionList.map((s) => `PROMPT_${s}.md`).join(", ");
2210
+ const outputFileList = sectionList.map((s) => SECTION_OUTPUT_FILES[s]).join(", ");
2211
+ p.log.info(`Have your agent enhance the skill. Give it this prompt:\n\x1B[2m\x1B[3m Read each prompt file (${promptFiles}) in ${relDir}/, read the\n referenced files, then write your output to the matching file (${outputFileList}).\n When done, run: skilld assemble\x1B[0m`);
2212
+ }
2213
+ export { writePromptFiles as _, updateCommandDef as a, SKILLD_MARKER_START as c, ensureAgentInstructions as d, ensureGitignore as f, selectSkillSections as g, selectModel as h, syncCommand as i, classifyCachedDoc as l, selectLlmConfig as m, ejectCommandDef as n, DEFAULT_SECTIONS as o, indexResources as p, exportPortablePrompts as r, SKILLD_MARKER_END as s, addCommandDef as t, enhanceSkillWithLLM as u };
1941
2214
 
1942
2215
  //# sourceMappingURL=sync.mjs.map