itismyskillmarket 1.2.8 → 1.2.10

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.
Files changed (46) hide show
  1. package/README.md +6 -75
  2. package/dist/index.js +186 -536
  3. package/package.json +6 -1
  4. package/src/cli.ts +49 -128
  5. package/src/commands/info.ts +15 -4
  6. package/src/commands/install.ts +54 -93
  7. package/src/commands/ls.ts +17 -129
  8. package/src/commands/npm.ts +13 -97
  9. package/src/commands/sync.ts +27 -6
  10. package/src/commands/uninstall.ts +7 -60
  11. package/src/commands/update.ts +2 -2
  12. package/src/index.ts +0 -27
  13. package/src/types.ts +0 -35
  14. package/.github/workflows/publish-npm.yml +0 -54
  15. package/.github/workflows/publish-skill.yml +0 -72
  16. package/5e51cb7aa8b8e60d49d86f4689f5d4d1.png +0 -0
  17. package/CHANGELOG.md +0 -255
  18. package/DEVELOPMENT.md +0 -376
  19. package/SKILLMARKET-GUIDE.md +0 -288
  20. package/docs/plans/2026-04-01-skillmarket-design.md +0 -267
  21. package/docs/plans/2026-04-01-skillmarket-implementation.md +0 -1031
  22. package/docs/plans/2026-04-15-cross-platform-adapter-design.md +0 -416
  23. package/docs/plans/2026-04-15-cross-platform-adapter-plan.md +0 -833
  24. package/docs/plans/2026-04-16-keyword-search-design.md +0 -143
  25. package/skills/README.md +0 -54
  26. package/skills/test-skill/SKILL.md +0 -25
  27. package/skills/test-skill/index.js +0 -66
  28. package/skills/test-skill/metadata.json +0 -9
  29. package/skills/test-skill/package.json +0 -19
  30. package/skills/test-skill-1/SKILL.md +0 -24
  31. package/skills/test-skill-1/index.js +0 -13
  32. package/skills/test-skill-1/metadata.json +0 -9
  33. package/skills/test-skill-1/package.json +0 -16
  34. package/skills/test-skill-2/SKILL.md +0 -25
  35. package/skills/test-skill-2/index.js +0 -13
  36. package/skills/test-skill-2/metadata.json +0 -9
  37. package/skills/test-skill-2/package.json +0 -16
  38. package/src/adapters/base.ts +0 -87
  39. package/src/adapters/claude.ts +0 -31
  40. package/src/adapters/index.ts +0 -9
  41. package/src/adapters/opencode.ts +0 -40
  42. package/src/adapters/registry.ts +0 -77
  43. package/src/adapters/vscode.ts +0 -62
  44. package/tsconfig.json +0 -10
  45. package/tsup.config.ts +0 -22
  46. package/wanxuchen-skillmarket-1.0.1.tgz +0 -0
package/dist/index.js CHANGED
@@ -2,17 +2,6 @@
2
2
 
3
3
  // src/cli.ts
4
4
  import { Command } from "commander";
5
- import { readFileSync } from "fs";
6
- import { fileURLToPath } from "url";
7
- import { dirname, resolve } from "path";
8
-
9
- // src/commands/registry.ts
10
- import fs2 from "fs-extra";
11
-
12
- // src/utils/dirs.ts
13
- import os from "os";
14
- import path from "path";
15
- import fs from "fs-extra";
16
5
 
17
6
  // src/constants.ts
18
7
  var MARKET_DIR = "skillmarket";
@@ -41,7 +30,13 @@ var PLATFORMS = [
41
30
  var REGISTRY_FILE = "registry.json";
42
31
  var LATEST_LINK = "latest";
43
32
 
33
+ // src/commands/registry.ts
34
+ import fs2 from "fs-extra";
35
+
44
36
  // src/utils/dirs.ts
37
+ import os from "os";
38
+ import path from "path";
39
+ import fs from "fs-extra";
45
40
  function getMarketHome() {
46
41
  return path.join(os.homedir(), MARKET_DIR);
47
42
  }
@@ -100,7 +95,7 @@ async function isSkillInstalled(skillId) {
100
95
  import https from "https";
101
96
  import { URL } from "url";
102
97
  async function fetchNpmPackage(packageName) {
103
- return new Promise((resolve2, reject) => {
98
+ return new Promise((resolve, reject) => {
104
99
  const isScoped = packageName.startsWith("@");
105
100
  let encodedName;
106
101
  if (isScoped) {
@@ -126,12 +121,12 @@ async function fetchNpmPackage(packageName) {
126
121
  try {
127
122
  const parsed = JSON.parse(data);
128
123
  if (parsed.error) {
129
- resolve2(null);
124
+ resolve(null);
130
125
  return;
131
126
  }
132
- resolve2(parsed);
127
+ resolve(parsed);
133
128
  } catch {
134
- resolve2(null);
129
+ resolve(null);
135
130
  }
136
131
  });
137
132
  });
@@ -142,50 +137,12 @@ async function fetchNpmPackage(packageName) {
142
137
  });
143
138
  });
144
139
  }
145
- var SKILL_SCOPES = [
146
- "@wanxuchen",
147
- // 原作者 scope
148
- "@itismyskillmarket",
149
- // 当前包名 scope
150
- "@thisisskillmarket",
151
- // 曾用 scope
152
- "@this-is-skillmarket",
153
- // 曾用 scope (带横线)
154
- "@skillmarket"
155
- // 通用 scope
156
- ];
157
- function getPossiblePackageNames(skillId) {
158
- if (skillId.startsWith("@")) {
159
- return [skillId];
160
- }
161
- return SKILL_SCOPES.map((scope) => `${scope}/${skillId}`);
162
- }
163
- async function fetchSkillPackage(skillId) {
164
- const packageNames = getPossiblePackageNames(skillId);
165
- for (const packageName of packageNames) {
166
- try {
167
- const info = await fetchNpmPackage(packageName);
168
- if (info) {
169
- return info;
170
- }
171
- } catch {
172
- }
173
- }
174
- return null;
175
- }
176
- async function searchSkillmarketPackages(options = {}) {
177
- const { from = 0, size = 100, keyword } = options;
140
+ async function searchSkillmarketPackages() {
178
141
  const packages = [];
179
- let total = 0;
180
- return new Promise((resolve2, reject) => {
142
+ return new Promise((resolve, reject) => {
181
143
  const url = new URL("https://registry.npmjs.org/-/v1/search");
182
- if (keyword) {
183
- url.searchParams.set("text", `${keyword} keywords:skillmarket`);
184
- } else {
185
- url.searchParams.set("text", "keywords:skillmarket");
186
- }
187
- url.searchParams.set("size", String(size));
188
- url.searchParams.set("from", String(from));
144
+ url.searchParams.set("text", "keywords:skillmarket");
145
+ url.searchParams.set("size", "100");
189
146
  const req = https.get(url.toString(), { timeout: 1e4 }, (res) => {
190
147
  let data = "";
191
148
  res.on("data", (chunk) => {
@@ -194,17 +151,14 @@ async function searchSkillmarketPackages(options = {}) {
194
151
  res.on("end", () => {
195
152
  try {
196
153
  const result = JSON.parse(data);
197
- total = result.total || 0;
198
- if (result.objects) {
199
- for (const item of result.objects) {
200
- if (item?.package?.name) {
201
- packages.push(item.package.name);
202
- }
154
+ for (const item of result.objects || []) {
155
+ if (item?.package?.name) {
156
+ packages.push(item.package.name);
203
157
  }
204
158
  }
205
- resolve2({ packages, total });
159
+ resolve(packages);
206
160
  } catch {
207
- resolve2({ packages: [], total: 0 });
161
+ resolve([]);
208
162
  }
209
163
  });
210
164
  });
@@ -217,105 +171,42 @@ async function searchSkillmarketPackages(options = {}) {
217
171
  }
218
172
 
219
173
  // src/commands/ls.ts
220
- function filterInstalledSkills(skills, keyword) {
221
- const lower = keyword.toLowerCase();
222
- return skills.filter(
223
- (s) => s.id.toLowerCase().includes(lower) || s.displayName && s.displayName.toLowerCase().includes(lower) || s.description && s.description.toLowerCase().includes(lower)
224
- );
225
- }
226
174
  async function listSkills(options) {
227
- const { installed, updates, page = 1, limit = 20, search } = options;
175
+ const { installed, updates } = options;
228
176
  if (installed) {
229
- let skills = await getInstalledSkills();
230
- if (search) {
231
- skills = filterInstalledSkills(skills, search);
232
- }
233
- const total = skills.length;
234
- const totalPages = Math.ceil(total / limit) || 1;
235
- const currentPage = Math.min(Math.max(1, page), totalPages);
177
+ const skills = await getInstalledSkills();
236
178
  if (skills.length === 0) {
237
- if (search) {
238
- console.log(`No skills found matching "${search}".`);
239
- } else {
240
- console.log('No skills installed yet. Run "skm ls" to see available skills.');
241
- }
179
+ console.log('No skills installed yet. Run "skm --ls" to see available skills.');
242
180
  return;
243
181
  }
244
- if (search) {
245
- console.log(`Found ${total} match(es) for "${search}":
246
- `);
247
- } else {
248
- console.log(`Installed Skills (${total}):
249
- `);
250
- }
251
- const start = (currentPage - 1) * limit;
252
- const end = Math.min(start + limit, total);
253
- const pageSkills = skills.slice(start, end);
254
- for (const skill of pageSkills) {
182
+ console.log("Installed Skills:\n");
183
+ for (const skill of skills) {
255
184
  console.log(` ${skill.id}@${skill.version}`);
256
185
  console.log(` Platforms: ${skill.platforms.join(", ")}`);
257
186
  console.log(` Installed: ${skill.installedAt}`);
258
187
  console.log();
259
188
  }
260
- console.log(`Page ${currentPage}/${totalPages} (${limit} per page) | Use --page N to navigate`);
261
189
  return;
262
190
  }
263
- if (search) {
264
- console.log(`Searching npm for "${search}"...
265
- `);
266
- } else {
267
- console.log("Searching npm registry...\n");
268
- }
191
+ console.log("Searching npm registry...\n");
269
192
  try {
270
- const offset = (page - 1) * limit;
271
- const { packages, total } = await searchSkillmarketPackages({
272
- from: offset,
273
- size: limit,
274
- keyword: search
275
- });
276
- const totalPages = Math.ceil(total / limit) || 1;
277
- const currentPage = Math.min(Math.max(1, page), totalPages);
193
+ const packages = await searchSkillmarketPackages();
278
194
  if (packages.length === 0) {
279
- if (search) {
280
- console.log(`No skills found matching "${search}".`);
281
- } else {
282
- console.log("No skills found. Check back later!");
283
- }
195
+ console.log("No skills found. Check back later!");
284
196
  return;
285
197
  }
286
- if (search) {
287
- console.log(`Found ${total} match(es) for "${search}":
198
+ console.log(`Found ${packages.length} skill(s):
288
199
  `);
289
- } else {
290
- console.log(`Found ${total} skill(s):
291
- `);
292
- }
293
200
  for (const pkgName of packages) {
294
- try {
295
- const info = await fetchNpmPackage(pkgName);
296
- if (!info) {
297
- console.log(`\u{1F4E6} ${pkgName} (\u4FE1\u606F\u83B7\u53D6\u5931\u8D25)`);
298
- console.log();
299
- continue;
300
- }
301
- const latestVersion = info["dist-tags"]?.latest || "unknown";
201
+ const info = await fetchNpmPackage(pkgName);
202
+ if (info && info["dist-tags"]?.latest) {
203
+ const latestVersion = info["dist-tags"].latest;
302
204
  const pkg = info.versions?.[latestVersion];
303
- const skillMeta = pkg?.skillmarket;
304
- console.log(`\u{1F4E6} ${info.name}@${latestVersion}`);
305
- const displayName = skillMeta?.displayName || info.name;
306
- console.log(` \u540D\u79F0: ${displayName}`);
307
- console.log(` \u63CF\u8FF0: ${pkg?.description || "N/A"}`);
308
- const platforms = skillMeta?.platforms || [];
309
- console.log(` \u5E73\u53F0: ${platforms.length > 0 ? platforms.join(", ") : "N/A"}`);
310
- const npmLink = pkg?.links?.npm || `https://www.npmjs.com/package/${info.name}`;
311
- console.log(` \u94FE\u63A5: ${npmLink}`);
312
- console.log();
313
- } catch (e) {
314
- console.log(`\u{1F4E6} ${pkgName} (\u83B7\u53D6\u5931\u8D25: ${e})`);
205
+ console.log(` ${info.name}@${latestVersion}`);
206
+ console.log(` ${pkg?.description || "No description"}`);
315
207
  console.log();
316
208
  }
317
209
  }
318
- console.log(`Page ${currentPage}/${totalPages} (${limit} per page) | Use --page N to navigate`);
319
210
  } catch (error) {
320
211
  console.log(`Error fetching skills: ${error}`);
321
212
  }
@@ -323,10 +214,11 @@ async function listSkills(options) {
323
214
 
324
215
  // src/commands/info.ts
325
216
  async function showSkillInfo(skillId) {
326
- console.log(`Fetching info for: ${skillId}
217
+ const packageName = skillId.startsWith("@") ? skillId : `@skillmarket/${skillId}`;
218
+ console.log(`Fetching info for: ${packageName}
327
219
  `);
328
220
  try {
329
- const info = await fetchSkillPackage(skillId);
221
+ const info = await fetchNpmPackage(packageName);
330
222
  if (!info) {
331
223
  console.log(`Skill "${skillId}" not found in npm registry.`);
332
224
  return;
@@ -366,344 +258,174 @@ Status: Not installed (use skm install ${skillId} to install)`);
366
258
  }
367
259
 
368
260
  // src/commands/install.ts
369
- import fs7 from "fs-extra";
370
- import path6 from "path";
261
+ import fs4 from "fs-extra";
262
+ import path3 from "path";
371
263
  import { exec } from "child_process";
372
264
  import { promisify } from "util";
373
265
 
374
- // src/adapters/base.ts
266
+ // src/utils/platform.ts
267
+ function detectPlatform() {
268
+ if (process.env.OPENCODE) return "opencode";
269
+ if (process.env.CURSOR) return "cursor";
270
+ if (process.env.VSCODE) return "vscode";
271
+ if (process.env.CLAUDE_CODE) return "claude";
272
+ if (process.env.ANTIGRAVITY) return "antigravity";
273
+ return "codex";
274
+ }
275
+ function isValidPlatform(name) {
276
+ return PLATFORMS.includes(name);
277
+ }
278
+ function getPlatformFromInput(name) {
279
+ const lowerName = name.toLowerCase();
280
+ if (isValidPlatform(lowerName)) {
281
+ return lowerName;
282
+ }
283
+ return null;
284
+ }
285
+
286
+ // src/commands/sync.ts
375
287
  import fs3 from "fs-extra";
376
288
  import path2 from "path";
377
- var BaseAdapter = class {
378
- /**
379
- * Get the path where a specific skill should be installed
380
- */
381
- getSkillPath(skillId) {
382
- return path2.join(this.skillDir, skillId);
383
- }
384
- /**
385
- * Get the path to the SKILL.md file for a skill
386
- */
387
- getSkillFilePath(skillId) {
388
- return path2.join(this.getSkillPath(skillId), "SKILL.md");
389
- }
390
- async isAvailable() {
391
- try {
392
- await fs3.ensureDir(this.skillDir);
393
- return true;
394
- } catch {
395
- return false;
396
- }
397
- }
398
- async isInstalled(skillId) {
399
- const skillFile = this.getSkillFilePath(skillId);
400
- return fs3.pathExists(skillFile);
401
- }
402
- async install(skillId, sourceDir) {
403
- const targetDir = this.getSkillPath(skillId);
404
- const targetFile = this.getSkillFilePath(skillId);
405
- await fs3.ensureDir(targetDir);
406
- const sourceFile = path2.join(sourceDir, "SKILL.md");
407
- if (!await fs3.pathExists(sourceFile)) {
408
- throw new Error(`SKILL.md not found in ${sourceDir}`);
409
- }
410
- await fs3.copy(sourceFile, targetFile, { overwrite: true });
411
- }
412
- async uninstall(skillId) {
413
- const targetDir = this.getSkillPath(skillId);
414
- if (await fs3.pathExists(targetDir)) {
415
- await fs3.remove(targetDir);
289
+ async function syncPlatformLinks(targetPlatform) {
290
+ await ensureMarketDirs();
291
+ const skillsDir = getSkillsDir();
292
+ const platformLinksDir = getPlatformLinksDir();
293
+ const registry = await loadRegistry();
294
+ let platformsToSync;
295
+ if (targetPlatform) {
296
+ const parsed = getPlatformFromInput(targetPlatform);
297
+ if (!parsed) {
298
+ console.warn(`Invalid platform: ${targetPlatform}, syncing all platforms`);
299
+ platformsToSync = PLATFORMS;
300
+ } else {
301
+ platformsToSync = [parsed];
416
302
  }
303
+ } else {
304
+ platformsToSync = PLATFORMS;
417
305
  }
418
- async listInstalled() {
419
- if (!await fs3.pathExists(this.skillDir)) {
420
- return [];
421
- }
422
- const entries = await fs3.readdir(this.skillDir, { withFileTypes: true });
423
- const skills = [];
424
- for (const entry of entries) {
425
- if (entry.isDirectory()) {
426
- const skillFile = path2.join(this.skillDir, entry.name, "SKILL.md");
427
- if (await fs3.pathExists(skillFile)) {
428
- skills.push(entry.name);
306
+ const targetDesc = targetPlatform ? targetPlatform : "all platforms";
307
+ console.log(`Syncing platform links to ${targetDesc}...
308
+ `);
309
+ for (const platform of platformsToSync) {
310
+ const platformDir = path2.join(platformLinksDir, platform, "skills");
311
+ await fs3.ensureDir(platformDir);
312
+ for (const [skillId, skillInfo] of Object.entries(registry.skills)) {
313
+ const skillLatestLink = path2.join(skillsDir, skillId, LATEST_LINK);
314
+ const targetPlatformDir = path2.join(skillLatestLink, platform);
315
+ const platformSkillDir = path2.join(platformDir, skillId);
316
+ if (await fs3.pathExists(skillLatestLink)) {
317
+ if (await fs3.pathExists(targetPlatformDir)) {
318
+ try {
319
+ await fs3.remove(platformSkillDir);
320
+ await fs3.symlink(targetPlatformDir, platformSkillDir, "junction");
321
+ console.log(` Linked: ${platform}/${skillId}`);
322
+ } catch {
323
+ await fs3.copy(targetPlatformDir, platformSkillDir, { overwrite: true });
324
+ console.log(` Copied: ${platform}/${skillId}`);
325
+ }
429
326
  }
430
327
  }
431
328
  }
432
- return skills;
433
329
  }
434
- };
435
-
436
- // src/adapters/opencode.ts
437
- import path3 from "path";
438
- import os2 from "os";
439
- import fs4 from "fs-extra";
440
- var OpenCodeAdapter = class extends BaseAdapter {
441
- id = "opencode";
442
- name = "OpenCode";
443
- get skillDir() {
444
- const configDir = process.env.OPENCODE_CONFIG_DIR || path3.join(os2.homedir(), ".config", "opencode");
445
- return path3.join(configDir, "skills");
446
- }
447
- async isAvailable() {
448
- if (process.env.OPENCODE) return true;
449
- const configDir = process.env.OPENCODE_CONFIG_DIR || path3.join(os2.homedir(), ".config", "opencode");
450
- try {
451
- await fs4.ensureDir(path3.join(configDir, "skills"));
452
- return true;
453
- } catch {
454
- return false;
455
- }
456
- }
457
- };
458
-
459
- // src/adapters/claude.ts
460
- import path4 from "path";
461
- import os3 from "os";
462
- import fs5 from "fs-extra";
463
- var ClaudeAdapter = class extends BaseAdapter {
464
- id = "claude";
465
- name = "Claude Code";
466
- get skillDir() {
467
- return path4.join(os3.homedir(), ".claude", "skills");
468
- }
469
- async isAvailable() {
470
- if (process.env.CLAUDE_CODE) return true;
471
- const claudeDir = path4.join(os3.homedir(), ".claude");
472
- return fs5.pathExists(claudeDir);
473
- }
474
- };
475
-
476
- // src/adapters/vscode.ts
477
- import path5 from "path";
478
- import os4 from "os";
479
- import fs6 from "fs-extra";
480
- var VSCodeAdapter = class extends BaseAdapter {
481
- id = "vscode";
482
- name = "VSCode";
483
- get skillDir() {
484
- return path5.join(os4.homedir(), ".copilot", "skills");
485
- }
486
- async isAvailable() {
487
- const possibleDirs = [
488
- path5.join(os4.homedir(), ".copilot", "skills"),
489
- path5.join(os4.homedir(), ".claude", "skills")
490
- ];
491
- for (const dir of possibleDirs) {
492
- try {
493
- await fs6.ensureDir(dir);
494
- return true;
495
- } catch {
496
- continue;
497
- }
498
- }
499
- return false;
500
- }
501
- async install(skillId, sourceDir) {
502
- await super.install(skillId, sourceDir);
503
- const claudeSkillDir = path5.join(os4.homedir(), ".claude", "skills");
504
- const targetPath = this.getSkillPath(skillId);
505
- const claudeTargetPath = path5.join(claudeSkillDir, skillId);
506
- try {
507
- await fs6.ensureDir(claudeSkillDir);
508
- await fs6.remove(claudeTargetPath);
509
- await fs6.symlink(targetPath, claudeTargetPath, "junction");
510
- } catch {
511
- }
512
- }
513
- };
514
-
515
- // src/adapters/registry.ts
516
- var adapters = /* @__PURE__ */ new Map();
517
- function registerAdapters() {
518
- const opencode = new OpenCodeAdapter();
519
- const claude = new ClaudeAdapter();
520
- const vscode = new VSCodeAdapter();
521
- adapters.set(opencode.id, opencode);
522
- adapters.set(claude.id, claude);
523
- adapters.set(vscode.id, vscode);
524
- }
525
- registerAdapters();
526
- async function detectPlatforms() {
527
- const available = [];
528
- for (const adapter of adapters.values()) {
529
- if (await adapter.isAvailable()) {
530
- available.push(adapter);
531
- }
532
- }
533
- return available;
534
- }
535
- function getAdapterByPlatform(platform) {
536
- const idMap = {
537
- opencode: "opencode",
538
- claude: "claude",
539
- vscode: "vscode",
540
- cursor: "opencode",
541
- // Cursor uses OpenCode-compatible structure
542
- codex: "opencode",
543
- // Codex uses OpenCode-compatible structure
544
- antigravity: "opencode"
545
- // Antigravity uses OpenCode-compatible structure
546
- };
547
- return adapters.get(idMap[platform]);
330
+ console.log("\n\u2705 Sync complete!");
548
331
  }
549
332
 
550
333
  // src/commands/install.ts
551
334
  var execAsync = promisify(exec);
552
- async function installSkill(skillId, version, options) {
335
+ async function installSkill(skillId, version, targetPlatform) {
553
336
  await ensureMarketDirs();
554
- console.log(`Installing ${skillId}${version ? `@${version}` : ""}...`);
555
- const pkgInfo = await fetchSkillPackage(skillId);
337
+ const isScoped = skillId.startsWith("@");
338
+ const packageName = isScoped ? skillId : `@skillmarket/${skillId}`;
339
+ const shortName = skillId;
340
+ console.log(`Installing ${packageName}${version ? `@${version}` : ""}...`);
341
+ const pkgInfo = await fetchNpmPackage(packageName);
556
342
  if (!pkgInfo) {
557
- throw new Error(`Package ${skillId} not found`);
343
+ throw new Error(`Package ${packageName} not found`);
558
344
  }
559
- const packageName = pkgInfo.name;
560
345
  const targetVersion = version || pkgInfo["dist-tags"]?.latest;
561
346
  if (!targetVersion) {
562
347
  throw new Error(`No version found for ${packageName}`);
563
348
  }
564
349
  const cacheDir = getCacheDir();
565
- const targetDir = path6.join(cacheDir, `${packageName}@${targetVersion}`);
566
- if (!await fs7.pathExists(targetDir)) {
350
+ const targetDir = path3.join(cacheDir, `${packageName}@${targetVersion}`);
351
+ if (!await fs4.pathExists(targetDir)) {
567
352
  console.log("Downloading package...");
568
- await fs7.ensureDir(cacheDir);
353
+ await fs4.ensureDir(cacheDir);
569
354
  try {
570
355
  await execAsync(`npm pack ${packageName}@${targetVersion} --pack-destination ${cacheDir}`);
571
- const files = await fs7.readdir(cacheDir);
356
+ const files = await fs4.readdir(cacheDir);
572
357
  const tarball = files.find(
573
- (f) => f.endsWith(".tgz") && f.includes(packageName.replace(/^@/, "").replace("/", "-"))
358
+ (f) => f.endsWith(".tgz") && f.includes(packageName.replace("/", "-"))
574
359
  );
575
360
  if (tarball) {
576
- await execAsync(`tar -xzf "${path6.join(cacheDir, tarball)}" -C "${cacheDir}"`);
577
- await fs7.remove(path6.join(cacheDir, tarball));
578
- const extractedDir = path6.join(cacheDir, "package");
361
+ await execAsync(`tar -xzf "${path3.join(cacheDir, tarball)}" -C "${cacheDir}"`);
362
+ await fs4.remove(path3.join(cacheDir, tarball));
363
+ const extractedDir = path3.join(cacheDir, "package");
579
364
  const finalDir = targetDir;
580
- await fs7.move(extractedDir, finalDir, { overwrite: true });
365
+ await fs4.move(extractedDir, finalDir, { overwrite: true });
581
366
  }
582
367
  } catch (err) {
583
368
  throw new Error(`Failed to download package: ${err}`);
584
369
  }
585
370
  }
586
371
  const skillsDir = getSkillsDir();
587
- const skillVersionDir = path6.join(skillsDir, `${skillId}@${targetVersion}`);
372
+ const skillVersionDir = path3.join(skillsDir, `${skillId}@${targetVersion}`);
588
373
  console.log("Setting up skill...");
589
- await fs7.ensureDir(skillVersionDir);
374
+ await fs4.ensureDir(skillVersionDir);
590
375
  const pkgRoot = targetDir;
591
- if (await fs7.pathExists(path6.join(pkgRoot, "SKILL.md"))) {
592
- await fs7.copy(
593
- path6.join(pkgRoot, "SKILL.md"),
594
- path6.join(skillVersionDir, "SKILL.md")
376
+ if (await fs4.pathExists(path3.join(pkgRoot, "SKILL.md"))) {
377
+ await fs4.copy(
378
+ path3.join(pkgRoot, "SKILL.md"),
379
+ path3.join(skillVersionDir, "SKILL.md")
595
380
  );
596
381
  }
597
- if (await fs7.pathExists(path6.join(pkgRoot, "metadata.json"))) {
598
- await fs7.copy(
599
- path6.join(pkgRoot, "metadata.json"),
600
- path6.join(skillVersionDir, "metadata.json")
382
+ if (await fs4.pathExists(path3.join(pkgRoot, "metadata.json"))) {
383
+ await fs4.copy(
384
+ path3.join(pkgRoot, "metadata.json"),
385
+ path3.join(skillVersionDir, "metadata.json")
601
386
  );
602
387
  }
603
- const skillDir = path6.join(skillsDir, skillId);
604
- await fs7.ensureDir(skillDir);
605
- const latestLink = path6.join(skillDir, LATEST_LINK);
388
+ const skillDir = path3.join(skillsDir, skillId);
389
+ await fs4.ensureDir(skillDir);
390
+ const latestLink = path3.join(skillDir, LATEST_LINK);
606
391
  try {
607
- await fs7.remove(latestLink);
608
- await fs7.symlink(skillVersionDir, latestLink, "junction");
392
+ await fs4.remove(latestLink);
393
+ await fs4.symlink(skillVersionDir, latestLink, "junction");
609
394
  } catch {
610
- await fs7.copy(skillVersionDir, path6.join(skillDir, LATEST_LINK), { overwrite: true });
395
+ await fs4.copy(skillVersionDir, path3.join(skillDir, LATEST_LINK), { overwrite: true });
611
396
  }
612
- let targetAdapters = [];
613
- if (options?.platforms && options.platforms.length > 0) {
614
- for (const platformStr of options.platforms) {
615
- const platform = platformStr;
616
- const adapter = getAdapterByPlatform(platform);
617
- if (adapter) {
618
- targetAdapters.push(adapter);
619
- } else {
620
- console.warn(`\u26A0\uFE0F Unknown platform: ${platformStr}`);
621
- }
397
+ let finalPlatform;
398
+ if (targetPlatform) {
399
+ const parsed = getPlatformFromInput(targetPlatform);
400
+ if (!parsed) {
401
+ throw new Error(`Invalid platform: ${targetPlatform}. Valid platforms: ${PLATFORMS.join(", ")}`);
622
402
  }
403
+ finalPlatform = parsed;
623
404
  } else {
624
- targetAdapters = await detectPlatforms();
625
- }
626
- if (targetAdapters.length === 0) {
627
- console.log("No target platforms detected.");
628
- console.log("Use --platform to specify platforms manually.");
629
- } else {
630
- console.log(`
631
- Installing to ${targetAdapters.length} platform(s)...
632
- `);
633
- const results = [];
634
- for (const adapter of targetAdapters) {
635
- try {
636
- const isInstalled = await adapter.isInstalled(skillId);
637
- if (isInstalled && !options?.force) {
638
- console.log(`${adapter.name.padEnd(12)} \u26A0\uFE0F Already installed (use --force to overwrite)`);
639
- results.push({ name: adapter.name, status: "skipped" });
640
- continue;
641
- }
642
- await adapter.install(skillId, skillVersionDir);
643
- console.log(`${adapter.name.padEnd(12)} \u2705 Installed successfully`);
644
- results.push({ name: adapter.name, status: "installed" });
645
- } catch (error) {
646
- console.log(`${adapter.name.padEnd(12)} \u274C Failed: ${error}`);
647
- results.push({ name: adapter.name, status: "failed", error: String(error) });
648
- }
649
- }
650
- const installed = results.filter((r) => r.status === "installed").length;
651
- const skipped = results.filter((r) => r.status === "skipped").length;
652
- const failed = results.filter((r) => r.status === "failed").length;
653
- console.log(`
654
- \u{1F4CA} Summary: ${installed} installed, ${skipped} skipped, ${failed} failed`);
405
+ finalPlatform = detectPlatform();
655
406
  }
407
+ console.log(`Target platform: ${finalPlatform}`);
656
408
  const registry = await loadRegistry();
657
- const installedPlatforms = targetAdapters.map((a) => a.id);
409
+ const existingSkill = registry.skills[skillId];
410
+ const existingPlatforms = existingSkill?.platforms || [];
658
411
  registry.skills[skillId] = {
659
412
  id: skillId,
660
413
  version: targetVersion,
661
414
  installedAt: (/* @__PURE__ */ new Date()).toISOString(),
662
- platforms: installedPlatforms
415
+ platforms: existingPlatforms.includes(finalPlatform) ? existingPlatforms : [...existingPlatforms, finalPlatform]
663
416
  };
664
417
  await saveRegistry(registry);
418
+ console.log(`Syncing to ${finalPlatform}...`);
419
+ await syncPlatformLinks(finalPlatform);
665
420
  console.log(`
666
421
  \u2705 ${skillId}@${targetVersion} installed successfully!`);
667
422
  console.log(` Use "skm info ${skillId}" for more details`);
668
423
  }
669
424
 
670
- // src/commands/sync.ts
671
- import fs8 from "fs-extra";
672
- import path7 from "path";
673
- async function syncPlatformLinks() {
674
- await ensureMarketDirs();
675
- const skillsDir = getSkillsDir();
676
- const platformLinksDir = getPlatformLinksDir();
677
- const registry = await loadRegistry();
678
- console.log("Syncing platform links...\n");
679
- for (const platform of PLATFORMS) {
680
- const platformDir = path7.join(platformLinksDir, platform, "skills");
681
- await fs8.ensureDir(platformDir);
682
- for (const [skillId, skillInfo] of Object.entries(registry.skills)) {
683
- const skillLatestLink = path7.join(skillsDir, skillId, LATEST_LINK);
684
- const targetPlatformDir = path7.join(skillLatestLink, platform);
685
- const platformSkillDir = path7.join(platformDir, skillId);
686
- if (await fs8.pathExists(skillLatestLink)) {
687
- if (await fs8.pathExists(targetPlatformDir)) {
688
- try {
689
- await fs8.remove(platformSkillDir);
690
- await fs8.symlink(targetPlatformDir, platformSkillDir, "junction");
691
- console.log(` Linked: ${platform}/${skillId}`);
692
- } catch {
693
- await fs8.copy(targetPlatformDir, platformSkillDir, { overwrite: true });
694
- console.log(` Copied: ${platform}/${skillId}`);
695
- }
696
- }
697
- }
698
- }
699
- }
700
- console.log("\n\u2705 Sync complete!");
701
- }
702
-
703
425
  // src/commands/update.ts
704
426
  async function updateSkill(skillId) {
705
427
  if (skillId) {
706
- const pkgInfo = await fetchNpmPackage(`@itismyskillmarket/${skillId}`);
428
+ const pkgInfo = await fetchNpmPackage(`@skillmarket/${skillId}`);
707
429
  if (pkgInfo) {
708
430
  const latestVersion = pkgInfo["dist-tags"]?.latest;
709
431
  console.log(`Updating ${skillId} to ${latestVersion}...`);
@@ -720,7 +442,7 @@ async function updateSkill(skillId) {
720
442
  `);
721
443
  let hasUpdates = false;
722
444
  for (const skill of installed) {
723
- const pkgInfo = await fetchNpmPackage(`@wanxuchen/${skill.id}`);
445
+ const pkgInfo = await fetchNpmPackage(`@skillmarket/${skill.id}`);
724
446
  if (pkgInfo) {
725
447
  const latestVersion = pkgInfo["dist-tags"]?.latest;
726
448
  if (latestVersion && latestVersion !== skill.version) {
@@ -742,9 +464,9 @@ async function updateSkill(skillId) {
742
464
  }
743
465
 
744
466
  // src/commands/uninstall.ts
745
- import fs9 from "fs-extra";
746
- import path8 from "path";
747
- async function uninstallSkill(skillId, options) {
467
+ import fs5 from "fs-extra";
468
+ import path4 from "path";
469
+ async function uninstallSkill(skillId) {
748
470
  const registry = await loadRegistry();
749
471
  if (!(skillId in registry.skills)) {
750
472
  console.log(`Skill "${skillId}" is not installed.`);
@@ -752,37 +474,14 @@ async function uninstallSkill(skillId, options) {
752
474
  }
753
475
  const skillInfo = registry.skills[skillId];
754
476
  console.log(`Uninstalling ${skillId}@${skillInfo.version}...`);
755
- let targetAdapters = [];
756
- if (options?.platforms && options.platforms.length > 0) {
757
- for (const platformStr of options.platforms) {
758
- const platform = platformStr;
759
- targetAdapters.push(getAdapterByPlatform(platform));
760
- }
761
- } else {
762
- targetAdapters = await detectPlatforms();
763
- }
764
- const validAdapters = targetAdapters.filter((a) => a !== void 0);
765
- if (validAdapters.length > 0) {
766
- console.log(`
767
- Uninstalling from ${validAdapters.length} platform(s)...
768
- `);
769
- for (const adapter of validAdapters) {
770
- try {
771
- await adapter.uninstall(skillId);
772
- console.log(`${adapter.name.padEnd(12)} \u2705 Uninstalled`);
773
- } catch (error) {
774
- console.log(`${adapter.name.padEnd(12)} \u274C Failed: ${error}`);
775
- }
776
- }
777
- }
778
477
  const skillsDir = getSkillsDir();
779
- const skillDir = path8.join(skillsDir, skillId);
780
- await fs9.remove(skillDir);
478
+ const skillDir = path4.join(skillsDir, skillId);
479
+ await fs5.remove(skillDir);
781
480
  const platformLinksDir = getPlatformLinksDir();
782
481
  for (const platform of PLATFORMS) {
783
- const linkPath = path8.join(platformLinksDir, platform, "skills", skillId);
784
- if (await fs9.pathExists(linkPath)) {
785
- await fs9.remove(linkPath);
482
+ const linkPath = path4.join(platformLinksDir, platform, "skills", skillId);
483
+ if (await fs5.pathExists(linkPath)) {
484
+ await fs5.remove(linkPath);
786
485
  }
787
486
  }
788
487
  delete registry.skills[skillId];
@@ -792,89 +491,61 @@ Uninstalling from ${validAdapters.length} platform(s)...
792
491
  }
793
492
 
794
493
  // src/cli.ts
795
- var __filename = fileURLToPath(import.meta.url);
796
- var __dirname = dirname(__filename);
797
- var packageJson = JSON.parse(readFileSync(resolve(__dirname, "../package.json"), "utf-8"));
798
- var VERSION = packageJson.version;
799
494
  var program = new Command();
800
- program.name("skm").description("SkillMarket - Cross-platform skill manager for AI coding tools").version(VERSION);
801
- program.hook("preAction", (thisCommand) => {
802
- if (thisCommand.opts().help) {
803
- console.log(`
495
+ program.name("skm").description("SkillMarket - Cross-platform skill manager for AI coding tools").version("1.2.0");
496
+ var helpCmd = program.command("help").description("Display help information");
497
+ helpCmd.action(() => {
498
+ console.log(`
804
499
  SkillMarket CLI
805
500
 
806
501
  Usage: skm <command> [options]
807
502
 
808
503
  Commands:
809
- ls [options] List available skills
810
- --installed Show only installed skills
811
- --updates Check for updates
812
- --page <n> Page number (default: 1)
813
- --limit <n> Items per page (default: 20)
814
- -s, --search Search by keyword
815
- info <skill-id> Display skill information
816
- install <skill> Install a skill
817
- @version Install specific version
818
- --platform Target platforms (opencode,claude,vscode)
819
- --force Overwrite if already installed
820
- uninstall <skill> Remove an installed skill
821
- --platform Target platforms
822
- update [options] Update skills
823
- --all Update all skills
824
- sync Synchronize platform links
825
- platforms Show available platforms
504
+ --help, -h Display this help message
505
+ --ls [options] List available skills
506
+ --installed Show only installed skills
507
+ --updates Check for updates
508
+ --info <skill-id> Display skill information
509
+ --install <skill> Install a skill (e.g., skm --install brainstorming)
510
+ @version Install specific version
511
+ --all Install all available skills
512
+ --uninstall <skill> Remove an installed skill
513
+ --update [options] Update skills
514
+ --all Update all skills
515
+ --sync Synchronize platform links
516
+ --platform <name> Set target platform (${PLATFORMS.join(", ")})
826
517
 
827
518
  Examples:
828
- skm ls List all available skills (page 1)
829
- skm ls --page 2 Go to page 2
830
- skm ls --limit 10 Show 10 items per page
831
- skm ls --search brain Search skills by keyword
832
- skm ls -s brain Search with short form
833
- skm ls --installed Show installed skills only
834
- skm ls --installed --search test Search installed skills
835
- skm ls --installed --page 2
836
- skm info brainstorming View skill details
837
- skm install brainstorming Install to all platforms
838
- skm install brainstorming --platform opencode Install to OpenCode only
839
- skm install brainstorming --platform claude,vscode Install to multiple
840
- skm uninstall brainstorming
841
- skm platforms Show available platforms
842
- `);
843
- process.exit(0);
844
- }
519
+ skm --ls List all available skills
520
+ skm --ls --installed Show installed skills only
521
+ skm --info brainstorming View skill details
522
+ skm --install brainstorming Install a skill
523
+ skm --install brainstorming@1.0.0 Install specific version
524
+ skm --update --all Update all installed skills
525
+ skm --sync Sync platform links
526
+ `);
845
527
  });
846
528
  var lsCmd = program.command("ls").description("List available skills");
847
- 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) => {
848
- const options = {
849
- ...opts,
850
- page: opts.page ?? 1,
851
- limit: opts.limit ?? 20,
852
- search: opts.search
853
- };
854
- listSkills(options);
529
+ lsCmd.option("--installed", "Show only installed skills").option("--updates", "Check for updates").action((opts) => {
530
+ listSkills(opts);
855
531
  });
856
532
  var infoCmd = program.command("info").description("Display skill information");
857
533
  infoCmd.argument("<skill-id>", "Skill ID to show info").action((skillId) => {
858
534
  showSkillInfo(skillId);
859
535
  });
860
- var installCmd = program.command("install").description("Install a skill to local and platform directories");
861
- installCmd.argument("<skill>", "Skill ID to install (e.g., brainstorming or @scope/name)").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").action(async (skill, opts) => {
536
+ var installCmd = program.command("install").description("Install a skill");
537
+ installCmd.argument("<skill>", "Skill ID to install (e.g., brainstorming or @scope/name)").option("--all", "Install all available skills").option("-p, --platform <platform>", `Target platform (${PLATFORMS.join(", ")})`).action(async (skill, opts) => {
862
538
  try {
863
- const platforms = opts.platform ? opts.platform.split(",").map((p) => p.trim()) : void 0;
864
- await installSkill(skill, opts.version, {
865
- platforms,
866
- force: opts.force
867
- });
539
+ await installSkill(skill, void 0, opts.platform);
868
540
  } catch (err) {
869
541
  console.error("Installation failed:", err);
870
542
  process.exit(1);
871
543
  }
872
544
  });
873
- var uninstallCmd = program.command("uninstall").description("Remove an installed skill from local and platform directories");
874
- uninstallCmd.argument("<skill>", "Skill ID to uninstall").option("-p, --platform <platforms>", "Target platforms (comma-separated)").action(async (skill, opts) => {
545
+ var uninstallCmd = program.command("uninstall").description("Remove an installed skill");
546
+ uninstallCmd.argument("<skill>", "Skill ID to uninstall").action(async (skill) => {
875
547
  try {
876
- const platforms = opts.platform ? opts.platform.split(",").map((p) => p.trim()) : void 0;
877
- await uninstallSkill(skill, { platforms });
548
+ await uninstallSkill(skill);
878
549
  } catch (err) {
879
550
  console.error("Uninstall failed:", err);
880
551
  process.exit(1);
@@ -901,29 +572,8 @@ program.command("sync").description("Synchronize platform links").action(async (
901
572
  process.exit(1);
902
573
  }
903
574
  });
904
- var platformsCmd = program.command("platforms").description("Show available platforms");
905
- platformsCmd.action(async () => {
906
- try {
907
- const available = await detectPlatforms();
908
- console.log("\n\u{1F4CD} Available Platforms:\n");
909
- const allPlatforms = [
910
- { name: "OpenCode", adapter: new OpenCodeAdapter() },
911
- { name: "Claude Code", adapter: new ClaudeAdapter() },
912
- { name: "VSCode", adapter: new VSCodeAdapter() }
913
- ];
914
- for (const { name, adapter } of allPlatforms) {
915
- const isAvailable = available.find((a) => a.id === adapter.id);
916
- const installed = await adapter.listInstalled();
917
- if (isAvailable) {
918
- console.log(`${name.padEnd(12)} \u2705 Available (${installed.length} skills installed)`);
919
- } else {
920
- console.log(`${name.padEnd(12)} \u274C Not detected`);
921
- }
922
- }
923
- console.log("");
924
- } catch (err) {
925
- console.error("Failed to list platforms:", err);
926
- process.exit(1);
927
- }
575
+ var platformCmd = program.command("platform").description("Set target platform");
576
+ platformCmd.argument("<name>", "Platform name").action((name) => {
577
+ console.log("Platform command - name:", name);
928
578
  });
929
579
  program.parse();