@openskillmd/osm 0.3.0 → 0.3.1
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/dist/add-77ZPOLTV.js +3 -0
- package/dist/browse-P7RXLMMF.js +37 -0
- package/dist/chunk-5CDG6OB7.js +68 -0
- package/dist/chunk-AXKAVWKJ.js +3 -0
- package/dist/chunk-IZJHFL7T.js +7 -0
- package/dist/chunk-MWJMJUS4.js +35 -0
- package/dist/chunk-ONVELHE6.js +8 -0
- package/dist/chunk-OVTYCRA4.js +7 -0
- package/dist/chunk-YAZPI4SK.js +3 -0
- package/dist/index.js +30 -1527
- package/dist/info-5GSXNJ5W.js +46 -0
- package/dist/init-ZDBNGFX7.js +69 -0
- package/dist/list-SMKTYTII.js +9 -0
- package/dist/mcp-UHV7L4RE.js +6 -0
- package/dist/remove-QKFHXT73.js +7 -0
- package/dist/router-AVHY4U3G.js +3 -0
- package/dist/score-CPVOUARV.js +4 -0
- package/dist/search-JQMXVSCW.js +24 -0
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -1,1528 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
var
|
|
29
|
-
|
|
30
|
-
var
|
|
31
|
-
|
|
32
|
-
${purple(" \u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E")}
|
|
33
|
-
${purple(" \u2502")} ${purpleBright(" \u256D\u2500\u2500\u2500\u256E \u256D\u2500\u2500\u2500\u256E ")} ${purple("\u2502")}
|
|
34
|
-
${purple(" \u2502")} ${purpleBright(" \u256D\u2524")} ${chalk.white("\u25C9")} ${purpleBright("\u251C\u2500\u2524")} ${chalk.white("\u25C9")} ${purpleBright("\u251C\u256E ")} ${purple("\u2502")}
|
|
35
|
-
${purple(" \u2502")} ${purpleBright(" \u2570\u2524")} ${purpleBright("\u251C\u2500\u2524")} ${purpleBright("\u251C\u256F ")} ${purple("\u2502")}
|
|
36
|
-
${purple(" \u2502")} ${purpleBright(" \u2570\u2500\u2500\u2500\u256F \u2570\u2500\u2500\u2500\u256F ")} ${purple("\u2502")}
|
|
37
|
-
${gold("\u2590\u258C")}${purple("\u2502")} ${chalk.white("\u2570\u2500\u203F\u2500\u256F")} ${purple("\u2502")}
|
|
38
|
-
${purple(" \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F")}`;
|
|
39
|
-
function getBannerString() {
|
|
40
|
-
return boxen(
|
|
41
|
-
`${MASCOT}
|
|
42
|
-
|
|
43
|
-
${purpleBright.bold(" OpenSkill.md")} ${purpleDim("\u2014 the npm for AI skills")}`,
|
|
44
|
-
{
|
|
45
|
-
padding: { top: 0, bottom: 0, left: 1, right: 1 },
|
|
46
|
-
borderColor: "#7C3AED",
|
|
47
|
-
borderStyle: "round",
|
|
48
|
-
textAlignment: "center"
|
|
49
|
-
}
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
function showBanner() {
|
|
53
|
-
process.stderr.write(getBannerString() + "\n\n");
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// src/lib/format.ts
|
|
57
|
-
function verifiedBadge(publisher) {
|
|
58
|
-
if (publisher?.verificationStatus === "verified") {
|
|
59
|
-
return chalk2.green(" \u2713 verified");
|
|
60
|
-
}
|
|
61
|
-
return "";
|
|
62
|
-
}
|
|
63
|
-
function scoreColor(score, max) {
|
|
64
|
-
const pct = score / max;
|
|
65
|
-
if (pct >= 0.8) return chalk2.green(String(score));
|
|
66
|
-
if (pct >= 0.6) return chalk2.yellow(String(score));
|
|
67
|
-
return chalk2.red(String(score));
|
|
68
|
-
}
|
|
69
|
-
function scoreBar(score, max) {
|
|
70
|
-
const filled = Math.round(score / max * 20);
|
|
71
|
-
const empty = 20 - filled;
|
|
72
|
-
const pct = score / max;
|
|
73
|
-
const color = pct >= 0.8 ? chalk2.green : pct >= 0.6 ? chalk2.yellow : chalk2.red;
|
|
74
|
-
return color("\u2588".repeat(filled)) + chalk2.gray("\u2591".repeat(empty));
|
|
75
|
-
}
|
|
76
|
-
function formatDownloads(n) {
|
|
77
|
-
if (!n) return "0";
|
|
78
|
-
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}k`;
|
|
79
|
-
return String(n);
|
|
80
|
-
}
|
|
81
|
-
function sectionHeader(title) {
|
|
82
|
-
return purpleBright.bold(`
|
|
83
|
-
${title}
|
|
84
|
-
${"\u2500".repeat(title.length)}
|
|
85
|
-
`);
|
|
86
|
-
}
|
|
87
|
-
function errorMessage(msg, suggestion) {
|
|
88
|
-
let out = chalk2.red(` \u2716 ${msg}`);
|
|
89
|
-
if (suggestion) {
|
|
90
|
-
out += chalk2.gray(`
|
|
91
|
-
\u2192 ${suggestion}`);
|
|
92
|
-
}
|
|
93
|
-
return out;
|
|
94
|
-
}
|
|
95
|
-
function successMessage(msg) {
|
|
96
|
-
return chalk2.green(` \u2714 ${msg}`);
|
|
97
|
-
}
|
|
98
|
-
function jsonResult(obj) {
|
|
99
|
-
process.stdout.write(JSON.stringify(obj) + "\n");
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// src/lib/env.ts
|
|
103
|
-
var envSchema = z.object({
|
|
104
|
-
OPENSKILL_API_URL: z.preprocess(
|
|
105
|
-
// An empty string behaved like "unset" before validation existed
|
|
106
|
-
// (`process.env.X || fallback`); keep that contract.
|
|
107
|
-
(value) => value === "" ? void 0 : value,
|
|
108
|
-
z.url(
|
|
109
|
-
"OPENSKILL_API_URL must be a full URL, e.g. https://staging.openskill.md/api"
|
|
110
|
-
).optional()
|
|
111
|
-
)
|
|
112
|
-
});
|
|
113
|
-
function parseEnv(raw) {
|
|
114
|
-
const result = envSchema.safeParse(raw);
|
|
115
|
-
if (!result.success) {
|
|
116
|
-
const issue = result.error.issues[0];
|
|
117
|
-
const where = issue?.path.join(".") ?? "environment";
|
|
118
|
-
return { ok: false, message: `${where}: ${issue?.message ?? "invalid"}` };
|
|
119
|
-
}
|
|
120
|
-
return { ok: true, env: result.data };
|
|
121
|
-
}
|
|
122
|
-
var cached;
|
|
123
|
-
function getEnv() {
|
|
124
|
-
if (cached) return cached;
|
|
125
|
-
const result = parseEnv(process.env);
|
|
126
|
-
if (!result.ok) {
|
|
127
|
-
console.error(
|
|
128
|
-
errorMessage(
|
|
129
|
-
result.message,
|
|
130
|
-
"Fix or unset the variable, then re-run the command."
|
|
131
|
-
)
|
|
132
|
-
);
|
|
133
|
-
process.exit(2);
|
|
134
|
-
}
|
|
135
|
-
cached = result.env;
|
|
136
|
-
return cached;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// src/lib/config.ts
|
|
140
|
-
var CONFIG_DIR = join(homedir(), ".openskill");
|
|
141
|
-
var CONFIG_FILE = join(CONFIG_DIR, "config.json");
|
|
142
|
-
var configSchema = z2.object({
|
|
143
|
-
token: z2.string().min(1).optional(),
|
|
144
|
-
email: z2.email().optional(),
|
|
145
|
-
baseUrl: z2.url().optional()
|
|
146
|
-
});
|
|
147
|
-
async function loadConfig() {
|
|
148
|
-
let raw;
|
|
149
|
-
try {
|
|
150
|
-
raw = await readFile(CONFIG_FILE, "utf-8");
|
|
151
|
-
} catch {
|
|
152
|
-
return {};
|
|
153
|
-
}
|
|
154
|
-
let parsed;
|
|
155
|
-
try {
|
|
156
|
-
parsed = JSON.parse(raw);
|
|
157
|
-
} catch {
|
|
158
|
-
warnInvalidConfig("not valid JSON");
|
|
159
|
-
return {};
|
|
160
|
-
}
|
|
161
|
-
const result = configSchema.safeParse(parsed);
|
|
162
|
-
if (!result.success) {
|
|
163
|
-
const issue = result.error.issues[0];
|
|
164
|
-
warnInvalidConfig(
|
|
165
|
-
`${issue?.path.join(".") ?? "config"}: ${issue?.message ?? "invalid"}`
|
|
166
|
-
);
|
|
167
|
-
return {};
|
|
168
|
-
}
|
|
169
|
-
return result.data;
|
|
170
|
-
}
|
|
171
|
-
function warnInvalidConfig(reason) {
|
|
172
|
-
process.stderr.write(
|
|
173
|
-
`Warning: ignoring invalid ${CONFIG_FILE} (${reason}) \u2014 re-run \`osm login\` or fix the file.
|
|
174
|
-
`
|
|
175
|
-
);
|
|
176
|
-
}
|
|
177
|
-
var DEFAULT_API_BASE_URL = "https://staging.openskill.md/api";
|
|
178
|
-
function getApiBaseUrl(config) {
|
|
179
|
-
const raw = getEnv().OPENSKILL_API_URL || config.baseUrl || DEFAULT_API_BASE_URL;
|
|
180
|
-
return raw.replace(/\/+$/, "");
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// src/lib/api.ts
|
|
184
|
-
var _apiBase;
|
|
185
|
-
async function getApiBase() {
|
|
186
|
-
if (_apiBase) return _apiBase;
|
|
187
|
-
const config = await loadConfig();
|
|
188
|
-
_apiBase = getApiBaseUrl(config);
|
|
189
|
-
return _apiBase;
|
|
190
|
-
}
|
|
191
|
-
async function resolveApiBase() {
|
|
192
|
-
return getApiBase();
|
|
193
|
-
}
|
|
194
|
-
async function resolveWebOrigin() {
|
|
195
|
-
return (await getApiBase()).replace(/\/api\/?$/, "");
|
|
196
|
-
}
|
|
197
|
-
var ApiError = class extends Error {
|
|
198
|
-
statusCode;
|
|
199
|
-
constructor(statusCode, message) {
|
|
200
|
-
super(message);
|
|
201
|
-
this.name = "ApiError";
|
|
202
|
-
this.statusCode = statusCode;
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
async function fetchApi(path6) {
|
|
206
|
-
const base = await getApiBase();
|
|
207
|
-
const url = `${base}${path6}`;
|
|
208
|
-
const res = await fetch(url);
|
|
209
|
-
if (!res.ok) {
|
|
210
|
-
throw new ApiError(res.status, `API returned ${res.status} for ${path6}`);
|
|
211
|
-
}
|
|
212
|
-
return res.json();
|
|
213
|
-
}
|
|
214
|
-
async function searchApi(query) {
|
|
215
|
-
return fetchApi(`/search?q=${encodeURIComponent(query)}`);
|
|
216
|
-
}
|
|
217
|
-
async function getSkill(slug) {
|
|
218
|
-
return fetchApi(`/skills/${encodeURIComponent(slug)}`);
|
|
219
|
-
}
|
|
220
|
-
async function getBlueprint(slug) {
|
|
221
|
-
return fetchApi(`/blueprints/${encodeURIComponent(slug)}`);
|
|
222
|
-
}
|
|
223
|
-
async function getCollections(params) {
|
|
224
|
-
const qs = new URLSearchParams();
|
|
225
|
-
if (params?.search) qs.set("search", params.search);
|
|
226
|
-
qs.set("limit", String(params?.limit ?? 50));
|
|
227
|
-
const res = await fetchApi(
|
|
228
|
-
`/collections?${qs.toString()}`
|
|
229
|
-
);
|
|
230
|
-
return res.data;
|
|
231
|
-
}
|
|
232
|
-
async function getCollection(slug) {
|
|
233
|
-
return fetchApi(`/collections/${encodeURIComponent(slug)}`);
|
|
234
|
-
}
|
|
235
|
-
async function listMcpServers(params) {
|
|
236
|
-
const qs = new URLSearchParams();
|
|
237
|
-
if (params?.search) qs.set("search", params.search);
|
|
238
|
-
if (params?.category) qs.set("category", params.category);
|
|
239
|
-
qs.set("limit", String(params?.limit ?? 50));
|
|
240
|
-
qs.set("sort", "stars");
|
|
241
|
-
qs.set("order", "desc");
|
|
242
|
-
return fetchApi(`/mcp-servers?${qs.toString()}`);
|
|
243
|
-
}
|
|
244
|
-
async function getMcpCategories() {
|
|
245
|
-
return fetchApi("/mcp-servers/categories");
|
|
246
|
-
}
|
|
247
|
-
async function getMcpServer(slug) {
|
|
248
|
-
return fetchApi(`/mcp-servers/${encodeURIComponent(slug)}`);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// src/commands/add.ts
|
|
252
|
-
var require2 = createRequire(import.meta.url);
|
|
253
|
-
function stripSkillsBanner(chunk) {
|
|
254
|
-
return chunk.replace(/^.*[█╔╗╚╝═║].*\r?\n?/gm, "").replace(/^.*open agent skills ecosystem.*\r?\n?/gm, "");
|
|
255
|
-
}
|
|
256
|
-
function validateSource(source) {
|
|
257
|
-
if (!source || typeof source !== "string" || source.length === 0 || source.length > 500) {
|
|
258
|
-
return {
|
|
259
|
-
ok: false,
|
|
260
|
-
code: 2,
|
|
261
|
-
message: "Source is required, e.g. owner/repo or owner/repo@skill"
|
|
262
|
-
};
|
|
263
|
-
}
|
|
264
|
-
if (!/[/@:.]/.test(source)) {
|
|
265
|
-
return { ok: false, code: "needs-resolution", slug: source };
|
|
266
|
-
}
|
|
267
|
-
return { ok: true };
|
|
268
|
-
}
|
|
269
|
-
async function resolveSlug(slug) {
|
|
270
|
-
let skill;
|
|
271
|
-
try {
|
|
272
|
-
skill = await getSkill(slug);
|
|
273
|
-
} catch (err) {
|
|
274
|
-
if (err instanceof ApiError && err.statusCode === 404) {
|
|
275
|
-
return {
|
|
276
|
-
ok: false,
|
|
277
|
-
message: `No skill named "${slug}" in the registry.`,
|
|
278
|
-
suggestion: "Run `osm search <query>` to find it, or pass owner/repo directly."
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
return {
|
|
282
|
-
ok: false,
|
|
283
|
-
message: `Couldn't reach the registry to resolve "${slug}".`,
|
|
284
|
-
suggestion: "Check your connection (and OPENSKILL_API_URL, if set), or pass owner/repo directly."
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
const skillName = skill.name || null;
|
|
288
|
-
if (skill.githubOwner && skill.githubRepo) {
|
|
289
|
-
const source = `${skill.githubOwner}/${skill.githubRepo}`;
|
|
290
|
-
return {
|
|
291
|
-
ok: true,
|
|
292
|
-
source,
|
|
293
|
-
skillName,
|
|
294
|
-
note: skillName ? `resolved ${slug} \u2192 ${source} (skill: ${skillName})` : `resolved ${slug} \u2192 ${source}`
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
if (skill.sourceUrl && /^https?:\/\//.test(skill.sourceUrl)) {
|
|
298
|
-
return {
|
|
299
|
-
ok: true,
|
|
300
|
-
source: skill.sourceUrl,
|
|
301
|
-
skillName,
|
|
302
|
-
note: skillName ? `resolved ${slug} \u2192 ${skill.sourceUrl} (skill: ${skillName})` : `resolved ${slug} \u2192 ${skill.sourceUrl}`
|
|
303
|
-
};
|
|
304
|
-
}
|
|
305
|
-
return {
|
|
306
|
-
ok: false,
|
|
307
|
-
message: `"${slug}" lives only in the OpenSkill registry \u2014 it has no GitHub source to install from yet.`,
|
|
308
|
-
suggestion: `Run \`osm info ${slug}\` to inspect it.`
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
function toSkillSlug(name) {
|
|
312
|
-
return name.toLowerCase().replace(/[\s_]+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
313
|
-
}
|
|
314
|
-
function buildSkillsArgs(source, opts = {}, skillFilter = null) {
|
|
315
|
-
const args = ["add", source, "-y"];
|
|
316
|
-
if (skillFilter) {
|
|
317
|
-
args.push("--skill", skillFilter);
|
|
318
|
-
const kebab = toSkillSlug(skillFilter);
|
|
319
|
-
if (kebab && kebab !== skillFilter.toLowerCase()) {
|
|
320
|
-
args.push("--skill", kebab);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
for (const a of opts.agent ?? []) {
|
|
324
|
-
args.push("-a", a);
|
|
325
|
-
}
|
|
326
|
-
if (opts.global) args.push("-g");
|
|
327
|
-
if (opts.copy) args.push("--copy");
|
|
328
|
-
return args;
|
|
329
|
-
}
|
|
330
|
-
function buildJsonResult(source, opts, code, capturedStderr, resolvedFrom = null) {
|
|
331
|
-
if (code === 0) {
|
|
332
|
-
return {
|
|
333
|
-
ok: true,
|
|
334
|
-
source,
|
|
335
|
-
resolvedFrom,
|
|
336
|
-
agent: opts.agent ?? null,
|
|
337
|
-
scope: opts.global ? "user" : "project"
|
|
338
|
-
};
|
|
339
|
-
}
|
|
340
|
-
return {
|
|
341
|
-
ok: false,
|
|
342
|
-
source,
|
|
343
|
-
resolvedFrom,
|
|
344
|
-
error: {
|
|
345
|
-
code: `INSTALL_EXIT_${code}`,
|
|
346
|
-
message: capturedStderr.trim() || "install failed"
|
|
347
|
-
}
|
|
348
|
-
};
|
|
349
|
-
}
|
|
350
|
-
async function addCommand(source, opts = {}) {
|
|
351
|
-
let installSource = source;
|
|
352
|
-
let resolvedFrom = null;
|
|
353
|
-
let skillFilter = null;
|
|
354
|
-
const validation = validateSource(source);
|
|
355
|
-
if (!validation.ok) {
|
|
356
|
-
if (validation.code !== "needs-resolution") {
|
|
357
|
-
console.error(errorMessage(validation.message, validation.suggestion));
|
|
358
|
-
process.exit(validation.code);
|
|
359
|
-
}
|
|
360
|
-
const spinner = opts.json ? null : ora({
|
|
361
|
-
text: `Resolving "${validation.slug}" in the registry...`,
|
|
362
|
-
color: "magenta"
|
|
363
|
-
}).start();
|
|
364
|
-
const resolved = await resolveSlug(validation.slug);
|
|
365
|
-
spinner?.stop();
|
|
366
|
-
if (!resolved.ok) {
|
|
367
|
-
if (opts.json) {
|
|
368
|
-
jsonResult({
|
|
369
|
-
ok: false,
|
|
370
|
-
source,
|
|
371
|
-
resolvedFrom: null,
|
|
372
|
-
error: { code: "SLUG_RESOLUTION_FAILED", message: resolved.message }
|
|
373
|
-
});
|
|
374
|
-
} else {
|
|
375
|
-
console.error(errorMessage(resolved.message, resolved.suggestion));
|
|
376
|
-
}
|
|
377
|
-
process.exit(2);
|
|
378
|
-
}
|
|
379
|
-
if (!opts.json) {
|
|
380
|
-
console.error(chalk3.gray(` \u2192 ${resolved.note}`));
|
|
381
|
-
}
|
|
382
|
-
installSource = resolved.source;
|
|
383
|
-
resolvedFrom = validation.slug;
|
|
384
|
-
skillFilter = resolved.skillName;
|
|
385
|
-
}
|
|
386
|
-
let binPath;
|
|
387
|
-
try {
|
|
388
|
-
binPath = require2.resolve("skills/bin/cli.mjs");
|
|
389
|
-
} catch {
|
|
390
|
-
console.error(
|
|
391
|
-
errorMessage(
|
|
392
|
-
"The installer backend is missing.",
|
|
393
|
-
"Reinstall @openskillmd/osm to restore its dependencies."
|
|
394
|
-
)
|
|
395
|
-
);
|
|
396
|
-
process.exit(3);
|
|
397
|
-
}
|
|
398
|
-
const args = buildSkillsArgs(installSource, opts, skillFilter);
|
|
399
|
-
if (!opts.json) {
|
|
400
|
-
console.error(chalk3.gray(" \u2192 fetching skill files\u2026"));
|
|
401
|
-
console.error("");
|
|
402
|
-
}
|
|
403
|
-
const child = spawn(process.execPath, [binPath, ...args], {
|
|
404
|
-
stdio: ["inherit", "pipe", "pipe"],
|
|
405
|
-
// env.ts carve-out: this is a *write* into the child installer's env
|
|
406
|
-
// (opting it out of telemetry), not a read of our own config — so it
|
|
407
|
-
// doesn't go through getEnv().
|
|
408
|
-
env: { ...process.env, DISABLE_TELEMETRY: "1" }
|
|
409
|
-
});
|
|
410
|
-
let capturedStderr = "";
|
|
411
|
-
if (child.stdout) {
|
|
412
|
-
child.stdout.on("data", (chunk) => {
|
|
413
|
-
const filtered = stripSkillsBanner(chunk.toString("utf-8"));
|
|
414
|
-
if (filtered && !opts.json) process.stdout.write(filtered);
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
if (child.stderr) {
|
|
418
|
-
child.stderr.on("data", (chunk) => {
|
|
419
|
-
const text = chunk.toString("utf-8");
|
|
420
|
-
if (opts.json) {
|
|
421
|
-
capturedStderr += text;
|
|
422
|
-
} else {
|
|
423
|
-
const filtered = stripSkillsBanner(text);
|
|
424
|
-
if (filtered) process.stderr.write(filtered);
|
|
425
|
-
}
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
const code = await new Promise((resolve) => {
|
|
429
|
-
child.once("exit", (c) => resolve(c ?? 1));
|
|
430
|
-
child.once("error", () => resolve(3));
|
|
431
|
-
});
|
|
432
|
-
if (opts.json) {
|
|
433
|
-
jsonResult(
|
|
434
|
-
buildJsonResult(installSource, opts, code, capturedStderr, resolvedFrom)
|
|
435
|
-
);
|
|
436
|
-
}
|
|
437
|
-
process.exit(code);
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
// src/commands/browse.ts
|
|
441
|
-
import chalk4 from "chalk";
|
|
442
|
-
import inquirer from "inquirer";
|
|
443
|
-
import ora2 from "ora";
|
|
444
|
-
var EXIT_SENTINEL = "__exit__";
|
|
445
|
-
async function browseCommand() {
|
|
446
|
-
try {
|
|
447
|
-
const { mode } = await inquirer.prompt([
|
|
448
|
-
{
|
|
449
|
-
type: "list",
|
|
450
|
-
name: "mode",
|
|
451
|
-
message: purpleBright("What would you like to explore?"),
|
|
452
|
-
choices: [
|
|
453
|
-
{ name: "\u{1F4DA} Collections (curated sets of skills & blueprints)", value: "collections" },
|
|
454
|
-
{ name: "\u{1F50C} MCP servers", value: "mcp" },
|
|
455
|
-
{ name: chalk4.gray("\u2190 Exit"), value: EXIT_SENTINEL }
|
|
456
|
-
]
|
|
457
|
-
}
|
|
458
|
-
]);
|
|
459
|
-
if (mode === EXIT_SENTINEL) return;
|
|
460
|
-
if (mode === "mcp") {
|
|
461
|
-
await browseMcpServers();
|
|
462
|
-
return;
|
|
463
|
-
}
|
|
464
|
-
await browseCollections();
|
|
465
|
-
} catch (err) {
|
|
466
|
-
process.stderr.write(
|
|
467
|
-
errorMessage(err instanceof Error ? err.message : "Unknown error") + "\n"
|
|
468
|
-
);
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
async function browseCollections() {
|
|
472
|
-
const spinner = ora2({ text: "Loading collections...", color: "magenta" }).start();
|
|
473
|
-
const collections = await getCollections({ limit: 50 });
|
|
474
|
-
spinner.stop();
|
|
475
|
-
if (collections.length === 0) {
|
|
476
|
-
process.stderr.write(errorMessage("No collections found.") + "\n");
|
|
477
|
-
return;
|
|
478
|
-
}
|
|
479
|
-
const choices = collections.map((c) => ({
|
|
480
|
-
name: `${c.icon || "\u{1F4E6}"} ${c.name} ${chalk4.gray(`(${c.itemCount} items)`)}`,
|
|
481
|
-
value: c.slug
|
|
482
|
-
}));
|
|
483
|
-
choices.push({ name: chalk4.gray("\u2190 Exit"), value: EXIT_SENTINEL });
|
|
484
|
-
const { slug } = await inquirer.prompt([
|
|
485
|
-
{
|
|
486
|
-
type: "list",
|
|
487
|
-
name: "slug",
|
|
488
|
-
message: purpleBright("Choose a collection to explore:"),
|
|
489
|
-
choices,
|
|
490
|
-
pageSize: 15
|
|
491
|
-
}
|
|
492
|
-
]);
|
|
493
|
-
if (slug === EXIT_SENTINEL) return;
|
|
494
|
-
const detailSpinner = ora2({ text: "Loading collection...", color: "magenta" }).start();
|
|
495
|
-
const collection = await getCollection(slug);
|
|
496
|
-
detailSpinner.stop();
|
|
497
|
-
renderCollection(collection);
|
|
498
|
-
}
|
|
499
|
-
function renderCollection(collection) {
|
|
500
|
-
process.stderr.write(
|
|
501
|
-
sectionHeader(`${collection.icon || "\u{1F4E6}"} ${collection.name}`) + "\n"
|
|
502
|
-
);
|
|
503
|
-
if (collection.description) {
|
|
504
|
-
process.stderr.write(` ${chalk4.white(collection.description)}
|
|
505
|
-
|
|
506
|
-
`);
|
|
507
|
-
}
|
|
508
|
-
const skills = collection.skills ?? [];
|
|
509
|
-
const blueprints = collection.blueprints ?? [];
|
|
510
|
-
const mcpServers = collection.mcpServers ?? [];
|
|
511
|
-
if (skills.length === 0 && blueprints.length === 0 && mcpServers.length === 0) {
|
|
512
|
-
process.stderr.write(chalk4.gray(" This collection is empty.\n\n"));
|
|
513
|
-
return;
|
|
514
|
-
}
|
|
515
|
-
if (skills.length > 0) {
|
|
516
|
-
process.stderr.write(sectionHeader(`Skills (${skills.length})`) + "\n");
|
|
517
|
-
for (const skill of skills) {
|
|
518
|
-
const score = skill.scoreOverall != null ? scoreColor(skill.scoreOverall, 100) : chalk4.gray("--");
|
|
519
|
-
process.stdout.write(
|
|
520
|
-
` ${purpleBright(skill.name)}${verifiedBadge(skill.publisher)} ${chalk4.gray("\xB7")} score: ${score} ${chalk4.gray("\xB7")} ${formatDownloads(skill.downloads)} downloads
|
|
521
|
-
`
|
|
522
|
-
);
|
|
523
|
-
if (skill.description) {
|
|
524
|
-
process.stdout.write(` ${chalk4.gray(skill.description.slice(0, 100))}
|
|
525
|
-
`);
|
|
526
|
-
}
|
|
527
|
-
process.stdout.write(` ${chalk4.gray(`slug: ${skill.slug}`)}
|
|
528
|
-
|
|
529
|
-
`);
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
if (blueprints.length > 0) {
|
|
533
|
-
process.stderr.write(sectionHeader(`Blueprints (${blueprints.length})`) + "\n");
|
|
534
|
-
for (const bp of blueprints) {
|
|
535
|
-
process.stdout.write(
|
|
536
|
-
` ${purpleBright(bp.name)}${verifiedBadge(bp.publisher)} ${chalk4.gray("\xB7")} ${formatDownloads(bp.downloads)} downloads
|
|
537
|
-
`
|
|
538
|
-
);
|
|
539
|
-
if (bp.description) {
|
|
540
|
-
process.stdout.write(` ${chalk4.gray(bp.description.slice(0, 100))}
|
|
541
|
-
`);
|
|
542
|
-
}
|
|
543
|
-
process.stdout.write(` ${chalk4.gray(`slug: ${bp.slug}`)}
|
|
544
|
-
|
|
545
|
-
`);
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
if (mcpServers.length > 0) {
|
|
549
|
-
process.stderr.write(sectionHeader(`MCP Servers (${mcpServers.length})`) + "\n");
|
|
550
|
-
for (const mcp of mcpServers) {
|
|
551
|
-
const stars = mcp.stargazerCount != null ? `\u2605 ${mcp.stargazerCount}` : "";
|
|
552
|
-
process.stdout.write(
|
|
553
|
-
` ${purpleBright(mcp.displayName || mcp.name)} ${chalk4.gray(stars)}
|
|
554
|
-
`
|
|
555
|
-
);
|
|
556
|
-
if (mcp.description) {
|
|
557
|
-
process.stdout.write(` ${chalk4.gray(mcp.description.slice(0, 100))}
|
|
558
|
-
`);
|
|
559
|
-
}
|
|
560
|
-
process.stdout.write(` ${chalk4.gray(`slug: ${mcp.slug}`)}
|
|
561
|
-
|
|
562
|
-
`);
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
process.stderr.write(
|
|
566
|
-
chalk4.gray(` Run ${purpleBright("osm info <slug>")} (skills/blueprints) or ${purpleBright("osm mcp info <slug>")} for details.
|
|
567
|
-
|
|
568
|
-
`)
|
|
569
|
-
);
|
|
570
|
-
}
|
|
571
|
-
async function browseMcpServers() {
|
|
572
|
-
const spinner = ora2({ text: "Loading MCP categories...", color: "magenta" }).start();
|
|
573
|
-
const categories = await getMcpCategories();
|
|
574
|
-
spinner.stop();
|
|
575
|
-
if (categories.length === 0) {
|
|
576
|
-
process.stderr.write(errorMessage("No MCP server categories found.") + "\n");
|
|
577
|
-
return;
|
|
578
|
-
}
|
|
579
|
-
const choices = categories.map((c) => ({
|
|
580
|
-
name: `${c.category} ${chalk4.gray(`(${c.count})`)}`,
|
|
581
|
-
value: c.category
|
|
582
|
-
}));
|
|
583
|
-
choices.push({ name: chalk4.gray("\u2190 Exit"), value: EXIT_SENTINEL });
|
|
584
|
-
const { category } = await inquirer.prompt([
|
|
585
|
-
{
|
|
586
|
-
type: "list",
|
|
587
|
-
name: "category",
|
|
588
|
-
message: purpleBright("Choose an MCP category:"),
|
|
589
|
-
choices,
|
|
590
|
-
pageSize: 15
|
|
591
|
-
}
|
|
592
|
-
]);
|
|
593
|
-
if (category === EXIT_SENTINEL) return;
|
|
594
|
-
const listSpinner = ora2({ text: "Loading MCP servers...", color: "magenta" }).start();
|
|
595
|
-
const { data: servers } = await listMcpServers({ category, limit: 50 });
|
|
596
|
-
listSpinner.stop();
|
|
597
|
-
process.stderr.write(sectionHeader(`MCP Servers \xB7 ${category}`) + "\n");
|
|
598
|
-
if (servers.length === 0) {
|
|
599
|
-
process.stderr.write(chalk4.gray(" No servers in this category yet.\n\n"));
|
|
600
|
-
return;
|
|
601
|
-
}
|
|
602
|
-
for (const mcp of servers) {
|
|
603
|
-
const stars = mcp.stargazerCount != null ? `\u2605 ${mcp.stargazerCount}` : "";
|
|
604
|
-
process.stdout.write(` ${purpleBright(mcp.displayName || mcp.name)} ${chalk4.gray(stars)}
|
|
605
|
-
`);
|
|
606
|
-
if (mcp.description) {
|
|
607
|
-
process.stdout.write(` ${chalk4.gray(mcp.description.slice(0, 100))}
|
|
608
|
-
`);
|
|
609
|
-
}
|
|
610
|
-
process.stdout.write(` ${chalk4.gray(`slug: ${mcp.slug}`)}
|
|
611
|
-
|
|
612
|
-
`);
|
|
613
|
-
}
|
|
614
|
-
process.stderr.write(
|
|
615
|
-
chalk4.gray(` Run ${purpleBright("osm mcp info <slug>")} for details.
|
|
616
|
-
|
|
617
|
-
`)
|
|
618
|
-
);
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
// src/commands/info.ts
|
|
622
|
-
import chalk5 from "chalk";
|
|
623
|
-
import ora3 from "ora";
|
|
624
|
-
async function infoCommand(slug) {
|
|
625
|
-
const spinner = ora3({ text: `Fetching info for "${slug}"...`, color: "magenta" }).start();
|
|
626
|
-
try {
|
|
627
|
-
const skill = await getSkill(slug);
|
|
628
|
-
spinner.stop();
|
|
629
|
-
printSkillInfo(skill);
|
|
630
|
-
return;
|
|
631
|
-
} catch (err) {
|
|
632
|
-
if (!(err instanceof ApiError && err.statusCode === 404)) {
|
|
633
|
-
spinner.fail("Failed to fetch info");
|
|
634
|
-
process.stderr.write(errorMessage(err instanceof Error ? err.message : "Unknown error") + "\n");
|
|
635
|
-
return;
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
try {
|
|
639
|
-
const bp = await getBlueprint(slug);
|
|
640
|
-
spinner.stop();
|
|
641
|
-
await printBlueprintInfo(bp);
|
|
642
|
-
return;
|
|
643
|
-
} catch (err) {
|
|
644
|
-
spinner.stop();
|
|
645
|
-
if (err instanceof ApiError && err.statusCode === 404) {
|
|
646
|
-
process.stderr.write(errorMessage(
|
|
647
|
-
`"${slug}" not found.`,
|
|
648
|
-
`Try ${chalk5.cyan("osm search <query>")} to find it.`
|
|
649
|
-
) + "\n");
|
|
650
|
-
} else {
|
|
651
|
-
process.stderr.write(errorMessage(err instanceof Error ? err.message : "Unknown error") + "\n");
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
function printSkillInfo(skill) {
|
|
656
|
-
process.stdout.write("\n");
|
|
657
|
-
process.stdout.write(` ${purpleBright.bold(skill.name)}${verifiedBadge(skill.publisher)} ${chalk5.gray("(skill)")}
|
|
658
|
-
`);
|
|
659
|
-
process.stdout.write(purpleDim(` ${skill.slug}`) + "\n\n");
|
|
660
|
-
if (skill.description) {
|
|
661
|
-
process.stdout.write(` ${chalk5.white(skill.description)}
|
|
662
|
-
|
|
663
|
-
`);
|
|
664
|
-
}
|
|
665
|
-
const meta = [];
|
|
666
|
-
if (skill.domain) meta.push(`${chalk5.gray("Domain:")} ${skill.domain}`);
|
|
667
|
-
if (skill.subcategory) meta.push(`${chalk5.gray("Category:")} ${skill.subcategory}`);
|
|
668
|
-
if (skill.downloads != null) meta.push(`${chalk5.gray("Downloads:")} ${formatDownloads(skill.downloads)}`);
|
|
669
|
-
if (skill.license) meta.push(`${chalk5.gray("License:")} ${skill.license}`);
|
|
670
|
-
if (skill.publisher) meta.push(`${chalk5.gray("Publisher:")} ${skill.publisher.name}`);
|
|
671
|
-
if (skill.githubOwner && skill.githubRepo) {
|
|
672
|
-
meta.push(`${chalk5.gray("Repository:")} github.com/${skill.githubOwner}/${skill.githubRepo}`);
|
|
673
|
-
}
|
|
674
|
-
if (skill.sourceUrl) meta.push(`${chalk5.gray("Source:")} ${skill.sourceUrl}`);
|
|
675
|
-
for (const m of meta) {
|
|
676
|
-
process.stdout.write(` ${m}
|
|
677
|
-
`);
|
|
678
|
-
}
|
|
679
|
-
const whenToUse = extractSection(skill.content, "when to use");
|
|
680
|
-
if (whenToUse) {
|
|
681
|
-
process.stderr.write(sectionHeader("When to Use") + "\n");
|
|
682
|
-
for (const line of whenToUse.split("\n")) {
|
|
683
|
-
process.stdout.write(` ${chalk5.white(line)}
|
|
684
|
-
`);
|
|
685
|
-
}
|
|
686
|
-
process.stdout.write("\n");
|
|
687
|
-
}
|
|
688
|
-
if (skill.scoreOverall != null) {
|
|
689
|
-
process.stderr.write(sectionHeader("Score Breakdown") + "\n");
|
|
690
|
-
const categories = [
|
|
691
|
-
{ label: "Format", score: skill.scoreFormat ?? 0, max: 25 },
|
|
692
|
-
{ label: "Structure", score: skill.scoreStructure ?? 0, max: 25 },
|
|
693
|
-
{ label: "Security", score: skill.scoreSecurity ?? 0, max: 25 },
|
|
694
|
-
{ label: "Specificity", score: skill.scoreSpecificity ?? 0, max: 25 }
|
|
695
|
-
];
|
|
696
|
-
for (const cat of categories) {
|
|
697
|
-
process.stdout.write(` ${cat.label.padEnd(14)} ${scoreBar(cat.score, cat.max)} ${scoreColor(cat.score, cat.max)}/${cat.max}
|
|
698
|
-
`);
|
|
699
|
-
}
|
|
700
|
-
process.stdout.write("\n");
|
|
701
|
-
process.stdout.write(` ${"Overall".padEnd(14)} ${scoreBar(skill.scoreOverall, 100)} ${scoreColor(skill.scoreOverall, 100)}/100
|
|
702
|
-
`);
|
|
703
|
-
}
|
|
704
|
-
process.stderr.write("\n");
|
|
705
|
-
if (skill.githubOwner && skill.githubRepo) {
|
|
706
|
-
process.stderr.write(chalk5.gray(` Install: ${purpleBright(`osm add ${skill.githubOwner}/${skill.githubRepo}`)}`) + "\n\n");
|
|
707
|
-
} else if (skill.sourceUrl) {
|
|
708
|
-
process.stderr.write(chalk5.gray(` Source: ${skill.sourceUrl}`) + "\n\n");
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
async function printBlueprintInfo(bp) {
|
|
712
|
-
process.stdout.write("\n");
|
|
713
|
-
process.stdout.write(` ${purpleBright.bold(bp.name)}${verifiedBadge(bp.publisher)} ${chalk5.gray("(blueprint)")}
|
|
714
|
-
`);
|
|
715
|
-
process.stdout.write(purpleDim(` ${bp.slug}`) + "\n\n");
|
|
716
|
-
if (bp.description) {
|
|
717
|
-
process.stdout.write(` ${chalk5.white(bp.description)}
|
|
718
|
-
|
|
719
|
-
`);
|
|
720
|
-
}
|
|
721
|
-
const meta = [];
|
|
722
|
-
if (bp.category) meta.push(`${chalk5.gray("Category:")} ${bp.category}`);
|
|
723
|
-
if (bp.downloads != null) meta.push(`${chalk5.gray("Downloads:")} ${formatDownloads(bp.downloads)}`);
|
|
724
|
-
if (bp.publisher) meta.push(`${chalk5.gray("Publisher:")} ${bp.publisher.name}`);
|
|
725
|
-
for (const m of meta) {
|
|
726
|
-
process.stdout.write(` ${m}
|
|
727
|
-
`);
|
|
728
|
-
}
|
|
729
|
-
const bpSections = [
|
|
730
|
-
{ field: bp.constraints, label: "Constraints" },
|
|
731
|
-
{ field: bp.commonFailures, label: "Common Failures" },
|
|
732
|
-
{ field: bp.verificationRules, label: "Verification Rules" },
|
|
733
|
-
{ field: bp.recoveryGuidance, label: "Recovery Guidance" }
|
|
734
|
-
];
|
|
735
|
-
for (const sec of bpSections) {
|
|
736
|
-
if (sec.field) {
|
|
737
|
-
process.stderr.write(sectionHeader(sec.label) + "\n");
|
|
738
|
-
for (const line of sec.field.split("\n")) {
|
|
739
|
-
process.stdout.write(` ${chalk5.white(line)}
|
|
740
|
-
`);
|
|
741
|
-
}
|
|
742
|
-
process.stdout.write("\n");
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
if (!bpSections.some((s) => s.field)) {
|
|
746
|
-
const whenToUse = extractSection(bp.content, "when to use");
|
|
747
|
-
if (whenToUse) {
|
|
748
|
-
process.stderr.write(sectionHeader("When to Use") + "\n");
|
|
749
|
-
for (const line of whenToUse.split("\n")) {
|
|
750
|
-
process.stdout.write(` ${chalk5.white(line)}
|
|
751
|
-
`);
|
|
752
|
-
}
|
|
753
|
-
process.stdout.write("\n");
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
process.stderr.write("\n");
|
|
757
|
-
const origin = await resolveWebOrigin();
|
|
758
|
-
process.stderr.write(chalk5.gray(` View: ${purpleBright(`${origin}/blueprints/${bp.slug}`)}`) + "\n\n");
|
|
759
|
-
}
|
|
760
|
-
function extractSection(content, sectionName) {
|
|
761
|
-
if (!content) return null;
|
|
762
|
-
const lines = content.split("\n");
|
|
763
|
-
const pattern = new RegExp(`^##\\s+.*${sectionName}`, "i");
|
|
764
|
-
const startIdx = lines.findIndex((l) => pattern.test(l));
|
|
765
|
-
if (startIdx === -1) return null;
|
|
766
|
-
let endIdx = lines.length;
|
|
767
|
-
for (let i = startIdx + 1; i < lines.length; i++) {
|
|
768
|
-
if (/^##\s+/.test(lines[i])) {
|
|
769
|
-
endIdx = i;
|
|
770
|
-
break;
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
const sectionLines = lines.slice(startIdx + 1, endIdx).join("\n").trim();
|
|
774
|
-
if (sectionLines.length === 0) return null;
|
|
775
|
-
return sectionLines;
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
// src/commands/init.ts
|
|
779
|
-
import fs from "fs";
|
|
780
|
-
import path2 from "path";
|
|
781
|
-
import chalk6 from "chalk";
|
|
782
|
-
import inquirer2 from "inquirer";
|
|
783
|
-
|
|
784
|
-
// src/lib/validate.ts
|
|
785
|
-
import path from "path";
|
|
786
|
-
var SAFE_SLUG_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
|
|
787
|
-
function sanitizeSlug(slug) {
|
|
788
|
-
if (!SAFE_SLUG_PATTERN.test(slug)) {
|
|
789
|
-
throw new Error(
|
|
790
|
-
`Invalid slug "${slug}". Slugs must contain only lowercase letters, numbers, hyphens, dots, and underscores.`
|
|
791
|
-
);
|
|
792
|
-
}
|
|
793
|
-
if (slug.includes("..") || slug.includes("/") || slug.includes("\\")) {
|
|
794
|
-
throw new Error(`Invalid slug "${slug}". Path separators are not allowed.`);
|
|
795
|
-
}
|
|
796
|
-
return slug;
|
|
797
|
-
}
|
|
798
|
-
function safeFilePath(baseDir, filename) {
|
|
799
|
-
const resolved = path.resolve(baseDir, filename);
|
|
800
|
-
const resolvedBase = path.resolve(baseDir);
|
|
801
|
-
if (!resolved.startsWith(resolvedBase + path.sep) && resolved !== resolvedBase) {
|
|
802
|
-
throw new Error(`File path "${filename}" escapes target directory.`);
|
|
803
|
-
}
|
|
804
|
-
return resolved;
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
// src/commands/init.ts
|
|
808
|
-
async function initCommand(type) {
|
|
809
|
-
if (type !== "skill" && type !== "blueprint") {
|
|
810
|
-
console.error(errorMessage(
|
|
811
|
-
`Unknown type "${type}".`,
|
|
812
|
-
`Use ${chalk6.cyan("osm init skill")} or ${chalk6.cyan("osm init blueprint")}`
|
|
813
|
-
));
|
|
814
|
-
return;
|
|
815
|
-
}
|
|
816
|
-
if (type === "skill") {
|
|
817
|
-
await initSkill();
|
|
818
|
-
} else {
|
|
819
|
-
await initBlueprint();
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
async function initSkill() {
|
|
823
|
-
const answers = await inquirer2.prompt([
|
|
824
|
-
{ type: "input", name: "name", message: "Skill name (slug):", validate: (v) => {
|
|
825
|
-
try {
|
|
826
|
-
sanitizeSlug(v.trim());
|
|
827
|
-
return true;
|
|
828
|
-
} catch (e) {
|
|
829
|
-
return e instanceof Error ? e.message : "Invalid slug";
|
|
830
|
-
}
|
|
831
|
-
} },
|
|
832
|
-
{ type: "input", name: "description", message: "Short description:", validate: (v) => v.trim().length > 0 || "Required" },
|
|
833
|
-
{ type: "input", name: "version", message: "Version:", default: "1.0.0" }
|
|
834
|
-
]);
|
|
835
|
-
const name = sanitizeSlug(answers.name.trim());
|
|
836
|
-
const content = `---
|
|
837
|
-
name: ${name}
|
|
838
|
-
description: ${answers.description}
|
|
839
|
-
version: ${answers.version}
|
|
840
|
-
---
|
|
841
|
-
|
|
842
|
-
# ${name}
|
|
843
|
-
|
|
844
|
-
${answers.description}
|
|
845
|
-
|
|
846
|
-
## When to Use
|
|
847
|
-
|
|
848
|
-
Describe when an AI agent should use this skill.
|
|
849
|
-
|
|
850
|
-
## Workflow
|
|
851
|
-
|
|
852
|
-
1. Step one
|
|
853
|
-
2. Step two
|
|
854
|
-
3. Step three
|
|
855
|
-
|
|
856
|
-
## Rules & Guidelines
|
|
857
|
-
|
|
858
|
-
- Always do X
|
|
859
|
-
- Never do Y
|
|
860
|
-
- Avoid Z
|
|
861
|
-
|
|
862
|
-
## Examples
|
|
863
|
-
|
|
864
|
-
\`\`\`
|
|
865
|
-
Example usage here
|
|
866
|
-
\`\`\`
|
|
867
|
-
|
|
868
|
-
## Edge Cases
|
|
869
|
-
|
|
870
|
-
Document any edge cases or error handling scenarios here.
|
|
871
|
-
`;
|
|
872
|
-
const dir = path2.join(process.cwd(), ".skills");
|
|
873
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
874
|
-
const filePath = safeFilePath(dir, `${name}.md`);
|
|
875
|
-
if (fs.existsSync(filePath)) {
|
|
876
|
-
const { overwrite } = await inquirer2.prompt([
|
|
877
|
-
{ type: "confirm", name: "overwrite", message: `${filePath} already exists. Overwrite?`, default: false }
|
|
878
|
-
]);
|
|
879
|
-
if (!overwrite) {
|
|
880
|
-
console.error(chalk6.gray(" Aborted."));
|
|
881
|
-
return;
|
|
882
|
-
}
|
|
883
|
-
}
|
|
884
|
-
fs.writeFileSync(filePath, content, "utf-8");
|
|
885
|
-
console.error(successMessage(`Created .skills/${name}.md`));
|
|
886
|
-
console.error(chalk6.gray(`
|
|
887
|
-
Edit the file, then run ${purpleBright(`osm score .skills/${name}.md`)} to check quality.
|
|
888
|
-
`));
|
|
889
|
-
}
|
|
890
|
-
async function initBlueprint() {
|
|
891
|
-
const answers = await inquirer2.prompt([
|
|
892
|
-
{ type: "input", name: "name", message: "Blueprint name (slug):", validate: (v) => {
|
|
893
|
-
try {
|
|
894
|
-
sanitizeSlug(v.trim());
|
|
895
|
-
return true;
|
|
896
|
-
} catch (e) {
|
|
897
|
-
return e instanceof Error ? e.message : "Invalid slug";
|
|
898
|
-
}
|
|
899
|
-
} },
|
|
900
|
-
{ type: "input", name: "description", message: "Short description:", validate: (v) => v.trim().length > 0 || "Required" },
|
|
901
|
-
{ type: "input", name: "category", message: "Category:", default: "general" }
|
|
902
|
-
]);
|
|
903
|
-
const bpName = sanitizeSlug(answers.name.trim());
|
|
904
|
-
const content = `---
|
|
905
|
-
name: ${bpName}
|
|
906
|
-
description: ${answers.description}
|
|
907
|
-
category: ${answers.category}
|
|
908
|
-
---
|
|
909
|
-
|
|
910
|
-
# ${bpName}
|
|
911
|
-
|
|
912
|
-
${answers.description}
|
|
913
|
-
|
|
914
|
-
## Constraints
|
|
915
|
-
|
|
916
|
-
Define the constraints for the output format here.
|
|
917
|
-
|
|
918
|
-
## Common Failures
|
|
919
|
-
|
|
920
|
-
List common failure patterns and how to detect them.
|
|
921
|
-
|
|
922
|
-
## Verification Rules
|
|
923
|
-
|
|
924
|
-
- [ ] Rule 1: Description
|
|
925
|
-
- [ ] Rule 2: Description
|
|
926
|
-
- [ ] Rule 3: Description
|
|
927
|
-
|
|
928
|
-
## Recovery Guidance
|
|
929
|
-
|
|
930
|
-
If a verification rule fails, describe how to fix it here.
|
|
931
|
-
`;
|
|
932
|
-
const dir = path2.join(process.cwd(), ".blueprints");
|
|
933
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
934
|
-
const filePath = safeFilePath(dir, `${bpName}.md`);
|
|
935
|
-
if (fs.existsSync(filePath)) {
|
|
936
|
-
const { overwrite } = await inquirer2.prompt([
|
|
937
|
-
{ type: "confirm", name: "overwrite", message: `${filePath} already exists. Overwrite?`, default: false }
|
|
938
|
-
]);
|
|
939
|
-
if (!overwrite) {
|
|
940
|
-
console.error(chalk6.gray(" Aborted."));
|
|
941
|
-
return;
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
fs.writeFileSync(filePath, content, "utf-8");
|
|
945
|
-
console.error(successMessage(`Created .blueprints/${bpName}.md`));
|
|
946
|
-
console.error(chalk6.gray(`
|
|
947
|
-
Edit the file and customize the constraints, verification rules, and recovery guidance.
|
|
948
|
-
`));
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
// src/commands/list.ts
|
|
952
|
-
import fs2 from "fs";
|
|
953
|
-
import path3 from "path";
|
|
954
|
-
import chalk7 from "chalk";
|
|
955
|
-
async function listCommand() {
|
|
956
|
-
const cwd = process.cwd();
|
|
957
|
-
const skillsDir = path3.join(cwd, ".skills");
|
|
958
|
-
const blueprintsDir = path3.join(cwd, ".blueprints");
|
|
959
|
-
const skills = readDir(skillsDir);
|
|
960
|
-
const blueprints = readDir(blueprintsDir);
|
|
961
|
-
if (skills.length === 0 && blueprints.length === 0) {
|
|
962
|
-
process.stderr.write(errorMessage(
|
|
963
|
-
"No skills or blueprints installed in this project.",
|
|
964
|
-
`Run ${chalk7.cyan("osm search <query>")} to find and install skills.`
|
|
965
|
-
) + "\n");
|
|
966
|
-
return;
|
|
967
|
-
}
|
|
968
|
-
if (skills.length > 0) {
|
|
969
|
-
process.stderr.write(sectionHeader(`Installed Skills (${skills.length})`) + "\n");
|
|
970
|
-
for (const file of skills) {
|
|
971
|
-
const slug = path3.basename(file, ".md");
|
|
972
|
-
process.stdout.write(` ${purpleBright("\u2022")} ${chalk7.white(slug)} ${chalk7.gray(`(.skills/${file})`)}
|
|
973
|
-
`);
|
|
974
|
-
}
|
|
975
|
-
}
|
|
976
|
-
if (blueprints.length > 0) {
|
|
977
|
-
process.stderr.write(sectionHeader(`Installed Blueprints (${blueprints.length})`) + "\n");
|
|
978
|
-
for (const file of blueprints) {
|
|
979
|
-
const slug = path3.basename(file, ".md");
|
|
980
|
-
process.stdout.write(` ${purpleBright("\u2022")} ${chalk7.white(slug)} ${chalk7.gray(`(.blueprints/${file})`)}
|
|
981
|
-
`);
|
|
982
|
-
}
|
|
983
|
-
}
|
|
984
|
-
process.stdout.write("\n");
|
|
985
|
-
}
|
|
986
|
-
function readDir(dir) {
|
|
987
|
-
try {
|
|
988
|
-
return fs2.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
|
|
989
|
-
} catch {
|
|
990
|
-
return [];
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
// src/commands/mcp.ts
|
|
995
|
-
import chalk8 from "chalk";
|
|
996
|
-
async function mcpSetupCommand() {
|
|
997
|
-
const base = await resolveApiBase();
|
|
998
|
-
const config = {
|
|
999
|
-
mcpServers: {
|
|
1000
|
-
openskill: {
|
|
1001
|
-
url: `${base}/mcp/sse`
|
|
1002
|
-
}
|
|
1003
|
-
}
|
|
1004
|
-
};
|
|
1005
|
-
console.error(sectionHeader("MCP Server Configuration"));
|
|
1006
|
-
console.error(
|
|
1007
|
-
chalk8.gray(" Add this to your Claude Desktop or Cursor MCP config:\n")
|
|
1008
|
-
);
|
|
1009
|
-
console.log(JSON.stringify(config, null, 2));
|
|
1010
|
-
console.error("");
|
|
1011
|
-
console.error(purpleBright.bold(" For Claude Desktop:"));
|
|
1012
|
-
console.error(
|
|
1013
|
-
chalk8.gray(
|
|
1014
|
-
" Add to ~/Library/Application Support/Claude/claude_desktop_config.json"
|
|
1015
|
-
)
|
|
1016
|
-
);
|
|
1017
|
-
console.error("");
|
|
1018
|
-
console.error(purpleBright.bold(" For Cursor:"));
|
|
1019
|
-
console.error(chalk8.gray(" Add to .cursor/mcp.json in your project root"));
|
|
1020
|
-
console.error("");
|
|
1021
|
-
console.error(
|
|
1022
|
-
chalk8.gray(
|
|
1023
|
-
" The OpenSkill MCP server gives your AI agent access to the full"
|
|
1024
|
-
)
|
|
1025
|
-
);
|
|
1026
|
-
console.error(chalk8.gray(" skill and blueprint registry via tool calls."));
|
|
1027
|
-
console.error("");
|
|
1028
|
-
}
|
|
1029
|
-
async function mcpInfoCommand(slug) {
|
|
1030
|
-
console.error(sectionHeader(`MCP Server: ${slug}`));
|
|
1031
|
-
let server;
|
|
1032
|
-
try {
|
|
1033
|
-
server = await getMcpServer(slug);
|
|
1034
|
-
} catch (err) {
|
|
1035
|
-
if (err instanceof ApiError && err.statusCode === 404) {
|
|
1036
|
-
const origin = await resolveWebOrigin();
|
|
1037
|
-
process.stderr.write(
|
|
1038
|
-
errorMessage(
|
|
1039
|
-
`MCP server "${slug}" not found.`,
|
|
1040
|
-
`Browse available servers at ${origin}/mcp-servers`
|
|
1041
|
-
) + "\n"
|
|
1042
|
-
);
|
|
1043
|
-
return;
|
|
1044
|
-
}
|
|
1045
|
-
process.stderr.write(
|
|
1046
|
-
errorMessage(err instanceof Error ? err.message : "Unknown error") + "\n"
|
|
1047
|
-
);
|
|
1048
|
-
return;
|
|
1049
|
-
}
|
|
1050
|
-
console.error("");
|
|
1051
|
-
console.error(purpleBright.bold(` ${server.displayName || server.name}`));
|
|
1052
|
-
if (server.description) console.error(chalk8.gray(` ${server.description}`));
|
|
1053
|
-
console.error("");
|
|
1054
|
-
if (server.mcpEndpointUrl) {
|
|
1055
|
-
console.error(chalk8.green.bold(" Endpoint URL:"));
|
|
1056
|
-
console.error(chalk8.green(` ${server.mcpEndpointUrl}`));
|
|
1057
|
-
console.error("");
|
|
1058
|
-
}
|
|
1059
|
-
const details = [];
|
|
1060
|
-
if (server.transportType) {
|
|
1061
|
-
const remote = server.transportType === "sse" || server.transportType === "streamable-http";
|
|
1062
|
-
details.push(["Transport", remote ? "Remote (SSE)" : "Local install (stdio)"]);
|
|
1063
|
-
}
|
|
1064
|
-
if (server.authType) {
|
|
1065
|
-
details.push(["Auth", server.authType === "none" ? "None required" : server.authType]);
|
|
1066
|
-
}
|
|
1067
|
-
if (server.verified) details.push(["Verified", "Yes"]);
|
|
1068
|
-
if (server.status) details.push(["Status", server.status]);
|
|
1069
|
-
if (server.stargazerCount != null) details.push(["Stars", String(server.stargazerCount)]);
|
|
1070
|
-
if (server.toolCount) details.push(["Tools", String(server.toolCount)]);
|
|
1071
|
-
if (server.primaryLanguage) details.push(["Language", server.primaryLanguage]);
|
|
1072
|
-
if (server.category) details.push(["Category", server.category]);
|
|
1073
|
-
for (const [label, value] of details) {
|
|
1074
|
-
console.error(` ${chalk8.gray(`${label}:`)} ${chalk8.white(value)}`);
|
|
1075
|
-
}
|
|
1076
|
-
console.error("");
|
|
1077
|
-
if (server.installCommand) {
|
|
1078
|
-
console.error(purpleBright.bold(" Install:"));
|
|
1079
|
-
console.error(chalk8.white(` ${server.installCommand}`));
|
|
1080
|
-
console.error("");
|
|
1081
|
-
}
|
|
1082
|
-
if (server.toolNames && server.toolNames.length > 0) {
|
|
1083
|
-
console.error(purpleBright.bold(" Tools:"));
|
|
1084
|
-
for (const tool of server.toolNames.slice(0, 20)) {
|
|
1085
|
-
console.error(chalk8.gray(` - ${tool}`));
|
|
1086
|
-
}
|
|
1087
|
-
if (server.toolNames.length > 20) {
|
|
1088
|
-
console.error(chalk8.gray(` ... and ${server.toolNames.length - 20} more`));
|
|
1089
|
-
}
|
|
1090
|
-
console.error("");
|
|
1091
|
-
}
|
|
1092
|
-
if (server.mcpEndpointUrl) {
|
|
1093
|
-
console.error(purpleBright.bold(" Config JSON (Claude Desktop / Cursor):"));
|
|
1094
|
-
const config = {
|
|
1095
|
-
mcpServers: {
|
|
1096
|
-
[server.slug]: { url: server.mcpEndpointUrl }
|
|
1097
|
-
}
|
|
1098
|
-
};
|
|
1099
|
-
console.log(JSON.stringify(config, null, 2));
|
|
1100
|
-
console.error("");
|
|
1101
|
-
} else if (server.githubUrl) {
|
|
1102
|
-
console.error(purpleBright.bold(" GitHub:"));
|
|
1103
|
-
console.error(chalk8.white(` ${server.githubUrl}`));
|
|
1104
|
-
console.error("");
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
// src/commands/remove.ts
|
|
1109
|
-
import fs3 from "fs";
|
|
1110
|
-
import path4 from "path";
|
|
1111
|
-
import chalk9 from "chalk";
|
|
1112
|
-
async function removeCommand(slug) {
|
|
1113
|
-
try {
|
|
1114
|
-
slug = sanitizeSlug(slug);
|
|
1115
|
-
} catch (err) {
|
|
1116
|
-
process.stderr.write(errorMessage(err instanceof Error ? err.message : "Invalid slug") + "\n");
|
|
1117
|
-
return;
|
|
1118
|
-
}
|
|
1119
|
-
const cwd = process.cwd();
|
|
1120
|
-
const skillPath = path4.join(cwd, ".skills", `${slug}.md`);
|
|
1121
|
-
const blueprintPath = path4.join(cwd, ".blueprints", `${slug}.md`);
|
|
1122
|
-
let removed = false;
|
|
1123
|
-
if (fs3.existsSync(skillPath)) {
|
|
1124
|
-
safeFilePath(path4.join(cwd, ".skills"), `${slug}.md`);
|
|
1125
|
-
fs3.unlinkSync(skillPath);
|
|
1126
|
-
process.stderr.write(successMessage(`Removed skill "${slug}" from .skills/`) + "\n");
|
|
1127
|
-
removed = true;
|
|
1128
|
-
}
|
|
1129
|
-
if (fs3.existsSync(blueprintPath)) {
|
|
1130
|
-
safeFilePath(path4.join(cwd, ".blueprints"), `${slug}.md`);
|
|
1131
|
-
fs3.unlinkSync(blueprintPath);
|
|
1132
|
-
process.stderr.write(successMessage(`Removed blueprint "${slug}" from .blueprints/`) + "\n");
|
|
1133
|
-
removed = true;
|
|
1134
|
-
}
|
|
1135
|
-
if (!removed) {
|
|
1136
|
-
process.stderr.write(errorMessage(
|
|
1137
|
-
`"${slug}" is not installed.`,
|
|
1138
|
-
`Run ${chalk9.cyan("osm list")} to see installed skills and blueprints.`
|
|
1139
|
-
) + "\n");
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
|
|
1143
|
-
// src/commands/router.ts
|
|
1144
|
-
import fs4 from "fs";
|
|
1145
|
-
import path5 from "path";
|
|
1146
|
-
import chalk10 from "chalk";
|
|
1147
|
-
import ora4 from "ora";
|
|
1148
|
-
async function routerInstallCommand() {
|
|
1149
|
-
const spinner = ora4({ text: "Downloading OpenSkill router...", color: "magenta" }).start();
|
|
1150
|
-
try {
|
|
1151
|
-
const origin = await resolveWebOrigin();
|
|
1152
|
-
const res = await fetch(`${origin}/skills/router/SKILL.md`);
|
|
1153
|
-
if (!res.ok) {
|
|
1154
|
-
throw new Error(`Failed to download router SKILL.md (HTTP ${res.status})`);
|
|
1155
|
-
}
|
|
1156
|
-
const content = await res.text();
|
|
1157
|
-
const dir = path5.join(process.cwd(), ".skills");
|
|
1158
|
-
fs4.mkdirSync(dir, { recursive: true });
|
|
1159
|
-
const filePath = path5.join(dir, "openskill-router.md");
|
|
1160
|
-
fs4.writeFileSync(filePath, content, "utf-8");
|
|
1161
|
-
spinner.stop();
|
|
1162
|
-
console.error(successMessage("Installed OpenSkill router to .skills/openskill-router.md"));
|
|
1163
|
-
console.error("");
|
|
1164
|
-
console.error(purpleBright.bold(" What is the router?"));
|
|
1165
|
-
console.error(chalk10.gray(" The router skill teaches your AI agent how to discover and install"));
|
|
1166
|
-
console.error(chalk10.gray(" skills on-demand from the OpenSkill registry."));
|
|
1167
|
-
console.error("");
|
|
1168
|
-
console.error(purpleBright.bold(" How to use:"));
|
|
1169
|
-
console.error(chalk10.white(' Point your agent at the file: "Read .skills/openskill-router.md"'));
|
|
1170
|
-
console.error(chalk10.gray(" The agent will then automatically search for relevant skills as needed."));
|
|
1171
|
-
console.error("");
|
|
1172
|
-
} catch (err) {
|
|
1173
|
-
spinner.fail("Failed to install router");
|
|
1174
|
-
console.error(errorMessage(err instanceof Error ? err.message : "Unknown error"));
|
|
1175
|
-
}
|
|
1176
|
-
}
|
|
1177
|
-
|
|
1178
|
-
// src/commands/score.ts
|
|
1179
|
-
import fs5 from "fs";
|
|
1180
|
-
import chalk11 from "chalk";
|
|
1181
|
-
|
|
1182
|
-
// src/lib/scoring.ts
|
|
1183
|
-
function scoreSkillContent(content) {
|
|
1184
|
-
const suggestions = [];
|
|
1185
|
-
const format = scoreFormat(content, suggestions);
|
|
1186
|
-
const structure = scoreStructure(content, suggestions);
|
|
1187
|
-
const security = scoreSecurity(content, suggestions);
|
|
1188
|
-
const specificity = scoreSpecificity(content, suggestions);
|
|
1189
|
-
const overall = format + structure + security + specificity;
|
|
1190
|
-
return { overall, format, structure, security, specificity, suggestions };
|
|
1191
|
-
}
|
|
1192
|
-
function scoreFormat(content, suggestions) {
|
|
1193
|
-
let score = 0;
|
|
1194
|
-
const lines = content.split("\n");
|
|
1195
|
-
const hasFrontmatter = content.startsWith("---");
|
|
1196
|
-
if (hasFrontmatter) {
|
|
1197
|
-
const endIdx = content.indexOf("---", 3);
|
|
1198
|
-
if (endIdx > 3) {
|
|
1199
|
-
const fm = content.slice(3, endIdx).trim();
|
|
1200
|
-
const hasName = /^name:/m.test(fm);
|
|
1201
|
-
const hasDescription = /^description:/m.test(fm);
|
|
1202
|
-
const hasVersion = /^version:/m.test(fm);
|
|
1203
|
-
if (hasName) score += 3;
|
|
1204
|
-
else suggestions.push("Add a 'name' field to your YAML frontmatter");
|
|
1205
|
-
if (hasDescription) score += 3;
|
|
1206
|
-
else suggestions.push("Add a 'description' field to your YAML frontmatter");
|
|
1207
|
-
if (hasVersion) score += 2;
|
|
1208
|
-
else suggestions.push("Add a 'version' field to your YAML frontmatter");
|
|
1209
|
-
score += 4;
|
|
1210
|
-
} else {
|
|
1211
|
-
suggestions.push("Your YAML frontmatter is not properly closed with '---'");
|
|
1212
|
-
}
|
|
1213
|
-
} else {
|
|
1214
|
-
suggestions.push("Add YAML frontmatter at the top of your SKILL.md (between --- delimiters)");
|
|
1215
|
-
}
|
|
1216
|
-
const hasH1 = lines.some((l) => /^# /.test(l));
|
|
1217
|
-
const hasH2 = lines.some((l) => /^## /.test(l));
|
|
1218
|
-
if (hasH1) score += 4;
|
|
1219
|
-
else suggestions.push("Add a top-level heading (# Title)");
|
|
1220
|
-
if (hasH2) score += 3;
|
|
1221
|
-
else suggestions.push("Add section headings (## Section)");
|
|
1222
|
-
const hasCodeBlock = /```[\s\S]*?```/.test(content);
|
|
1223
|
-
if (hasCodeBlock) score += 3;
|
|
1224
|
-
const hasList = lines.some((l) => /^\s*[-*]\s/.test(l) || /^\s*\d+\.\s/.test(l));
|
|
1225
|
-
if (hasList) score += 3;
|
|
1226
|
-
return Math.min(score, 25);
|
|
1227
|
-
}
|
|
1228
|
-
function scoreStructure(content, suggestions) {
|
|
1229
|
-
let score = 0;
|
|
1230
|
-
const requiredSections = [
|
|
1231
|
-
{ pattern: /when to use/i, name: "When to Use", points: 5 },
|
|
1232
|
-
{ pattern: /workflow|process|steps/i, name: "Workflow", points: 5 },
|
|
1233
|
-
{ pattern: /rules|guidelines|constraints/i, name: "Rules/Guidelines", points: 5 }
|
|
1234
|
-
];
|
|
1235
|
-
for (const section of requiredSections) {
|
|
1236
|
-
if (section.pattern.test(content)) {
|
|
1237
|
-
score += section.points;
|
|
1238
|
-
} else {
|
|
1239
|
-
suggestions.push(`Add a '${section.name}' section to improve structure`);
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
const headings = content.match(/^##?\s+.+$/gm) || [];
|
|
1243
|
-
if (headings.length >= 3) score += 4;
|
|
1244
|
-
else if (headings.length >= 2) score += 2;
|
|
1245
|
-
else suggestions.push("Add more sections to organize your content (aim for 3+ headings)");
|
|
1246
|
-
const wordCount = content.split(/\s+/).length;
|
|
1247
|
-
if (wordCount >= 500) score += 3;
|
|
1248
|
-
else if (wordCount >= 200) score += 2;
|
|
1249
|
-
else suggestions.push("Expand your content \u2014 aim for at least 500 words for a comprehensive skill");
|
|
1250
|
-
if (/examples?/i.test(content)) score += 3;
|
|
1251
|
-
else suggestions.push("Add an 'Examples' section with concrete usage scenarios");
|
|
1252
|
-
return Math.min(score, 25);
|
|
1253
|
-
}
|
|
1254
|
-
function scoreSecurity(content, suggestions) {
|
|
1255
|
-
let score = 25;
|
|
1256
|
-
const dangerPatterns = [
|
|
1257
|
-
{ pattern: /(?:api[_-]?key|secret|password|token)\s*[:=]\s*['"][^'"]+['"]/gi, name: "hardcoded secrets", penalty: 8 },
|
|
1258
|
-
{ pattern: /rm\s+-rf\s+\//g, name: "dangerous rm -rf / commands", penalty: 8 },
|
|
1259
|
-
{ pattern: /eval\s*\(/g, name: "eval() usage", penalty: 5 },
|
|
1260
|
-
{ pattern: /sudo\s+/g, name: "sudo commands", penalty: 3 },
|
|
1261
|
-
{ pattern: /chmod\s+777/g, name: "chmod 777 permissions", penalty: 5 },
|
|
1262
|
-
{ pattern: /curl.*\|\s*(ba)?sh/g, name: "piping curl to shell", penalty: 5 }
|
|
1263
|
-
];
|
|
1264
|
-
for (const dp of dangerPatterns) {
|
|
1265
|
-
if (dp.pattern.test(content)) {
|
|
1266
|
-
score -= dp.penalty;
|
|
1267
|
-
suggestions.push(`Security concern: contains ${dp.name}`);
|
|
1268
|
-
}
|
|
1269
|
-
}
|
|
1270
|
-
if (/environment\s*variable|env\s+var|\$\{?\w+\}?/i.test(content) && !/hardcod/i.test(content)) {
|
|
1271
|
-
score = Math.min(score + 2, 25);
|
|
1272
|
-
}
|
|
1273
|
-
if (/sanitiz|validat|escape|safe/i.test(content)) {
|
|
1274
|
-
score = Math.min(score + 2, 25);
|
|
1275
|
-
}
|
|
1276
|
-
return Math.max(score, 0);
|
|
1277
|
-
}
|
|
1278
|
-
function scoreSpecificity(content, suggestions) {
|
|
1279
|
-
let score = 0;
|
|
1280
|
-
const codeBlocks = content.match(/```[\s\S]*?```/g) || [];
|
|
1281
|
-
if (codeBlocks.length >= 3) score += 6;
|
|
1282
|
-
else if (codeBlocks.length >= 1) score += 3;
|
|
1283
|
-
else suggestions.push("Add code examples to make your skill more actionable");
|
|
1284
|
-
const hasConcreteExamples = /for example|e\.g\.|such as|here's|consider this/i.test(content);
|
|
1285
|
-
if (hasConcreteExamples) score += 4;
|
|
1286
|
-
else suggestions.push("Add concrete examples with phrases like 'For example...' or 'Here's how...'");
|
|
1287
|
-
const hasFileRefs = /\.\w{2,4}\b/.test(content) && /file|path|directory|folder/i.test(content);
|
|
1288
|
-
if (hasFileRefs) score += 3;
|
|
1289
|
-
const hasDosAndDonts = /do not|don't|avoid|never|always|must|should not/i.test(content);
|
|
1290
|
-
if (hasDosAndDonts) score += 4;
|
|
1291
|
-
else suggestions.push("Add clear do's and don'ts (use 'Always...', 'Never...', 'Avoid...')");
|
|
1292
|
-
const hasOutputExamples = /output|result|returns|produces|generates/i.test(content);
|
|
1293
|
-
if (hasOutputExamples) score += 3;
|
|
1294
|
-
const hasEdgeCases = /edge case|corner case|error|exception|fallback|handle/i.test(content);
|
|
1295
|
-
if (hasEdgeCases) score += 3;
|
|
1296
|
-
else suggestions.push("Document edge cases and error handling scenarios");
|
|
1297
|
-
const wordCount = content.split(/\s+/).length;
|
|
1298
|
-
if (wordCount >= 1e3) score += 2;
|
|
1299
|
-
return Math.min(score, 25);
|
|
1300
|
-
}
|
|
1301
|
-
|
|
1302
|
-
// src/commands/score.ts
|
|
1303
|
-
async function scoreCommand(filepath) {
|
|
1304
|
-
if (!fs5.existsSync(filepath)) {
|
|
1305
|
-
console.error(errorMessage(
|
|
1306
|
-
`File not found: ${filepath}`,
|
|
1307
|
-
"Provide a path to a SKILL.md file."
|
|
1308
|
-
));
|
|
1309
|
-
return;
|
|
1310
|
-
}
|
|
1311
|
-
const content = fs5.readFileSync(filepath, "utf-8");
|
|
1312
|
-
if (content.trim().length === 0) {
|
|
1313
|
-
console.error(errorMessage("File is empty."));
|
|
1314
|
-
return;
|
|
1315
|
-
}
|
|
1316
|
-
const result = scoreSkillContent(content);
|
|
1317
|
-
console.error(sectionHeader(`Score: ${filepath}`));
|
|
1318
|
-
const categories = [
|
|
1319
|
-
{ label: "Format", score: result.format, max: 25 },
|
|
1320
|
-
{ label: "Structure", score: result.structure, max: 25 },
|
|
1321
|
-
{ label: "Security", score: result.security, max: 25 },
|
|
1322
|
-
{ label: "Specificity", score: result.specificity, max: 25 }
|
|
1323
|
-
];
|
|
1324
|
-
for (const cat of categories) {
|
|
1325
|
-
console.error(` ${cat.label.padEnd(14)} ${scoreBar(cat.score, cat.max)} ${scoreColor(cat.score, cat.max)}/${cat.max}`);
|
|
1326
|
-
}
|
|
1327
|
-
console.error("");
|
|
1328
|
-
console.error(` ${"Overall".padEnd(14)} ${scoreBar(result.overall, 100)} ${scoreColor(result.overall, 100)}/100`);
|
|
1329
|
-
if (result.suggestions.length > 0) {
|
|
1330
|
-
console.error(sectionHeader("Suggestions"));
|
|
1331
|
-
for (const s of result.suggestions) {
|
|
1332
|
-
console.error(` ${chalk11.yellow("\u2192")} ${s}`);
|
|
1333
|
-
}
|
|
1334
|
-
} else {
|
|
1335
|
-
console.error("");
|
|
1336
|
-
console.error(chalk11.green(" \u2728 Great job! No suggestions for improvement."));
|
|
1337
|
-
}
|
|
1338
|
-
console.error("");
|
|
1339
|
-
console.log(JSON.stringify(result));
|
|
1340
|
-
}
|
|
1341
|
-
|
|
1342
|
-
// src/commands/search.ts
|
|
1343
|
-
import chalk12 from "chalk";
|
|
1344
|
-
import ora5 from "ora";
|
|
1345
|
-
async function searchCommand(query) {
|
|
1346
|
-
const spinner = ora5({ text: `Searching for "${query}"...`, color: "magenta" }).start();
|
|
1347
|
-
try {
|
|
1348
|
-
const results = await searchApi(query);
|
|
1349
|
-
spinner.stop();
|
|
1350
|
-
const mcpServers = results.mcpServers ?? [];
|
|
1351
|
-
const totalResults = results.skills.length + results.blueprints.length + mcpServers.length;
|
|
1352
|
-
if (totalResults === 0) {
|
|
1353
|
-
process.stderr.write(errorMessage(`No results found for "${query}".`) + "\n");
|
|
1354
|
-
process.stderr.write(chalk12.gray(` \u2192 Try broader search terms or run ${purpleBright("osm browse")} to explore categories.
|
|
1355
|
-
`) + "\n");
|
|
1356
|
-
return;
|
|
1357
|
-
}
|
|
1358
|
-
if (results.skills.length > 0) {
|
|
1359
|
-
process.stderr.write(sectionHeader(`Skills (${results.skills.length})`) + "\n");
|
|
1360
|
-
const enriched = await Promise.allSettled(
|
|
1361
|
-
results.skills.map((s) => getSkill(s.slug))
|
|
1362
|
-
);
|
|
1363
|
-
for (let i = 0; i < results.skills.length; i++) {
|
|
1364
|
-
const basic = results.skills[i];
|
|
1365
|
-
const detail = enriched[i];
|
|
1366
|
-
const full = detail.status === "fulfilled" ? detail.value : null;
|
|
1367
|
-
const name = full?.name || basic.name;
|
|
1368
|
-
const score = full?.scoreOverall != null ? scoreColor(full.scoreOverall, 100) : chalk12.gray("--");
|
|
1369
|
-
const downloads = full?.downloads != null ? formatDownloads(full.downloads) : "--";
|
|
1370
|
-
const badge = full ? verifiedBadge(full.publisher) : "";
|
|
1371
|
-
const desc = full?.description || basic.description || "";
|
|
1372
|
-
process.stdout.write(` ${purpleBright(name)}${badge} ${chalk12.gray("\xB7")} score: ${score} ${chalk12.gray("\xB7")} ${downloads} downloads
|
|
1373
|
-
`);
|
|
1374
|
-
if (desc) {
|
|
1375
|
-
process.stdout.write(` ${chalk12.gray(typeof desc === "string" ? desc.slice(0, 120) : "")}
|
|
1376
|
-
`);
|
|
1377
|
-
}
|
|
1378
|
-
process.stdout.write(` ${chalk12.gray(`slug: ${basic.slug}`)}
|
|
1379
|
-
|
|
1380
|
-
`);
|
|
1381
|
-
}
|
|
1382
|
-
}
|
|
1383
|
-
if (results.blueprints.length > 0) {
|
|
1384
|
-
process.stderr.write(sectionHeader(`Blueprints (${results.blueprints.length})`) + "\n");
|
|
1385
|
-
const enriched = await Promise.allSettled(
|
|
1386
|
-
results.blueprints.map((b) => getBlueprint(b.slug))
|
|
1387
|
-
);
|
|
1388
|
-
for (let i = 0; i < results.blueprints.length; i++) {
|
|
1389
|
-
const basic = results.blueprints[i];
|
|
1390
|
-
const detail = enriched[i];
|
|
1391
|
-
const full = detail.status === "fulfilled" ? detail.value : null;
|
|
1392
|
-
const name = full?.name || basic.name;
|
|
1393
|
-
const downloads = full?.downloads != null ? formatDownloads(full.downloads) : "--";
|
|
1394
|
-
const badge = full ? verifiedBadge(full.publisher) : "";
|
|
1395
|
-
const desc = full?.description || basic.description || "";
|
|
1396
|
-
process.stdout.write(` ${purpleBright(name)}${badge} ${chalk12.gray("\xB7")} ${downloads} downloads
|
|
1397
|
-
`);
|
|
1398
|
-
if (desc) {
|
|
1399
|
-
process.stdout.write(` ${chalk12.gray(typeof desc === "string" ? desc.slice(0, 120) : "")}
|
|
1400
|
-
`);
|
|
1401
|
-
}
|
|
1402
|
-
process.stdout.write(` ${chalk12.gray(`slug: ${basic.slug}`)}
|
|
1403
|
-
|
|
1404
|
-
`);
|
|
1405
|
-
}
|
|
1406
|
-
}
|
|
1407
|
-
if (mcpServers.length > 0) {
|
|
1408
|
-
process.stderr.write(sectionHeader(`MCP Servers (${mcpServers.length})`) + "\n");
|
|
1409
|
-
for (const mcp of mcpServers) {
|
|
1410
|
-
process.stdout.write(` ${purpleBright(mcp.name)}
|
|
1411
|
-
`);
|
|
1412
|
-
if (mcp.description) {
|
|
1413
|
-
process.stdout.write(` ${chalk12.gray(mcp.description.slice(0, 120))}
|
|
1414
|
-
`);
|
|
1415
|
-
}
|
|
1416
|
-
process.stdout.write(` ${chalk12.gray(`slug: ${mcp.slug}`)}
|
|
1417
|
-
|
|
1418
|
-
`);
|
|
1419
|
-
}
|
|
1420
|
-
}
|
|
1421
|
-
process.stderr.write(chalk12.gray(` Run ${purpleBright("osm info <slug>")} for details, ${purpleBright("osm add <source>")} to install, or ${purpleBright("osm mcp info <slug>")} for MCP servers.
|
|
1422
|
-
|
|
1423
|
-
`));
|
|
1424
|
-
} catch (err) {
|
|
1425
|
-
spinner.fail("Search failed");
|
|
1426
|
-
process.stderr.write(errorMessage(err instanceof Error ? err.message : "Unknown error") + "\n");
|
|
1427
|
-
}
|
|
1428
|
-
}
|
|
1429
|
-
|
|
1430
|
-
// src/program.ts
|
|
1431
|
-
var VERSION = "0.3.0";
|
|
1432
|
-
var BrandedCommand = class _BrandedCommand extends Command {
|
|
1433
|
-
createCommand(name) {
|
|
1434
|
-
return new _BrandedCommand(name);
|
|
1435
|
-
}
|
|
1436
|
-
helpInformation() {
|
|
1437
|
-
const banner = getBannerString();
|
|
1438
|
-
return `${banner}
|
|
1439
|
-
${super.helpInformation()}`;
|
|
1440
|
-
}
|
|
1441
|
-
};
|
|
1442
|
-
function buildProgram() {
|
|
1443
|
-
const program = new BrandedCommand();
|
|
1444
|
-
function defineCommand(name, description, action) {
|
|
1445
|
-
program.command(name).description(description).action(async (...args) => {
|
|
1446
|
-
showBanner();
|
|
1447
|
-
await action(...args.slice(0, -1));
|
|
1448
|
-
});
|
|
1449
|
-
}
|
|
1450
|
-
program.name("osm").description(
|
|
1451
|
-
"The CLI for OpenSkill.md \u2014 search, add, score, and explore AI agent skills"
|
|
1452
|
-
).version(VERSION);
|
|
1453
|
-
defineCommand(
|
|
1454
|
-
"search <query>",
|
|
1455
|
-
"Search skills and blueprints by keyword",
|
|
1456
|
-
(query) => searchCommand(query)
|
|
1457
|
-
);
|
|
1458
|
-
defineCommand(
|
|
1459
|
-
"info <slug>",
|
|
1460
|
-
"Show details about a skill or blueprint",
|
|
1461
|
-
(slug) => infoCommand(slug)
|
|
1462
|
-
);
|
|
1463
|
-
program.command("add <source>").alias("install").description(
|
|
1464
|
-
"Add a skill from a source repo (owner/repo or owner/repo@skill)"
|
|
1465
|
-
).option(
|
|
1466
|
-
"-a, --agent <agent...>",
|
|
1467
|
-
"Target coding agent(s) \u2014 may repeat. If omitted, auto-detects installed agents."
|
|
1468
|
-
).option("-g, --global", "Add at user scope (~/) instead of project").option("--copy", "Copy files instead of symlinking to agent directories").option(
|
|
1469
|
-
"--json",
|
|
1470
|
-
"Emit a single-line JSON result on stdout (machine-readable)"
|
|
1471
|
-
).action(async (source, options) => {
|
|
1472
|
-
showBanner();
|
|
1473
|
-
await addCommand(source, options);
|
|
1474
|
-
});
|
|
1475
|
-
defineCommand(
|
|
1476
|
-
"list",
|
|
1477
|
-
"Show installed skills and blueprints in this project",
|
|
1478
|
-
() => listCommand()
|
|
1479
|
-
);
|
|
1480
|
-
defineCommand(
|
|
1481
|
-
"score <filepath>",
|
|
1482
|
-
"Score a local SKILL.md file for quality",
|
|
1483
|
-
(filepath) => scoreCommand(filepath)
|
|
1484
|
-
);
|
|
1485
|
-
defineCommand(
|
|
1486
|
-
"init <type>",
|
|
1487
|
-
"Scaffold a new skill or blueprint (type: skill | blueprint)",
|
|
1488
|
-
(type) => initCommand(type)
|
|
1489
|
-
);
|
|
1490
|
-
defineCommand(
|
|
1491
|
-
"browse",
|
|
1492
|
-
"Explore skills by category (interactive)",
|
|
1493
|
-
() => browseCommand()
|
|
1494
|
-
);
|
|
1495
|
-
defineCommand(
|
|
1496
|
-
"remove <slug>",
|
|
1497
|
-
"Remove an installed skill or blueprint from the project",
|
|
1498
|
-
(slug) => removeCommand(slug)
|
|
1499
|
-
);
|
|
1500
|
-
const router = program.command("router").description("Manage the OpenSkill router skill");
|
|
1501
|
-
router.command("install").description("Download the OpenSkill router SKILL.md into .skills/").action(async () => {
|
|
1502
|
-
showBanner();
|
|
1503
|
-
await routerInstallCommand();
|
|
1504
|
-
});
|
|
1505
|
-
const mcp = program.command("mcp").description("Explore and configure MCP servers");
|
|
1506
|
-
mcp.command("setup").description("Print MCP configuration for Claude/Cursor").action(async () => {
|
|
1507
|
-
showBanner();
|
|
1508
|
-
await mcpSetupCommand();
|
|
1509
|
-
});
|
|
1510
|
-
mcp.command("info <slug>").description("Show details about an MCP server").action(async (slug) => {
|
|
1511
|
-
showBanner();
|
|
1512
|
-
await mcpInfoCommand(slug);
|
|
1513
|
-
});
|
|
1514
|
-
program.configureOutput({
|
|
1515
|
-
writeOut: (str) => process.stderr.write(str),
|
|
1516
|
-
writeErr: (str) => process.stderr.write(str)
|
|
1517
|
-
});
|
|
1518
|
-
program.action(() => {
|
|
1519
|
-
program.outputHelp();
|
|
1520
|
-
});
|
|
1521
|
-
return program;
|
|
1522
|
-
}
|
|
1523
|
-
|
|
1524
|
-
// src/index.ts
|
|
1525
|
-
buildProgram().parseAsync(process.argv).catch((err) => {
|
|
1526
|
-
console.error(err);
|
|
1527
|
-
process.exit(1);
|
|
1528
|
-
});
|
|
2
|
+
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
3
|
+
import{a as O,b as g,d as lt,f as R,k as U,m as B}from"./chunk-OVTYCRA4.js";var C=g(x=>{"use strict";var b=class extends Error{constructor(t,e,i){super(i),Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.code=e,this.exitCode=t,this.nestedError=void 0}},y=class extends b{constructor(t){super(1,"commander.invalidArgument",t),Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name}};x.CommanderError=b;x.InvalidArgumentError=y});var A=g(S=>{"use strict";var{InvalidArgumentError:ut}=C(),E=class{constructor(t,e){switch(this.description=e||"",this.variadic=!1,this.parseArg=void 0,this.defaultValue=void 0,this.defaultValueDescription=void 0,this.argChoices=void 0,t[0]){case"<":this.required=!0,this._name=t.slice(1,-1);break;case"[":this.required=!1,this._name=t.slice(1,-1);break;default:this.required=!0,this._name=t;break}this._name.length>3&&this._name.slice(-3)==="..."&&(this.variadic=!0,this._name=this._name.slice(0,-3))}name(){return this._name}_concatValue(t,e){return e===this.defaultValue||!Array.isArray(e)?[t]:e.concat(t)}default(t,e){return this.defaultValue=t,this.defaultValueDescription=e,this}argParser(t){return this.parseArg=t,this}choices(t){return this.argChoices=t.slice(),this.parseArg=(e,i)=>{if(!this.argChoices.includes(e))throw new ut(`Allowed choices are ${this.argChoices.join(", ")}.`);return this.variadic?this._concatValue(e,i):e},this}argRequired(){return this.required=!0,this}argOptional(){return this.required=!1,this}};function ht(l){let t=l.name()+(l.variadic===!0?"...":"");return l.required?"<"+t+">":"["+t+"]"}S.Argument=E;S.humanReadableArgName=ht});var k=g($=>{"use strict";var{humanReadableArgName:ct}=A(),v=class{constructor(){this.helpWidth=void 0,this.minWidthToWrap=40,this.sortSubcommands=!1,this.sortOptions=!1,this.showGlobalOptions=!1}prepareContext(t){this.helpWidth=this.helpWidth??t.helpWidth??80}visibleCommands(t){let e=t.commands.filter(n=>!n._hidden),i=t._getHelpCommand();return i&&!i._hidden&&e.push(i),this.sortSubcommands&&e.sort((n,s)=>n.name().localeCompare(s.name())),e}compareOptions(t,e){let i=n=>n.short?n.short.replace(/^-/,""):n.long.replace(/^--/,"");return i(t).localeCompare(i(e))}visibleOptions(t){let e=t.options.filter(n=>!n.hidden),i=t._getHelpOption();if(i&&!i.hidden){let n=i.short&&t._findOption(i.short),s=i.long&&t._findOption(i.long);!n&&!s?e.push(i):i.long&&!s?e.push(t.createOption(i.long,i.description)):i.short&&!n&&e.push(t.createOption(i.short,i.description))}return this.sortOptions&&e.sort(this.compareOptions),e}visibleGlobalOptions(t){if(!this.showGlobalOptions)return[];let e=[];for(let i=t.parent;i;i=i.parent){let n=i.options.filter(s=>!s.hidden);e.push(...n)}return this.sortOptions&&e.sort(this.compareOptions),e}visibleArguments(t){return t._argsDescription&&t.registeredArguments.forEach(e=>{e.description=e.description||t._argsDescription[e.name()]||""}),t.registeredArguments.find(e=>e.description)?t.registeredArguments:[]}subcommandTerm(t){let e=t.registeredArguments.map(i=>ct(i)).join(" ");return t._name+(t._aliases[0]?"|"+t._aliases[0]:"")+(t.options.length?" [options]":"")+(e?" "+e:"")}optionTerm(t){return t.flags}argumentTerm(t){return t.name()}longestSubcommandTermLength(t,e){return e.visibleCommands(t).reduce((i,n)=>Math.max(i,this.displayWidth(e.styleSubcommandTerm(e.subcommandTerm(n)))),0)}longestOptionTermLength(t,e){return e.visibleOptions(t).reduce((i,n)=>Math.max(i,this.displayWidth(e.styleOptionTerm(e.optionTerm(n)))),0)}longestGlobalOptionTermLength(t,e){return e.visibleGlobalOptions(t).reduce((i,n)=>Math.max(i,this.displayWidth(e.styleOptionTerm(e.optionTerm(n)))),0)}longestArgumentTermLength(t,e){return e.visibleArguments(t).reduce((i,n)=>Math.max(i,this.displayWidth(e.styleArgumentTerm(e.argumentTerm(n)))),0)}commandUsage(t){let e=t._name;t._aliases[0]&&(e=e+"|"+t._aliases[0]);let i="";for(let n=t.parent;n;n=n.parent)i=n.name()+" "+i;return i+e+" "+t.usage()}commandDescription(t){return t.description()}subcommandDescription(t){return t.summary()||t.description()}optionDescription(t){let e=[];return t.argChoices&&e.push(`choices: ${t.argChoices.map(i=>JSON.stringify(i)).join(", ")}`),t.defaultValue!==void 0&&(t.required||t.optional||t.isBoolean()&&typeof t.defaultValue=="boolean")&&e.push(`default: ${t.defaultValueDescription||JSON.stringify(t.defaultValue)}`),t.presetArg!==void 0&&t.optional&&e.push(`preset: ${JSON.stringify(t.presetArg)}`),t.envVar!==void 0&&e.push(`env: ${t.envVar}`),e.length>0?`${t.description} (${e.join(", ")})`:t.description}argumentDescription(t){let e=[];if(t.argChoices&&e.push(`choices: ${t.argChoices.map(i=>JSON.stringify(i)).join(", ")}`),t.defaultValue!==void 0&&e.push(`default: ${t.defaultValueDescription||JSON.stringify(t.defaultValue)}`),e.length>0){let i=`(${e.join(", ")})`;return t.description?`${t.description} ${i}`:i}return t.description}formatHelp(t,e){let i=e.padWidth(t,e),n=e.helpWidth??80;function s(c,p){return e.formatItem(c,i,p,e)}let r=[`${e.styleTitle("Usage:")} ${e.styleUsage(e.commandUsage(t))}`,""],a=e.commandDescription(t);a.length>0&&(r=r.concat([e.boxWrap(e.styleCommandDescription(a),n),""]));let o=e.visibleArguments(t).map(c=>s(e.styleArgumentTerm(e.argumentTerm(c)),e.styleArgumentDescription(e.argumentDescription(c))));o.length>0&&(r=r.concat([e.styleTitle("Arguments:"),...o,""]));let h=e.visibleOptions(t).map(c=>s(e.styleOptionTerm(e.optionTerm(c)),e.styleOptionDescription(e.optionDescription(c))));if(h.length>0&&(r=r.concat([e.styleTitle("Options:"),...h,""])),e.showGlobalOptions){let c=e.visibleGlobalOptions(t).map(p=>s(e.styleOptionTerm(e.optionTerm(p)),e.styleOptionDescription(e.optionDescription(p))));c.length>0&&(r=r.concat([e.styleTitle("Global Options:"),...c,""]))}let u=e.visibleCommands(t).map(c=>s(e.styleSubcommandTerm(e.subcommandTerm(c)),e.styleSubcommandDescription(e.subcommandDescription(c))));return u.length>0&&(r=r.concat([e.styleTitle("Commands:"),...u,""])),r.join(`
|
|
4
|
+
`)}displayWidth(t){return G(t).length}styleTitle(t){return t}styleUsage(t){return t.split(" ").map(e=>e==="[options]"?this.styleOptionText(e):e==="[command]"?this.styleSubcommandText(e):e[0]==="["||e[0]==="<"?this.styleArgumentText(e):this.styleCommandText(e)).join(" ")}styleCommandDescription(t){return this.styleDescriptionText(t)}styleOptionDescription(t){return this.styleDescriptionText(t)}styleSubcommandDescription(t){return this.styleDescriptionText(t)}styleArgumentDescription(t){return this.styleDescriptionText(t)}styleDescriptionText(t){return t}styleOptionTerm(t){return this.styleOptionText(t)}styleSubcommandTerm(t){return t.split(" ").map(e=>e==="[options]"?this.styleOptionText(e):e[0]==="["||e[0]==="<"?this.styleArgumentText(e):this.styleSubcommandText(e)).join(" ")}styleArgumentTerm(t){return this.styleArgumentText(t)}styleOptionText(t){return t}styleArgumentText(t){return t}styleSubcommandText(t){return t}styleCommandText(t){return t}padWidth(t,e){return Math.max(e.longestOptionTermLength(t,e),e.longestGlobalOptionTermLength(t,e),e.longestSubcommandTermLength(t,e),e.longestArgumentTermLength(t,e))}preformatted(t){return/\n[^\S\r\n]/.test(t)}formatItem(t,e,i,n){let r=" ".repeat(2);if(!i)return r+t;let a=t.padEnd(e+t.length-n.displayWidth(t)),o=2,u=(this.helpWidth??80)-e-o-2,c;return u<this.minWidthToWrap||n.preformatted(i)?c=i:c=n.boxWrap(i,u).replace(/\n/g,`
|
|
5
|
+
`+" ".repeat(e+o)),r+a+" ".repeat(o)+c.replace(/\n/g,`
|
|
6
|
+
${r}`)}boxWrap(t,e){if(e<this.minWidthToWrap)return t;let i=t.split(/\r\n|\n/),n=/[\s]*[^\s]+/g,s=[];return i.forEach(r=>{let a=r.match(n);if(a===null){s.push("");return}let o=[a.shift()],h=this.displayWidth(o[0]);a.forEach(u=>{let c=this.displayWidth(u);if(h+c<=e){o.push(u),h+=c;return}s.push(o.join(""));let p=u.trimStart();o=[p],h=this.displayWidth(p)}),s.push(o.join(""))}),s.join(`
|
|
7
|
+
`)}};function G(l){let t=/\x1b\[\d*(;\d*)*m/g;return l.replace(t,"")}$.Help=v;$.stripColor=G});var P=g(T=>{"use strict";var{InvalidArgumentError:mt}=C(),V=class{constructor(t,e){this.flags=t,this.description=e||"",this.required=t.includes("<"),this.optional=t.includes("["),this.variadic=/\w\.\.\.[>\]]$/.test(t),this.mandatory=!1;let i=pt(t);this.short=i.shortFlag,this.long=i.longFlag,this.negate=!1,this.long&&(this.negate=this.long.startsWith("--no-")),this.defaultValue=void 0,this.defaultValueDescription=void 0,this.presetArg=void 0,this.envVar=void 0,this.parseArg=void 0,this.hidden=!1,this.argChoices=void 0,this.conflictsWith=[],this.implied=void 0}default(t,e){return this.defaultValue=t,this.defaultValueDescription=e,this}preset(t){return this.presetArg=t,this}conflicts(t){return this.conflictsWith=this.conflictsWith.concat(t),this}implies(t){let e=t;return typeof t=="string"&&(e={[t]:!0}),this.implied=Object.assign(this.implied||{},e),this}env(t){return this.envVar=t,this}argParser(t){return this.parseArg=t,this}makeOptionMandatory(t=!0){return this.mandatory=!!t,this}hideHelp(t=!0){return this.hidden=!!t,this}_concatValue(t,e){return e===this.defaultValue||!Array.isArray(e)?[t]:e.concat(t)}choices(t){return this.argChoices=t.slice(),this.parseArg=(e,i)=>{if(!this.argChoices.includes(e))throw new mt(`Allowed choices are ${this.argChoices.join(", ")}.`);return this.variadic?this._concatValue(e,i):e},this}name(){return this.long?this.long.replace(/^--/,""):this.short.replace(/^-/,"")}attributeName(){return this.negate?J(this.name().replace(/^no-/,"")):J(this.name())}is(t){return this.short===t||this.long===t}isBoolean(){return!this.required&&!this.optional&&!this.negate}},H=class{constructor(t){this.positiveOptions=new Map,this.negativeOptions=new Map,this.dualOptions=new Set,t.forEach(e=>{e.negate?this.negativeOptions.set(e.attributeName(),e):this.positiveOptions.set(e.attributeName(),e)}),this.negativeOptions.forEach((e,i)=>{this.positiveOptions.has(i)&&this.dualOptions.add(i)})}valueFromOption(t,e){let i=e.attributeName();if(!this.dualOptions.has(i))return!0;let n=this.negativeOptions.get(i).presetArg,s=n!==void 0?n:!1;return e.negate===(s===t)}};function J(l){return l.split("-").reduce((t,e)=>t+e[0].toUpperCase()+e.slice(1))}function pt(l){let t,e,i=/^-[^-]$/,n=/^--[^-]/,s=l.split(/[ |,]+/).concat("guard");if(i.test(s[0])&&(t=s.shift()),n.test(s[0])&&(e=s.shift()),!t&&i.test(s[0])&&(t=s.shift()),!t&&n.test(s[0])&&(t=e,e=s.shift()),s[0].startsWith("-")){let r=s[0],a=`option creation failed due to '${r}' in option flags '${l}'`;throw/^-[^-][^-]/.test(r)?new Error(`${a}
|
|
8
|
+
- a short flag is a single dash and a single character
|
|
9
|
+
- either use a single dash and a single character (for a short flag)
|
|
10
|
+
- or use a double dash for a long option (and can have two, like '--ws, --workspace')`):i.test(r)?new Error(`${a}
|
|
11
|
+
- too many short flags`):n.test(r)?new Error(`${a}
|
|
12
|
+
- too many long flags`):new Error(`${a}
|
|
13
|
+
- unrecognised flag format`)}if(t===void 0&&e===void 0)throw new Error(`option creation failed due to no flags found in '${l}'.`);return{shortFlag:t,longFlag:e}}T.Option=V;T.DualOptions=H});var Y=g(K=>{"use strict";function dt(l,t){if(Math.abs(l.length-t.length)>3)return Math.max(l.length,t.length);let e=[];for(let i=0;i<=l.length;i++)e[i]=[i];for(let i=0;i<=t.length;i++)e[0][i]=i;for(let i=1;i<=t.length;i++)for(let n=1;n<=l.length;n++){let s=1;l[n-1]===t[i-1]?s=0:s=1,e[n][i]=Math.min(e[n-1][i]+1,e[n][i-1]+1,e[n-1][i-1]+s),n>1&&i>1&&l[n-1]===t[i-2]&&l[n-2]===t[i-1]&&(e[n][i]=Math.min(e[n][i],e[n-2][i-2]+1))}return e[l.length][t.length]}function ft(l,t){if(!t||t.length===0)return"";t=Array.from(new Set(t));let e=l.startsWith("--");e&&(l=l.slice(2),t=t.map(r=>r.slice(2)));let i=[],n=3,s=.4;return t.forEach(r=>{if(r.length<=1)return;let a=dt(l,r),o=Math.max(l.length,r.length);(o-a)/o>s&&(a<n?(n=a,i=[r]):a===n&&i.push(r))}),i.sort((r,a)=>r.localeCompare(a)),e&&(i=i.map(r=>`--${r}`)),i.length>1?`
|
|
14
|
+
(Did you mean one of ${i.join(", ")}?)`:i.length===1?`
|
|
15
|
+
(Did you mean ${i[0]}?)`:""}K.suggestSimilar=ft});var Z=g(N=>{"use strict";var gt=O("events").EventEmitter,W=O("child_process"),f=O("path"),w=O("fs"),m=O("process"),{Argument:_t,humanReadableArgName:Ot}=A(),{CommanderError:D}=C(),{Help:Ct,stripColor:bt}=k(),{Option:z,DualOptions:At}=P(),{suggestSimilar:Q}=Y(),F=class l extends gt{constructor(t){super(),this.commands=[],this.options=[],this.parent=null,this._allowUnknownOption=!1,this._allowExcessArguments=!1,this.registeredArguments=[],this._args=this.registeredArguments,this.args=[],this.rawArgs=[],this.processedArgs=[],this._scriptPath=null,this._name=t||"",this._optionValues={},this._optionValueSources={},this._storeOptionsAsProperties=!1,this._actionHandler=null,this._executableHandler=!1,this._executableFile=null,this._executableDir=null,this._defaultCommandName=null,this._exitCallback=null,this._aliases=[],this._combineFlagAndOptionalValue=!0,this._description="",this._summary="",this._argsDescription=void 0,this._enablePositionalOptions=!1,this._passThroughOptions=!1,this._lifeCycleHooks={},this._showHelpAfterError=!1,this._showSuggestionAfterError=!0,this._savedState=null,this._outputConfiguration={writeOut:e=>m.stdout.write(e),writeErr:e=>m.stderr.write(e),outputError:(e,i)=>i(e),getOutHelpWidth:()=>m.stdout.isTTY?m.stdout.columns:void 0,getErrHelpWidth:()=>m.stderr.isTTY?m.stderr.columns:void 0,getOutHasColors:()=>I()??(m.stdout.isTTY&&m.stdout.hasColors?.()),getErrHasColors:()=>I()??(m.stderr.isTTY&&m.stderr.hasColors?.()),stripColor:e=>bt(e)},this._hidden=!1,this._helpOption=void 0,this._addImplicitHelpCommand=void 0,this._helpCommand=void 0,this._helpConfiguration={}}copyInheritedSettings(t){return this._outputConfiguration=t._outputConfiguration,this._helpOption=t._helpOption,this._helpCommand=t._helpCommand,this._helpConfiguration=t._helpConfiguration,this._exitCallback=t._exitCallback,this._storeOptionsAsProperties=t._storeOptionsAsProperties,this._combineFlagAndOptionalValue=t._combineFlagAndOptionalValue,this._allowExcessArguments=t._allowExcessArguments,this._enablePositionalOptions=t._enablePositionalOptions,this._showHelpAfterError=t._showHelpAfterError,this._showSuggestionAfterError=t._showSuggestionAfterError,this}_getCommandAndAncestors(){let t=[];for(let e=this;e;e=e.parent)t.push(e);return t}command(t,e,i){let n=e,s=i;typeof n=="object"&&n!==null&&(s=n,n=null),s=s||{};let[,r,a]=t.match(/([^ ]+) *(.*)/),o=this.createCommand(r);return n&&(o.description(n),o._executableHandler=!0),s.isDefault&&(this._defaultCommandName=o._name),o._hidden=!!(s.noHelp||s.hidden),o._executableFile=s.executableFile||null,a&&o.arguments(a),this._registerCommand(o),o.parent=this,o.copyInheritedSettings(this),n?this:o}createCommand(t){return new l(t)}createHelp(){return Object.assign(new Ct,this.configureHelp())}configureHelp(t){return t===void 0?this._helpConfiguration:(this._helpConfiguration=t,this)}configureOutput(t){return t===void 0?this._outputConfiguration:(Object.assign(this._outputConfiguration,t),this)}showHelpAfterError(t=!0){return typeof t!="string"&&(t=!!t),this._showHelpAfterError=t,this}showSuggestionAfterError(t=!0){return this._showSuggestionAfterError=!!t,this}addCommand(t,e){if(!t._name)throw new Error(`Command passed to .addCommand() must have a name
|
|
16
|
+
- specify the name in Command constructor or using .name()`);return e=e||{},e.isDefault&&(this._defaultCommandName=t._name),(e.noHelp||e.hidden)&&(t._hidden=!0),this._registerCommand(t),t.parent=this,t._checkForBrokenPassThrough(),this}createArgument(t,e){return new _t(t,e)}argument(t,e,i,n){let s=this.createArgument(t,e);return typeof i=="function"?s.default(n).argParser(i):s.default(i),this.addArgument(s),this}arguments(t){return t.trim().split(/ +/).forEach(e=>{this.argument(e)}),this}addArgument(t){let e=this.registeredArguments.slice(-1)[0];if(e&&e.variadic)throw new Error(`only the last argument can be variadic '${e.name()}'`);if(t.required&&t.defaultValue!==void 0&&t.parseArg===void 0)throw new Error(`a default value for a required argument is never used: '${t.name()}'`);return this.registeredArguments.push(t),this}helpCommand(t,e){if(typeof t=="boolean")return this._addImplicitHelpCommand=t,this;t=t??"help [command]";let[,i,n]=t.match(/([^ ]+) *(.*)/),s=e??"display help for command",r=this.createCommand(i);return r.helpOption(!1),n&&r.arguments(n),s&&r.description(s),this._addImplicitHelpCommand=!0,this._helpCommand=r,this}addHelpCommand(t,e){return typeof t!="object"?(this.helpCommand(t,e),this):(this._addImplicitHelpCommand=!0,this._helpCommand=t,this)}_getHelpCommand(){return this._addImplicitHelpCommand??(this.commands.length&&!this._actionHandler&&!this._findCommand("help"))?(this._helpCommand===void 0&&this.helpCommand(void 0,void 0),this._helpCommand):null}hook(t,e){let i=["preSubcommand","preAction","postAction"];if(!i.includes(t))throw new Error(`Unexpected value for event passed to hook : '${t}'.
|
|
17
|
+
Expecting one of '${i.join("', '")}'`);return this._lifeCycleHooks[t]?this._lifeCycleHooks[t].push(e):this._lifeCycleHooks[t]=[e],this}exitOverride(t){return t?this._exitCallback=t:this._exitCallback=e=>{if(e.code!=="commander.executeSubCommandAsync")throw e},this}_exit(t,e,i){this._exitCallback&&this._exitCallback(new D(t,e,i)),m.exit(t)}action(t){let e=i=>{let n=this.registeredArguments.length,s=i.slice(0,n);return this._storeOptionsAsProperties?s[n]=this:s[n]=this.opts(),s.push(this),t.apply(this,s)};return this._actionHandler=e,this}createOption(t,e){return new z(t,e)}_callParseArg(t,e,i,n){try{return t.parseArg(e,i)}catch(s){if(s.code==="commander.invalidArgument"){let r=`${n} ${s.message}`;this.error(r,{exitCode:s.exitCode,code:s.code})}throw s}}_registerOption(t){let e=t.short&&this._findOption(t.short)||t.long&&this._findOption(t.long);if(e){let i=t.long&&this._findOption(t.long)?t.long:t.short;throw new Error(`Cannot add option '${t.flags}'${this._name&&` to command '${this._name}'`} due to conflicting flag '${i}'
|
|
18
|
+
- already used by option '${e.flags}'`)}this.options.push(t)}_registerCommand(t){let e=n=>[n.name()].concat(n.aliases()),i=e(t).find(n=>this._findCommand(n));if(i){let n=e(this._findCommand(i)).join("|"),s=e(t).join("|");throw new Error(`cannot add command '${s}' as already have command '${n}'`)}this.commands.push(t)}addOption(t){this._registerOption(t);let e=t.name(),i=t.attributeName();if(t.negate){let s=t.long.replace(/^--no-/,"--");this._findOption(s)||this.setOptionValueWithSource(i,t.defaultValue===void 0?!0:t.defaultValue,"default")}else t.defaultValue!==void 0&&this.setOptionValueWithSource(i,t.defaultValue,"default");let n=(s,r,a)=>{s==null&&t.presetArg!==void 0&&(s=t.presetArg);let o=this.getOptionValue(i);s!==null&&t.parseArg?s=this._callParseArg(t,s,o,r):s!==null&&t.variadic&&(s=t._concatValue(s,o)),s==null&&(t.negate?s=!1:t.isBoolean()||t.optional?s=!0:s=""),this.setOptionValueWithSource(i,s,a)};return this.on("option:"+e,s=>{let r=`error: option '${t.flags}' argument '${s}' is invalid.`;n(s,r,"cli")}),t.envVar&&this.on("optionEnv:"+e,s=>{let r=`error: option '${t.flags}' value '${s}' from env '${t.envVar}' is invalid.`;n(s,r,"env")}),this}_optionEx(t,e,i,n,s){if(typeof e=="object"&&e instanceof z)throw new Error("To add an Option object use addOption() instead of option() or requiredOption()");let r=this.createOption(e,i);if(r.makeOptionMandatory(!!t.mandatory),typeof n=="function")r.default(s).argParser(n);else if(n instanceof RegExp){let a=n;n=(o,h)=>{let u=a.exec(o);return u?u[0]:h},r.default(s).argParser(n)}else r.default(n);return this.addOption(r)}option(t,e,i,n){return this._optionEx({},t,e,i,n)}requiredOption(t,e,i,n){return this._optionEx({mandatory:!0},t,e,i,n)}combineFlagAndOptionalValue(t=!0){return this._combineFlagAndOptionalValue=!!t,this}allowUnknownOption(t=!0){return this._allowUnknownOption=!!t,this}allowExcessArguments(t=!0){return this._allowExcessArguments=!!t,this}enablePositionalOptions(t=!0){return this._enablePositionalOptions=!!t,this}passThroughOptions(t=!0){return this._passThroughOptions=!!t,this._checkForBrokenPassThrough(),this}_checkForBrokenPassThrough(){if(this.parent&&this._passThroughOptions&&!this.parent._enablePositionalOptions)throw new Error(`passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`)}storeOptionsAsProperties(t=!0){if(this.options.length)throw new Error("call .storeOptionsAsProperties() before adding options");if(Object.keys(this._optionValues).length)throw new Error("call .storeOptionsAsProperties() before setting option values");return this._storeOptionsAsProperties=!!t,this}getOptionValue(t){return this._storeOptionsAsProperties?this[t]:this._optionValues[t]}setOptionValue(t,e){return this.setOptionValueWithSource(t,e,void 0)}setOptionValueWithSource(t,e,i){return this._storeOptionsAsProperties?this[t]=e:this._optionValues[t]=e,this._optionValueSources[t]=i,this}getOptionValueSource(t){return this._optionValueSources[t]}getOptionValueSourceWithGlobals(t){let e;return this._getCommandAndAncestors().forEach(i=>{i.getOptionValueSource(t)!==void 0&&(e=i.getOptionValueSource(t))}),e}_prepareUserArgs(t,e){if(t!==void 0&&!Array.isArray(t))throw new Error("first parameter to parse must be array or undefined");if(e=e||{},t===void 0&&e.from===void 0){m.versions?.electron&&(e.from="electron");let n=m.execArgv??[];(n.includes("-e")||n.includes("--eval")||n.includes("-p")||n.includes("--print"))&&(e.from="eval")}t===void 0&&(t=m.argv),this.rawArgs=t.slice();let i;switch(e.from){case void 0:case"node":this._scriptPath=t[1],i=t.slice(2);break;case"electron":m.defaultApp?(this._scriptPath=t[1],i=t.slice(2)):i=t.slice(1);break;case"user":i=t.slice(0);break;case"eval":i=t.slice(1);break;default:throw new Error(`unexpected parse option { from: '${e.from}' }`)}return!this._name&&this._scriptPath&&this.nameFromFilename(this._scriptPath),this._name=this._name||"program",i}parse(t,e){this._prepareForParse();let i=this._prepareUserArgs(t,e);return this._parseCommand([],i),this}async parseAsync(t,e){this._prepareForParse();let i=this._prepareUserArgs(t,e);return await this._parseCommand([],i),this}_prepareForParse(){this._savedState===null?this.saveStateBeforeParse():this.restoreStateBeforeParse()}saveStateBeforeParse(){this._savedState={_name:this._name,_optionValues:{...this._optionValues},_optionValueSources:{...this._optionValueSources}}}restoreStateBeforeParse(){if(this._storeOptionsAsProperties)throw new Error(`Can not call parse again when storeOptionsAsProperties is true.
|
|
19
|
+
- either make a new Command for each call to parse, or stop storing options as properties`);this._name=this._savedState._name,this._scriptPath=null,this.rawArgs=[],this._optionValues={...this._savedState._optionValues},this._optionValueSources={...this._savedState._optionValueSources},this.args=[],this.processedArgs=[]}_checkForMissingExecutable(t,e,i){if(w.existsSync(t))return;let n=e?`searched for local subcommand relative to directory '${e}'`:"no directory for search for local subcommand, use .executableDir() to supply a custom directory",s=`'${t}' does not exist
|
|
20
|
+
- if '${i}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
|
|
21
|
+
- if the default executable name is not suitable, use the executableFile option to supply a custom name or path
|
|
22
|
+
- ${n}`;throw new Error(s)}_executeSubCommand(t,e){e=e.slice();let i=!1,n=[".js",".ts",".tsx",".mjs",".cjs"];function s(u,c){let p=f.resolve(u,c);if(w.existsSync(p))return p;if(n.includes(f.extname(c)))return;let L=n.find(at=>w.existsSync(`${p}${at}`));if(L)return`${p}${L}`}this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let r=t._executableFile||`${this._name}-${t._name}`,a=this._executableDir||"";if(this._scriptPath){let u;try{u=w.realpathSync(this._scriptPath)}catch{u=this._scriptPath}a=f.resolve(f.dirname(u),a)}if(a){let u=s(a,r);if(!u&&!t._executableFile&&this._scriptPath){let c=f.basename(this._scriptPath,f.extname(this._scriptPath));c!==this._name&&(u=s(a,`${c}-${t._name}`))}r=u||r}i=n.includes(f.extname(r));let o;m.platform!=="win32"?i?(e.unshift(r),e=X(m.execArgv).concat(e),o=W.spawn(m.argv[0],e,{stdio:"inherit"})):o=W.spawn(r,e,{stdio:"inherit"}):(this._checkForMissingExecutable(r,a,t._name),e.unshift(r),e=X(m.execArgv).concat(e),o=W.spawn(m.execPath,e,{stdio:"inherit"})),o.killed||["SIGUSR1","SIGUSR2","SIGTERM","SIGINT","SIGHUP"].forEach(c=>{m.on(c,()=>{o.killed===!1&&o.exitCode===null&&o.kill(c)})});let h=this._exitCallback;o.on("close",u=>{u=u??1,h?h(new D(u,"commander.executeSubCommandAsync","(close)")):m.exit(u)}),o.on("error",u=>{if(u.code==="ENOENT")this._checkForMissingExecutable(r,a,t._name);else if(u.code==="EACCES")throw new Error(`'${r}' not executable`);if(!h)m.exit(1);else{let c=new D(1,"commander.executeSubCommandAsync","(error)");c.nestedError=u,h(c)}}),this.runningCommand=o}_dispatchSubcommand(t,e,i){let n=this._findCommand(t);n||this.help({error:!0}),n._prepareForParse();let s;return s=this._chainOrCallSubCommandHook(s,n,"preSubcommand"),s=this._chainOrCall(s,()=>{if(n._executableHandler)this._executeSubCommand(n,e.concat(i));else return n._parseCommand(e,i)}),s}_dispatchHelpCommand(t){t||this.help();let e=this._findCommand(t);return e&&!e._executableHandler&&e.help(),this._dispatchSubcommand(t,[],[this._getHelpOption()?.long??this._getHelpOption()?.short??"--help"])}_checkNumberOfArguments(){this.registeredArguments.forEach((t,e)=>{t.required&&this.args[e]==null&&this.missingArgument(t.name())}),!(this.registeredArguments.length>0&&this.registeredArguments[this.registeredArguments.length-1].variadic)&&this.args.length>this.registeredArguments.length&&this._excessArguments(this.args)}_processArguments(){let t=(i,n,s)=>{let r=n;if(n!==null&&i.parseArg){let a=`error: command-argument value '${n}' is invalid for argument '${i.name()}'.`;r=this._callParseArg(i,n,s,a)}return r};this._checkNumberOfArguments();let e=[];this.registeredArguments.forEach((i,n)=>{let s=i.defaultValue;i.variadic?n<this.args.length?(s=this.args.slice(n),i.parseArg&&(s=s.reduce((r,a)=>t(i,a,r),i.defaultValue))):s===void 0&&(s=[]):n<this.args.length&&(s=this.args[n],i.parseArg&&(s=t(i,s,i.defaultValue))),e[n]=s}),this.processedArgs=e}_chainOrCall(t,e){return t&&t.then&&typeof t.then=="function"?t.then(()=>e()):e()}_chainOrCallHooks(t,e){let i=t,n=[];return this._getCommandAndAncestors().reverse().filter(s=>s._lifeCycleHooks[e]!==void 0).forEach(s=>{s._lifeCycleHooks[e].forEach(r=>{n.push({hookedCommand:s,callback:r})})}),e==="postAction"&&n.reverse(),n.forEach(s=>{i=this._chainOrCall(i,()=>s.callback(s.hookedCommand,this))}),i}_chainOrCallSubCommandHook(t,e,i){let n=t;return this._lifeCycleHooks[i]!==void 0&&this._lifeCycleHooks[i].forEach(s=>{n=this._chainOrCall(n,()=>s(this,e))}),n}_parseCommand(t,e){let i=this.parseOptions(e);if(this._parseOptionsEnv(),this._parseOptionsImplied(),t=t.concat(i.operands),e=i.unknown,this.args=t.concat(e),t&&this._findCommand(t[0]))return this._dispatchSubcommand(t[0],t.slice(1),e);if(this._getHelpCommand()&&t[0]===this._getHelpCommand().name())return this._dispatchHelpCommand(t[1]);if(this._defaultCommandName)return this._outputHelpIfRequested(e),this._dispatchSubcommand(this._defaultCommandName,t,e);this.commands.length&&this.args.length===0&&!this._actionHandler&&!this._defaultCommandName&&this.help({error:!0}),this._outputHelpIfRequested(i.unknown),this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let n=()=>{i.unknown.length>0&&this.unknownOption(i.unknown[0])},s=`command:${this.name()}`;if(this._actionHandler){n(),this._processArguments();let r;return r=this._chainOrCallHooks(r,"preAction"),r=this._chainOrCall(r,()=>this._actionHandler(this.processedArgs)),this.parent&&(r=this._chainOrCall(r,()=>{this.parent.emit(s,t,e)})),r=this._chainOrCallHooks(r,"postAction"),r}if(this.parent&&this.parent.listenerCount(s))n(),this._processArguments(),this.parent.emit(s,t,e);else if(t.length){if(this._findCommand("*"))return this._dispatchSubcommand("*",t,e);this.listenerCount("command:*")?this.emit("command:*",t,e):this.commands.length?this.unknownCommand():(n(),this._processArguments())}else this.commands.length?(n(),this.help({error:!0})):(n(),this._processArguments())}_findCommand(t){if(t)return this.commands.find(e=>e._name===t||e._aliases.includes(t))}_findOption(t){return this.options.find(e=>e.is(t))}_checkForMissingMandatoryOptions(){this._getCommandAndAncestors().forEach(t=>{t.options.forEach(e=>{e.mandatory&&t.getOptionValue(e.attributeName())===void 0&&t.missingMandatoryOptionValue(e)})})}_checkForConflictingLocalOptions(){let t=this.options.filter(i=>{let n=i.attributeName();return this.getOptionValue(n)===void 0?!1:this.getOptionValueSource(n)!=="default"});t.filter(i=>i.conflictsWith.length>0).forEach(i=>{let n=t.find(s=>i.conflictsWith.includes(s.attributeName()));n&&this._conflictingOption(i,n)})}_checkForConflictingOptions(){this._getCommandAndAncestors().forEach(t=>{t._checkForConflictingLocalOptions()})}parseOptions(t){let e=[],i=[],n=e,s=t.slice();function r(o){return o.length>1&&o[0]==="-"}let a=null;for(;s.length;){let o=s.shift();if(o==="--"){n===i&&n.push(o),n.push(...s);break}if(a&&!r(o)){this.emit(`option:${a.name()}`,o);continue}if(a=null,r(o)){let h=this._findOption(o);if(h){if(h.required){let u=s.shift();u===void 0&&this.optionMissingArgument(h),this.emit(`option:${h.name()}`,u)}else if(h.optional){let u=null;s.length>0&&!r(s[0])&&(u=s.shift()),this.emit(`option:${h.name()}`,u)}else this.emit(`option:${h.name()}`);a=h.variadic?h:null;continue}}if(o.length>2&&o[0]==="-"&&o[1]!=="-"){let h=this._findOption(`-${o[1]}`);if(h){h.required||h.optional&&this._combineFlagAndOptionalValue?this.emit(`option:${h.name()}`,o.slice(2)):(this.emit(`option:${h.name()}`),s.unshift(`-${o.slice(2)}`));continue}}if(/^--[^=]+=/.test(o)){let h=o.indexOf("="),u=this._findOption(o.slice(0,h));if(u&&(u.required||u.optional)){this.emit(`option:${u.name()}`,o.slice(h+1));continue}}if(r(o)&&(n=i),(this._enablePositionalOptions||this._passThroughOptions)&&e.length===0&&i.length===0){if(this._findCommand(o)){e.push(o),s.length>0&&i.push(...s);break}else if(this._getHelpCommand()&&o===this._getHelpCommand().name()){e.push(o),s.length>0&&e.push(...s);break}else if(this._defaultCommandName){i.push(o),s.length>0&&i.push(...s);break}}if(this._passThroughOptions){n.push(o),s.length>0&&n.push(...s);break}n.push(o)}return{operands:e,unknown:i}}opts(){if(this._storeOptionsAsProperties){let t={},e=this.options.length;for(let i=0;i<e;i++){let n=this.options[i].attributeName();t[n]=n===this._versionOptionName?this._version:this[n]}return t}return this._optionValues}optsWithGlobals(){return this._getCommandAndAncestors().reduce((t,e)=>Object.assign(t,e.opts()),{})}error(t,e){this._outputConfiguration.outputError(`${t}
|
|
23
|
+
`,this._outputConfiguration.writeErr),typeof this._showHelpAfterError=="string"?this._outputConfiguration.writeErr(`${this._showHelpAfterError}
|
|
24
|
+
`):this._showHelpAfterError&&(this._outputConfiguration.writeErr(`
|
|
25
|
+
`),this.outputHelp({error:!0}));let i=e||{},n=i.exitCode||1,s=i.code||"commander.error";this._exit(n,s,t)}_parseOptionsEnv(){this.options.forEach(t=>{if(t.envVar&&t.envVar in m.env){let e=t.attributeName();(this.getOptionValue(e)===void 0||["default","config","env"].includes(this.getOptionValueSource(e)))&&(t.required||t.optional?this.emit(`optionEnv:${t.name()}`,m.env[t.envVar]):this.emit(`optionEnv:${t.name()}`))}})}_parseOptionsImplied(){let t=new At(this.options),e=i=>this.getOptionValue(i)!==void 0&&!["default","implied"].includes(this.getOptionValueSource(i));this.options.filter(i=>i.implied!==void 0&&e(i.attributeName())&&t.valueFromOption(this.getOptionValue(i.attributeName()),i)).forEach(i=>{Object.keys(i.implied).filter(n=>!e(n)).forEach(n=>{this.setOptionValueWithSource(n,i.implied[n],"implied")})})}missingArgument(t){let e=`error: missing required argument '${t}'`;this.error(e,{code:"commander.missingArgument"})}optionMissingArgument(t){let e=`error: option '${t.flags}' argument missing`;this.error(e,{code:"commander.optionMissingArgument"})}missingMandatoryOptionValue(t){let e=`error: required option '${t.flags}' not specified`;this.error(e,{code:"commander.missingMandatoryOptionValue"})}_conflictingOption(t,e){let i=r=>{let a=r.attributeName(),o=this.getOptionValue(a),h=this.options.find(c=>c.negate&&a===c.attributeName()),u=this.options.find(c=>!c.negate&&a===c.attributeName());return h&&(h.presetArg===void 0&&o===!1||h.presetArg!==void 0&&o===h.presetArg)?h:u||r},n=r=>{let a=i(r),o=a.attributeName();return this.getOptionValueSource(o)==="env"?`environment variable '${a.envVar}'`:`option '${a.flags}'`},s=`error: ${n(t)} cannot be used with ${n(e)}`;this.error(s,{code:"commander.conflictingOption"})}unknownOption(t){if(this._allowUnknownOption)return;let e="";if(t.startsWith("--")&&this._showSuggestionAfterError){let n=[],s=this;do{let r=s.createHelp().visibleOptions(s).filter(a=>a.long).map(a=>a.long);n=n.concat(r),s=s.parent}while(s&&!s._enablePositionalOptions);e=Q(t,n)}let i=`error: unknown option '${t}'${e}`;this.error(i,{code:"commander.unknownOption"})}_excessArguments(t){if(this._allowExcessArguments)return;let e=this.registeredArguments.length,i=e===1?"":"s",s=`error: too many arguments${this.parent?` for '${this.name()}'`:""}. Expected ${e} argument${i} but got ${t.length}.`;this.error(s,{code:"commander.excessArguments"})}unknownCommand(){let t=this.args[0],e="";if(this._showSuggestionAfterError){let n=[];this.createHelp().visibleCommands(this).forEach(s=>{n.push(s.name()),s.alias()&&n.push(s.alias())}),e=Q(t,n)}let i=`error: unknown command '${t}'${e}`;this.error(i,{code:"commander.unknownCommand"})}version(t,e,i){if(t===void 0)return this._version;this._version=t,e=e||"-V, --version",i=i||"output the version number";let n=this.createOption(e,i);return this._versionOptionName=n.attributeName(),this._registerOption(n),this.on("option:"+n.name(),()=>{this._outputConfiguration.writeOut(`${t}
|
|
26
|
+
`),this._exit(0,"commander.version",t)}),this}description(t,e){return t===void 0&&e===void 0?this._description:(this._description=t,e&&(this._argsDescription=e),this)}summary(t){return t===void 0?this._summary:(this._summary=t,this)}alias(t){if(t===void 0)return this._aliases[0];let e=this;if(this.commands.length!==0&&this.commands[this.commands.length-1]._executableHandler&&(e=this.commands[this.commands.length-1]),t===e._name)throw new Error("Command alias can't be the same as its name");let i=this.parent?._findCommand(t);if(i){let n=[i.name()].concat(i.aliases()).join("|");throw new Error(`cannot add alias '${t}' to command '${this.name()}' as already have command '${n}'`)}return e._aliases.push(t),this}aliases(t){return t===void 0?this._aliases:(t.forEach(e=>this.alias(e)),this)}usage(t){if(t===void 0){if(this._usage)return this._usage;let e=this.registeredArguments.map(i=>Ot(i));return[].concat(this.options.length||this._helpOption!==null?"[options]":[],this.commands.length?"[command]":[],this.registeredArguments.length?e:[]).join(" ")}return this._usage=t,this}name(t){return t===void 0?this._name:(this._name=t,this)}nameFromFilename(t){return this._name=f.basename(t,f.extname(t)),this}executableDir(t){return t===void 0?this._executableDir:(this._executableDir=t,this)}helpInformation(t){let e=this.createHelp(),i=this._getOutputContext(t);e.prepareContext({error:i.error,helpWidth:i.helpWidth,outputHasColors:i.hasColors});let n=e.formatHelp(this,e);return i.hasColors?n:this._outputConfiguration.stripColor(n)}_getOutputContext(t){t=t||{};let e=!!t.error,i,n,s;return e?(i=a=>this._outputConfiguration.writeErr(a),n=this._outputConfiguration.getErrHasColors(),s=this._outputConfiguration.getErrHelpWidth()):(i=a=>this._outputConfiguration.writeOut(a),n=this._outputConfiguration.getOutHasColors(),s=this._outputConfiguration.getOutHelpWidth()),{error:e,write:a=>(n||(a=this._outputConfiguration.stripColor(a)),i(a)),hasColors:n,helpWidth:s}}outputHelp(t){let e;typeof t=="function"&&(e=t,t=void 0);let i=this._getOutputContext(t),n={error:i.error,write:i.write,command:this};this._getCommandAndAncestors().reverse().forEach(r=>r.emit("beforeAllHelp",n)),this.emit("beforeHelp",n);let s=this.helpInformation({error:i.error});if(e&&(s=e(s),typeof s!="string"&&!Buffer.isBuffer(s)))throw new Error("outputHelp callback must return a string or a Buffer");i.write(s),this._getHelpOption()?.long&&this.emit(this._getHelpOption().long),this.emit("afterHelp",n),this._getCommandAndAncestors().forEach(r=>r.emit("afterAllHelp",n))}helpOption(t,e){return typeof t=="boolean"?(t?this._helpOption=this._helpOption??void 0:this._helpOption=null,this):(t=t??"-h, --help",e=e??"display help for command",this._helpOption=this.createOption(t,e),this)}_getHelpOption(){return this._helpOption===void 0&&this.helpOption(void 0,void 0),this._helpOption}addHelpOption(t){return this._helpOption=t,this}help(t){this.outputHelp(t);let e=Number(m.exitCode??0);e===0&&t&&typeof t!="function"&&t.error&&(e=1),this._exit(e,"commander.help","(outputHelp)")}addHelpText(t,e){let i=["beforeAll","before","after","afterAll"];if(!i.includes(t))throw new Error(`Unexpected value for position to addHelpText.
|
|
27
|
+
Expecting one of '${i.join("', '")}'`);let n=`${t}Help`;return this.on(n,s=>{let r;typeof e=="function"?r=e({error:s.error,command:s.command}):r=e,r&&s.write(`${r}
|
|
28
|
+
`)}),this}_outputHelpIfRequested(t){let e=this._getHelpOption();e&&t.find(n=>e.is(n))&&(this.outputHelp(),this._exit(0,"commander.helpDisplayed","(outputHelp)"))}};function X(l){return l.map(t=>{if(!t.startsWith("--inspect"))return t;let e,i="127.0.0.1",n="9229",s;return(s=t.match(/^(--inspect(-brk)?)$/))!==null?e=s[1]:(s=t.match(/^(--inspect(-brk|-port)?)=([^:]+)$/))!==null?(e=s[1],/^\d+$/.test(s[3])?n=s[3]:i=s[3]):(s=t.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/))!==null&&(e=s[1],i=s[3],n=s[4]),e&&n!=="0"?`${e}=${i}:${parseInt(n)+1}`:t})}function I(){if(m.env.NO_COLOR||m.env.FORCE_COLOR==="0"||m.env.FORCE_COLOR==="false")return!1;if(m.env.FORCE_COLOR||m.env.CLICOLOR_FORCE!==void 0)return!0}N.Command=F;N.useColor=I});var nt=g(d=>{"use strict";var{Argument:tt}=A(),{Command:q}=Z(),{CommanderError:wt,InvalidArgumentError:et}=C(),{Help:yt}=k(),{Option:it}=P();d.program=new q;d.createCommand=l=>new q(l);d.createOption=(l,t)=>new it(l,t);d.createArgument=(l,t)=>new tt(l,t);d.Command=q;d.Option=it;d.Argument=tt;d.Help=yt;d.CommanderError=wt;d.InvalidArgumentError=et;d.InvalidOptionArgumentError=et});var st=lt(nt(),1),{program:Wt,createCommand:Dt,createArgument:Ft,createOption:It,CommanderError:Nt,InvalidArgumentError:qt,InvalidOptionArgumentError:jt,Command:rt,Argument:Mt,Option:Lt,Help:Rt}=st.default;var xt=[" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557","\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551","\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551","\u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551","\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551"," \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D"],Et="OpenSkill.md \u2014 the npm for AI skills";function j(){return["",...xt.map(l=>R(l)),B(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),U.bold(` ${Et}`),""].join(`
|
|
29
|
+
`)}function _(){process.stderr.write(j()+`
|
|
30
|
+
`)}var St="0.3.1",M=class l extends rt{createCommand(t){return new l(t)}helpInformation(){return`${j()}
|
|
31
|
+
${super.helpInformation()}`}};function ot(){let l=new M;function t(n,s,r){l.command(n).description(s).action(async(...a)=>{_(),await(await r())(...a.slice(0,-1))})}l.name("osm").description("The CLI for OpenSkill.md \u2014 search, add, score, and explore AI agent skills").version(St),t("search <query>","Search skills and blueprints by keyword",async()=>(await import("./search-JQMXVSCW.js")).searchCommand),t("info <slug>","Show details about a skill or blueprint",async()=>(await import("./info-5GSXNJ5W.js")).infoCommand),l.command("add <source>").alias("install").description("Add a skill from a source repo (owner/repo or owner/repo@skill)").option("-a, --agent <agent...>","Target coding agent(s) \u2014 may repeat. If omitted, auto-detects installed agents.").option("-g, --global","Add at user scope (~/) instead of project").option("--copy","Copy files instead of symlinking to agent directories").option("--json","Emit a single-line JSON result on stdout (machine-readable)").action(async(n,s)=>{_();let{addCommand:r}=await import("./add-77ZPOLTV.js");await r(n,s)}),t("list","Show installed skills and blueprints in this project",async()=>(await import("./list-SMKTYTII.js")).listCommand),t("score <filepath>","Score a local SKILL.md file for quality",async()=>(await import("./score-CPVOUARV.js")).scoreCommand),t("init <type>","Scaffold a new skill or blueprint (type: skill | blueprint)",async()=>(await import("./init-ZDBNGFX7.js")).initCommand),t("browse","Explore skills by category (interactive)",async()=>(await import("./browse-P7RXLMMF.js")).browseCommand),t("remove <slug>","Remove an installed skill or blueprint from the project",async()=>(await import("./remove-QKFHXT73.js")).removeCommand),l.command("router").description("Manage the OpenSkill router skill").command("install").description("Download the OpenSkill router SKILL.md into .skills/").action(async()=>{_();let{routerInstallCommand:n}=await import("./router-AVHY4U3G.js");await n()});let i=l.command("mcp").description("Explore and configure MCP servers");return i.command("setup").description("Print MCP configuration for Claude/Cursor").action(async()=>{_();let{mcpSetupCommand:n}=await import("./mcp-UHV7L4RE.js");await n()}),i.command("info <slug>").description("Show details about an MCP server").action(async n=>{_();let{mcpInfoCommand:s}=await import("./mcp-UHV7L4RE.js");await s(n)}),l.configureOutput({writeOut:n=>process.stderr.write(n),writeErr:n=>process.stderr.write(n)}),l.action(()=>{l.outputHelp()}),l}ot().parseAsync(process.argv).catch(l=>{console.error(l),process.exit(1)});
|