itismyskillmarket 1.3.0 → 1.3.2

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 (49) hide show
  1. package/.github/workflows/publish-npm.yml +59 -0
  2. package/.github/workflows/publish-skill.yml +72 -0
  3. package/5e51cb7aa8b8e60d49d86f4689f5d4d1.png +0 -0
  4. package/CHANGELOG.md +410 -0
  5. package/DEVELOPMENT.md +376 -0
  6. package/README.md +75 -6
  7. package/SKILLMARKET-GUIDE.md +288 -0
  8. package/dist/index.js +733 -212
  9. package/docs/WEEKLY-UPDATE-2026-04-23.md +43 -0
  10. package/docs/plans/2026-04-01-skillmarket-design.md +267 -0
  11. package/docs/plans/2026-04-01-skillmarket-implementation.md +1031 -0
  12. package/docs/plans/2026-04-15-cross-platform-adapter-design.md +416 -0
  13. package/docs/plans/2026-04-15-cross-platform-adapter-plan.md +833 -0
  14. package/docs/plans/2026-04-16-keyword-search-design.md +143 -0
  15. package/docs/plans/2026-04-29-weekly-update.md +57 -0
  16. package/package.json +1 -6
  17. package/skills/README.md +54 -0
  18. package/skills/test-skill/SKILL.md +25 -0
  19. package/skills/test-skill/index.js +66 -0
  20. package/skills/test-skill/metadata.json +9 -0
  21. package/skills/test-skill/package.json +19 -0
  22. package/skills/test-skill-1/SKILL.md +24 -0
  23. package/skills/test-skill-1/index.js +13 -0
  24. package/skills/test-skill-1/metadata.json +9 -0
  25. package/skills/test-skill-1/package.json +16 -0
  26. package/skills/test-skill-2/SKILL.md +25 -0
  27. package/skills/test-skill-2/index.js +13 -0
  28. package/skills/test-skill-2/metadata.json +9 -0
  29. package/skills/test-skill-2/package.json +16 -0
  30. package/src/adapters/base.ts +87 -0
  31. package/src/adapters/claude.ts +31 -0
  32. package/src/adapters/index.ts +9 -0
  33. package/src/adapters/opencode.ts +40 -0
  34. package/src/adapters/registry.ts +77 -0
  35. package/src/adapters/vscode.ts +62 -0
  36. package/src/cli.ts +189 -75
  37. package/src/commands/info.ts +4 -15
  38. package/src/commands/install.ts +93 -54
  39. package/src/commands/ls.ts +182 -17
  40. package/src/commands/npm.ts +118 -16
  41. package/src/commands/search.ts +12 -7
  42. package/src/commands/sync.ts +6 -27
  43. package/src/commands/uninstall.ts +313 -15
  44. package/src/commands/update.ts +2 -2
  45. package/src/index.ts +27 -0
  46. package/src/types.ts +35 -0
  47. package/tsconfig.json +10 -0
  48. package/tsup.config.ts +22 -0
  49. package/wanxuchen-skillmarket-1.0.1.tgz +0 -0
@@ -0,0 +1,833 @@
1
+ # Cross-Platform Skill Adapter Implementation Plan
2
+
3
+ > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
4
+
5
+ **Goal:** Enable users to install skills to OpenCode, Claude Code, and VSCode platforms with a single `skm install` command.
6
+
7
+ **Architecture:** Create platform adapter classes that follow a common interface, detect available platforms automatically, and install skills to each platform's native skill directory.
8
+
9
+ **Tech Stack:** TypeScript, Node.js, fs-extra
10
+
11
+ ---
12
+
13
+ ## Task 1: Create Platform Adapter Base Class
14
+
15
+ **Files:**
16
+ - Create: `src/adapters/base.ts`
17
+ - Create: `src/adapters/index.ts`
18
+ - Modify: `src/types.ts`
19
+
20
+ **Step 1: Add PlatformAdapter type to types.ts**
21
+
22
+ Add to `src/types.ts`:
23
+
24
+ ```typescript
25
+ /**
26
+ * Platform adapter interface for cross-platform skill installation
27
+ */
28
+ export interface PlatformAdapter {
29
+ /** Unique platform identifier */
30
+ readonly id: string;
31
+
32
+ /** Human-readable platform name */
33
+ readonly name: string;
34
+
35
+ /** Platform's skill directory path */
36
+ readonly skillDir: string;
37
+
38
+ /** Check if this platform is available on the current system */
39
+ isAvailable(): Promise<boolean>;
40
+
41
+ /** Check if a skill is installed on this platform */
42
+ isInstalled(skillId: string): Promise<boolean>;
43
+
44
+ /** Install a skill to this platform */
45
+ install(skillId: string, sourceDir: string): Promise<void>;
46
+
47
+ /** Uninstall a skill from this platform */
48
+ uninstall(skillId: string): Promise<void>;
49
+
50
+ /** List all skills installed on this platform */
51
+ listInstalled(): Promise<string[]>;
52
+ }
53
+ ```
54
+
55
+ **Step 2: Create base adapter class**
56
+
57
+ Create `src/adapters/base.ts`:
58
+
59
+ ```typescript
60
+ /**
61
+ * =============================================================================
62
+ * Base Platform Adapter
63
+ * =============================================================================
64
+ *
65
+ * Abstract base class for platform-specific skill adapters.
66
+ * Provides common functionality for all platforms.
67
+ */
68
+
69
+ import fs from 'fs-extra';
70
+ import path from 'path';
71
+ import type { PlatformAdapter } from '../types.js';
72
+
73
+ export abstract class BaseAdapter implements PlatformAdapter {
74
+ abstract readonly id: string;
75
+ abstract readonly name: string;
76
+ abstract readonly skillDir: string;
77
+
78
+ /**
79
+ * Get the path where a specific skill should be installed
80
+ */
81
+ protected getSkillPath(skillId: string): string {
82
+ return path.join(this.skillDir, skillId);
83
+ }
84
+
85
+ /**
86
+ * Get the path to the SKILL.md file for a skill
87
+ */
88
+ protected getSkillFilePath(skillId: string): string {
89
+ return path.join(this.getSkillPath(skillId), 'SKILL.md');
90
+ }
91
+
92
+ async isAvailable(): Promise<boolean> {
93
+ // Check if skill directory is writable or can be created
94
+ try {
95
+ await fs.ensureDir(this.skillDir);
96
+ return true;
97
+ } catch {
98
+ return false;
99
+ }
100
+ }
101
+
102
+ async isInstalled(skillId: string): Promise<boolean> {
103
+ const skillFile = this.getSkillFilePath(skillId);
104
+ return fs.pathExists(skillFile);
105
+ }
106
+
107
+ async install(skillId: string, sourceDir: string): Promise<void> {
108
+ const targetDir = this.getSkillPath(skillId);
109
+ const targetFile = this.getSkillFilePath(skillId);
110
+
111
+ // Ensure target directory exists
112
+ await fs.ensureDir(targetDir);
113
+
114
+ // Check if SKILL.md exists in source
115
+ const sourceFile = path.join(sourceDir, 'SKILL.md');
116
+ if (!(await fs.pathExists(sourceFile))) {
117
+ throw new Error(`SKILL.md not found in ${sourceDir}`);
118
+ }
119
+
120
+ // Copy SKILL.md to target
121
+ await fs.copy(sourceFile, targetFile, { overwrite: true });
122
+ }
123
+
124
+ async uninstall(skillId: string): Promise<void> {
125
+ const targetDir = this.getSkillPath(skillId);
126
+ if (await fs.pathExists(targetDir)) {
127
+ await fs.remove(targetDir);
128
+ }
129
+ }
130
+
131
+ async listInstalled(): Promise<string[]> {
132
+ if (!(await fs.pathExists(this.skillDir))) {
133
+ return [];
134
+ }
135
+
136
+ const entries = await fs.readdir(this.skillDir, { withFileTypes: true });
137
+ const skills: string[] = [];
138
+
139
+ for (const entry of entries) {
140
+ if (entry.isDirectory()) {
141
+ const skillFile = path.join(this.skillDir, entry.name, 'SKILL.md');
142
+ if (await fs.pathExists(skillFile)) {
143
+ skills.push(entry.name);
144
+ }
145
+ }
146
+ }
147
+
148
+ return skills;
149
+ }
150
+ }
151
+ ```
152
+
153
+ **Step 3: Create index file**
154
+
155
+ Create `src/adapters/index.ts`:
156
+
157
+ ```typescript
158
+ /**
159
+ * Platform adapters index
160
+ */
161
+
162
+ export { BaseAdapter } from './base.js';
163
+ export { OpenCodeAdapter } from './opencode.js';
164
+ export { ClaudeAdapter } from './claude.js';
165
+ export { VSCodeAdapter } from './vscode.js';
166
+ export { detectPlatforms, getPlatformAdapter } from './registry.js';
167
+ ```
168
+
169
+ **Step 4: Commit**
170
+
171
+ ```bash
172
+ git add src/adapters/base.ts src/adapters/index.ts src/types.ts
173
+ git commit -m "feat: add base platform adapter class"
174
+ ```
175
+
176
+ ---
177
+
178
+ ## Task 2: Create OpenCode Adapter
179
+
180
+ **Files:**
181
+ - Create: `src/adapters/opencode.ts`
182
+
183
+ **Step 1: Create OpenCode adapter**
184
+
185
+ Create `src/adapters/opencode.ts`:
186
+
187
+ ```typescript
188
+ /**
189
+ * =============================================================================
190
+ * OpenCode Platform Adapter
191
+ * =============================================================================
192
+ *
193
+ * Handles skill installation for OpenCode AI coding tool.
194
+ * Skills are installed to ~/.config/opencode/skills/<skill-id>/
195
+ */
196
+
197
+ import path from 'path';
198
+ import os from 'os';
199
+ import { BaseAdapter } from './base.js';
200
+
201
+ export class OpenCodeAdapter extends BaseAdapter {
202
+ readonly id = 'opencode';
203
+ readonly name = 'OpenCode';
204
+
205
+ get skillDir(): string {
206
+ // Respect OPENCODE_CONFIG_DIR environment variable
207
+ const configDir = process.env.OPENCODE_CONFIG_DIR
208
+ || path.join(os.homedir(), '.config', 'opencode');
209
+ return path.join(configDir, 'skills');
210
+ }
211
+
212
+ async isAvailable(): Promise<boolean> {
213
+ // Check for environment variable or directory
214
+ if (process.env.OPENCODE) return true;
215
+
216
+ const configDir = process.env.OPENCODE_CONFIG_DIR
217
+ || path.join(os.homedir(), '.config', 'opencode');
218
+
219
+ try {
220
+ await fs.ensureDir(path.join(configDir, 'skills'));
221
+ return true;
222
+ } catch {
223
+ return false;
224
+ }
225
+ }
226
+ }
227
+
228
+ import fs from 'fs-extra';
229
+ ```
230
+
231
+ **Step 2: Commit**
232
+
233
+ ```bash
234
+ git add src/adapters/opencode.ts
235
+ git commit -m "feat: add OpenCode platform adapter"
236
+ ```
237
+
238
+ ---
239
+
240
+ ## Task 3: Create Claude Code Adapter
241
+
242
+ **Files:**
243
+ - Create: `src/adapters/claude.ts`
244
+
245
+ **Step 1: Create Claude adapter**
246
+
247
+ Create `src/adapters/claude.ts`:
248
+
249
+ ```typescript
250
+ /**
251
+ * =============================================================================
252
+ * Claude Code Platform Adapter
253
+ * =============================================================================
254
+ *
255
+ * Handles skill installation for Claude Code CLI.
256
+ * Skills are installed to ~/.claude/skills/<skill-id>/
257
+ */
258
+
259
+ import path from 'path';
260
+ import os from 'os';
261
+ import fs from 'fs-extra';
262
+ import { BaseAdapter } from './base.js';
263
+
264
+ export class ClaudeAdapter extends BaseAdapter {
265
+ readonly id = 'claude';
266
+ readonly name = 'Claude Code';
267
+
268
+ get skillDir(): string {
269
+ return path.join(os.homedir(), '.claude', 'skills');
270
+ }
271
+
272
+ async isAvailable(): Promise<boolean> {
273
+ // Check for environment variable or directory
274
+ if (process.env.CLAUDE_CODE) return true;
275
+
276
+ // Check if .claude directory exists
277
+ const claudeDir = path.join(os.homedir(), '.claude');
278
+ return fs.pathExists(claudeDir);
279
+ }
280
+ }
281
+ ```
282
+
283
+ **Step 2: Commit**
284
+
285
+ ```bash
286
+ git add src/adapters/claude.ts
287
+ git commit -m "feat: add Claude Code platform adapter"
288
+ ```
289
+
290
+ ---
291
+
292
+ ## Task 4: Create VSCode Adapter
293
+
294
+ **Files:**
295
+ - Create: `src/adapters/vscode.ts`
296
+
297
+ **Step 1: Create VSCode adapter**
298
+
299
+ Create `src/adapters/vscode.ts`:
300
+
301
+ ```typescript
302
+ /**
303
+ * =============================================================================
304
+ * VSCode (Copilot) Platform Adapter
305
+ * =============================================================================
306
+ *
307
+ * Handles skill installation for VSCode GitHub Copilot Agent Skills.
308
+ * Skills are installed to ~/.copilot/skills/<skill-id>/
309
+ *
310
+ * Note: Also supports ~/.claude/skills/ for cross-compatibility.
311
+ */
312
+
313
+ import path from 'path';
314
+ import os from 'os';
315
+ import fs from 'fs-extra';
316
+ import { BaseAdapter } from './base.js';
317
+
318
+ export class VSCodeAdapter extends BaseAdapter {
319
+ readonly id = 'vscode';
320
+ readonly name = 'VSCode';
321
+
322
+ get skillDir(): string {
323
+ // Try ~/.copilot/skills first, fallback to ~/.claude/skills
324
+ return path.join(os.homedir(), '.copilot', 'skills');
325
+ }
326
+
327
+ async isAvailable(): Promise<boolean> {
328
+ // Check multiple possible locations
329
+ const possibleDirs = [
330
+ path.join(os.homedir(), '.copilot', 'skills'),
331
+ path.join(os.homedir(), '.claude', 'skills'),
332
+ ];
333
+
334
+ for (const dir of possibleDirs) {
335
+ try {
336
+ await fs.ensureDir(dir);
337
+ return true;
338
+ } catch {
339
+ continue;
340
+ }
341
+ }
342
+
343
+ return false;
344
+ }
345
+
346
+ async install(skillId: string, sourceDir: string): Promise<void> {
347
+ // Install to ~/.copilot/skills, but also create symlink in ~/.claude/skills
348
+ await super.install(skillId, sourceDir);
349
+
350
+ // Create cross-compatible symlink in ~/.claude/skills
351
+ const claudeSkillDir = path.join(os.homedir(), '.claude', 'skills');
352
+ const targetPath = this.getSkillPath(skillId);
353
+ const claudeTargetPath = path.join(claudeSkillDir, skillId);
354
+
355
+ try {
356
+ await fs.ensureDir(claudeSkillDir);
357
+ await fs.remove(claudeTargetPath);
358
+ await fs.symlink(targetPath, claudeTargetPath, 'junction');
359
+ } catch {
360
+ // Silently fail if symlink not possible (cross-platform compatibility)
361
+ }
362
+ }
363
+ }
364
+ ```
365
+
366
+ **Step 2: Commit**
367
+
368
+ ```bash
369
+ git add src/adapters/vscode.ts
370
+ git commit -m "feat: add VSCode platform adapter"
371
+ ```
372
+
373
+ ---
374
+
375
+ ## Task 5: Create Platform Registry
376
+
377
+ **Files:**
378
+ - Create: `src/adapters/registry.ts`
379
+
380
+ **Step 1: Create platform registry**
381
+
382
+ Create `src/adapters/registry.ts`:
383
+
384
+ ```typescript
385
+ /**
386
+ * =============================================================================
387
+ * Platform Registry
388
+ * =============================================================================
389
+ *
390
+ * Central registry for platform adapters.
391
+ * Handles platform detection and selection.
392
+ */
393
+
394
+ import { OpenCodeAdapter } from './opencode.js';
395
+ import { ClaudeAdapter } from './claude.js';
396
+ import { VSCodeAdapter } from './vscode.js';
397
+ import type { PlatformAdapter } from '../types.js';
398
+ import type { Platform } from '../constants.js';
399
+
400
+ const adapters: Map<string, PlatformAdapter> = new Map();
401
+
402
+ /**
403
+ * Register all built-in platform adapters
404
+ */
405
+ function registerAdapters(): void {
406
+ const opencode = new OpenCodeAdapter();
407
+ const claude = new ClaudeAdapter();
408
+ const vscode = new VSCodeAdapter();
409
+
410
+ adapters.set(opencode.id, opencode);
411
+ adapters.set(claude.id, claude);
412
+ adapters.set(vscode.id, vscode);
413
+ }
414
+
415
+ // Register adapters on module load
416
+ registerAdapters();
417
+
418
+ /**
419
+ * Detect which platforms are available on the current system
420
+ */
421
+ export async function detectPlatforms(): Promise<PlatformAdapter[]> {
422
+ const available: PlatformAdapter[] = [];
423
+
424
+ for (const adapter of adapters.values()) {
425
+ if (await adapter.isAvailable()) {
426
+ available.push(adapter);
427
+ }
428
+ }
429
+
430
+ return available;
431
+ }
432
+
433
+ /**
434
+ * Get adapter for a specific platform
435
+ */
436
+ export function getPlatformAdapter(platformId: string): PlatformAdapter | undefined {
437
+ return adapters.get(platformId);
438
+ }
439
+
440
+ /**
441
+ * Get all registered adapters
442
+ */
443
+ export function getAllAdapters(): PlatformAdapter[] {
444
+ return Array.from(adapters.values());
445
+ }
446
+
447
+ /**
448
+ * Get adapter by platform type
449
+ */
450
+ export function getAdapterByPlatform(platform: Platform): PlatformAdapter | undefined {
451
+ const idMap: Record<Platform, string> = {
452
+ opencode: 'opencode',
453
+ claude: 'claude',
454
+ vscode: 'vscode',
455
+ cursor: 'opencode', // Cursor uses OpenCode-compatible structure
456
+ codex: 'opencode', // Codex uses OpenCode-compatible structure
457
+ antigravity: 'opencode', // Antigravity uses OpenCode-compatible structure
458
+ };
459
+
460
+ return adapters.get(idMap[platform]);
461
+ }
462
+ ```
463
+
464
+ **Step 2: Commit**
465
+
466
+ ```bash
467
+ git add src/adapters/registry.ts
468
+ git commit -m "feat: add platform registry and detection"
469
+ ```
470
+
471
+ ---
472
+
473
+ ## Task 6: Update Install Command
474
+
475
+ **Files:**
476
+ - Modify: `src/commands/install.ts`
477
+
478
+ **Step 1: Update install command with platform support**
479
+
480
+ Modify `src/commands/install.ts`, add these imports and functions:
481
+
482
+ ```typescript
483
+ // Add to imports
484
+ import { detectPlatforms, getAdapterByPlatform } from '../adapters/index.js';
485
+ import type { PlatformAdapter } from '../types.js';
486
+ import type { Platform } from '../constants.js';
487
+
488
+ // Add platform option parsing to installSkill function
489
+ export async function installSkill(
490
+ skillId: string,
491
+ version?: string,
492
+ options?: {
493
+ platforms?: string[];
494
+ force?: boolean;
495
+ }
496
+ ): Promise<void> {
497
+ // ... existing code until step 3 ...
498
+
499
+ // ==========================================================================
500
+ // Step 4 (NEW): Determine target platforms
501
+ // ==========================================================================
502
+
503
+ let targetAdapters: PlatformAdapter[] = [];
504
+
505
+ if (options?.platforms && options.platforms.length > 0) {
506
+ // User specified platforms
507
+ for (const platformStr of options.platforms) {
508
+ const platform = platformStr as Platform;
509
+ const adapter = getAdapterByPlatform(platform);
510
+ if (adapter) {
511
+ targetAdapters.push(adapter);
512
+ } else {
513
+ console.warn(`⚠️ Unknown platform: ${platformStr}`);
514
+ }
515
+ }
516
+ } else {
517
+ // Auto-detect available platforms
518
+ targetAdapters = await detectPlatforms();
519
+ }
520
+
521
+ if (targetAdapters.length === 0) {
522
+ console.log('No target platforms found.');
523
+ console.log('Use --platform to specify platforms manually.');
524
+ return;
525
+ }
526
+
527
+ console.log(`\nInstalling to ${targetAdapters.length} platform(s)...\n`);
528
+
529
+ // ==========================================================================
530
+ // Step 5 (NEW): Install to each platform
531
+ // ==========================================================================
532
+
533
+ const results: { adapter: PlatformAdapter; status: 'installed' | 'skipped' | 'failed'; error?: string }[] = [];
534
+
535
+ for (const adapter of targetAdapters) {
536
+ try {
537
+ const isInstalled = await adapter.isInstalled(skillId);
538
+
539
+ if (isInstalled && !options?.force) {
540
+ console.log(`${adapter.name} ⚠️ Already installed (use --force to overwrite)`);
541
+ results.push({ adapter, status: 'skipped' });
542
+ continue;
543
+ }
544
+
545
+ // Install skill
546
+ await adapter.install(skillId, skillVersionDir);
547
+ console.log(`${adapter.name} ✅ Installed successfully`);
548
+ results.push({ adapter, status: 'installed' });
549
+ } catch (error) {
550
+ console.log(`${adapter.name} ❌ Failed: ${error}`);
551
+ results.push({ adapter, status: 'failed', error: String(error) });
552
+ }
553
+ }
554
+
555
+ // ==========================================================================
556
+ // Step 6 (NEW): Display summary
557
+ // ==========================================================================
558
+
559
+ const installed = results.filter(r => r.status === 'installed').length;
560
+ const skipped = results.filter(r => r.status === 'skipped').length;
561
+ const failed = results.filter(r => r.status === 'failed').length;
562
+
563
+ console.log(`\n📊 Summary: ${installed} installed, ${skipped} skipped, ${failed} failed`);
564
+ }
565
+ ```
566
+
567
+ **Step 2: Commit**
568
+
569
+ ```bash
570
+ git add src/commands/install.ts
571
+ git commit -m "feat: add platform support to install command"
572
+ ```
573
+
574
+ ---
575
+
576
+ ## Task 7: Update CLI Parser
577
+
578
+ **Files:**
579
+ - Modify: `src/cli.ts`
580
+
581
+ **Step 1: Update CLI to parse --platform flag**
582
+
583
+ Modify `src/cli.ts`, update the install command handler:
584
+
585
+ ```typescript
586
+ // In the install command section, update the handler:
587
+
588
+ .command('install <skill>')
589
+ .description('Install a skill to local and/or platform directories')
590
+ .option('-p, --platform <platforms>', 'Target platforms (comma-separated: opencode,claude,vscode)')
591
+ .option('-f, --force', 'Overwrite if already installed')
592
+ .option('-v, --version <version>', 'Specific version to install')
593
+ .action(async (skill, options) => {
594
+ const platforms = options.platform
595
+ ? options.platform.split(',').map(p => p.trim())
596
+ : undefined;
597
+
598
+ await installSkill(skill, options.version, {
599
+ platforms,
600
+ force: options.force
601
+ });
602
+ });
603
+
604
+ // Also add new platforms command
605
+ .command('platforms', 'Show available platforms')
606
+ .action(async () => {
607
+ const { detectPlatforms } = await import('./adapters/index.js');
608
+ const adapters = await detectPlatforms();
609
+
610
+ console.log('\n📍 Available Platforms:\n');
611
+
612
+ const { OpenCodeAdapter, ClaudeAdapter, VSCodeAdapter } = await import('./adapters/index.js');
613
+
614
+ const allPlatforms = [
615
+ { name: 'OpenCode', adapter: new OpenCodeAdapter() },
616
+ { name: 'Claude Code', adapter: new ClaudeAdapter() },
617
+ { name: 'VSCode', adapter: new VSCodeAdapter() },
618
+ ];
619
+
620
+ for (const { name, adapter } of allPlatforms) {
621
+ const available = adapters.find(a => a.id === adapter.id);
622
+ const installed = await adapter.listInstalled();
623
+
624
+ if (available) {
625
+ console.log(`${name.padEnd(12)} ✅ Available (${installed.length} skills installed)`);
626
+ } else {
627
+ console.log(`${name.padEnd(12)} ❌ Not detected`);
628
+ }
629
+ }
630
+
631
+ console.log('');
632
+ });
633
+ ```
634
+
635
+ **Step 2: Commit**
636
+
637
+ ```bash
638
+ git add src/cli.ts
639
+ git commit -m "feat: add --platform flag and platforms command"
640
+ ```
641
+
642
+ ---
643
+
644
+ ## Task 8: Update Uninstall Command
645
+
646
+ **Files:**
647
+ - Modify: `src/commands/uninstall.ts`
648
+
649
+ **Step 1: Update uninstall to support platforms**
650
+
651
+ Modify `src/commands/uninstall.ts`:
652
+
653
+ ```typescript
654
+ // Add platform support to uninstall
655
+
656
+ import { detectPlatforms, getAdapterByPlatform } from '../adapters/index.js';
657
+ import type { Platform } from '../constants.js';
658
+
659
+ export async function uninstallSkill(
660
+ skillId: string,
661
+ options?: {
662
+ platforms?: string[];
663
+ }
664
+ ): Promise<void> {
665
+ // ... existing registry code ...
666
+
667
+ let targetAdapters = options?.platforms
668
+ ? options.platforms.map(p => getAdapterByPlatform(p as Platform)).filter(Boolean)
669
+ : await detectPlatforms();
670
+
671
+ console.log(`\nUninstalling from ${targetAdapters.length} platform(s)...\n`);
672
+
673
+ for (const adapter of targetAdapters) {
674
+ if (!adapter) continue;
675
+
676
+ try {
677
+ await adapter.uninstall(skillId);
678
+ console.log(`${adapter.name} ✅ Uninstalled`);
679
+ } catch (error) {
680
+ console.log(`${adapter.name} ❌ Failed: ${error}`);
681
+ }
682
+ }
683
+
684
+ // ... rest of existing code ...
685
+ }
686
+ ```
687
+
688
+ **Step 2: Update CLI to pass platform option**
689
+
690
+ Update `src/cli.ts` uninstall handler to pass platforms:
691
+
692
+ ```typescript
693
+ .option('-p, --platform <platforms>', 'Target platforms (comma-separated)')
694
+ .action(async (skill, options) => {
695
+ const platforms = options.platform
696
+ ? options.platform.split(',').map(p => p.trim())
697
+ : undefined;
698
+
699
+ await uninstallSkill(skill, { platforms });
700
+ });
701
+ ```
702
+
703
+ **Step 3: Commit**
704
+
705
+ ```bash
706
+ git add src/commands/uninstall.ts src/cli.ts
707
+ git commit -m "feat: add platform support to uninstall command"
708
+ ```
709
+
710
+ ---
711
+
712
+ ## Task 9: Build and Test
713
+
714
+ **Step 1: Build the project**
715
+
716
+ ```bash
717
+ npm run build
718
+ ```
719
+
720
+ **Step 2: Test platform detection**
721
+
722
+ ```bash
723
+ npx skillmarket platforms
724
+ ```
725
+
726
+ Expected output:
727
+ ```
728
+ 📍 Available Platforms:
729
+
730
+ OpenCode ✅ Available (X skills installed)
731
+ Claude Code ✅/❌ Available/Not detected
732
+ VSCode ✅/❌ Available/Not detected
733
+ ```
734
+
735
+ **Step 3: Test install with platform flag**
736
+
737
+ ```bash
738
+ # Test install to specific platform
739
+ npx skillmarket install test-skill --platform opencode
740
+
741
+ # Test install to all platforms
742
+ npx skillmarket install test-skill
743
+ ```
744
+
745
+ **Step 4: Test uninstall**
746
+
747
+ ```bash
748
+ npx skillmarket uninstall test-skill --platform opencode
749
+ ```
750
+
751
+ ---
752
+
753
+ ## Task 10: Update Documentation
754
+
755
+ **Files:**
756
+ - Modify: `README.md`
757
+ - Create: `docs/CROSS-PLATFORM.md`
758
+
759
+ **Step 1: Update README with new commands**
760
+
761
+ Add to README.md:
762
+
763
+ ```markdown
764
+ ## Cross-Platform Installation
765
+
766
+ Install skills to multiple AI coding platforms with one command:
767
+
768
+ ```bash
769
+ # Install to all detected platforms
770
+ skm install brainstorming
771
+
772
+ # Install to specific platform
773
+ skm install brainstorming --platform opencode
774
+
775
+ # Install to multiple platforms
776
+ skm install brainstorming --platform opencode,claude,vscode
777
+
778
+ # Show available platforms
779
+ skm platforms
780
+ ```
781
+ ```
782
+
783
+ **Step 2: Create cross-platform guide**
784
+
785
+ Create `docs/CROSS-PLATFORM.md` with detailed documentation.
786
+
787
+ **Step 3: Commit**
788
+
789
+ ```bash
790
+ git add README.md docs/CROSS-PLATFORM.md
791
+ git commit -m "docs: add cross-platform installation guide"
792
+ ```
793
+
794
+ ---
795
+
796
+ ## Task 11: Final Verification and Push
797
+
798
+ **Step 1: Run full build**
799
+
800
+ ```bash
801
+ npm run build && npm run test
802
+ ```
803
+
804
+ **Step 2: Check git status**
805
+
806
+ ```bash
807
+ git status
808
+ ```
809
+
810
+ **Step 3: Push to GitHub**
811
+
812
+ ```bash
813
+ git push
814
+ ```
815
+
816
+ ---
817
+
818
+ ## Summary of Changes
819
+
820
+ | Task | Files | Description |
821
+ |------|-------|-------------|
822
+ | 1 | `src/adapters/base.ts`, `src/types.ts` | Base adapter class |
823
+ | 2 | `src/adapters/opencode.ts` | OpenCode adapter |
824
+ | 3 | `src/adapters/claude.ts` | Claude Code adapter |
825
+ | 4 | `src/adapters/vscode.ts` | VSCode adapter |
826
+ | 5 | `src/adapters/registry.ts`, `src/adapters/index.ts` | Registry and detection |
827
+ | 6 | `src/commands/install.ts` | Enhanced install with platform support |
828
+ | 7 | `src/cli.ts` | CLI parser updates |
829
+ | 8 | `src/commands/uninstall.ts` | Enhanced uninstall with platform support |
830
+ | 9 | - | Build and test |
831
+ | 10 | `README.md`, `docs/CROSS-PLATFORM.md` | Documentation |
832
+
833
+ **Total: ~11 tasks, estimated 2-3 hours**