skillmds 1.3.5 → 1.3.7
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 +10 -1
- package/README.md +11 -11
- package/bin/skillmd.mjs +1 -1
- package/dist/{chunk-6JVWN3IG.js → chunk-MPBRLZWJ.js} +46 -4
- package/dist/cli.js +53 -18
- package/dist/mcp.js +1 -1
- package/package.json +6 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
All notable changes to `skillmds` are documented here. Versions follow [semver](https://semver.org).
|
|
3
|
+
All notable changes to `get-skill` (published as `skillmds` until 1.3.6) are documented here. Versions follow [semver](https://semver.org).
|
|
4
|
+
|
|
5
|
+
## 1.3.7
|
|
6
|
+
|
|
7
|
+
- **The package is now `get-skill`.** Install and run it as `npx get-skill add owner/name`, `npx get-skill search "pdf"`, and so on; MCP clients start the server with `npx -y get-skill`. `npm i -g get-skill` installs the `get-skill` and `skillmd` commands. Every release is still published as `skillmds` too, with identical contents, so existing setups keep working.
|
|
8
|
+
|
|
9
|
+
## 1.3.6
|
|
10
|
+
|
|
11
|
+
- **Installed skills name where they came from.** A skill installed from the registry (with `add`, `update` or the MCP install tool) gets one line in its frontmatter, `metadata.source: https://skillmd.com/skills/<owner>/<name>`, so an agent reading it knows its SkillMD page. Every other byte is the author's: an existing `metadata` block gains that one line, and an author's own `metadata.source` is never replaced. The line is added after the integrity checks, and the lock file's digest still covers the bytes the registry served, so `update` is unaffected. GitHub, gist and local installs are written exactly as fetched.
|
|
12
|
+
- **find-skills, offered once.** After your first successful install in a terminal, `add` asks once whether to also add `skillmd/find-skills`, a skill that tells your agent to look on SkillMD when a task needs know-how it doesn't have, and to vet what it finds before suggesting it. Yes or no, it never asks again; an agent running the CLI, `-y` and `--json` are never asked.
|
|
4
13
|
|
|
5
14
|
## 1.3.5
|
|
6
15
|
|
package/README.md
CHANGED
|
@@ -2,32 +2,32 @@
|
|
|
2
2
|
<img src="https://skillmd.com/brand/banner.png" alt="SkillMD" width="560">
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
|
-
#
|
|
5
|
+
# get-skill
|
|
6
6
|
|
|
7
|
-
[](https://www.npmjs.com/package/get-skill)
|
|
8
|
+
[](https://github.com/skillmds/skillmd/blob/main/LICENSE)
|
|
9
9
|
[](https://github.com/skillmds/skillmd)
|
|
10
10
|
|
|
11
11
|
Tools for working with [Agent Skills](https://docs.claude.com/en/docs/agents-and-tools/agent-skills) (`SKILL.md`) from the [SkillMD](https://skillmd.com) registry. One package, two binaries:
|
|
12
12
|
|
|
13
13
|
- **`skillmd`** — a CLI to lint, scan, search, install, and publish skills.
|
|
14
|
-
- **`
|
|
14
|
+
- **`get-skill`** — the same CLI, and an MCP server exposing the registry to MCP clients (Claude Code, Claude Desktop, Cursor, …).
|
|
15
15
|
|
|
16
16
|
Both validate `SKILL.md` with the same engine ([`@skillmds/core`](https://www.npmjs.com/package/@skillmds/core)), so the CLI and the registry apply identical rules. Source lives at [github.com/skillmds/skillmd](https://github.com/skillmds/skillmd).
|
|
17
17
|
|
|
18
18
|
## Install
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
-
npm i -g
|
|
21
|
+
npm i -g get-skill
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
This installs both the `
|
|
24
|
+
This installs both the `get-skill` and `skillmd` commands. To run the CLI without installing:
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
|
-
npx
|
|
27
|
+
npx get-skill lint .
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
**Which binary runs what.** `
|
|
30
|
+
**Which binary runs what.** `get-skill` with any argument runs the CLI. `get-skill` with no arguments starts the **MCP server** when stdin is piped (how an MCP client launches it), and opens the interactive CLI menu when there's a terminal attached. `skillmd` is always the CLI.
|
|
31
31
|
|
|
32
32
|
## CLI: `skillmd`
|
|
33
33
|
|
|
@@ -152,12 +152,12 @@ skillmd publish ./my-skill --dry-run
|
|
|
152
152
|
skillmd publish ./my-skill --force # publish despite warnings; never bypasses errors
|
|
153
153
|
```
|
|
154
154
|
|
|
155
|
-
## MCP server: `
|
|
155
|
+
## MCP server: `get-skill`
|
|
156
156
|
|
|
157
157
|
Claude Code:
|
|
158
158
|
|
|
159
159
|
```bash
|
|
160
|
-
claude mcp add skillmd -- npx -y
|
|
160
|
+
claude mcp add skillmd -- npx -y get-skill
|
|
161
161
|
```
|
|
162
162
|
|
|
163
163
|
Other MCP clients:
|
|
@@ -165,7 +165,7 @@ Other MCP clients:
|
|
|
165
165
|
```jsonc
|
|
166
166
|
{
|
|
167
167
|
"mcpServers": {
|
|
168
|
-
"skillmd": { "command": "npx", "args": ["-y", "
|
|
168
|
+
"skillmd": { "command": "npx", "args": ["-y", "get-skill"] }
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
171
|
```
|
package/bin/skillmd.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { existsSync } from "fs";
|
|
3
3
|
import { homedir } from "os";
|
|
4
4
|
import { join } from "path";
|
|
5
|
-
var UNSUPPORTED = (what) => new Error(`${what} sources are not supported yet \u2014 clone it locally and run \`
|
|
5
|
+
var UNSUPPORTED = (what) => new Error(`${what} sources are not supported yet \u2014 clone it locally and run \`npx get-skill add ./path/to/skill\`.`);
|
|
6
6
|
function assertSubpath(sub) {
|
|
7
7
|
if (!sub) return void 0;
|
|
8
8
|
const clean = sub.replace(/^\/+|\/+$/g, "");
|
|
@@ -321,7 +321,7 @@ async function resolveSource(arg, opts = {}) {
|
|
|
321
321
|
if (st.isFile()) return [loadLocal(spec.path)];
|
|
322
322
|
const files = findSkillFiles(spec.path);
|
|
323
323
|
if (files.length === 0) {
|
|
324
|
-
throw new Error(`No SKILL.md found under ${spec.path}. Point at a skill directory, e.g. "
|
|
324
|
+
throw new Error(`No SKILL.md found under ${spec.path}. Point at a skill directory, e.g. "npx get-skill lint ./my-skill", or run "npx get-skill init" to create one.`);
|
|
325
325
|
}
|
|
326
326
|
return files.map(loadLocal);
|
|
327
327
|
}
|
|
@@ -337,7 +337,7 @@ async function resolveSource(arg, opts = {}) {
|
|
|
337
337
|
return [{ path: spec.display, raw, slug: `gist-${spec.id.slice(0, 8)}` }];
|
|
338
338
|
}
|
|
339
339
|
if (spec.kind === "plugin") {
|
|
340
|
-
throw new Error(`"${spec.display}" is a plugin, not a single skill \u2014 install it with \`
|
|
340
|
+
throw new Error(`"${spec.display}" is a plugin, not a single skill \u2014 install it with \`npx get-skill add ${spec.display}\`.`);
|
|
341
341
|
}
|
|
342
342
|
const gh = asGithub(spec);
|
|
343
343
|
const { dir, cleanup } = await downloadGithub(gh, "skillmd-src-", opts, Boolean(gh.subpath));
|
|
@@ -622,6 +622,48 @@ import { createHash as createHash2 } from "crypto";
|
|
|
622
622
|
import { cpSync, existsSync as existsSync5, lstatSync as lstatSync2, mkdirSync as mkdirSync3, readdirSync as readdirSync2, renameSync as renameSync2, rmSync as rmSync3, symlinkSync, writeFileSync as writeFileSync3 } from "fs";
|
|
623
623
|
import { platform } from "os";
|
|
624
624
|
import { dirname as dirname3, join as join7, relative as relative2, resolve as resolve2, sep as sep2 } from "path";
|
|
625
|
+
|
|
626
|
+
// src/provenance.ts
|
|
627
|
+
import { parseSkillMd } from "@skillmds/core";
|
|
628
|
+
var SKILLMD_ORIGIN = "https://skillmd.com";
|
|
629
|
+
var FRONTMATTER = /^(?---\r?\n)([\s\S]*?)(\r?\n---[ \t]*(?:\r?\n|$))/;
|
|
630
|
+
function withRegistrySource(md, slug) {
|
|
631
|
+
const m = FRONTMATTER.exec(md);
|
|
632
|
+
if (!m) return md;
|
|
633
|
+
const [whole, open, block, close] = m;
|
|
634
|
+
const nl = open.endsWith("\r\n") ? "\r\n" : "\n";
|
|
635
|
+
const source = `${SKILLMD_ORIGIN}/skills/${slug}`;
|
|
636
|
+
const lines = block.split(/\r?\n/);
|
|
637
|
+
const at = lines.findIndex((l) => /^metadata[ \t]*:/.test(l));
|
|
638
|
+
if (at === -1) {
|
|
639
|
+
lines.push("metadata:", ` source: ${source}`);
|
|
640
|
+
} else {
|
|
641
|
+
if (!/^metadata[ \t]*:[ \t]*(#.*)?$/.test(lines[at])) return md;
|
|
642
|
+
let end = at + 1;
|
|
643
|
+
while (end < lines.length && (/^[ \t]/.test(lines[end]) || lines[end].trim() === "")) end++;
|
|
644
|
+
const children = lines.slice(at + 1, end);
|
|
645
|
+
if (children.some((l) => /^[ \t]+source[ \t]*:/.test(l))) return md;
|
|
646
|
+
const indent = /^([ \t]+)\S/.exec(children.find((l) => l.trim() !== "") ?? "")?.[1] ?? " ";
|
|
647
|
+
lines.splice(at + 1, 0, `${indent}source: ${source}`);
|
|
648
|
+
}
|
|
649
|
+
const out = open + lines.join(nl) + close + md.slice(whole.length);
|
|
650
|
+
const before = parseSkillMd(md);
|
|
651
|
+
const after = parseSkillMd(out);
|
|
652
|
+
return "error" in after && !("error" in before) ? md : out;
|
|
653
|
+
}
|
|
654
|
+
function filesForInstall(files, source) {
|
|
655
|
+
const slug = /^registry:([^/\s]+\/[^/\s]+)$/.exec(source)?.[1];
|
|
656
|
+
if (!slug) return files;
|
|
657
|
+
return files.map((f) => {
|
|
658
|
+
if (f.path.replace(/\\/g, "/") !== "SKILL.md") return f;
|
|
659
|
+
const text = typeof f.contents === "string" ? f.contents : f.contents.toString("utf8");
|
|
660
|
+
const next = withRegistrySource(text, slug);
|
|
661
|
+
if (next === text) return f;
|
|
662
|
+
return { ...f, contents: typeof f.contents === "string" ? next : Buffer.from(next, "utf8") };
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// src/installer.ts
|
|
625
667
|
var NAME_OK = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
|
|
626
668
|
function assertSafeName(name) {
|
|
627
669
|
if (!NAME_OK.test(name) || name.includes("..")) throw new Error(`refused unsafe skill name: "${name}"`);
|
|
@@ -712,7 +754,7 @@ async function installSkill(req) {
|
|
|
712
754
|
const staging = `${canonical}.tmp-${process.pid}`;
|
|
713
755
|
rmSync3(staging, { recursive: true, force: true });
|
|
714
756
|
try {
|
|
715
|
-
writeTree(staging, req.files);
|
|
757
|
+
writeTree(staging, filesForInstall(req.files, req.source));
|
|
716
758
|
} catch (e) {
|
|
717
759
|
rmSync3(staging, { recursive: true, force: true });
|
|
718
760
|
throw e;
|
package/dist/cli.js
CHANGED
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
uninstallSkill,
|
|
32
32
|
upsertEntry,
|
|
33
33
|
writeConfig
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-MPBRLZWJ.js";
|
|
35
35
|
|
|
36
36
|
// src/index.ts
|
|
37
37
|
import { Command as Command13 } from "commander";
|
|
@@ -608,7 +608,7 @@ async function runInfo(slug, flags, deps = {}) {
|
|
|
608
608
|
const commitSha = safeText(s.provenance?.commit_sha ?? s.commit_sha, 100);
|
|
609
609
|
if (sourceRepo) lines.push(pc7.dim(` source: ${sourceRepo}${commitSha ? ` @ ${commitSha.slice(0, 8)}` : ""}`));
|
|
610
610
|
lines.push(pc7.dim(` page: https://skillmd.com/skills/${slugTxt}`));
|
|
611
|
-
lines.push(pc7.dim(` install: ${safeText(s.install?.cli, 300) || `npx
|
|
611
|
+
lines.push(pc7.dim(` install: ${safeText(s.install?.cli, 300) || `npx get-skill add ${slugTxt}`}`));
|
|
612
612
|
return { ok: true, exitCode: 0, output: lines.join("\n"), skill: s };
|
|
613
613
|
}
|
|
614
614
|
function infoCommand() {
|
|
@@ -1137,7 +1137,9 @@ function finish2(flags, outcome) {
|
|
|
1137
1137
|
written,
|
|
1138
1138
|
blocked,
|
|
1139
1139
|
exitCode,
|
|
1140
|
-
output: json ? JSON.stringify(doc, null, 2) : renderHuman(outcome.notices, outcome.records, outcome.paths)
|
|
1140
|
+
output: json ? JSON.stringify(doc, null, 2) : renderHuman(outcome.notices, outcome.records, outcome.paths),
|
|
1141
|
+
scope: outcome.scope,
|
|
1142
|
+
agents: [...new Set(installed.flatMap((d) => d.targets.map((t) => t.agent)))]
|
|
1141
1143
|
};
|
|
1142
1144
|
}
|
|
1143
1145
|
case "list": {
|
|
@@ -1387,8 +1389,40 @@ var clackUI = {
|
|
|
1387
1389
|
spinner: () => p3.spinner(),
|
|
1388
1390
|
message: (m) => p3.log.message(m),
|
|
1389
1391
|
outro: (m) => p3.outro(m),
|
|
1390
|
-
cancel: (m) => p3.cancel(m)
|
|
1392
|
+
cancel: (m) => p3.cancel(m),
|
|
1393
|
+
confirm: async (m) => {
|
|
1394
|
+
const answer = await p3.confirm({ message: m, initialValue: true });
|
|
1395
|
+
return p3.isCancel(answer) ? null : answer;
|
|
1396
|
+
}
|
|
1391
1397
|
};
|
|
1398
|
+
var FIND_SKILLS = "skillmd/find-skills";
|
|
1399
|
+
async function offerFindSkills(source, flags, run2, ui, deps) {
|
|
1400
|
+
if (!ui.confirm || run2.exitCode !== 0 || !run2.written.length || !run2.scope || !run2.agents?.length) return;
|
|
1401
|
+
if (source.replace(/^registry:/, "").toLowerCase() === FIND_SKILLS) return;
|
|
1402
|
+
const cfg = readConfig(flags.home);
|
|
1403
|
+
if (cfg.findSkillsOffered) return;
|
|
1404
|
+
const global = run2.scope === "global";
|
|
1405
|
+
const lock = readLock({ global, cwd: flags.cwd, home: flags.home });
|
|
1406
|
+
if (Object.values(lock.skills).some((e) => e.source === `registry:${FIND_SKILLS}`)) return;
|
|
1407
|
+
try {
|
|
1408
|
+
writeConfig({ ...cfg, findSkillsOffered: true }, flags.home);
|
|
1409
|
+
} catch {
|
|
1410
|
+
}
|
|
1411
|
+
const yes = await ui.confirm("Also add find-skills, so your agent can look for more skills on SkillMD when a task needs one?");
|
|
1412
|
+
if (!yes) return;
|
|
1413
|
+
const r = await runAdd(FIND_SKILLS, {
|
|
1414
|
+
...flags,
|
|
1415
|
+
yes: true,
|
|
1416
|
+
json: false,
|
|
1417
|
+
skill: void 0,
|
|
1418
|
+
list: void 0,
|
|
1419
|
+
ref: void 0,
|
|
1420
|
+
global,
|
|
1421
|
+
project: !global,
|
|
1422
|
+
agent: run2.agents
|
|
1423
|
+
}, deps);
|
|
1424
|
+
ui.message(r.exitCode === 0 ? `${pc8.green(GLYPH.ok)} find-skills added` : pc8.yellow(`${GLYPH.warn} find-skills could not be added. Try later: npx get-skill add ${FIND_SKILLS}`));
|
|
1425
|
+
}
|
|
1392
1426
|
async function runAddWithUI(source, flags, opts = {}) {
|
|
1393
1427
|
const term = opts.term ?? { ...realTerminal(), env: flags.env ?? process.env };
|
|
1394
1428
|
const base = opts.deps ?? makeDefaultDeps(flags);
|
|
@@ -1421,7 +1455,8 @@ async function runAddWithUI(source, flags, opts = {}) {
|
|
|
1421
1455
|
return { run: run2, printed: true };
|
|
1422
1456
|
}
|
|
1423
1457
|
ui.message(run2.output);
|
|
1424
|
-
|
|
1458
|
+
await offerFindSkills(source, flags, run2, ui, base);
|
|
1459
|
+
ui.outro(run2.exitCode === 0 ? `Done. Run ${pc8.cyan("npx get-skill list")} to see everything installed.` : pc8.red("Some skills were not installed."));
|
|
1425
1460
|
return { run: run2, printed: true };
|
|
1426
1461
|
} catch (e) {
|
|
1427
1462
|
ui.outro(pc8.red("Nothing was installed."));
|
|
@@ -1454,7 +1489,7 @@ function runList(flags = {}) {
|
|
|
1454
1489
|
if (flags.json) {
|
|
1455
1490
|
return { items, output: JSON.stringify(items.map(({ name, scope, path, agents, source, mode, tracked, description }) => ({ name, scope, path, agents, source: source ?? null, mode, tracked, description })), null, 2) };
|
|
1456
1491
|
}
|
|
1457
|
-
if (items.length === 0) return { items, output: pc9.dim("No installed skills found. Install one with `
|
|
1492
|
+
if (items.length === 0) return { items, output: pc9.dim("No installed skills found. Install one with `npx get-skill add owner/name`.") };
|
|
1458
1493
|
const w = Math.max(...items.map((i) => i.name.length), 4);
|
|
1459
1494
|
const lines = items.map((i) => {
|
|
1460
1495
|
const tag = i.tracked ? pc9.dim(i.source ?? "") : pc9.yellow("untracked");
|
|
@@ -1672,7 +1707,7 @@ async function runUpdate(names, flags, deps = defaultUpdateDeps) {
|
|
|
1672
1707
|
const label2 = `${s.name}${scopes.length > 1 ? pc11.dim(` [${s.scope}]`) : ""}`;
|
|
1673
1708
|
const entry = lock.skills[s.name];
|
|
1674
1709
|
if (!entry) {
|
|
1675
|
-
lines.push(pc11.dim(`- ${label2} untracked \u2014 reinstall with \`
|
|
1710
|
+
lines.push(pc11.dim(`- ${label2} untracked \u2014 reinstall with \`npx get-skill add\` to track updates`));
|
|
1676
1711
|
continue;
|
|
1677
1712
|
}
|
|
1678
1713
|
if (entry.source.startsWith("local:")) {
|
|
@@ -1752,7 +1787,7 @@ var defaultDeps2 = {
|
|
|
1752
1787
|
resolve: resolveSource,
|
|
1753
1788
|
async submit(payload, flags) {
|
|
1754
1789
|
const { api, hasToken } = createClient(flags);
|
|
1755
|
-
if (!hasToken) throw new Error("No token. Run `
|
|
1790
|
+
if (!hasToken) throw new Error("No token. Run `npx get-skill login` or pass --token.");
|
|
1756
1791
|
return api(`/api/skills`, {
|
|
1757
1792
|
method: "POST",
|
|
1758
1793
|
headers: { "content-type": "application/json" },
|
|
@@ -2078,18 +2113,18 @@ try {
|
|
|
2078
2113
|
version = JSON.parse(readFileSync3(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
2079
2114
|
} catch {
|
|
2080
2115
|
}
|
|
2081
|
-
var program = new Command13("
|
|
2116
|
+
var program = new Command13("get-skill").version(version).description("Lint, validate, and install Agent Skills from the SkillMD registry.").option("--json", "machine-readable output").option("--token <token>", "personal access token (prefer `npx get-skill login` or SKILLMD_TOKEN \u2014 command-line tokens show up in process lists)").option("--api <url>", "override the registry API base URL").option("--insecure-http", "allow an http:// --api base (local development only)");
|
|
2082
2117
|
program.configureHelp({ sortSubcommands: false });
|
|
2083
2118
|
program.addHelpText("after", `
|
|
2084
2119
|
Examples:
|
|
2085
|
-
$
|
|
2086
|
-
$
|
|
2087
|
-
$
|
|
2088
|
-
$
|
|
2089
|
-
$
|
|
2090
|
-
$
|
|
2091
|
-
$
|
|
2092
|
-
$
|
|
2120
|
+
$ npx get-skill add anthropic/pdf install from the registry (asks project vs global)
|
|
2121
|
+
$ npx get-skill add owner/repo/skills/x#main -g a GitHub subfolder at a ref, into your user dirs
|
|
2122
|
+
$ npx get-skill add ./my-skill -a claude-code -p a local skill into this project for one agent
|
|
2123
|
+
$ npx get-skill add anthropic/pdf -y --json non-interactive, machine-readable
|
|
2124
|
+
$ npx get-skill list everything installed, project and global
|
|
2125
|
+
$ npx get-skill check which installed skills have updates
|
|
2126
|
+
$ npx get-skill update -g update your user-level skills
|
|
2127
|
+
$ npx get-skill remove pdf remove a skill from every agent
|
|
2093
2128
|
|
|
2094
2129
|
Quality: lint scan rules init
|
|
2095
2130
|
Registry: search info add list remove update check
|
|
@@ -2099,7 +2134,7 @@ Docs: https://skillmd.com/docs/cli`);
|
|
|
2099
2134
|
program.hook("preAction", (thisCmd) => {
|
|
2100
2135
|
const opts = thisCmd.opts();
|
|
2101
2136
|
if (opts.token && process.stderr.isTTY) {
|
|
2102
|
-
console.error(pc15.yellow("\u26A0 --token is visible in your shell history and process list; prefer `
|
|
2137
|
+
console.error(pc15.yellow("\u26A0 --token is visible in your shell history and process list; prefer `npx get-skill login` or SKILLMD_TOKEN."));
|
|
2103
2138
|
}
|
|
2104
2139
|
});
|
|
2105
2140
|
program.addCommand(lintCommand());
|
package/dist/mcp.js
CHANGED
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skillmds",
|
|
3
|
-
"version": "1.3.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.3.7",
|
|
4
|
+
"description": "Find, install, lint and publish Agent Skills (SKILL.md) from skillmd.com: the get-skill CLI and MCP server.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "SkillMD",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"mcpName": "com.skillmd/skillmd",
|
|
9
9
|
"bin": {
|
|
10
|
-
"
|
|
11
|
-
"skillmd": "bin/skillmd.mjs"
|
|
10
|
+
"get-skill": "bin/skillmd-mcp.mjs",
|
|
11
|
+
"skillmd": "bin/skillmd.mjs",
|
|
12
|
+
"skillmds": "bin/skillmd-mcp.mjs"
|
|
12
13
|
},
|
|
13
14
|
"files": [
|
|
14
15
|
"bin",
|
|
@@ -21,6 +22,7 @@
|
|
|
21
22
|
"node": ">=18"
|
|
22
23
|
},
|
|
23
24
|
"keywords": [
|
|
25
|
+
"get-skill",
|
|
24
26
|
"mcp",
|
|
25
27
|
"model-context-protocol",
|
|
26
28
|
"cli",
|