itismyskillmarket 1.3.46 → 1.3.48

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # SkillMarket
2
2
 
3
- > **v1.3.42** — Cross-platform skill manager for AI coding tools (Cursor, VSCode, Codex CLI, OpenCode, Claude Code, Antigravity, OpenClaw, Hermes Agent, Saitec TUI).
3
+ > **v1.3.48** — Cross-platform skill manager for AI coding tools (Cursor, VSCode, Codex CLI, OpenCode, Claude Code, Antigravity, OpenClaw, Hermes Agent, Saitec TUI).
4
4
 
5
5
  ## Installation
6
6
 
@@ -1264,6 +1264,24 @@ async function publishSkill(skillName, options) {
1264
1264
 
1265
1265
  // src/commands/admin.ts
1266
1266
  import { execSync as execSync2 } from "child_process";
1267
+
1268
+ // src/utils/concurrency.ts
1269
+ async function throttledMap(items, fn, concurrency = 3, batchDelayMs = 200) {
1270
+ const results = [];
1271
+ for (let i = 0; i < items.length; i += concurrency) {
1272
+ const batch = items.slice(i, i + concurrency);
1273
+ const batchResults = await Promise.all(
1274
+ batch.map((item, idx) => fn(item, i + idx))
1275
+ );
1276
+ results.push(...batchResults);
1277
+ if (i + concurrency < items.length) {
1278
+ await new Promise((r) => setTimeout(r, batchDelayMs));
1279
+ }
1280
+ }
1281
+ return results;
1282
+ }
1283
+
1284
+ // src/commands/admin.ts
1267
1285
  async function fetchScopePackages() {
1268
1286
  const all = /* @__PURE__ */ new Set();
1269
1287
  for (const scope of SKILL_SCOPES) {
@@ -1277,15 +1295,12 @@ async function fetchScopePackages() {
1277
1295
  }
1278
1296
  return [...all].sort();
1279
1297
  }
1280
- async function adminList() {
1281
- console.log("\n\u{1F50D} Fetching all published skills...\n");
1298
+ async function fetchScopePackageDetails() {
1282
1299
  const packages = await fetchScopePackages();
1283
- if (packages.length === 0) {
1284
- console.log("No published skills found.");
1285
- return;
1286
- }
1287
- const details = await Promise.all(
1288
- packages.map(async (pkg) => {
1300
+ if (packages.length === 0) return [];
1301
+ const details = await throttledMap(
1302
+ packages,
1303
+ async (pkg) => {
1289
1304
  try {
1290
1305
  const info = await fetchNpmPackage(pkg);
1291
1306
  if (!info) return null;
@@ -1302,19 +1317,191 @@ async function adminList() {
1302
1317
  } catch {
1303
1318
  return null;
1304
1319
  }
1305
- })
1320
+ },
1321
+ 3,
1322
+ 200
1306
1323
  );
1307
1324
  const valid = details.filter(Boolean);
1308
- console.log(`\u{1F4E6} ${valid.length} published skill(s):
1309
- `);
1310
1325
  valid.sort((a, b) => a.name.localeCompare(b.name));
1326
+ return valid;
1327
+ }
1328
+ async function getPublishingStats() {
1329
+ const packages = await fetchScopePackages();
1330
+ if (packages.length === 0) {
1331
+ return {
1332
+ totalSkills: 0,
1333
+ totalVersions: 0,
1334
+ averageVersions: "0",
1335
+ withMetadata: 0,
1336
+ totalSizeMB: "0",
1337
+ platformCount: 0,
1338
+ platforms: []
1339
+ };
1340
+ }
1341
+ const infos = (await throttledMap(
1342
+ packages,
1343
+ async (pkg) => {
1344
+ try {
1345
+ const info = await fetchNpmPackage(pkg);
1346
+ return info ? { name: pkg, info } : null;
1347
+ } catch {
1348
+ return null;
1349
+ }
1350
+ },
1351
+ 3,
1352
+ 200
1353
+ )).filter((item) => item !== null);
1354
+ let totalVersions = 0;
1355
+ let totalSize = 0;
1356
+ const platformSet = /* @__PURE__ */ new Set();
1357
+ let withMetadata = 0;
1358
+ let mostVersions = { name: "", count: 0 };
1359
+ let mostRecent = { name: "", date: "" };
1360
+ for (const { name, info } of infos) {
1361
+ const versions = Object.keys(info.versions || {});
1362
+ totalVersions += versions.length;
1363
+ if (versions.length > mostVersions.count) {
1364
+ mostVersions = { name, count: versions.length };
1365
+ }
1366
+ const latestVer = info["dist-tags"]?.latest;
1367
+ const latestPkg = latestVer ? info.versions?.[latestVer] : void 0;
1368
+ const meta = latestPkg?.skillmarket;
1369
+ if (meta) {
1370
+ withMetadata++;
1371
+ if (meta.platforms) meta.platforms.forEach((p) => platformSet.add(p));
1372
+ }
1373
+ if (latestPkg?.dist?.unpackedSize) totalSize += latestPkg.dist.unpackedSize;
1374
+ const modTime = info.time?.modified || "";
1375
+ if (modTime && modTime > mostRecent.date) {
1376
+ mostRecent = { name, date: modTime };
1377
+ }
1378
+ }
1379
+ return {
1380
+ totalSkills: infos.length,
1381
+ totalVersions,
1382
+ averageVersions: infos.length > 0 ? (totalVersions / infos.length).toFixed(1) : "0",
1383
+ withMetadata,
1384
+ totalSizeMB: (totalSize / 1024 / 1024).toFixed(2),
1385
+ platformCount: platformSet.size,
1386
+ platforms: [...platformSet],
1387
+ mostVersions,
1388
+ mostRecent,
1389
+ registry: NPM_REGISTRY,
1390
+ scopes: [...SKILL_SCOPES]
1391
+ };
1392
+ }
1393
+ async function verifySkillData(skillId) {
1394
+ const info = await fetchSkillPackage(skillId);
1395
+ if (!info) return null;
1396
+ const checks = [];
1397
+ let passed = 0;
1398
+ let failed = 0;
1399
+ let warnings = 0;
1400
+ const nameValid = /^@[^/]+\/[^/]+$/.test(info.name);
1401
+ if (nameValid) {
1402
+ checks.push({ label: "Package name format", status: "pass", message: info.name });
1403
+ passed++;
1404
+ } else {
1405
+ checks.push({ label: "Package name format", status: "warn", message: `Unusual: ${info.name}` });
1406
+ warnings++;
1407
+ }
1408
+ const tags = info["dist-tags"] || {};
1409
+ if (tags.latest) {
1410
+ checks.push({ label: "dist-tags.latest", status: "pass", message: tags.latest });
1411
+ passed++;
1412
+ } else {
1413
+ checks.push({ label: "dist-tags.latest", status: "fail", message: "Missing" });
1414
+ failed++;
1415
+ }
1416
+ const latestVer = tags.latest;
1417
+ const latestPkg = latestVer ? info.versions?.[latestVer] : void 0;
1418
+ if (latestPkg) {
1419
+ checks.push({ label: "Latest version exists", status: "pass", message: `${latestVer} exists in versions` });
1420
+ passed++;
1421
+ } else {
1422
+ checks.push({ label: "Latest version exists", status: "fail", message: `${latestVer} not found in versions` });
1423
+ failed++;
1424
+ }
1425
+ const meta = latestPkg?.skillmarket;
1426
+ if (meta) {
1427
+ checks.push({ label: "skillmarket metadata", status: "pass", message: "Present" });
1428
+ passed++;
1429
+ const subChecks = [
1430
+ { label: "skillmarket.id", ok: !!meta.id },
1431
+ { label: "skillmarket.displayName", ok: !!meta.displayName },
1432
+ { label: "skillmarket.platforms", ok: Array.isArray(meta.platforms) && meta.platforms.length > 0 }
1433
+ ];
1434
+ for (const c of subChecks) {
1435
+ if (c.ok) {
1436
+ checks.push({ label: c.label, status: "pass", message: "Present" });
1437
+ passed++;
1438
+ } else {
1439
+ checks.push({ label: c.label, status: "warn", message: "Missing or empty" });
1440
+ warnings++;
1441
+ }
1442
+ }
1443
+ if (meta.platforms) {
1444
+ const unknown = meta.platforms.filter((p) => !PLATFORMS.includes(p));
1445
+ if (unknown.length > 0) {
1446
+ checks.push({ label: "Platforms recognized", status: "warn", message: `Unknown: ${unknown.join(", ")}` });
1447
+ warnings++;
1448
+ } else {
1449
+ checks.push({ label: "Platforms recognized", status: "pass", message: "All recognized" });
1450
+ passed++;
1451
+ }
1452
+ }
1453
+ } else {
1454
+ checks.push({ label: "skillmarket metadata", status: "warn", message: "Not a skillmarket-formatted skill" });
1455
+ warnings++;
1456
+ }
1457
+ if (latestPkg?.description) {
1458
+ checks.push({ label: "Description", status: "pass", message: `${latestPkg.description.length} chars` });
1459
+ passed++;
1460
+ } else {
1461
+ checks.push({ label: "Description", status: "warn", message: "Missing" });
1462
+ warnings++;
1463
+ }
1464
+ if (info.license || latestPkg?.license) {
1465
+ checks.push({ label: "License", status: "pass", message: info.license || latestPkg?.license || "" });
1466
+ passed++;
1467
+ } else {
1468
+ checks.push({ label: "License", status: "warn", message: "Missing" });
1469
+ warnings++;
1470
+ }
1471
+ if (latestPkg?.dist?.unpackedSize) {
1472
+ const sizeKB = (latestPkg.dist.unpackedSize / 1024).toFixed(1);
1473
+ checks.push({ label: "Package size", status: "pass", message: `${sizeKB} KB (unpacked)` });
1474
+ passed++;
1475
+ }
1476
+ const versionCount = Object.keys(info.versions || {}).length;
1477
+ checks.push({ label: "Total versions", status: "info", message: String(versionCount) });
1478
+ return {
1479
+ skillId,
1480
+ valid: failed === 0,
1481
+ passed,
1482
+ failed,
1483
+ warnings,
1484
+ checks
1485
+ };
1486
+ }
1487
+ async function adminList() {
1488
+ console.log("\n\u{1F50D} Fetching all published skills...\n");
1489
+ const valid = await fetchScopePackageDetails();
1490
+ if (valid.length === 0) {
1491
+ console.log("No published skills found.");
1492
+ return;
1493
+ }
1494
+ let hasSkillmarketCount = 0;
1311
1495
  for (const d of valid) {
1496
+ if (d.hasSkillmarket) hasSkillmarketCount++;
1312
1497
  const flag = d.hasSkillmarket ? "\u2705" : "\u{1F4E6}";
1313
1498
  console.log(` ${flag} ${d.name}@${d.version}`);
1314
1499
  if (d.description) console.log(` ${d.description.slice(0, 80)}`);
1315
1500
  if (d.platforms) console.log(` Platforms: ${d.platforms}`);
1316
1501
  console.log();
1317
1502
  }
1503
+ console.log(`\u{1F4E6} ${valid.length} published skill(s) \uFF08${hasSkillmarketCount} with skillmarket metadata\uFF09
1504
+ `);
1318
1505
  }
1319
1506
  async function adminInfo(skillId) {
1320
1507
  console.log(`
@@ -1322,9 +1509,10 @@ async function adminInfo(skillId) {
1322
1509
  `);
1323
1510
  const info = await fetchSkillPackage(skillId);
1324
1511
  if (!info) {
1325
- console.error(`\u274C Skill "${skillId}" not found in any configured scope.`);
1326
- console.log(` Scopes checked: ${SKILL_SCOPES.join(", ")}`);
1327
- process.exit(1);
1512
+ throw new Error(
1513
+ `Skill "${skillId}" not found in any configured scope.
1514
+ Scopes checked: ${SKILL_SCOPES.join(", ")}`
1515
+ );
1328
1516
  }
1329
1517
  const latestVer = info["dist-tags"]?.latest || "unknown";
1330
1518
  const latestPkg = info.versions?.[latestVer];
@@ -1424,164 +1612,44 @@ async function adminSearch(keyword, limit = 20) {
1424
1612
  }
1425
1613
  async function adminStats() {
1426
1614
  console.log("\n\u{1F4CA} SkillMarket Publishing Statistics\n");
1427
- const packages = await fetchScopePackages();
1428
- if (packages.length === 0) {
1615
+ const stats = await getPublishingStats();
1616
+ if (stats.totalSkills === 0) {
1429
1617
  console.log("No published skills found.");
1430
1618
  return;
1431
1619
  }
1432
- const infos = (await Promise.all(
1433
- packages.map(async (pkg) => {
1434
- try {
1435
- const info = await fetchNpmPackage(pkg);
1436
- return info ? { name: pkg, info } : null;
1437
- } catch {
1438
- return null;
1439
- }
1440
- })
1441
- )).filter(Boolean);
1442
- const totalSkills = infos.length;
1443
- let totalVersions = 0;
1444
- let totalSize = 0;
1445
- const platformSet = /* @__PURE__ */ new Set();
1446
- let withMetadata = 0;
1447
- let mostVersions = { name: "", count: 0 };
1448
- let mostRecent = { name: "", date: "" };
1449
- for (const { name, info } of infos) {
1450
- const versions = Object.keys(info.versions || {});
1451
- totalVersions += versions.length;
1452
- if (versions.length > mostVersions.count) {
1453
- mostVersions = { name, count: versions.length };
1454
- }
1455
- const latestVer = info["dist-tags"]?.latest;
1456
- const latestPkg = latestVer ? info.versions?.[latestVer] : void 0;
1457
- const meta = latestPkg?.skillmarket;
1458
- if (meta) {
1459
- withMetadata++;
1460
- if (meta.platforms) {
1461
- for (const p of meta.platforms) platformSet.add(p);
1462
- }
1463
- }
1464
- if (latestPkg?.dist?.unpackedSize) {
1465
- totalSize += latestPkg.dist.unpackedSize;
1466
- }
1467
- const modTime = info.time?.modified || "";
1468
- if (modTime && modTime > mostRecent.date) {
1469
- mostRecent = { name, date: modTime };
1470
- }
1471
- }
1472
- console.log(`\u{1F4E6} Total published skills: ${totalSkills}`);
1473
- console.log(`\u{1F4DD} Total versions: ${totalVersions}`);
1474
- console.log(` Avg versions/skill: ${(totalVersions / totalSkills).toFixed(1)}`);
1475
- console.log(`\u{1F4CB} Skills with skillmarket metadata: ${withMetadata}/${totalSkills}`);
1476
- console.log(`\u{1F4BE} Total unpacked size: ${(totalSize / 1024 / 1024).toFixed(2)} MB`);
1477
- console.log(`\u{1F527} Platforms covered: ${platformSet.size} (${[...platformSet].join(", ")})`);
1478
- console.log(`\u{1F3C6} Most versions: ${mostVersions.name} (${mostVersions.count})`);
1479
- if (mostRecent.date) {
1480
- console.log(`\u{1F550} Most recent update: ${mostRecent.name} (${new Date(mostRecent.date).toLocaleDateString()})`);
1481
- }
1482
- console.log(`\u{1F517} Registry: ${NPM_REGISTRY}`);
1620
+ console.log(`\u{1F4E6} Total published skills: ${stats.totalSkills}`);
1621
+ console.log(`\u{1F4DD} Total versions: ${stats.totalVersions}`);
1622
+ console.log(` Avg versions/skill: ${stats.averageVersions}`);
1623
+ console.log(`\u{1F4CB} Skills with skillmarket metadata: ${stats.withMetadata}/${stats.totalSkills}`);
1624
+ console.log(`\u{1F4BE} Total unpacked size: ${stats.totalSizeMB} MB`);
1625
+ console.log(`\u{1F527} Platforms covered: ${stats.platformCount} (${stats.platforms.join(", ")})`);
1626
+ console.log(`\u{1F3C6} Most versions: ${stats.mostVersions.name} (${stats.mostVersions.count})`);
1627
+ if (stats.mostRecent.date) {
1628
+ console.log(`\u{1F550} Most recent update: ${stats.mostRecent.name} (${new Date(stats.mostRecent.date).toLocaleDateString()})`);
1629
+ }
1630
+ console.log(`\u{1F517} Registry: ${stats.registry}`);
1483
1631
  console.log(`
1484
- Configured scopes: ${SKILL_SCOPES.join(", ")}`);
1632
+ Configured scopes: ${stats.scopes.join(", ")}`);
1485
1633
  console.log();
1486
1634
  }
1487
1635
  async function adminVerify(skillId) {
1488
1636
  console.log(`
1489
1637
  \u{1F50D} Verifying published skill "${skillId}"...
1490
1638
  `);
1491
- const info = await fetchSkillPackage(skillId);
1492
- if (!info) {
1493
- console.error(`\u274C Skill "${skillId}" not found.`);
1494
- process.exit(1);
1639
+ const result = await verifySkillData(skillId);
1640
+ if (!result) {
1641
+ throw new Error(`Skill "${skillId}" not found.`);
1495
1642
  }
1496
- let passed = 0;
1497
- let failed = 0;
1498
- let warnings = 0;
1499
- const nameValid = /^@[^/]+\/[^/]+$/.test(info.name);
1500
- if (nameValid) {
1501
- console.log(`\u2705 Package name format: ${info.name}`);
1502
- passed++;
1503
- } else {
1504
- console.log(`\u26A0\uFE0F Package name format unusual: ${info.name}`);
1505
- warnings++;
1643
+ for (const check of result.checks) {
1644
+ const icon = check.status === "pass" ? "\u2705" : check.status === "fail" ? "\u274C" : check.status === "warn" ? "\u26A0\uFE0F" : "\u2139\uFE0F";
1645
+ console.log(` ${icon} ${check.label}: ${check.message}`);
1506
1646
  }
1507
- const tags = info["dist-tags"] || {};
1508
- if (tags.latest) {
1509
- console.log(`\u2705 dist-tags.latest: ${tags.latest}`);
1510
- passed++;
1511
- } else {
1512
- console.log(`\u274C dist-tags.latest missing`);
1513
- failed++;
1514
- }
1515
- const latestVer = tags.latest;
1516
- const latestPkg = latestVer ? info.versions?.[latestVer] : void 0;
1517
- if (latestPkg) {
1518
- console.log(`\u2705 Latest version ${latestVer} exists in versions`);
1519
- passed++;
1520
- } else {
1521
- console.log(`\u274C Latest version ${latestVer} not found in versions object`);
1522
- failed++;
1523
- }
1524
- const meta = latestPkg?.skillmarket;
1525
- if (meta) {
1526
- console.log(`\u2705 Has skillmarket metadata`);
1527
- const checks = [
1528
- { name: "id", ok: !!meta.id },
1529
- { name: "displayName", ok: !!meta.displayName },
1530
- { name: "platforms (array)", ok: Array.isArray(meta.platforms) && meta.platforms.length > 0 }
1531
- ];
1532
- for (const c of checks) {
1533
- if (c.ok) {
1534
- console.log(` \u2705 skillmarket.${c.name}`);
1535
- passed++;
1536
- } else {
1537
- console.log(` \u26A0\uFE0F skillmarket.${c.name} missing or empty`);
1538
- warnings++;
1539
- }
1540
- }
1541
- if (meta.platforms) {
1542
- const unknown = meta.platforms.filter(
1543
- (p) => !PLATFORMS.includes(p)
1544
- );
1545
- if (unknown.length > 0) {
1546
- console.log(` \u26A0\uFE0F Unknown platforms: ${unknown.join(", ")}`);
1547
- warnings++;
1548
- } else {
1549
- console.log(` \u2705 All platforms recognized`);
1550
- passed++;
1551
- }
1552
- }
1553
- } else {
1554
- console.log(`\u26A0\uFE0F No skillmarket metadata (not a skillmarket-formatted skill)`);
1555
- warnings++;
1556
- }
1557
- if (latestPkg?.description) {
1558
- console.log(`\u2705 Has description (${latestPkg.description.length} chars)`);
1559
- passed++;
1560
- } else {
1561
- console.log(`\u26A0\uFE0F No description`);
1562
- warnings++;
1563
- }
1564
- if (info.license || latestPkg?.license) {
1565
- console.log(`\u2705 License: ${info.license || latestPkg?.license}`);
1566
- passed++;
1567
- } else {
1568
- console.log(`\u26A0\uFE0F No license specified`);
1569
- warnings++;
1570
- }
1571
- if (latestPkg?.dist?.unpackedSize) {
1572
- const sizeKB = (latestPkg.dist.unpackedSize / 1024).toFixed(1);
1573
- console.log(`\u2705 Package size: ${sizeKB} KB (unpacked)`);
1574
- passed++;
1575
- }
1576
- const versionCount = Object.keys(info.versions || {}).length;
1577
- console.log(`\u2139\uFE0F Total versions: ${versionCount}`);
1578
- const total = passed + failed;
1579
1647
  console.log(`
1580
1648
  \u{1F4CA} Verification Result:`);
1581
- console.log(` \u2705 Passed: ${passed}`);
1582
- console.log(` \u26A0\uFE0F Warnings: ${warnings}`);
1583
- console.log(` \u274C Failed: ${failed}`);
1584
- if (failed === 0) {
1649
+ console.log(` \u2705 Passed: ${result.passed}`);
1650
+ console.log(` \u26A0\uFE0F Warnings: ${result.warnings}`);
1651
+ console.log(` \u274C Failed: ${result.failed}`);
1652
+ if (result.valid) {
1585
1653
  console.log(`
1586
1654
  \u2705 Skill "${skillId}" is valid!
1587
1655
  `);
@@ -1889,9 +1957,10 @@ function getSourceBadge(source) {
1889
1957
  async function getConfigValue(key) {
1890
1958
  const entry = await getConfig(key);
1891
1959
  if (!entry) {
1892
- console.error(`\u274C Unknown config key: "${key}"`);
1893
- console.log(` Valid keys: ${CONFIG_DEFINITIONS.map((d) => d.key).join(", ")}`);
1894
- process.exit(1);
1960
+ throw new Error(
1961
+ `Unknown config key: "${key}"
1962
+ Valid keys: ${CONFIG_DEFINITIONS.map((d) => d.key).join(", ")}`
1963
+ );
1895
1964
  }
1896
1965
  console.log(`
1897
1966
  \u{1F527} ${entry.key}`);
@@ -1905,9 +1974,10 @@ async function getConfigValue(key) {
1905
1974
  async function setConfigValue(key, value) {
1906
1975
  const def = CONFIG_DEFINITIONS.find((d) => d.key === key);
1907
1976
  if (!def) {
1908
- console.error(`\u274C Unknown config key: "${key}"`);
1909
- console.log(` Valid keys: ${CONFIG_DEFINITIONS.map((d) => d.key).join(", ")}`);
1910
- process.exit(1);
1977
+ throw new Error(
1978
+ `Unknown config key: "${key}"
1979
+ Valid keys: ${CONFIG_DEFINITIONS.map((d) => d.key).join(", ")}`
1980
+ );
1911
1981
  }
1912
1982
  await writeConfigFile({ [key]: value });
1913
1983
  console.log(`
@@ -1931,9 +2001,10 @@ async function resetConfig(key, all = false) {
1931
2001
  if (key) {
1932
2002
  const def = CONFIG_DEFINITIONS.find((d) => d.key === key);
1933
2003
  if (!def) {
1934
- console.error(`\u274C Unknown config key: "${key}"`);
1935
- console.log(` Valid keys: ${CONFIG_DEFINITIONS.map((d) => d.key).join(", ")}`);
1936
- process.exit(1);
2004
+ throw new Error(
2005
+ `Unknown config key: "${key}"
2006
+ Valid keys: ${CONFIG_DEFINITIONS.map((d) => d.key).join(", ")}`
2007
+ );
1937
2008
  }
1938
2009
  await removeConfigKeys([key]);
1939
2010
  const sourceNow = process.env[def.envVar] ? "env" : "default";
@@ -1965,18 +2036,6 @@ function getRepoUrl(repo) {
1965
2036
  if (typeof repo === "string") return repo;
1966
2037
  return repo.url || "";
1967
2038
  }
1968
- async function throttledMap(items, fn, concurrency = 3) {
1969
- const results = [];
1970
- for (let i = 0; i < items.length; i += concurrency) {
1971
- const batch = items.slice(i, i + concurrency);
1972
- const batchResults = await Promise.all(batch.map((item, idx) => fn(item, i + idx)));
1973
- results.push(...batchResults);
1974
- if (i + concurrency < items.length) {
1975
- await new Promise((r) => setTimeout(r, 200));
1976
- }
1977
- }
1978
- return results;
1979
- }
1980
2039
  var MIME_TYPES = {
1981
2040
  ".html": "text/html; charset=utf-8",
1982
2041
  ".js": "application/javascript; charset=utf-8",
@@ -2298,42 +2357,8 @@ API_ROUTES.POST["/api/uninstall"] = async (req, res, _url) => {
2298
2357
  };
2299
2358
  API_ROUTES.GET["/api/admin/stats"] = async (_req, res, _url) => {
2300
2359
  try {
2301
- const packages = await fetchScopePackages();
2302
- const infos = (await Promise.all(
2303
- packages.map(async (pkg) => {
2304
- try {
2305
- const info = await fetchNpmPackage(pkg);
2306
- return info ? { name: pkg, info } : null;
2307
- } catch {
2308
- return null;
2309
- }
2310
- })
2311
- )).filter((item) => item !== null);
2312
- let totalVersions = 0;
2313
- let totalSize = 0;
2314
- const platformSet = /* @__PURE__ */ new Set();
2315
- let withMetadata = 0;
2316
- for (const { info } of infos) {
2317
- const versions = Object.keys(info.versions || {});
2318
- totalVersions += versions.length;
2319
- const latestVer = info["dist-tags"]?.latest;
2320
- const latestPkg = latestVer ? info.versions?.[latestVer] : void 0;
2321
- const meta = latestPkg?.skillmarket;
2322
- if (meta) {
2323
- withMetadata++;
2324
- if (meta.platforms) meta.platforms.forEach((p) => platformSet.add(p));
2325
- }
2326
- if (latestPkg?.dist?.unpackedSize) totalSize += latestPkg.dist.unpackedSize;
2327
- }
2328
- jsonResponse(res, 200, {
2329
- totalSkills: infos.length,
2330
- totalVersions,
2331
- averageVersions: infos.length > 0 ? (totalVersions / infos.length).toFixed(1) : "0",
2332
- withMetadata,
2333
- totalSizeMB: (totalSize / 1024 / 1024).toFixed(2),
2334
- platformCount: platformSet.size,
2335
- platforms: [...platformSet]
2336
- });
2360
+ const stats = await getPublishingStats();
2361
+ jsonResponse(res, 200, stats);
2337
2362
  } catch (err) {
2338
2363
  jsonResponse(res, 500, { error: String(err) });
2339
2364
  }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startGuiServer
4
- } from "./chunk-ARRJETWL.js";
4
+ } from "./chunk-B3B5NGC6.js";
5
5
  export {
6
6
  startGuiServer
7
7
  };
package/dist/index.js CHANGED
@@ -39,7 +39,7 @@ import {
39
39
  uninstallAll,
40
40
  uninstallSkill,
41
41
  updateSkill
42
- } from "./chunk-ARRJETWL.js";
42
+ } from "./chunk-B3B5NGC6.js";
43
43
 
44
44
  // src/cli.ts
45
45
  import { Command } from "commander";
@@ -262,9 +262,14 @@ async function syncPlatformLinks() {
262
262
  await fs.remove(platformSkillDir);
263
263
  await fs.symlink(targetPlatformDir, platformSkillDir, "junction");
264
264
  console.log(` Linked: ${platform}/${skillId}`);
265
- } catch {
266
- await fs.copy(targetPlatformDir, platformSkillDir, { overwrite: true });
267
- console.log(` Copied: ${platform}/${skillId}`);
265
+ } catch (err) {
266
+ const nodeErr = err;
267
+ if (nodeErr.code === "EPERM" || nodeErr.code === "EACCES" || nodeErr.code === "ENOTSUP") {
268
+ await fs.copy(targetPlatformDir, platformSkillDir, { overwrite: true });
269
+ console.log(` Copied: ${platform}/${skillId}`);
270
+ } else {
271
+ throw err;
272
+ }
268
273
  }
269
274
  }
270
275
  }
@@ -650,58 +655,7 @@ var packageJson = JSON.parse(readFileSync(resolve(__dirname, "../package.json"),
650
655
  var VERSION = packageJson.version || "1.3.1";
651
656
  var program = new Command();
652
657
  program.name("skm").description("SkillMarket - Cross-platform skill manager for AI coding tools").version(VERSION);
653
- program.hook("preAction", (thisCommand) => {
654
- if (thisCommand.opts().help) {
655
- console.log(`
656
- SkillMarket CLI
657
-
658
- Usage: skm <command> [options]
659
-
660
- Commands:
661
- ls [options] List available skills
662
- --installed Show only installed skills
663
- --updates Check for updates
664
- --page <n> Page number (default: 1)
665
- --limit <n> Items per page (default: 20)
666
- -s, --search Search by keyword
667
- search <keyword> Search skills from npm registry
668
- -l, --limit Max results (default: 20)
669
- info <skill> Display skill information
670
- install <skill> Install a skill from npm or GitHub
671
- @<version> Install specific version
672
- --platform Target platforms (opencode,claude,vscode,codex,...)
673
- --force Overwrite if already installed
674
- -b, --branch GitHub branch to install from
675
- -c, --commit GitHub commit to install from
676
- uninstall <skill> Remove an installed skill
677
- --platform Target platforms
678
- --all Uninstall ALL installed skills
679
- --dry-run Preview without deleting
680
- -y, --yes Skip confirmation
681
- update [skill] Update installed skills (all if no skill specified)
682
- --all Update all skills
683
- publish <skill> Publish a skill to npm
684
- -v, --version Specify version
685
- verify <skill> Verify skill integrity and format
686
- sync [skill] Synchronize platform links (or sync a skill to latest)
687
- platforms Show available platforms
688
- gui [port] Start SkillMarket GUI web interface
689
- config View and manage configuration
690
- config [ls] List all configuration values
691
- config get <key> Get a config value
692
- config set <key> <val> Set a config value
693
- config reset [key] Reset config to defaults
694
- admin Admin: manage published skills
695
- admin ls List all published skills
696
- admin info <skill> Show detailed info for a published skill
697
- admin search <keyword> Search published skills
698
- admin stats Publishing statistics
699
- admin verify <skill> Verify a published skill
700
- admin deprecate <skill> Deprecate a skill (--version, --message)
701
- admin unpublish <skill> Unpublish a skill (--version, --force)
702
- admin tag set/tag rm/tag ls Manage dist-tags
703
- admin owner add/rm Manage package maintainers
704
- admin access <skill> Set package access (public|restricted)
658
+ program.addHelpText("afterAll", `
705
659
 
706
660
  Examples:
707
661
  skm ls List available skills
@@ -736,11 +690,7 @@ Examples:
736
690
  skm config reset --all Reset all config
737
691
  skm admin ls List all published skills
738
692
  skm admin stats Publishing statistics
739
- skm admin deprecate my-skill --message "Use v2" Deprecate a skill
740
- `);
741
- process.exit(0);
742
- }
743
- });
693
+ skm admin deprecate my-skill --message "Use v2" Deprecate a skill`);
744
694
  var lsCmd = program.command("ls").description("List available skills");
745
695
  lsCmd.option("--installed", "Show only installed skills").option("--updates", "Check for updates").option("-p, --page <number>", "Page number (default: 1)", parseInt).option("-l, --limit <number>", "Items per page (default: 20)", parseInt).option("-s, --search <keyword>", "Search by keyword (id, displayName, description)").action((opts) => {
746
696
  const options = {
@@ -762,118 +712,82 @@ infoCmd.argument("<skill-id>", "Skill ID to show info").action((skillId) => {
762
712
  });
763
713
  var installCmd = program.command("install").description("Install a skill from npm or GitHub");
764
714
  installCmd.argument("<skill>", "Skill ID, npm package, or GitHub URL (owner/repo, https://github.com/owner/repo)").option("-p, --platform <platforms>", "Target platforms (comma-separated: opencode,claude,vscode)").option("-f, --force", "Overwrite if already installed").option("-v, --version <version>", "Specific version to install (npm only)").option("-b, --branch <branch>", "GitHub branch to install from").option("-c, --commit <commit>", "GitHub commit hash to install from").action(async (skill, opts) => {
765
- try {
766
- const platforms = opts.platform ? opts.platform.split(",").map((p) => p.trim()) : void 0;
767
- const githubSource = parseGitHubUrl(skill);
768
- if (githubSource) {
769
- await installFromGitHub(skill, {
770
- platforms,
771
- force: opts.force,
772
- branch: opts.branch,
773
- commit: opts.commit
774
- });
775
- } else {
776
- await installSkill(skill, opts.version, {
777
- platforms,
778
- force: opts.force
779
- });
780
- }
781
- } catch (err) {
782
- console.error("Installation failed:", err);
783
- process.exit(1);
715
+ const platforms = opts.platform ? opts.platform.split(",").map((p) => p.trim()) : void 0;
716
+ const githubSource = parseGitHubUrl(skill);
717
+ if (githubSource) {
718
+ await installFromGitHub(skill, {
719
+ platforms,
720
+ force: opts.force,
721
+ branch: opts.branch,
722
+ commit: opts.commit
723
+ });
724
+ } else {
725
+ await installSkill(skill, opts.version, {
726
+ platforms,
727
+ force: opts.force
728
+ });
784
729
  }
785
730
  });
786
731
  var uninstallCmd = program.command("uninstall").description("Remove an installed skill from local and platform directories");
787
732
  uninstallCmd.argument("[skill]", "Skill ID to uninstall (required unless using --all)").option("-p, --platform <platforms>", "Target platforms (comma-separated)").option("-a, --all", "Uninstall ALL installed skills (requires confirmation)").option("-d, --dry-run", "Preview what would be uninstalled without actually deleting").option("-y, --yes", "Skip confirmation prompts").action(async (skill, opts) => {
788
- try {
789
- const platforms = opts.platform ? opts.platform.split(",").map((p) => p.trim()) : void 0;
790
- if (opts.all) {
791
- await uninstallAll({
792
- platforms,
793
- dryRun: opts.dryRun,
794
- yes: opts.yes
795
- });
796
- return;
797
- }
798
- if (!skill) {
799
- console.error("Error: Skill ID is required (or use --all to uninstall all)");
800
- process.exit(1);
801
- }
802
- await uninstallSkill(skill, {
733
+ const platforms = opts.platform ? opts.platform.split(",").map((p) => p.trim()) : void 0;
734
+ if (opts.all) {
735
+ await uninstallAll({
803
736
  platforms,
804
737
  dryRun: opts.dryRun,
805
738
  yes: opts.yes
806
739
  });
807
- } catch (err) {
808
- console.error("Uninstall failed:", err);
809
- process.exit(1);
740
+ return;
741
+ }
742
+ if (!skill) {
743
+ throw new Error("Skill ID is required (or use --all to uninstall all)");
810
744
  }
745
+ await uninstallSkill(skill, {
746
+ platforms,
747
+ dryRun: opts.dryRun,
748
+ yes: opts.yes
749
+ });
811
750
  });
812
751
  var updateCmd = program.command("update").description("Update installed skills");
813
752
  updateCmd.argument("[skill]", "Skill ID to update (optional, updates all if not specified)").option("--all", "Update all skills").action(async (skill, opts) => {
814
- try {
815
- if (opts.all || !skill) {
816
- await updateSkill();
817
- } else {
818
- await updateSkill(skill);
819
- }
820
- } catch (err) {
821
- console.error("Update failed:", err);
822
- process.exit(1);
753
+ if (opts.all || !skill) {
754
+ await updateSkill();
755
+ } else {
756
+ await updateSkill(skill);
823
757
  }
824
758
  });
825
759
  program.command("sync [skill]").description("Synchronize platform links or sync skill to latest version").action(async (skill) => {
826
- try {
827
- if (skill) {
828
- await syncSkill(skill);
829
- } else {
830
- await syncPlatformLinks();
831
- }
832
- } catch (err) {
833
- console.error("Sync failed:", err);
834
- process.exit(1);
760
+ if (skill) {
761
+ await syncSkill(skill);
762
+ } else {
763
+ await syncPlatformLinks();
835
764
  }
836
765
  });
837
766
  var platformsCmd = program.command("platforms").description("Show available platforms");
838
767
  platformsCmd.action(async () => {
839
- try {
840
- const available = await detectPlatforms();
841
- const allAdapters = getAllAdapters();
842
- console.log("\n\u{1F4CD} Available Platforms:\n");
843
- for (const adapter of allAdapters) {
844
- const isAvailable = available.find((a) => a.id === adapter.id);
845
- const installed = await adapter.listInstalled();
846
- if (isAvailable) {
847
- console.log(`${adapter.name.padEnd(15)} \u2705 Available (${installed.length} skills installed)`);
848
- } else {
849
- console.log(`${adapter.name.padEnd(15)} \u274C Not detected`);
850
- }
768
+ const available = await detectPlatforms();
769
+ const allAdapters = getAllAdapters();
770
+ console.log("\n\u{1F4CD} Available Platforms:\n");
771
+ for (const adapter of allAdapters) {
772
+ const isAvailable = available.find((a) => a.id === adapter.id);
773
+ const installed = await adapter.listInstalled();
774
+ if (isAvailable) {
775
+ console.log(`${adapter.name.padEnd(15)} \u2705 Available (${installed.length} skills installed)`);
776
+ } else {
777
+ console.log(`${adapter.name.padEnd(15)} \u274C Not detected`);
851
778
  }
852
- console.log("");
853
- } catch (err) {
854
- console.error("Failed to list platforms:", err);
855
- process.exit(1);
856
779
  }
780
+ console.log("");
857
781
  });
858
782
  program.command("gui [port]").description("Start SkillMarket GUI (web interface)").action(async (port) => {
859
783
  const portNum = port ? parseInt(port) : 18770;
860
784
  startGuiServer(portNum);
861
785
  });
862
786
  program.command("publish <skill>").description("Publish a skill to npm").option("-v, --version <version>", "Specify version (optional, auto-increment patch if not specified)").action(async (skill, options) => {
863
- try {
864
- await publishSkill(skill, options.version ? { version: options.version } : void 0);
865
- } catch (err) {
866
- console.error("Publish failed:", err);
867
- process.exit(1);
868
- }
787
+ await publishSkill(skill, options.version ? { version: options.version } : void 0);
869
788
  });
870
789
  program.command("verify <skill>").description("Verify skill integrity and format").action(async (skill) => {
871
- try {
872
- await verifySkill(skill);
873
- } catch (err) {
874
- console.error("Verify failed:", err);
875
- process.exit(1);
876
- }
790
+ await verifySkill(skill);
877
791
  });
878
792
  var config = program.command("config").description("View and manage configuration");
879
793
  config.command("list").alias("ls").description("List all configuration values").action(async () => {
@@ -893,121 +807,56 @@ config.command("reset [key]").description("Reset configuration to default values
893
807
  });
894
808
  var admin = program.command("admin").description("Admin: manage published skills (cloud)");
895
809
  admin.command("ls").description("List all published skills").action(async () => {
896
- try {
897
- await adminList();
898
- } catch (err) {
899
- console.error("Admin ls failed:", err);
900
- process.exit(1);
901
- }
810
+ await adminList();
902
811
  });
903
812
  admin.command("info <skill>").description("Show detailed info for a published skill").action(async (skill) => {
904
- try {
905
- await adminInfo(skill);
906
- } catch (err) {
907
- console.error("Admin info failed:", err);
908
- process.exit(1);
909
- }
813
+ await adminInfo(skill);
910
814
  });
911
815
  admin.command("search <keyword>").description("Search across published skills").option("-l, --limit <number>", "Max results (default: 20)", parseInt).action(async (keyword, opts) => {
912
- try {
913
- await adminSearch(keyword, opts.limit ?? 20);
914
- } catch (err) {
915
- console.error("Admin search failed:", err);
916
- process.exit(1);
917
- }
816
+ await adminSearch(keyword, opts.limit ?? 20);
918
817
  });
919
818
  admin.command("stats").description("Show publishing statistics").action(async () => {
920
- try {
921
- await adminStats();
922
- } catch (err) {
923
- console.error("Admin stats failed:", err);
924
- process.exit(1);
925
- }
819
+ await adminStats();
926
820
  });
927
821
  admin.command("verify <skill>").description("Verify a published skill structure and metadata").action(async (skill) => {
928
- try {
929
- await adminVerify(skill);
930
- } catch (err) {
931
- console.error("Admin verify failed:", err);
932
- process.exit(1);
933
- }
822
+ await adminVerify(skill);
934
823
  });
935
824
  admin.command("deprecate <skill>").description("Deprecate a published skill (or specific version)").option("-v, --version <version>", "Deprecate a specific version only").option("-m, --message <message>", "Deprecation message").action(async (skill, opts) => {
936
- try {
937
- await adminDeprecate(skill, {
938
- version: opts.version,
939
- message: opts.message
940
- });
941
- } catch (err) {
942
- console.error("Admin deprecate failed:", err);
943
- process.exit(1);
944
- }
825
+ await adminDeprecate(skill, {
826
+ version: opts.version,
827
+ message: opts.message
828
+ });
945
829
  });
946
830
  admin.command("unpublish <skill>").description("Unpublish a skill (or specific version) from npm").option("-v, --version <version>", "Unpublish a specific version only").option("-f, --force", "Force unpublish entire package").action(async (skill, opts) => {
947
- try {
948
- await adminUnpublish(skill, {
949
- version: opts.version,
950
- force: opts.force
951
- });
952
- } catch (err) {
953
- console.error("Admin unpublish failed:", err);
954
- process.exit(1);
955
- }
831
+ await adminUnpublish(skill, {
832
+ version: opts.version,
833
+ force: opts.force
834
+ });
956
835
  });
957
836
  var adminTag = admin.command("tag").description("Manage dist-tags for a skill");
958
837
  adminTag.command("set <skill> <tag> <version>").description("Set a dist-tag for a specific version").action(async (skill, tag, version) => {
959
- try {
960
- await adminTagSet(skill, tag, version);
961
- } catch (err) {
962
- console.error("Admin tag set failed:", err);
963
- process.exit(1);
964
- }
838
+ await adminTagSet(skill, tag, version);
965
839
  });
966
840
  adminTag.command("rm <skill> <tag>").description("Remove a dist-tag").action(async (skill, tag) => {
967
- try {
968
- await adminTagRemove(skill, tag);
969
- } catch (err) {
970
- console.error("Admin tag rm failed:", err);
971
- process.exit(1);
972
- }
841
+ await adminTagRemove(skill, tag);
973
842
  });
974
843
  adminTag.command("ls <skill>").description("List all dist-tags for a skill").action(async (skill) => {
975
- try {
976
- await adminTagList(skill);
977
- } catch (err) {
978
- console.error("Admin tag ls failed:", err);
979
- process.exit(1);
980
- }
844
+ await adminTagList(skill);
981
845
  });
982
846
  var adminOwner = admin.command("owner").description("Manage package owners/maintainers");
983
847
  adminOwner.command("add <skill> <user>").description("Add an owner to a skill package").action(async (skill, user) => {
984
- try {
985
- await adminOwnerAdd(skill, user);
986
- } catch (err) {
987
- console.error("Admin owner add failed:", err);
988
- process.exit(1);
989
- }
848
+ await adminOwnerAdd(skill, user);
990
849
  });
991
850
  adminOwner.command("rm <skill> <user>").description("Remove an owner from a skill package").action(async (skill, user) => {
992
- try {
993
- await adminOwnerRemove(skill, user);
994
- } catch (err) {
995
- console.error("Admin owner rm failed:", err);
996
- process.exit(1);
997
- }
851
+ await adminOwnerRemove(skill, user);
998
852
  });
999
853
  admin.command("access <skill> <level>").description("Set package access (public|restricted)").action(async (skill, level) => {
1000
- try {
1001
- if (level !== "public" && level !== "restricted") {
1002
- console.error('\u274C Access level must be "public" or "restricted"');
1003
- process.exit(1);
1004
- }
1005
- await adminAccess(skill, level);
1006
- } catch (err) {
1007
- console.error("Admin access failed:", err);
1008
- process.exit(1);
854
+ if (level !== "public" && level !== "restricted") {
855
+ throw new Error('Access level must be "public" or "restricted"');
1009
856
  }
857
+ await adminAccess(skill, level);
1010
858
  });
859
+ program.exitOverride();
1011
860
  var hasArgs = process.argv.slice(2).length > 0;
1012
861
  if (!hasArgs) {
1013
862
  const port = 18770;
@@ -1019,5 +868,10 @@ if (!hasArgs) {
1019
868
  }, 1500);
1020
869
  startGuiServer(port);
1021
870
  } else {
1022
- program.parse();
871
+ try {
872
+ await program.parseAsync();
873
+ } catch (err) {
874
+ console.error(err instanceof Error ? err.message : String(err));
875
+ process.exit(1);
876
+ }
1023
877
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "itismyskillmarket",
3
- "version": "1.3.46",
3
+ "version": "1.3.48",
4
4
  "description": "Cross-platform skill manager for AI coding tools",
5
5
  "type": "module",
6
6
  "bin": {