skild 0.4.7 → 0.5.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.
Files changed (2) hide show
  1. package/dist/index.js +104 -86
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -19,6 +19,7 @@ import {
19
19
  materializeSourceToTemp,
20
20
  resolveRegistryAlias,
21
21
  resolveRegistryUrl,
22
+ stripSourceRef,
22
23
  SkildError,
23
24
  PLATFORMS as PLATFORMS2
24
25
  } from "@skild/core";
@@ -284,7 +285,9 @@ var PLATFORM_DISPLAY = {
284
285
  codex: "Codex",
285
286
  copilot: "Copilot",
286
287
  antigravity: "Antigravity",
287
- opencode: "OpenCode"
288
+ opencode: "OpenCode",
289
+ cursor: "Cursor",
290
+ windsurf: "Windsurf"
288
291
  };
289
292
  function formatTreeNode(node, selection, isCursor, options = {}) {
290
293
  const { state, selectedCount } = selection;
@@ -433,6 +436,8 @@ function discoverSkillDirsWithHeuristics(rootDir, options) {
433
436
  path.join(".claude", "skills"),
434
437
  path.join(".codex", "skills"),
435
438
  path.join(".opencode", "skill"),
439
+ path.join(".cursor", "skills"),
440
+ path.join(".windsurf", "skills"),
436
441
  path.join(".github", "skills")
437
442
  ];
438
443
  for (const rel of candidates) {
@@ -534,7 +539,8 @@ async function resolveSource(ctx) {
534
539
  const registryUrl = resolveRegistryUrl(ctx.registryUrl);
535
540
  const resolved = await resolveRegistryAlias(registryUrl, ctx.resolvedSource);
536
541
  if (!ctx.jsonOnly) {
537
- logger.info(`Resolved ${chalk3.cyan(ctx.resolvedSource)} \u2192 ${chalk3.cyan(resolved.spec)} (${resolved.type})`);
542
+ const displaySpec = stripSourceRef(resolved.spec);
543
+ logger.info(`Resolved ${chalk3.cyan(ctx.resolvedSource)} \u2192 ${chalk3.cyan(displaySpec)} (${resolved.type})`);
538
544
  }
539
545
  ctx.resolvedSource = resolved.spec;
540
546
  }
@@ -707,12 +713,14 @@ async function executeInstalls(ctx) {
707
713
  if (!selectedSkills || selectedSkills.length === 0) {
708
714
  return;
709
715
  }
710
- if (spinner) {
711
- spinner.text = selectedSkills.length > 1 ? `Installing ${chalk3.cyan(ctx.source)} \u2014 ${selectedSkills.length} skills...` : `Installing ${chalk3.cyan(ctx.source)}...`;
712
- }
716
+ const totalSkills = selectedSkills.length;
717
+ const isMulti = totalSkills > 1;
718
+ let currentIdx = 0;
713
719
  for (const skill of selectedSkills) {
720
+ currentIdx += 1;
721
+ const skillName = skill.relPath === "." ? ctx.source : skill.relPath;
714
722
  if (spinner) {
715
- spinner.text = `Installing ${chalk3.cyan(skill.relPath === "." ? ctx.source : skill.relPath)}...`;
723
+ spinner.text = isMulti ? `Installing ${chalk3.cyan(skillName)} ${chalk3.dim(`(${currentIdx}/${totalSkills})`)}...` : `Installing ${chalk3.cyan(skillName)}...`;
716
724
  }
717
725
  for (const platform of targets) {
718
726
  try {
@@ -768,65 +776,93 @@ function reportResults(ctx) {
768
776
  process.exitCode = errors.length ? 1 : 0;
769
777
  return;
770
778
  }
779
+ const platformsLabel = targets.length === PLATFORMS2.length ? "all platforms" : targets.length === 1 ? targets[0] : `${targets.length} platforms`;
771
780
  if (errors.length === 0 && (results.length > 0 || skipped.length > 0)) {
772
781
  const displayName = results[0]?.canonicalName || results[0]?.name || ctx.source;
773
- if (skipped.length > 0) {
782
+ const skillCount = selectedSkills?.length ?? results.length;
783
+ const uniqueSkippedSkills = [...new Set(skipped.map((s) => s.skillName))];
784
+ if (skipped.length > 0 && results.length > 0) {
785
+ spinner?.succeed(
786
+ `Installed ${chalk3.green(results.length)} skill${results.length > 1 ? "s" : ""}, skipped ${chalk3.dim(`${uniqueSkippedSkills.length} skill${uniqueSkippedSkills.length > 1 ? "s" : ""}`)} \u2192 ${chalk3.dim(platformsLabel)}`
787
+ );
788
+ } else if (skipped.length > 0) {
774
789
  spinner?.succeed(
775
- `Installed ${chalk3.green(results.length)} and skipped ${chalk3.dim(skipped.length)} (already installed) to ${chalk3.dim(`${targets.length} platforms`)}`
790
+ `Skipped ${chalk3.dim(`${uniqueSkippedSkills.length} skill${uniqueSkippedSkills.length > 1 ? "s" : ""}`)} (already installed) \u2192 ${chalk3.dim(platformsLabel)}`
776
791
  );
777
792
  } else {
778
793
  spinner?.succeed(
779
- isMultiSkill ? `Installed ${chalk3.green(String(selectedSkills?.length ?? results.length))}${chalk3.dim(" skills")} to ${chalk3.dim(`${targets.length} platforms`)}` : targets.length > 1 ? `Installed ${chalk3.green(displayName)} to ${chalk3.dim(`${results.length} platforms`)}` : `Installed ${chalk3.green(displayName)} to ${chalk3.dim(results[0]?.installDir || "")}`
794
+ isMultiSkill ? `Installed ${chalk3.green(skillCount)} skill${skillCount > 1 ? "s" : ""} \u2192 ${chalk3.dim(platformsLabel)}` : `Installed ${chalk3.green(displayName)} \u2192 ${chalk3.dim(results[0]?.installDir || platformsLabel)}`
780
795
  );
781
796
  }
782
797
  } else if (errors.length > 0) {
783
798
  const attempted = results.length + errors.length;
784
799
  spinner?.fail(
785
- isMultiSkill ? `Install had failures (${errors.length}/${attempted} installs failed)` : `Failed to install ${chalk3.red(ctx.source)} to ${errors.length}/${targets.length} platforms`
800
+ isMultiSkill ? `Install failed: ${chalk3.red(errors.length)}/${attempted} errors` : `Failed to install ${chalk3.red(ctx.source)}`
786
801
  );
787
802
  process.exitCode = 1;
788
- if (!isMultiSkill && targets.length === 1 && errors[0]) {
789
- console.error(chalk3.red(errors[0].error));
790
- }
791
803
  }
792
- if (isMultiSkill || targets.length > 1) {
793
- for (const r of results.slice(0, 60)) {
794
- const displayName = r.canonicalName || r.name;
795
- const suffix = r.hasSkillMd ? chalk3.green("\u2713") : chalk3.yellow("\u26A0");
796
- console.log(` ${suffix} ${chalk3.cyan(displayName)} \u2192 ${chalk3.dim(r.platform)}`);
804
+ if (isMultiSkill && results.length > 0) {
805
+ const groupedByPlatform = /* @__PURE__ */ new Map();
806
+ for (const r of results) {
807
+ const list2 = groupedByPlatform.get(r.platform) || [];
808
+ list2.push(r);
809
+ groupedByPlatform.set(r.platform, list2);
797
810
  }
798
- if (results.length > 60) console.log(chalk3.dim(` ... and ${results.length - 60} more`));
799
- if (errors.length) {
800
- console.log(chalk3.yellow("\nFailures:"));
801
- for (const e of errors) console.log(chalk3.yellow(` - ${e.platform}: ${e.error}`));
811
+ const uniqueSkillNames = [...new Set(results.map((r) => r.canonicalName || r.name))];
812
+ if (uniqueSkillNames.length <= 20) {
813
+ console.log();
814
+ for (const name of uniqueSkillNames.slice(0, 20)) {
815
+ const record = results.find((r) => (r.canonicalName || r.name) === name);
816
+ const icon = record?.hasSkillMd ? chalk3.green("\u2713") : chalk3.yellow("\u26A0");
817
+ console.log(` ${icon} ${chalk3.cyan(name)}`);
818
+ }
819
+ } else {
820
+ console.log(chalk3.dim(`
821
+ ${uniqueSkillNames.length} skills installed`));
822
+ for (const name of uniqueSkillNames.slice(0, 8)) {
823
+ console.log(chalk3.dim(` \u2022 ${name}`));
824
+ }
825
+ console.log(chalk3.dim(` ... and ${uniqueSkillNames.length - 8} more`));
802
826
  }
803
- process.exitCode = errors.length ? 1 : 0;
804
827
  } else if (!isMultiSkill && targets.length === 1 && results[0]) {
805
828
  const record = results[0];
806
- if (record.hasSkillMd) logger.installDetail("SKILL.md found \u2713");
807
- else logger.installDetail("Warning: No SKILL.md found", true);
829
+ if (!record.hasSkillMd) {
830
+ console.log(chalk3.yellow(` \u26A0 No SKILL.md found`));
831
+ }
808
832
  if (record.skill?.validation && !record.skill.validation.ok) {
809
- logger.installDetail(`Validation: ${chalk3.yellow("failed")} (${record.skill.validation.issues.length} issues)`, true);
810
- } else if (record.skill?.validation?.ok) {
811
- logger.installDetail(`Validation: ${chalk3.green("ok")}`);
833
+ console.log(chalk3.yellow(` \u26A0 Validation failed (${record.skill.validation.issues.length} issues)`));
834
+ }
835
+ }
836
+ if (errors.length > 0) {
837
+ console.log(chalk3.red(`
838
+ Errors:`));
839
+ for (const e of errors.slice(0, 10)) {
840
+ const prefix = e.inputSource ? `${e.inputSource} \u2192 ${e.platform}` : e.platform;
841
+ console.log(chalk3.red(` \u2717 ${prefix}: ${e.error}`));
842
+ }
843
+ if (errors.length > 10) {
844
+ console.log(chalk3.dim(` ... and ${errors.length - 10} more errors`));
812
845
  }
846
+ process.exitCode = 1;
813
847
  }
814
848
  if (skipped.length > 0) {
815
849
  const uniqueSkills = [...new Set(skipped.map((s) => s.skillName))];
816
850
  console.log(chalk3.dim(`
817
- Skipped ${skipped.length} already installed (${uniqueSkills.length} skill${uniqueSkills.length > 1 ? "s" : ""}):`));
851
+ ${uniqueSkills.length} skill${uniqueSkills.length > 1 ? "s" : ""} already installed (skipped):`));
818
852
  const bySkill = /* @__PURE__ */ new Map();
819
853
  for (const s of skipped) {
820
854
  const platforms = bySkill.get(s.skillName) || [];
821
855
  platforms.push(s.platform);
822
856
  bySkill.set(s.skillName, platforms);
823
857
  }
824
- for (const [skillName, platforms] of bySkill.entries()) {
825
- const platformsStr = platforms.length === PLATFORMS2.length ? "all platforms" : platforms.join(", ");
826
- console.log(chalk3.dim(` - ${skillName} (${platformsStr})`));
858
+ for (const [skillName] of [...bySkill.entries()].slice(0, 5)) {
859
+ console.log(chalk3.dim(` \u2022 ${skillName}`));
860
+ }
861
+ if (bySkill.size > 5) {
862
+ console.log(chalk3.dim(` ... and ${bySkill.size - 5} more`));
827
863
  }
828
864
  console.log(chalk3.dim(`
829
- To reinstall, use: ${chalk3.cyan("skild install <source> --force")}`));
865
+ \u{1F4A1} Reinstall with: ${chalk3.cyan(`skild install ${ctx.source} --force`)}`));
830
866
  }
831
867
  }
832
868
  async function install(source, options = {}) {
@@ -907,93 +943,74 @@ function missingSkillMdLabel(skill) {
907
943
  function formatDepName(dep, nameToDisplay) {
908
944
  return dep.canonicalName || nameToDisplay.get(dep.name) || dep.name;
909
945
  }
910
- function summarizeDeps(record) {
911
- const deps = record?.installedDependencies || [];
912
- if (deps.length === 0) return null;
913
- const byType = deps.reduce(
914
- (acc, d) => {
915
- acc.total += 1;
916
- if (d.sourceType === "inline") acc.inline += 1;
917
- else acc.external += 1;
918
- acc.bySourceType[d.sourceType] = (acc.bySourceType[d.sourceType] || 0) + 1;
919
- return acc;
920
- },
921
- { total: 0, inline: 0, external: 0, bySourceType: {} }
922
- );
923
- const parts = [];
924
- if (byType.inline) parts.push(`${byType.inline} inline`);
925
- const externalParts = Object.entries(byType.bySourceType).filter(([t]) => t !== "inline").sort(([a], [b]) => a.localeCompare(b)).map(([t, c2]) => `${c2} ${t}`);
926
- if (externalParts.length) parts.push(...externalParts);
927
- return `deps: ${byType.total}${parts.length ? ` (${parts.join(", ")})` : ""}`;
928
- }
929
946
  function printSkillsetSection(skills, nameToDisplay, options) {
930
- console.log(chalk4.bold(` Skillsets (${skills.length})`));
947
+ console.log(chalk4.bold(` \u{1F4E6} Skillsets`) + chalk4.dim(` (${skills.length})`));
931
948
  if (skills.length === 0) {
932
- console.log(chalk4.dim(" (none)"));
949
+ console.log(chalk4.dim(" No skillsets"));
933
950
  return;
934
951
  }
935
952
  for (const s of skills) {
936
- const label = `${chalk4.cyan(getDisplayName(s))}${chalk4.dim(" (skillset)")}${missingSkillMdLabel(s)}`;
937
- console.log(` ${statusIcon(s)} ${label}`);
938
- const summary = summarizeDeps(s.record);
939
- if (summary) console.log(chalk4.dim(` ${summary}`));
953
+ const depsCount = s.record?.installedDependencies?.length || 0;
954
+ const depsSuffix = depsCount > 0 ? chalk4.dim(` \u2192 ${depsCount} deps`) : "";
955
+ console.log(` ${statusIcon(s)} ${chalk4.cyan(getDisplayName(s))}${depsSuffix}${missingSkillMdLabel(s)}`);
940
956
  if (options.verbose) {
941
957
  const deps = (s.record?.installedDependencies || []).slice().sort((a, b) => a.name.localeCompare(b.name));
942
- if (deps.length) {
943
- console.log(chalk4.dim(` includes (${deps.length}):`));
944
- for (const dep of deps) {
945
- const depName = formatDepName(dep, nameToDisplay);
946
- console.log(chalk4.dim(` - ${depName} [${dep.sourceType}]`));
947
- }
958
+ for (const dep of deps) {
959
+ const depName = formatDepName(dep, nameToDisplay);
960
+ console.log(chalk4.dim(` \u2022 ${depName}`));
948
961
  }
949
962
  }
950
- if (options.paths || !s.hasSkillMd) console.log(chalk4.dim(` path: ${s.installDir}`));
963
+ if (options.paths || !s.hasSkillMd) console.log(chalk4.dim(` \u2514\u2500 ${s.installDir}`));
951
964
  }
952
965
  }
953
966
  function printSkillsSection(skills, options) {
954
- console.log(chalk4.bold(` Skills (${skills.length})`));
967
+ console.log(chalk4.bold(` \u26A1 Skills`) + chalk4.dim(` (${skills.length})`));
955
968
  if (skills.length === 0) {
956
- console.log(chalk4.dim(" (none)"));
969
+ console.log(chalk4.dim(" No skills"));
957
970
  return;
958
971
  }
959
972
  for (const s of skills) {
960
- const label = `${chalk4.cyan(getDisplayName(s))}${missingSkillMdLabel(s)}`;
961
- console.log(` ${statusIcon(s)} ${label}`);
962
- if (options.paths || !s.hasSkillMd) console.log(chalk4.dim(` path: ${s.installDir}`));
973
+ console.log(` ${statusIcon(s)} ${chalk4.cyan(getDisplayName(s))}${missingSkillMdLabel(s)}`);
974
+ if (options.paths || !s.hasSkillMd) console.log(chalk4.dim(` \u2514\u2500 ${s.installDir}`));
963
975
  }
964
976
  }
965
977
  function printDependenciesSection(skills, nameToDisplay, options) {
966
- console.log(chalk4.bold(` Dependencies (${skills.length})`));
978
+ console.log(chalk4.bold(` \u{1F517} Dependencies`) + chalk4.dim(` (${skills.length})`));
967
979
  if (skills.length === 0) {
968
- console.log(chalk4.dim(" (none)"));
980
+ console.log(chalk4.dim(" No dependencies"));
969
981
  return;
970
982
  }
971
983
  for (const s of skills) {
972
984
  const dependedBy = (s.record?.dependedBy || []).map((name) => nameToDisplay.get(name) || name).sort((a, b) => a.localeCompare(b));
973
- const requiredBy = dependedBy.length ? chalk4.dim(` \u2190 required by: ${dependedBy.join(", ")}`) : "";
974
- const label = `${chalk4.cyan(getDisplayName(s))}${missingSkillMdLabel(s)}${requiredBy}`;
975
- console.log(` ${statusIcon(s)} ${label}`);
976
- if (options.paths || !s.hasSkillMd) console.log(chalk4.dim(` path: ${s.installDir}`));
985
+ const requiredBy = dependedBy.length ? chalk4.dim(` \u2190 ${dependedBy.join(", ")}`) : "";
986
+ console.log(` ${statusIcon(s)} ${chalk4.cyan(getDisplayName(s))}${requiredBy}${missingSkillMdLabel(s)}`);
987
+ if (options.paths || !s.hasSkillMd) console.log(chalk4.dim(` \u2514\u2500 ${s.installDir}`));
977
988
  }
978
989
  }
979
990
  function printPlatform(skills, platform, scope, options) {
991
+ const platformLabel = platform.charAt(0).toUpperCase() + platform.slice(1);
980
992
  console.log(chalk4.bold(`
981
- \u{1F4E6} Installed Skills \u2014 ${platform} (${scope})
982
- `));
993
+ ${platformLabel}`) + chalk4.dim(` (${scope}, ${skills.length} total)`));
983
994
  if (skills.length === 0) {
984
995
  console.log(chalk4.dim(" No skills installed."));
985
- console.log(chalk4.dim(` Use ${chalk4.cyan("skild install <source>")} to install a skill.`));
996
+ console.log(chalk4.dim(` \u{1F4A1} Use ${chalk4.cyan("skild install <source>")} to get started.`));
986
997
  return;
987
998
  }
988
999
  const nameToDisplay = buildNameToDisplay(skills);
989
1000
  const skillsets = skills.filter(isSkillset).sort((a, b) => getDisplayName(a).localeCompare(getDisplayName(b)));
990
1001
  const dependencies = skills.filter((s) => !isSkillset(s) && Boolean(s.record?.dependedBy?.length)).sort((a, b) => getDisplayName(a).localeCompare(getDisplayName(b)));
991
1002
  const regular = skills.filter((s) => !isSkillset(s) && !Boolean(s.record?.dependedBy?.length)).sort((a, b) => getDisplayName(a).localeCompare(getDisplayName(b)));
992
- printSkillsetSection(skillsets, nameToDisplay, options);
993
- console.log("");
994
- printSkillsSection(regular, options);
995
- console.log("");
996
- printDependenciesSection(dependencies, nameToDisplay, options);
1003
+ if (skillsets.length > 0) {
1004
+ printSkillsetSection(skillsets, nameToDisplay, options);
1005
+ }
1006
+ if (regular.length > 0) {
1007
+ console.log("");
1008
+ printSkillsSection(regular, options);
1009
+ }
1010
+ if (dependencies.length > 0) {
1011
+ console.log("");
1012
+ printDependenciesSection(dependencies, nameToDisplay, options);
1013
+ }
997
1014
  console.log("");
998
1015
  }
999
1016
  async function list(options = {}) {
@@ -1016,8 +1033,9 @@ async function list(options = {}) {
1016
1033
  return;
1017
1034
  }
1018
1035
  if (allSkills.length === 0) {
1019
- console.log(chalk4.dim("No skills installed."));
1020
- console.log(chalk4.dim(`Use ${chalk4.cyan("skild install <source>")} to install a skill.`));
1036
+ console.log(chalk4.dim("\nNo skills installed."));
1037
+ console.log(chalk4.dim(`\u{1F4A1} Use ${chalk4.cyan("skild install <source>")} to get started.
1038
+ `));
1021
1039
  return;
1022
1040
  }
1023
1041
  for (const p of PLATFORMS3) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skild",
3
- "version": "0.4.7",
3
+ "version": "0.5.1",
4
4
  "description": "The npm for Agent Skills — Discover, install, manage, and publish AI Agent Skills with ease.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -38,7 +38,7 @@
38
38
  "commander": "^12.1.0",
39
39
  "ora": "^8.0.1",
40
40
  "tar": "^7.4.3",
41
- "@skild/core": "^0.4.7"
41
+ "@skild/core": "^0.5.1"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/node": "^20.10.0",