skillmds 1.0.13 → 1.0.14

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/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  All notable changes to `skillmds` are documented here. Versions follow [semver](https://semver.org).
4
4
 
5
+ ## 1.0.14
6
+
7
+ - Interactive menu (`skillmds` in a terminal) no longer exits after one action — it returns to the menu until you pick **Quit**; cancelling a sub-prompt goes back to the menu instead of quitting.
8
+ - "List installed skills" now shows project **and** global skills together, tagged `[agent/scope]`, replacing the misleading "Include global skills?" prompt (which actually toggled global-only vs project-only). Invalid skills show the parse reason.
9
+ - The in-menu command reference now includes `info`.
10
+
5
11
  ## 1.0.13
6
12
 
7
13
  Safe & easy installs release.
package/dist/cli.js CHANGED
@@ -1252,101 +1252,103 @@ function bail(v) {
1252
1252
  }
1253
1253
  async function runInteractive() {
1254
1254
  p4.intro(pc12.bgCyan(pc12.black(" skillmd ")));
1255
- const action = await p4.select({
1256
- message: "What would you like to do?",
1257
- options: [
1258
- { value: "lint", label: "Lint a skill", hint: "validate a SKILL.md" },
1259
- { value: "scan", label: "Security scan", hint: "scripts, network, secrets" },
1260
- { value: "search", label: "Search the registry" },
1261
- { value: "init", label: "Create a new skill" },
1262
- { value: "list", label: "List installed skills" },
1263
- { value: "help", label: "Show all commands" }
1264
- ]
1265
- });
1266
- if (bail(action)) return;
1267
- switch (action) {
1268
- case "lint":
1269
- case "scan": {
1270
- const path = await p4.text({ message: "Path to a skill or folder", placeholder: ".", defaultValue: "." });
1271
- if (bail(path)) return;
1272
- const target = String(path || ".");
1273
- const s = p4.spinner();
1274
- s.start(action === "lint" ? "Linting" : "Scanning");
1275
- try {
1276
- const run = action === "lint" ? await runLint(target, { format: "text" }) : await runScan(target, { format: "text" });
1277
- s.stop("Done");
1278
- console.log(run.output);
1279
- process.exitCode = run.exitCode;
1280
- } catch (err) {
1281
- s.stop(pc12.red(err instanceof Error ? err.message : String(err)));
1282
- process.exitCode = 1;
1255
+ for (; ; ) {
1256
+ const action = await p4.select({
1257
+ message: "What would you like to do?",
1258
+ options: [
1259
+ { value: "lint", label: "Lint a skill", hint: "validate a SKILL.md" },
1260
+ { value: "scan", label: "Security scan", hint: "scripts, network, secrets" },
1261
+ { value: "search", label: "Search the registry" },
1262
+ { value: "init", label: "Create a new skill" },
1263
+ { value: "list", label: "List installed skills" },
1264
+ { value: "help", label: "Show all commands" },
1265
+ { value: "quit", label: "Quit" }
1266
+ ]
1267
+ });
1268
+ if (bail(action) || action === "quit") break;
1269
+ switch (action) {
1270
+ case "lint":
1271
+ case "scan": {
1272
+ const path = await p4.text({ message: "Path to a skill or folder", placeholder: ".", defaultValue: "." });
1273
+ if (bail(path)) break;
1274
+ const target = String(path || ".");
1275
+ const s = p4.spinner();
1276
+ s.start(action === "lint" ? "Linting" : "Scanning");
1277
+ try {
1278
+ const run = action === "lint" ? await runLint(target, { format: "text" }) : await runScan(target, { format: "text" });
1279
+ s.stop("Done");
1280
+ console.log(run.output);
1281
+ process.exitCode = run.exitCode;
1282
+ } catch (err) {
1283
+ s.stop(pc12.red(err instanceof Error ? err.message : String(err)));
1284
+ process.exitCode = 1;
1285
+ }
1286
+ break;
1283
1287
  }
1284
- break;
1285
- }
1286
- case "search": {
1287
- const query = await p4.text({ message: "Search the registry for" });
1288
- if (bail(query)) return;
1289
- const verified = await p4.confirm({ message: "Verified skills only?", initialValue: false });
1290
- if (bail(verified)) return;
1291
- const s = p4.spinner();
1292
- s.start("Searching");
1293
- try {
1294
- const run = await runSearch(String(query), { verified: Boolean(verified), limit: "20" });
1295
- s.stop(`${run.items.length} result${run.items.length === 1 ? "" : "s"}`);
1296
- console.log(run.output);
1297
- } catch (err) {
1298
- s.stop(pc12.red(err instanceof Error ? err.message : String(err)));
1299
- process.exitCode = 1;
1288
+ case "search": {
1289
+ const query = await p4.text({ message: "Search the registry for" });
1290
+ if (bail(query)) break;
1291
+ const verified = await p4.confirm({ message: "Verified skills only?", initialValue: false });
1292
+ if (bail(verified)) break;
1293
+ const s = p4.spinner();
1294
+ s.start("Searching");
1295
+ try {
1296
+ const run = await runSearch(String(query), { verified: Boolean(verified), limit: "20" });
1297
+ s.stop(`${run.items.length} result${run.items.length === 1 ? "" : "s"}`);
1298
+ console.log(run.output);
1299
+ } catch (err) {
1300
+ s.stop(pc12.red(err instanceof Error ? err.message : String(err)));
1301
+ process.exitCode = 1;
1302
+ }
1303
+ break;
1300
1304
  }
1301
- break;
1302
- }
1303
- case "init": {
1304
- const name = await p4.text({ message: "Skill name", placeholder: "my-skill" });
1305
- if (bail(name)) return;
1306
- const description = await p4.text({ message: "One-line description", placeholder: "What this skill helps an agent do" });
1307
- if (bail(description)) return;
1308
- try {
1309
- const file = initSkill(String(name), { description: String(description || "") });
1310
- p4.log.success(`Created ${pc12.bold(file)}`);
1311
- } catch (err) {
1312
- p4.log.error(err instanceof Error ? err.message : String(err));
1313
- process.exitCode = 1;
1305
+ case "init": {
1306
+ const name = await p4.text({ message: "Skill name", placeholder: "my-skill" });
1307
+ if (bail(name)) break;
1308
+ const description = await p4.text({ message: "One-line description", placeholder: "What this skill helps an agent do" });
1309
+ if (bail(description)) break;
1310
+ try {
1311
+ const file = initSkill(String(name), { description: String(description || "") });
1312
+ p4.log.success(`Created ${pc12.bold(file)}`);
1313
+ } catch (err) {
1314
+ p4.log.error(err instanceof Error ? err.message : String(err));
1315
+ process.exitCode = 1;
1316
+ }
1317
+ break;
1314
1318
  }
1315
- break;
1316
- }
1317
- case "list": {
1318
- const global = await p4.confirm({ message: "Include global skills?", initialValue: true });
1319
- if (bail(global)) return;
1320
- const skills = installedSkills({ global: Boolean(global) });
1321
- if (skills.length === 0) {
1322
- p4.log.info("No installed skills found.");
1323
- } else {
1324
- p4.log.message(
1325
- skills.map((sk) => {
1326
- const parsed = parseSkillMd(sk.raw);
1327
- const desc = "error" in parsed ? pc12.red("(invalid)") : pc12.dim(parsed.description.slice(0, 70));
1328
- return `${pc12.bold(sk.name)} ${pc12.dim(`[${sk.agent}]`)}
1319
+ case "list": {
1320
+ const skills = [...installedSkills({}), ...installedSkills({ global: true })];
1321
+ if (skills.length === 0) {
1322
+ p4.log.info("No installed skills found (checked this folder and your user directory).");
1323
+ } else {
1324
+ p4.log.message(
1325
+ skills.map((sk) => {
1326
+ const parsed = parseSkillMd(sk.raw);
1327
+ const desc = "error" in parsed ? pc12.red(`(invalid SKILL.md \u2014 ${parsed.error})`) : pc12.dim(parsed.description.slice(0, 70));
1328
+ return `${pc12.bold(sk.name)} ${pc12.dim(`[${sk.agent}/${sk.scope}]`)}
1329
1329
  ${desc}`;
1330
- }).join("\n")
1330
+ }).join("\n")
1331
+ );
1332
+ }
1333
+ break;
1334
+ }
1335
+ case "help": {
1336
+ p4.note(
1337
+ [
1338
+ `${pc12.bold("lint")} [path] validate SKILL.md + quality score`,
1339
+ `${pc12.bold("scan")} [path] security scan`,
1340
+ `${pc12.bold("search")} <query> search the registry`,
1341
+ `${pc12.bold("add")} <source> install a skill (lints first)`,
1342
+ `${pc12.bold("info")} <slug> registry details for a skill`,
1343
+ `${pc12.bold("init")} [name] scaffold a new skill`,
1344
+ `${pc12.bold("list / remove / update")} manage installed skills`,
1345
+ `${pc12.bold("publish")} [path] publish (fails on lint errors)`,
1346
+ `${pc12.bold("rules / login")}`
1347
+ ].join("\n"),
1348
+ "Commands (run: skillmd <command>)"
1331
1349
  );
1350
+ break;
1332
1351
  }
1333
- break;
1334
- }
1335
- case "help": {
1336
- p4.note(
1337
- [
1338
- `${pc12.bold("lint")} [path] validate SKILL.md + quality score`,
1339
- `${pc12.bold("scan")} [path] security scan`,
1340
- `${pc12.bold("search")} <query> search the registry`,
1341
- `${pc12.bold("add")} <source> install a skill (lints first)`,
1342
- `${pc12.bold("init")} [name] scaffold a new skill`,
1343
- `${pc12.bold("list / remove / update")} manage installed skills`,
1344
- `${pc12.bold("publish")} [path] publish (fails on lint errors)`,
1345
- `${pc12.bold("rules / login")}`
1346
- ].join("\n"),
1347
- "Commands (run: skillmd <command>)"
1348
- );
1349
- break;
1350
1352
  }
1351
1353
  }
1352
1354
  p4.outro(pc12.dim("skillmd.com"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillmds",
3
- "version": "1.0.13",
3
+ "version": "1.0.14",
4
4
  "description": "SkillMD for agents: the `skillmds` MCP server + the `skillmd` CLI (lint, scan, search, install, publish Agent Skills) from skillmd.com.",
5
5
  "type": "module",
6
6
  "bin": {