skild 0.2.7 → 0.2.8

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 +121 -83
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -57,10 +57,10 @@ var logger = {
57
57
  /**
58
58
  * Log a skill entry with status indicator.
59
59
  */
60
- skillEntry: (name, path4, hasSkillMd) => {
60
+ skillEntry: (name, path3, hasSkillMd) => {
61
61
  const status = hasSkillMd ? chalk.green("\u2713") : chalk.yellow("\u26A0");
62
62
  console.log(` ${status} ${chalk.cyan(name)}`);
63
- console.log(chalk.dim(` \u2514\u2500 ${path4}`));
63
+ console.log(chalk.dim(` \u2514\u2500 ${path3}`));
64
64
  },
65
65
  /**
66
66
  * Log installation result details.
@@ -166,54 +166,122 @@ async function reportDownload(record, registryOverride) {
166
166
 
167
167
  // src/commands/list.ts
168
168
  import chalk3 from "chalk";
169
- import fs2 from "fs";
170
- import path2 from "path";
171
169
  import { PLATFORMS, listAllSkills, listSkills } from "@skild/core";
172
- function toDisplayName(name, mapping) {
173
- return mapping.get(name) || name;
170
+ function isSkillset(skill) {
171
+ return Boolean(skill.record?.skillset || skill.record?.skill?.frontmatter?.skillset);
174
172
  }
175
- function buildDisplayEntries(skills) {
176
- const nameToDisplay = /* @__PURE__ */ new Map();
177
- for (const skill of skills) {
178
- const displayName = skill.record?.canonicalName || skill.name;
179
- nameToDisplay.set(skill.name, displayName);
180
- }
181
- const entries = skills.map((skill) => {
182
- const displayName = toDisplayName(skill.name, nameToDisplay);
183
- const flags = [];
184
- if (skill.record?.skillset || skill.record?.skill?.frontmatter?.skillset) {
185
- flags.push("skillset");
186
- }
187
- if (skill.record?.dependedBy?.length) {
188
- const dependedBy = skill.record.dependedBy.map((name) => toDisplayName(name, nameToDisplay));
189
- flags.push(`dep of: ${dependedBy.join(", ")}`);
190
- }
191
- return {
192
- name: displayName,
193
- installDir: skill.installDir,
194
- status: skill.hasSkillMd ? "ok" : "warn",
195
- flags
196
- };
197
- });
173
+ function getDisplayName(skill) {
174
+ return skill.record?.canonicalName || skill.record?.skill?.frontmatter?.name || skill.name;
175
+ }
176
+ function buildNameToDisplay(skills) {
177
+ const mapping = /* @__PURE__ */ new Map();
198
178
  for (const skill of skills) {
199
- const inlineDeps = skill.record?.installedDependencies?.filter((dep) => dep.sourceType === "inline") || [];
200
- if (!inlineDeps.length) continue;
201
- const ownerName = toDisplayName(skill.name, nameToDisplay);
202
- for (const dep of inlineDeps) {
203
- const inlineDir = dep.inlinePath ? path2.join(skill.installDir, dep.inlinePath) : path2.join(skill.installDir, dep.name);
204
- const hasSkillMd = fs2.existsSync(path2.join(inlineDir, "SKILL.md"));
205
- entries.push({
206
- name: dep.name,
207
- installDir: inlineDir,
208
- status: hasSkillMd ? "ok" : "warn",
209
- flags: [`dep of: ${ownerName}`]
210
- });
179
+ mapping.set(skill.name, getDisplayName(skill));
180
+ }
181
+ return mapping;
182
+ }
183
+ function statusIcon(skill) {
184
+ return skill.hasSkillMd ? chalk3.green("\u2713") : chalk3.yellow("\u26A0");
185
+ }
186
+ function missingSkillMdLabel(skill) {
187
+ return skill.hasSkillMd ? "" : chalk3.yellow(" (missing SKILL.md)");
188
+ }
189
+ function formatDepName(dep, nameToDisplay) {
190
+ return dep.canonicalName || nameToDisplay.get(dep.name) || dep.name;
191
+ }
192
+ function summarizeDeps(record) {
193
+ const deps = record?.installedDependencies || [];
194
+ if (deps.length === 0) return null;
195
+ const byType = deps.reduce(
196
+ (acc, d) => {
197
+ acc.total += 1;
198
+ if (d.sourceType === "inline") acc.inline += 1;
199
+ else acc.external += 1;
200
+ acc.bySourceType[d.sourceType] = (acc.bySourceType[d.sourceType] || 0) + 1;
201
+ return acc;
202
+ },
203
+ { total: 0, inline: 0, external: 0, bySourceType: {} }
204
+ );
205
+ const parts = [];
206
+ if (byType.inline) parts.push(`${byType.inline} inline`);
207
+ const externalParts = Object.entries(byType.bySourceType).filter(([t]) => t !== "inline").sort(([a], [b]) => a.localeCompare(b)).map(([t, c2]) => `${c2} ${t}`);
208
+ if (externalParts.length) parts.push(...externalParts);
209
+ return `deps: ${byType.total}${parts.length ? ` (${parts.join(", ")})` : ""}`;
210
+ }
211
+ function printSkillsetSection(skills, nameToDisplay, options) {
212
+ console.log(chalk3.bold(` Skillsets (${skills.length})`));
213
+ if (skills.length === 0) {
214
+ console.log(chalk3.dim(" (none)"));
215
+ return;
216
+ }
217
+ for (const s of skills) {
218
+ const label = `${chalk3.cyan(getDisplayName(s))}${chalk3.dim(" (skillset)")}${missingSkillMdLabel(s)}`;
219
+ console.log(` ${statusIcon(s)} ${label}`);
220
+ const summary = summarizeDeps(s.record);
221
+ if (summary) console.log(chalk3.dim(` ${summary}`));
222
+ if (options.verbose) {
223
+ const deps = (s.record?.installedDependencies || []).slice().sort((a, b) => a.name.localeCompare(b.name));
224
+ if (deps.length) {
225
+ console.log(chalk3.dim(` includes (${deps.length}):`));
226
+ for (const dep of deps) {
227
+ const depName = formatDepName(dep, nameToDisplay);
228
+ console.log(chalk3.dim(` - ${depName} [${dep.sourceType}]`));
229
+ }
230
+ }
211
231
  }
232
+ if (options.paths || !s.hasSkillMd) console.log(chalk3.dim(` path: ${s.installDir}`));
212
233
  }
213
- return entries;
234
+ }
235
+ function printSkillsSection(skills, options) {
236
+ console.log(chalk3.bold(` Skills (${skills.length})`));
237
+ if (skills.length === 0) {
238
+ console.log(chalk3.dim(" (none)"));
239
+ return;
240
+ }
241
+ for (const s of skills) {
242
+ const label = `${chalk3.cyan(getDisplayName(s))}${missingSkillMdLabel(s)}`;
243
+ console.log(` ${statusIcon(s)} ${label}`);
244
+ if (options.paths || !s.hasSkillMd) console.log(chalk3.dim(` path: ${s.installDir}`));
245
+ }
246
+ }
247
+ function printDependenciesSection(skills, nameToDisplay, options) {
248
+ console.log(chalk3.bold(` Dependencies (${skills.length})`));
249
+ if (skills.length === 0) {
250
+ console.log(chalk3.dim(" (none)"));
251
+ return;
252
+ }
253
+ for (const s of skills) {
254
+ const dependedBy = (s.record?.dependedBy || []).map((name) => nameToDisplay.get(name) || name).sort((a, b) => a.localeCompare(b));
255
+ const requiredBy = dependedBy.length ? chalk3.dim(` \u2190 required by: ${dependedBy.join(", ")}`) : "";
256
+ const label = `${chalk3.cyan(getDisplayName(s))}${missingSkillMdLabel(s)}${requiredBy}`;
257
+ console.log(` ${statusIcon(s)} ${label}`);
258
+ if (options.paths || !s.hasSkillMd) console.log(chalk3.dim(` path: ${s.installDir}`));
259
+ }
260
+ }
261
+ function printPlatform(skills, platform, scope, options) {
262
+ console.log(chalk3.bold(`
263
+ \u{1F4E6} Installed Skills \u2014 ${platform} (${scope})
264
+ `));
265
+ if (skills.length === 0) {
266
+ console.log(chalk3.dim(" No skills installed."));
267
+ console.log(chalk3.dim(` Use ${chalk3.cyan("skild install <source>")} to install a skill.`));
268
+ return;
269
+ }
270
+ const nameToDisplay = buildNameToDisplay(skills);
271
+ const skillsets = skills.filter(isSkillset).sort((a, b) => getDisplayName(a).localeCompare(getDisplayName(b)));
272
+ const dependencies = skills.filter((s) => !isSkillset(s) && Boolean(s.record?.dependedBy?.length)).sort((a, b) => getDisplayName(a).localeCompare(getDisplayName(b)));
273
+ const regular = skills.filter((s) => !isSkillset(s) && !Boolean(s.record?.dependedBy?.length)).sort((a, b) => getDisplayName(a).localeCompare(getDisplayName(b)));
274
+ printSkillsetSection(skillsets, nameToDisplay, options);
275
+ console.log("");
276
+ printSkillsSection(regular, options);
277
+ console.log("");
278
+ printDependenciesSection(dependencies, nameToDisplay, options);
279
+ console.log("");
214
280
  }
215
281
  async function list(options = {}) {
216
282
  const scope = options.local ? "project" : "global";
283
+ const paths = Boolean(options.paths);
284
+ const verbose = Boolean(options.verbose);
217
285
  const platform = options.target;
218
286
  if (platform) {
219
287
  const skills = listSkills({ platform, scope });
@@ -221,22 +289,7 @@ async function list(options = {}) {
221
289
  console.log(JSON.stringify(skills, null, 2));
222
290
  return;
223
291
  }
224
- if (skills.length === 0) {
225
- console.log(chalk3.dim("No skills installed."));
226
- console.log(chalk3.dim(`Use ${chalk3.cyan("skild install <source>")} to install a skill.`));
227
- return;
228
- }
229
- const entries = buildDisplayEntries(skills);
230
- console.log(chalk3.bold(`
231
- \u{1F4E6} Installed Skills (${entries.length}) \u2014 ${platform} (${scope}):
232
- `));
233
- for (const entry of entries) {
234
- const status = entry.status === "ok" ? chalk3.green("\u2713") : chalk3.yellow("\u26A0");
235
- const label = entry.flags.length ? `${entry.name} (${entry.flags.join("; ")})` : entry.name;
236
- console.log(` ${status} ${chalk3.cyan(label)}`);
237
- console.log(chalk3.dim(` \u2514\u2500 ${entry.installDir}`));
238
- }
239
- console.log("");
292
+ printPlatform(skills, platform, scope, { paths, verbose });
240
293
  return;
241
294
  }
242
295
  const allSkills = listAllSkills({ scope });
@@ -249,26 +302,11 @@ async function list(options = {}) {
249
302
  console.log(chalk3.dim(`Use ${chalk3.cyan("skild install <source>")} to install a skill.`));
250
303
  return;
251
304
  }
252
- console.log(chalk3.bold(`
253
- \u{1F4E6} Installed Skills \u2014 all platforms (${scope}):
254
- `));
255
305
  for (const p of PLATFORMS) {
256
306
  const platformSkills = allSkills.filter((s) => s.platform === p).sort((a, b) => a.name.localeCompare(b.name));
257
- const entries = buildDisplayEntries(platformSkills);
258
- const header = `${p} (${entries.length})`;
259
- console.log(chalk3.bold(` ${header}`));
260
- if (entries.length === 0) {
261
- console.log(chalk3.dim(" (none)"));
262
- continue;
263
- }
264
- for (const entry of entries) {
265
- const status = entry.status === "ok" ? chalk3.green("\u2713") : chalk3.yellow("\u26A0");
266
- const label = entry.flags.length ? `${entry.name} (${entry.flags.join("; ")})` : entry.name;
267
- console.log(` ${status} ${chalk3.cyan(label)}`);
268
- console.log(chalk3.dim(` \u2514\u2500 ${entry.installDir}`));
269
- }
307
+ if (platformSkills.length === 0) continue;
308
+ printPlatform(platformSkills, p, scope, { paths, verbose });
270
309
  }
271
- console.log("");
272
310
  }
273
311
 
274
312
  // src/commands/info.ts
@@ -664,9 +702,9 @@ async function whoami() {
664
702
  }
665
703
 
666
704
  // src/commands/publish.ts
667
- import fs3 from "fs";
705
+ import fs2 from "fs";
668
706
  import os from "os";
669
- import path3 from "path";
707
+ import path2 from "path";
670
708
  import crypto from "crypto";
671
709
  import * as tar from "tar";
672
710
  import chalk13 from "chalk";
@@ -689,7 +727,7 @@ async function publish(options = {}) {
689
727
  process.exitCode = 1;
690
728
  return;
691
729
  }
692
- const dir = path3.resolve(options.dir || process.cwd());
730
+ const dir = path2.resolve(options.dir || process.cwd());
693
731
  const validation = validateSkillDir(dir);
694
732
  if (!validation.ok) {
695
733
  console.error(chalk13.red("Skill validation failed:"));
@@ -748,8 +786,8 @@ async function publish(options = {}) {
748
786
  return;
749
787
  }
750
788
  const spinner = createSpinner(`Publishing ${chalk13.cyan(`${name}@${version2}`)} to ${chalk13.dim(registry)}...`);
751
- const tempDir = fs3.mkdtempSync(path3.join(os.tmpdir(), "skild-publish-"));
752
- const tarballPath = path3.join(tempDir, "skill.tgz");
789
+ const tempDir = fs2.mkdtempSync(path2.join(os.tmpdir(), "skild-publish-"));
790
+ const tarballPath = path2.join(tempDir, "skill.tgz");
753
791
  try {
754
792
  await tar.c(
755
793
  {
@@ -761,7 +799,7 @@ async function publish(options = {}) {
761
799
  },
762
800
  ["."]
763
801
  );
764
- const buf = fs3.readFileSync(tarballPath);
802
+ const buf = fs2.readFileSync(tarballPath);
765
803
  const integrity = sha256Hex(buf);
766
804
  const form = new FormData();
767
805
  form.set("version", version2);
@@ -805,7 +843,7 @@ async function publish(options = {}) {
805
843
  console.error(chalk13.red(message));
806
844
  process.exitCode = 1;
807
845
  } finally {
808
- fs3.rmSync(tempDir, { recursive: true, force: true });
846
+ fs2.rmSync(tempDir, { recursive: true, force: true });
809
847
  }
810
848
  }
811
849
 
@@ -850,7 +888,7 @@ program.name("skild").description("The npm for Agent Skills \u2014 Discover, ins
850
888
  program.command("install <source>").alias("i").description("Install a Skill from a Git URL, degit shorthand, or local directory").option("-t, --target <platform>", `Target platform: ${PLATFORMS2.join(", ")}`, "claude").option("-l, --local", "Install to project-level directory instead of global").option("-f, --force", "Overwrite existing installation").option("--registry <url>", "Registry base URL (default: https://registry.skild.sh)").option("--json", "Output JSON").action(async (source, options) => {
851
889
  await install(source, options);
852
890
  });
853
- program.command("list").alias("ls").description("List installed Skills").option("-t, --target <platform>", `Target platform: ${PLATFORMS2.join(", ")} (optional; omit to list all)`).option("-l, --local", "List project-level directory instead of global").option("--json", "Output JSON").action(async (options) => list(options));
891
+ program.command("list").alias("ls").description("List installed Skills").option("-t, --target <platform>", `Target platform: ${PLATFORMS2.join(", ")} (optional; omit to list all)`).option("-l, --local", "List project-level directory instead of global").option("--paths", "Show install paths").option("--verbose", "Show skillset dependency details").option("--json", "Output JSON").action(async (options) => list(options));
854
892
  program.command("info <skill>").description("Show installed Skill details").option("-t, --target <platform>", `Target platform: ${PLATFORMS2.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("--json", "Output JSON").action(async (skill, options) => info(skill, options));
855
893
  program.command("uninstall <skill>").alias("rm").description("Uninstall a Skill").option("-t, --target <platform>", `Target platform: ${PLATFORMS2.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("-f, --force", "Uninstall even if metadata is missing").option("--with-deps", "Uninstall dependencies that are only required by this skill").action(async (skill, options) => uninstall(skill, options));
856
894
  program.command("update [skill]").alias("up").description("Update one or all installed Skills").option("-t, --target <platform>", `Target platform: ${PLATFORMS2.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("--json", "Output JSON").action(async (skill, options) => update(skill, options));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skild",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
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",
@@ -37,7 +37,7 @@
37
37
  "commander": "^12.1.0",
38
38
  "ora": "^8.0.1",
39
39
  "tar": "^7.4.3",
40
- "@skild/core": "^0.2.7"
40
+ "@skild/core": "^0.2.8"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "^20.10.0",