skilld 0.4.0 → 0.4.1

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.
package/dist/cli.mjs CHANGED
@@ -1,23 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
  import { _ as detectInstalledAgents, a as optimizeDocs, b as targets, c as computeSkillDirName, f as unlinkSkillFromAgents, i as getModelName, n as getAvailableModels, o as generateSkillMd, r as getModelLabel, t as detectImportedPackages, u as linkSkillToAgents, v as detectTargetAgent, y as getAgentVersion } from "./_chunks/detect-imports.mjs";
3
3
  import { i as getCacheDir, o as getVersionKey, r as getPackageDbPath, t as CACHE_DIR } from "./_chunks/config.mjs";
4
- import { n as sanitizeMarkdown } from "./_chunks/sanitize2.mjs";
5
- import { a as getShippedSkills, c as linkCachedDir, d as linkShippedSkill, g as resolvePkgDir, i as getPkgKeyFiles, l as linkPkg, m as readCachedDocs, n as clearCache, o as hasShippedDocs, p as listReferenceFiles, r as ensureCacheDir, s as isCached, u as linkPkgNamed, v as writeToCache } from "./_chunks/storage.mjs";
4
+ import { a as getShippedSkills, b as sanitizeMarkdown, c as linkCachedDir, d as linkShippedSkill, g as resolvePkgDir, i as getPkgKeyFiles, l as linkPkg, m as readCachedDocs, n as clearCache, o as hasShippedDocs, p as listReferenceFiles, r as ensureCacheDir, s as isCached, u as linkPkgNamed, v as writeToCache } from "./_chunks/storage.mjs";
6
5
  import "./cache/index.mjs";
7
6
  import { closePool, createIndex, openPool, searchPooled, searchSnippets } from "./retriv/index.mjs";
8
- import { C as fetchGitDocs, D as isShallowGitDocs, E as fetchReadmeContent, F as fetchGitHubIssues, I as formatIssueAsMarkdown, L as generateIssueIndex, M as fetchGitHubDiscussions, N as formatDiscussionAsMarkdown, P as generateDiscussionIndex, R as isGhAvailable, a as fetchNpmRegistryMeta, b as normalizeLlmsLinks, f as resolveLocalPackageDocs, g as downloadLlmsDocs, h as searchNpmPackages, i as fetchNpmPackage, j as resolveEntryFiles, l as readLocalDependencies, m as resolvePackageDocsWithAttempts, o as fetchPkgDist, p as resolvePackageDocs, r as fetchLatestVersion, t as fetchReleaseNotes, v as fetchLlmsTxt } from "./_chunks/releases.mjs";
7
+ import { C as fetchGitDocs, D as isShallowGitDocs, E as fetchReadmeContent, G as fetchGitHubIssues, H as fetchGitHubDiscussions, J as isGhAvailable, K as formatIssueAsMarkdown, M as parseGitSkillInput, P as $fetch, U as formatDiscussionAsMarkdown, V as resolveEntryFiles, W as generateDiscussionIndex, a as fetchNpmRegistryMeta, b as normalizeLlmsLinks, f as resolveLocalPackageDocs, g as downloadLlmsDocs, h as searchNpmPackages, i as fetchNpmPackage, j as fetchGitSkills, l as readLocalDependencies, m as resolvePackageDocsWithAttempts, o as fetchPkgDist, p as resolvePackageDocs, q as generateIssueIndex, r as fetchLatestVersion, t as fetchReleaseNotes, v as fetchLlmsTxt, z as parseGitHubUrl } from "./_chunks/releases.mjs";
9
8
  import { n as yamlParseKV, r as yamlUnescape, t as yamlEscape } from "./_chunks/yaml.mjs";
10
- import { a as $fetch, d as parseGitHubUrl } from "./_chunks/git-skills.mjs";
11
9
  import "./sources/index.mjs";
12
10
  import "./agent/index.mjs";
11
+ import { n as shutdownWorker } from "./_chunks/pool2.mjs";
13
12
  import { createRequire } from "node:module";
14
13
  import { homedir } from "node:os";
15
- import { join, relative, resolve } from "pathe";
14
+ import { dirname, join, relative, resolve } from "pathe";
16
15
  import { appendFileSync, copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, statSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
17
- import { execSync } from "node:child_process";
16
+ import { execSync, spawn } from "node:child_process";
18
17
  import pLimit from "p-limit";
19
18
  import * as p from "@clack/prompts";
20
19
  import { defineCommand, runMain } from "citty";
20
+ import logUpdate from "log-update";
21
21
  import { detectCurrentAgent } from "unagent/env";
22
22
  const LLM_CACHE_DIR = join(CACHE_DIR, "llm-cache");
23
23
  const LLM_CACHE_MAX_AGE = 10080 * 60 * 1e3;
@@ -871,6 +871,290 @@ async function indexResources(opts) {
871
871
  }
872
872
  });
873
873
  }
874
+ const STATUS_ICONS = {
875
+ pending: "○",
876
+ resolving: "◐",
877
+ downloading: "◒",
878
+ embedding: "◓",
879
+ exploring: "◔",
880
+ thinking: "◔",
881
+ generating: "◑",
882
+ done: "✓",
883
+ error: "✗"
884
+ };
885
+ const STATUS_COLORS = {
886
+ pending: "\x1B[90m",
887
+ resolving: "\x1B[36m",
888
+ downloading: "\x1B[36m",
889
+ embedding: "\x1B[36m",
890
+ exploring: "\x1B[34m",
891
+ thinking: "\x1B[35m",
892
+ generating: "\x1B[33m",
893
+ done: "\x1B[32m",
894
+ error: "\x1B[31m"
895
+ };
896
+ async function syncPackagesParallel(config) {
897
+ const { packages, concurrency = 5 } = config;
898
+ const agent = targets[config.agent];
899
+ const states = /* @__PURE__ */ new Map();
900
+ const cwd = process.cwd();
901
+ for (const pkg of packages) states.set(pkg, {
902
+ name: pkg,
903
+ status: "pending",
904
+ message: "Waiting..."
905
+ });
906
+ function render() {
907
+ const maxNameLen = Math.max(...packages.map((p) => p.length), 20);
908
+ const lines = [...states.values()].map((s) => {
909
+ const icon = STATUS_ICONS[s.status];
910
+ const color = STATUS_COLORS[s.status];
911
+ const reset = "\x1B[0m";
912
+ const dim = "\x1B[90m";
913
+ const name = s.name.padEnd(maxNameLen);
914
+ const version = s.version ? `${dim}${s.version}${reset} ` : "";
915
+ const elapsed = (s.status === "done" || s.status === "error") && s.startedAt && s.completedAt ? ` ${dim}(${formatDuration(s.completedAt - s.startedAt)})${reset}` : "";
916
+ const preview = s.streamPreview ? ` ${dim}${s.streamPreview}${reset}` : "";
917
+ return ` ${color}${icon}${reset} ${name} ${version}${s.message}${elapsed}${preview}`;
918
+ });
919
+ const doneCount = [...states.values()].filter((s) => s.status === "done").length;
920
+ const errorCount = [...states.values()].filter((s) => s.status === "error").length;
921
+ logUpdate(`\x1B[1mSyncing ${packages.length} packages\x1B[0m (${doneCount} done${errorCount > 0 ? `, ${errorCount} failed` : ""})\n` + lines.join("\n"));
922
+ }
923
+ function update(pkg, status, message, version) {
924
+ const state = states.get(pkg);
925
+ if (!state.startedAt && status !== "pending") state.startedAt = performance.now();
926
+ if ((status === "done" || status === "error") && !state.completedAt) state.completedAt = performance.now();
927
+ state.status = status;
928
+ state.message = message;
929
+ state.streamPreview = void 0;
930
+ if (version) state.version = version;
931
+ render();
932
+ }
933
+ ensureCacheDir();
934
+ render();
935
+ const limit = pLimit(concurrency);
936
+ const skillData = /* @__PURE__ */ new Map();
937
+ const baseResults = await Promise.allSettled(packages.map((pkg) => limit(() => syncBaseSkill(pkg, config, cwd, update))));
938
+ logUpdate.done();
939
+ const successfulPkgs = [];
940
+ const shippedPkgs = [];
941
+ const errors = [];
942
+ for (let i = 0; i < baseResults.length; i++) {
943
+ const r = baseResults[i];
944
+ if (r.status === "fulfilled" && r.value !== "shipped") {
945
+ successfulPkgs.push(packages[i]);
946
+ skillData.set(packages[i], r.value);
947
+ } else if (r.status === "fulfilled" && r.value === "shipped") shippedPkgs.push(packages[i]);
948
+ else if (r.status === "rejected") {
949
+ const err = r.reason;
950
+ const reason = err instanceof Error ? `${err.message}\n${err.stack}` : String(err);
951
+ errors.push({
952
+ pkg: packages[i],
953
+ reason
954
+ });
955
+ }
956
+ }
957
+ const skillMsg = `Created ${successfulPkgs.length} base skills${shippedPkgs.length > 1 ? ` (Skipping ${shippedPkgs.length})` : ""}`;
958
+ p.log.success(skillMsg);
959
+ if (errors.length > 0) for (const { pkg, reason } of errors) p.log.error(` ${pkg}: ${reason}`);
960
+ const globalConfig = readConfig();
961
+ if (successfulPkgs.length > 0 && !globalConfig.skipLlm && !(config.yes && !config.model)) {
962
+ const llmConfig = await selectLlmConfig(config.model);
963
+ if (llmConfig) {
964
+ p.log.step(getModelLabel(llmConfig.model));
965
+ for (const pkg of successfulPkgs) states.set(pkg, {
966
+ name: pkg,
967
+ status: "pending",
968
+ message: "Waiting..."
969
+ });
970
+ render();
971
+ const llmResults = await Promise.allSettled(successfulPkgs.map((pkg) => limit(() => enhanceWithLLM(pkg, skillData.get(pkg), {
972
+ ...config,
973
+ model: llmConfig.model
974
+ }, cwd, update, llmConfig.sections, llmConfig.customPrompt))));
975
+ logUpdate.done();
976
+ const llmSucceeded = llmResults.filter((r) => r.status === "fulfilled").length;
977
+ p.log.success(`Enhanced ${llmSucceeded}/${successfulPkgs.length} skills with LLM`);
978
+ }
979
+ }
980
+ await ensureGitignore(getSharedSkillsDir(cwd) ? SHARED_SKILLS_DIR : agent.skillsDir, cwd, config.global);
981
+ await shutdownWorker();
982
+ p.outro(`Synced ${successfulPkgs.length}/${packages.length} packages`);
983
+ }
984
+ async function syncBaseSkill(packageName, config, cwd, update) {
985
+ const localVersion = (await readLocalDependencies(cwd).catch(() => [])).find((d) => d.name === packageName)?.version;
986
+ const { package: resolvedPkg, attempts } = await resolvePackageDocsWithAttempts(packageName, {
987
+ version: localVersion,
988
+ cwd,
989
+ onProgress: (step) => update(packageName, "resolving", RESOLVE_STEP_LABELS[step])
990
+ });
991
+ let resolved = resolvedPkg;
992
+ if (!resolved) {
993
+ update(packageName, "resolving", "Local package...");
994
+ resolved = await resolveLocalDep(packageName, cwd);
995
+ }
996
+ if (!resolved) {
997
+ const npmAttempt = attempts.find((a) => a.source === "npm");
998
+ let reason;
999
+ if (npmAttempt?.status === "not-found") {
1000
+ const suggestions = await searchNpmPackages(packageName, 3);
1001
+ const hint = suggestions.length > 0 ? ` (try: ${suggestions.map((s) => s.name).join(", ")})` : "";
1002
+ reason = (npmAttempt.message || "Not on npm") + hint;
1003
+ } else reason = attempts.filter((a) => a.status !== "success").map((a) => a.message || a.source).join("; ") || "No docs found";
1004
+ update(packageName, "error", reason);
1005
+ throw new Error(`Could not find docs for: ${packageName}`);
1006
+ }
1007
+ const version = localVersion || resolved.version || "latest";
1008
+ const versionKey = getVersionKey(version);
1009
+ if (!existsSync(join(cwd, "node_modules", packageName))) {
1010
+ update(packageName, "downloading", "Downloading dist...", versionKey);
1011
+ await fetchPkgDist(packageName, version);
1012
+ }
1013
+ const shippedResult = handleShippedSkills(packageName, version, cwd, config.agent, config.global);
1014
+ if (shippedResult) {
1015
+ const shared = !config.global && getSharedSkillsDir(cwd);
1016
+ if (shared) for (const shipped of shippedResult.shipped) linkSkillToAgents(shipped.skillName, shared, cwd);
1017
+ update(packageName, "done", "Published SKILL.md", versionKey);
1018
+ return "shipped";
1019
+ }
1020
+ if (config.force) forceClearCache(packageName, version);
1021
+ const useCache = isCached(packageName, version);
1022
+ if (useCache) update(packageName, "downloading", "Using cache", versionKey);
1023
+ else update(packageName, "downloading", config.force ? "Re-fetching docs..." : "Fetching docs...", versionKey);
1024
+ const baseDir = resolveBaseDir(cwd, config.agent, config.global);
1025
+ const skillDirName = computeSkillDirName(packageName, resolved.repoUrl);
1026
+ const skillDir = join(baseDir, skillDirName);
1027
+ mkdirSync(skillDir, { recursive: true });
1028
+ const features = readConfig().features ?? defaultFeatures;
1029
+ const resources = await fetchAndCacheResources({
1030
+ packageName,
1031
+ resolved,
1032
+ version,
1033
+ useCache,
1034
+ features,
1035
+ onProgress: (msg) => update(packageName, "downloading", msg, versionKey)
1036
+ });
1037
+ update(packageName, "downloading", "Linking references...", versionKey);
1038
+ linkAllReferences(skillDir, packageName, cwd, version, resources.docsType);
1039
+ update(packageName, "embedding", "Indexing docs", versionKey);
1040
+ await indexResources({
1041
+ packageName,
1042
+ version,
1043
+ cwd,
1044
+ docsToIndex: resources.docsToIndex,
1045
+ features,
1046
+ onProgress: (msg) => update(packageName, "embedding", msg, versionKey)
1047
+ });
1048
+ const hasChangelog = detectChangelog(resolvePkgDir(packageName, cwd, version));
1049
+ const relatedSkills = await findRelatedSkills(packageName, baseDir);
1050
+ const shippedDocs = hasShippedDocs(packageName, cwd, version);
1051
+ const pkgFiles = getPkgKeyFiles(packageName, cwd, version);
1052
+ const repoSlug = resolved.repoUrl?.match(/github\.com\/([^/]+\/[^/]+?)(?:\.git)?(?:[/#]|$)/)?.[1];
1053
+ linkPkgNamed(skillDir, packageName, cwd, version);
1054
+ writeLock(baseDir, skillDirName, {
1055
+ packageName,
1056
+ version,
1057
+ repo: repoSlug,
1058
+ source: resources.docSource,
1059
+ syncedAt: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
1060
+ generator: "skilld"
1061
+ });
1062
+ const updatedLock = readLock(baseDir)?.skills[skillDirName];
1063
+ const allPackages = parsePackages(updatedLock?.packages).map((p) => ({ name: p.name }));
1064
+ const skillMd = generateSkillMd({
1065
+ name: packageName,
1066
+ version,
1067
+ releasedAt: resolved.releasedAt,
1068
+ description: resolved.description,
1069
+ dependencies: resolved.dependencies,
1070
+ distTags: resolved.distTags,
1071
+ relatedSkills,
1072
+ hasIssues: resources.hasIssues,
1073
+ hasDiscussions: resources.hasDiscussions,
1074
+ hasReleases: resources.hasReleases,
1075
+ hasChangelog,
1076
+ docsType: resources.docsType,
1077
+ hasShippedDocs: shippedDocs,
1078
+ pkgFiles,
1079
+ dirName: skillDirName,
1080
+ packages: allPackages.length > 1 ? allPackages : void 0,
1081
+ repoUrl: resolved.repoUrl
1082
+ });
1083
+ writeFileSync(join(skillDir, "SKILL.md"), skillMd);
1084
+ const shared = !config.global && getSharedSkillsDir(cwd);
1085
+ if (shared) linkSkillToAgents(skillDirName, shared, cwd);
1086
+ if (!config.global) registerProject(cwd);
1087
+ update(packageName, "done", "Base skill created", versionKey);
1088
+ return {
1089
+ resolved,
1090
+ version,
1091
+ skillDirName,
1092
+ docsType: resources.docsType,
1093
+ hasIssues: resources.hasIssues,
1094
+ hasDiscussions: resources.hasDiscussions,
1095
+ hasReleases: resources.hasReleases,
1096
+ hasChangelog,
1097
+ shippedDocs,
1098
+ pkgFiles,
1099
+ relatedSkills,
1100
+ packages: allPackages.length > 1 ? allPackages : void 0
1101
+ };
1102
+ }
1103
+ async function enhanceWithLLM(packageName, data, config, cwd, update, sections, customPrompt) {
1104
+ const versionKey = getVersionKey(data.version);
1105
+ const skillDir = join(resolveBaseDir(cwd, config.agent, config.global), data.skillDirName);
1106
+ const hasGithub = data.hasIssues || data.hasDiscussions;
1107
+ const docFiles = listReferenceFiles(skillDir);
1108
+ update(packageName, "generating", config.model, versionKey);
1109
+ const { optimized, wasOptimized, error } = await optimizeDocs({
1110
+ packageName,
1111
+ skillDir,
1112
+ model: config.model,
1113
+ version: data.version,
1114
+ hasGithub,
1115
+ hasReleases: data.hasReleases,
1116
+ hasChangelog: data.hasChangelog,
1117
+ docFiles,
1118
+ docsType: data.docsType,
1119
+ hasShippedDocs: data.shippedDocs,
1120
+ noCache: config.force,
1121
+ debug: config.debug,
1122
+ sections,
1123
+ customPrompt,
1124
+ onProgress: (progress) => {
1125
+ const status = progress.type === "reasoning" ? "exploring" : "generating";
1126
+ const sectionPrefix = progress.section ? `[${progress.section}] ` : "";
1127
+ update(packageName, status, progress.chunk.startsWith("[") ? `${sectionPrefix}${progress.chunk}` : `${sectionPrefix}${config.model}`, versionKey);
1128
+ }
1129
+ });
1130
+ if (error) {
1131
+ update(packageName, "error", error, versionKey);
1132
+ throw new Error(error);
1133
+ }
1134
+ if (wasOptimized) {
1135
+ const skillMd = generateSkillMd({
1136
+ name: packageName,
1137
+ version: data.version,
1138
+ releasedAt: data.resolved.releasedAt,
1139
+ dependencies: data.resolved.dependencies,
1140
+ distTags: data.resolved.distTags,
1141
+ body: optimized,
1142
+ relatedSkills: data.relatedSkills,
1143
+ hasIssues: data.hasIssues,
1144
+ hasDiscussions: data.hasDiscussions,
1145
+ hasReleases: data.hasReleases,
1146
+ hasChangelog: data.hasChangelog,
1147
+ docsType: data.docsType,
1148
+ hasShippedDocs: data.shippedDocs,
1149
+ pkgFiles: data.pkgFiles,
1150
+ dirName: data.skillDirName,
1151
+ packages: data.packages,
1152
+ repoUrl: data.resolved.repoUrl
1153
+ });
1154
+ writeFileSync(join(skillDir, "SKILL.md"), skillMd);
1155
+ }
1156
+ update(packageName, "done", "Skill optimized", versionKey);
1157
+ }
874
1158
  function showResolveAttempts(attempts) {
875
1159
  if (attempts.length === 0) return;
876
1160
  p.log.message("\x1B[90mResolution attempts:\x1B[0m");
@@ -901,30 +1185,8 @@ async function ensureGitignore(skillsDir, cwd, isGlobal) {
901
1185
  }
902
1186
  async function syncCommand(state, opts) {
903
1187
  if (opts.packages && opts.packages.length > 0) {
904
- if (opts.packages.length > 1) {
905
- const { syncPackagesParallel } = await import("./_chunks/sync-parallel.mjs");
906
- return syncPackagesParallel({
907
- packages: opts.packages,
908
- global: opts.global,
909
- agent: opts.agent,
910
- model: opts.model,
911
- yes: opts.yes,
912
- force: opts.force,
913
- debug: opts.debug
914
- });
915
- }
916
- await syncSinglePackage(opts.packages[0], opts);
917
- return;
918
- }
919
- const packages = await interactivePicker(state);
920
- if (!packages || packages.length === 0) {
921
- p.outro("No packages selected");
922
- return;
923
- }
924
- if (packages.length > 1) {
925
- const { syncPackagesParallel } = await import("./_chunks/sync-parallel.mjs");
926
- return syncPackagesParallel({
927
- packages,
1188
+ if (opts.packages.length > 1) return syncPackagesParallel({
1189
+ packages: opts.packages,
928
1190
  global: opts.global,
929
1191
  agent: opts.agent,
930
1192
  model: opts.model,
@@ -932,7 +1194,23 @@ async function syncCommand(state, opts) {
932
1194
  force: opts.force,
933
1195
  debug: opts.debug
934
1196
  });
1197
+ await syncSinglePackage(opts.packages[0], opts);
1198
+ return;
1199
+ }
1200
+ const packages = await interactivePicker(state);
1201
+ if (!packages || packages.length === 0) {
1202
+ p.outro("No packages selected");
1203
+ return;
935
1204
  }
1205
+ if (packages.length > 1) return syncPackagesParallel({
1206
+ packages,
1207
+ global: opts.global,
1208
+ agent: opts.agent,
1209
+ model: opts.model,
1210
+ yes: opts.yes,
1211
+ force: opts.force,
1212
+ debug: opts.debug
1213
+ });
936
1214
  await syncSinglePackage(packages[0], opts);
937
1215
  }
938
1216
  async function interactivePicker(state) {
@@ -1299,7 +1577,6 @@ async function syncSinglePackage(packageName, config) {
1299
1577
  if (shared) linkSkillToAgents(skillDirName, shared, cwd);
1300
1578
  if (!config.global) registerProject(cwd);
1301
1579
  await ensureGitignore(shared ? SHARED_SKILLS_DIR : targets[config.agent].skillsDir, cwd, config.global);
1302
- const { shutdownWorker } = await import("./_chunks/pool.mjs");
1303
1580
  await shutdownWorker();
1304
1581
  p.outro(`Synced ${packageName} to ${relative(cwd, skillDir)}`);
1305
1582
  }
@@ -1414,7 +1691,6 @@ async function installCommand(opts) {
1414
1691
  continue;
1415
1692
  }
1416
1693
  if (info.source === "github" || info.source === "gitlab" || info.source === "local") {
1417
- const { fetchGitSkills } = await import("./_chunks/git-skills.mjs").then((n) => n.n);
1418
1694
  const match = (await fetchGitSkills({
1419
1695
  type: info.source,
1420
1696
  ...info.repo?.includes("/") ? {
@@ -1426,8 +1702,6 @@ async function installCommand(opts) {
1426
1702
  ...info.source === "local" ? { localPath: info.repo } : {}
1427
1703
  })).skills.find((s) => s.name === name);
1428
1704
  if (match) {
1429
- const { sanitizeMarkdown } = await import("./_chunks/sanitize2.mjs").then((n) => n.r);
1430
- const { dirname } = await import("pathe");
1431
1705
  const skillDir = join(skillsDir, name);
1432
1706
  mkdirSync(skillDir, { recursive: true });
1433
1707
  writeFileSync(join(skillDir, "SKILL.md"), sanitizeMarkdown(match.content));
@@ -1642,7 +1916,6 @@ async function installCommand(opts) {
1642
1916
  for (const [name, info] of Object.entries(lock.skills)) writeLock(skillsDir, name, info);
1643
1917
  if (shared) for (const [name] of skills) linkSkillToAgents(name, shared, cwd);
1644
1918
  else syncLockfilesToDirs(lock, allSkillsDirs.filter((d) => d !== skillsDir));
1645
- const { shutdownWorker } = await import("./_chunks/pool.mjs");
1646
1919
  await shutdownWorker();
1647
1920
  p.outro("Install complete");
1648
1921
  }
@@ -2716,6 +2989,61 @@ async function runWizard() {
2716
2989
  });
2717
2990
  p.outro("Thanks, you're all set! Change config anytime with `skilld config`.");
2718
2991
  }
2992
+ async function syncGitSkills(opts) {
2993
+ const { source, agent, global: isGlobal, yes } = opts;
2994
+ const cwd = process.cwd();
2995
+ const agentConfig = targets[agent];
2996
+ const baseDir = isGlobal ? join(CACHE_DIR, "skills") : join(cwd, agentConfig.skillsDir);
2997
+ const label = source.type === "local" ? source.localPath : `${source.owner}/${source.repo}`;
2998
+ const spin = timedSpinner();
2999
+ spin.start(`Fetching skills from ${label}`);
3000
+ const { skills, commitSha } = await fetchGitSkills(source, (msg) => spin.message(msg));
3001
+ if (skills.length === 0) {
3002
+ spin.stop(`No skills found in ${label}`);
3003
+ return;
3004
+ }
3005
+ spin.stop(`Found ${skills.length} skill(s) in ${label}`);
3006
+ let selected = skills;
3007
+ if (source.skillPath) selected = skills;
3008
+ else if (skills.length > 1 && !yes) {
3009
+ const choices = await p.multiselect({
3010
+ message: `Select skills to install from ${label}`,
3011
+ options: skills.map((s) => ({
3012
+ label: s.name,
3013
+ value: s.name,
3014
+ hint: s.description || s.path
3015
+ })),
3016
+ initialValues: skills.map((s) => s.name)
3017
+ });
3018
+ if (p.isCancel(choices)) return;
3019
+ const selectedNames = new Set(choices);
3020
+ selected = skills.filter((s) => selectedNames.has(s.name));
3021
+ }
3022
+ mkdirSync(baseDir, { recursive: true });
3023
+ for (const skill of selected) {
3024
+ const skillDir = join(baseDir, skill.name);
3025
+ mkdirSync(skillDir, { recursive: true });
3026
+ writeFileSync(join(skillDir, "SKILL.md"), sanitizeMarkdown(skill.content));
3027
+ if (skill.files.length > 0) for (const f of skill.files) {
3028
+ const filePath = join(skillDir, ".skilld", f.path);
3029
+ mkdirSync(dirname(filePath), { recursive: true });
3030
+ writeFileSync(filePath, f.content);
3031
+ }
3032
+ const sourceType = source.type === "local" ? "local" : source.type;
3033
+ writeLock(baseDir, skill.name, {
3034
+ source: sourceType,
3035
+ repo: source.type === "local" ? source.localPath : `${source.owner}/${source.repo}`,
3036
+ path: skill.path || void 0,
3037
+ ref: source.ref || "main",
3038
+ commit: commitSha,
3039
+ syncedAt: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
3040
+ generator: "external"
3041
+ });
3042
+ }
3043
+ if (!isGlobal) registerProject(cwd);
3044
+ const names = selected.map((s) => `\x1B[36m${s.name}\x1B[0m`).join(", ");
3045
+ p.log.success(`Installed ${names}`);
3046
+ }
2719
3047
  const _emit = process.emit;
2720
3048
  process.emit = (event, ...args) => event === "warning" && args[0]?.name === "ExperimentalWarning" && args[0]?.message?.includes("SQLite") ? false : _emit.apply(process, [event, ...args]);
2721
3049
  function getRepoHint(name, cwd) {
@@ -2959,8 +3287,6 @@ const addCommand = defineCommand({
2959
3287
  if (!agent) return;
2960
3288
  }
2961
3289
  const rawInputs = [...new Set([args.package, ...args._ || []].map((s) => s.trim()).filter(Boolean))];
2962
- const { parseGitSkillInput } = await import("./_chunks/git-skills.mjs").then((n) => n.n);
2963
- const { syncGitSkills } = await import("./_chunks/sync-git.mjs");
2964
3290
  const gitSources = [];
2965
3291
  const npmTokens = [];
2966
3292
  for (const input of rawInputs) {
@@ -3232,7 +3558,6 @@ runMain(defineCommand({
3232
3558
  const cwd = process.cwd();
3233
3559
  if (args.prepare) {
3234
3560
  if (args.background) {
3235
- const { spawn } = await import("node:child_process");
3236
3561
  spawn(process.execPath, [
3237
3562
  process.argv[1],
3238
3563
  "--prepare",
@@ -3579,6 +3904,6 @@ runMain(defineCommand({
3579
3904
  }
3580
3905
  }
3581
3906
  }));
3582
- export { registerProject as S, writeLock as _, fetchAndCacheResources as a, defaultFeatures as b, handleShippedSkills as c, resolveBaseDir as d, resolveLocalDep as f, readLock as g, parsePackages as h, detectChangelog as i, indexResources as l, getSharedSkillsDir as m, selectLlmConfig as n, findRelatedSkills as o, SHARED_SKILLS_DIR as p, RESOLVE_STEP_LABELS as r, forceClearCache as s, ensureGitignore as t, linkAllReferences as u, formatDuration as v, readConfig as x, timedSpinner as y };
3907
+ export {};
3583
3908
 
3584
3909
  //# sourceMappingURL=cli.mjs.map