skillmds 1.0.15 → 1.0.16

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,10 @@
2
2
 
3
3
  All notable changes to `skillmds` are documented here. Versions follow [semver](https://semver.org).
4
4
 
5
+ ## 1.0.16
6
+
7
+ - **Installs are no longer gated on verification.** Any skill installs directly — verified or not — with no flag, no prompt, and no second step, from both the CLI (`skillmd add`) and the MCP `skillmd_install` tool. Security flags (network_calls, executes_scripts, reads_secrets, docs_only) are still shown on the result as information, but never block. `--deny <flag>` remains available as an opt-in for anyone who wants to exclude a flag; `--allow-unverified` is now a no-op kept for backward compatibility.
8
+
5
9
  ## 1.0.15
6
10
 
7
11
  - Search is now **browsable in the interactive menu**: arrow through results, press Enter on one to see a card, and install it to your project or user directory — all without leaving the CLI (`← Back` at each level; Esc goes up one step, never quits).
@@ -70,13 +70,12 @@ const TOOLS = [
70
70
  {
71
71
  name: "skillmd_install",
72
72
  description:
73
- "Install a skill by slug: validates it, then writes its SKILL.md into the agent's skills directory. Never executes any scripts. Unverified skills are refused unless allow_unverified is true. Do not set allow_unverified on your own initiative — only after the human has explicitly approved installing this specific unverified skill.",
73
+ "Install a skill by slug: writes its SKILL.md into the agent's skills directory. Never executes any scripts. Any skill installs; the response reports its security flags (docs_only / network_calls / executes_scripts / reads_secrets) as information.",
74
74
  inputSchema: {
75
75
  type: "object",
76
76
  properties: {
77
77
  slug: { type: "string", description: "owner/name, e.g. anthropic/pdf" },
78
78
  dest: { type: "string", description: "Target skills dir. Default ~/.claude/skills" },
79
- allow_unverified: { type: "boolean", description: "Install even if the skill is not verified by SkillMD. Never set this on your own initiative — only after the human has explicitly approved this specific skill." },
80
79
  },
81
80
  required: ["slug"],
82
81
  },
@@ -193,13 +192,8 @@ async function handleCall(name, args) {
193
192
  }
194
193
  const skill = await api(`/api/skills/${owner}/${slugName}`);
195
194
  const flags = skill.security_flags ?? [];
196
- if (skill.verified === false && !args.allow_unverified) {
197
- return text(
198
- `Refused: ${args.slug} is not yet verified by SkillMD (security flags: ${flags.join(", ") || "unscanned"}). ` +
199
- `Review it at https://skillmd.com/skills/${args.slug}. Only call skillmd_install again with allow_unverified: true ` +
200
- `if the human explicitly approves installing this specific unverified skill — do not decide this yourself.`,
201
- );
202
- }
195
+ // Verification never gates installs — any skill installs; flags are
196
+ // reported in the response as information, not a wall.
203
197
  const raw = reconstructSkillMd(skill); // returns raw_md verbatim when the registry has it
204
198
  if (lint) {
205
199
  const result = lint(raw, { slug: slugName });
package/dist/cli.js CHANGED
@@ -894,7 +894,7 @@ function infoCommand() {
894
894
  }
895
895
 
896
896
  // ../cli/src/commands/add.ts
897
- import { Command as Command7 } from "commander";
897
+ import { Command as Command7, Option } from "commander";
898
898
  import { existsSync as existsSync4 } from "fs";
899
899
  import pc7 from "picocolors";
900
900
 
@@ -1007,16 +1007,6 @@ var defaultDeps = {
1007
1007
  body: JSON.stringify({ via: "cli" })
1008
1008
  }).catch(() => {
1009
1009
  });
1010
- },
1011
- async confirmUnverified(c, score, secFlags) {
1012
- if (!process.stdin.isTTY) return false;
1013
- const { confirm: confirm2, isCancel: isCancel4 } = await import("@clack/prompts");
1014
- const ok = await confirm2({
1015
- message: `${c.name} is not yet verified by SkillMD (lint score ${score}${secFlags.length ? `; flags: ${secFlags.join(", ")}` : ""}). Install anyway?`,
1016
- initialValue: false
1017
- });
1018
- if (isCancel4(ok)) return false;
1019
- return ok === true;
1020
1010
  }
1021
1011
  };
1022
1012
  async function runAdd(arg, flags, deps = defaultDeps) {
@@ -1039,18 +1029,9 @@ async function runAdd(arg, flags, deps = defaultDeps) {
1039
1029
  }
1040
1030
  if (deniedFlags.length) {
1041
1031
  blocked.push({ name: c.name, reason: `denied security flags: ${deniedFlags.join(", ")}` });
1042
- lines.push(pc7.red(`\u2717 ${c.name} blocked \u2014 ${deniedFlags.join(", ")}`));
1032
+ lines.push(pc7.red(`\u2717 ${c.name} blocked \u2014 you passed --deny ${deniedFlags.join(", ")}`));
1043
1033
  continue;
1044
1034
  }
1045
- if (c.registrySlug && c.verified === false && !flags.allowUnverified) {
1046
- const ok = !flags.yes && deps.confirmUnverified ? await deps.confirmUnverified(c, result.score, allFlags) : false;
1047
- if (!ok) {
1048
- blocked.push({ name: c.name, reason: "unverified registry skill (use --allow-unverified)" });
1049
- lines.push(pc7.yellow(`\u2717 ${c.name} blocked \u2014 not yet verified by SkillMD${allFlags.length ? ` (flags: ${allFlags.join(", ")})` : ""}`));
1050
- lines.push(pc7.dim(` review at https://skillmd.com/skills/${c.registrySlug}, then re-run with --allow-unverified`));
1051
- continue;
1052
- }
1053
- }
1054
1035
  const files = c.files ?? [{ path: "SKILL.md", contents: c.raw }];
1055
1036
  for (const agentId of targets) {
1056
1037
  const dir = agentDir(agentId, scope);
@@ -1070,7 +1051,7 @@ async function runAdd(arg, flags, deps = defaultDeps) {
1070
1051
  return { written, blocked, exitCode, output: lines.join("\n") };
1071
1052
  }
1072
1053
  function addCommand() {
1073
- return new Command7("add").description("Install a skill from the registry, a GitHub repo, or a local path (lints before writing)").argument("<source>", "registry slug (owner/name), GitHub source, or local path").option("-g, --global", "install to the user directory instead of the project").option("-a, --agent <agents...>", "target specific agents").option("-s, --skill <names...>", "install only specific skills by name ('*' for all)").option("--copy", "copy files (default)", true).option("-y, --yes", "skip confirmation prompts").option("--allow-unverified", "allow installing unverified registry skills").option("--skip-lint", "install even if the skill fails lint").option("--deny <flags...>", "refuse skills with these security flags").action(async (source, opts, cmd) => {
1054
+ return new Command7("add").description("Install a skill from the registry, a GitHub repo, or a local path (lints before writing)").argument("<source>", "registry slug (owner/name), GitHub source, or local path").option("-g, --global", "install to the user directory instead of the project").option("-a, --agent <agents...>", "target specific agents").option("-s, --skill <names...>", "install only specific skills by name ('*' for all)").option("--copy", "copy files (default)", true).option("-y, --yes", "skip confirmation prompts").addOption(new Option("--allow-unverified").hideHelp()).option("--skip-lint", "install even if the skill fails lint").option("--deny <flags...>", "refuse skills carrying any of these security flags (opt-in)").action(async (source, opts, cmd) => {
1074
1055
  const merged = { ...cmd.parent?.opts(), ...opts };
1075
1056
  const run = await runAdd(source, merged);
1076
1057
  console.log(run.output);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillmds",
3
- "version": "1.0.15",
3
+ "version": "1.0.16",
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": {