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