itismyskillmarket 1.2.2 → 1.2.3

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/package.json CHANGED
@@ -1,13 +1,8 @@
1
1
  {
2
2
  "name": "itismyskillmarket",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "description": "Cross-platform skill manager for AI coding tools",
5
5
  "type": "module",
6
- "files": [
7
- "dist",
8
- "src",
9
- "README.md"
10
- ],
11
6
  "bin": {
12
7
  "skm": "dist/index.js"
13
8
  },
@@ -0,0 +1,52 @@
1
+ # SkillMarket Skills
2
+
3
+ This directory contains the skill packages that can be published to npm.
4
+
5
+ ## Adding a New Skill
6
+
7
+ 1. Create a new directory under `skills/<skill-name>/`
8
+ 2. Add the required files:
9
+ - `package.json` - Package configuration with `skillmarket` metadata
10
+ - `SKILL.md` - Skill documentation
11
+ - `metadata.json` - Skill metadata
12
+ - `index.js` - Main entry point (OpenCode plugin)
13
+
14
+ 3. Update the GitHub Actions workflow to include your skill (if using dropdown options)
15
+
16
+ ## Publishing a Skill
17
+
18
+ ### Option 1: GitHub Actions (Recommended)
19
+ 1. Go to repository Actions tab
20
+ 2. Select "Publish Skill" workflow
21
+ 3. Click "Run workflow"
22
+ 4. Enter skill name (e.g., `test-skill`)
23
+ 5. Optionally specify version
24
+
25
+ ### Option 2: Manual Publish
26
+ ```bash
27
+ cd skills/<skill-name>
28
+ npm install
29
+ npm publish --access=public
30
+ ```
31
+
32
+ ## Skill Package Requirements
33
+
34
+ ```json
35
+ {
36
+ "name": "@itismyskillmarket/<skill-name>",
37
+ "version": "1.0.0",
38
+ "type": "module",
39
+ "main": "index.js",
40
+ "keywords": ["skillmarket"],
41
+ "skillmarket": {
42
+ "id": "<skill-name>",
43
+ "displayName": "Display Name",
44
+ "description": "Description",
45
+ "platforms": ["opencode", "cursor", "vscode"]
46
+ }
47
+ }
48
+ ```
49
+
50
+ ## Current Skills
51
+
52
+ - `test-skill` - Test skill for validating the installation flow
@@ -0,0 +1,25 @@
1
+ # Test Skill
2
+
3
+ 这是一个用于测试 SkillMarket 安装流程的 skill。
4
+
5
+ ## 功能
6
+
7
+ - `test.greet` - 向用户打招呼
8
+ - `test.randomNumber` - 生成随机数
9
+ - `test.systemInfo` - 获取系统信息
10
+
11
+ ## 使用方法
12
+
13
+ ```bash
14
+ skm install test-skill
15
+ skm info test-skill
16
+ ```
17
+
18
+ ## 平台支持
19
+
20
+ - OpenCode
21
+ - Cursor
22
+ - VSCode
23
+ - Claude Code
24
+ - Codex
25
+ - Antigravity
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Test Skill - SkillMarket 测试技能
3
+ *
4
+ * 这是一个用于验证 SkillMarket 安装流程的示例 skill
5
+ */
6
+
7
+ import { tool } from "@opencode-ai/plugin";
8
+
9
+ export default async function TestSkill() {
10
+ console.log("✅ Test Skill 加载成功!");
11
+
12
+ return {
13
+ tool: {
14
+ // 1. 简单的问候工具
15
+ greet: tool({
16
+ description: "向用户打招呼",
17
+ args: {
18
+ name: tool.schema.string().describe("你的名字")
19
+ },
20
+ async execute({ name }, context) {
21
+ const { agent, sessionID } = context;
22
+ return `你好 ${name}!我是 ${agent} 代理,欢迎使用测试插件!会话ID: ${sessionID}`;
23
+ }
24
+ }),
25
+
26
+ // 2. 随机数生成工具
27
+ randomNumber: tool({
28
+ description: "生成指定范围的随机数",
29
+ args: {
30
+ min: tool.schema.number().describe("最小值").default(1),
31
+ max: tool.schema.number().describe("最大值").default(100)
32
+ },
33
+ async execute({ min, max }, context) {
34
+ const randomNum = Math.floor(Math.random() * (max - min + 1)) + min;
35
+ return `随机数(${min}-${max}): ${randomNum}`;
36
+ }
37
+ }),
38
+
39
+ // 3. 系统信息工具
40
+ systemInfo: tool({
41
+ description: "获取系统信息",
42
+ args: {},
43
+ async execute(args, context) {
44
+ const { sessionID, agent } = context;
45
+ const info = {
46
+ agent: agent,
47
+ sessionID: sessionID,
48
+ timestamp: new Date().toISOString(),
49
+ platform: process.platform,
50
+ nodeVersion: process.version
51
+ };
52
+ return JSON.stringify(info, null, 2);
53
+ }
54
+ })
55
+ },
56
+
57
+ // 钩子示例
58
+ "tool.execute.before": async (input, output) => {
59
+ console.log(`🛠️ 工具即将执行: ${input.tool}`);
60
+ },
61
+
62
+ "tool.execute.after": async (input, output) => {
63
+ console.log(`✅ 工具执行完成: ${input.tool}`);
64
+ }
65
+ };
66
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "id": "test-skill",
3
+ "displayName": "测试技能",
4
+ "description": "SkillMarket 测试技能 - 用于验证安装流程",
5
+ "version": "1.0.0",
6
+ "author": "SkillMarket",
7
+ "platforms": ["opencode", "cursor", "vscode", "claude", "codex", "antigravity"],
8
+ "tags": ["test", "demo"]
9
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@itismyskillmarket/test-skill",
3
+ "version": "1.0.1",
4
+ "description": "SkillMarket 测试技能 - 用于验证安装流程",
5
+ "type": "module",
6
+ "main": "index.js",
7
+ "keywords": ["skillmarket", "test"],
8
+ "author": "SkillMarket",
9
+ "license": "MIT",
10
+ "dependencies": {
11
+ "@opencode-ai/plugin": "^1.1.31"
12
+ },
13
+ "skillmarket": {
14
+ "id": "test-skill",
15
+ "displayName": "测试技能",
16
+ "description": "这是一个用于测试 SkillMarket 安装流程的 skill",
17
+ "platforms": ["opencode", "cursor", "vscode", "claude", "codex", "antigravity"]
18
+ }
19
+ }
@@ -0,0 +1,87 @@
1
+ /**
2
+ * =============================================================================
3
+ * Base Platform Adapter
4
+ * =============================================================================
5
+ *
6
+ * Abstract base class for platform-specific skill adapters.
7
+ * Provides common functionality for all platforms.
8
+ */
9
+
10
+ import fs from 'fs-extra';
11
+ import path from 'path';
12
+ import type { PlatformAdapter } from '../types.js';
13
+
14
+ export abstract class BaseAdapter implements PlatformAdapter {
15
+ abstract readonly id: string;
16
+ abstract readonly name: string;
17
+ abstract readonly skillDir: string;
18
+
19
+ /**
20
+ * Get the path where a specific skill should be installed
21
+ */
22
+ protected getSkillPath(skillId: string): string {
23
+ return path.join(this.skillDir, skillId);
24
+ }
25
+
26
+ /**
27
+ * Get the path to the SKILL.md file for a skill
28
+ */
29
+ protected getSkillFilePath(skillId: string): string {
30
+ return path.join(this.getSkillPath(skillId), 'SKILL.md');
31
+ }
32
+
33
+ async isAvailable(): Promise<boolean> {
34
+ try {
35
+ await fs.ensureDir(this.skillDir);
36
+ return true;
37
+ } catch {
38
+ return false;
39
+ }
40
+ }
41
+
42
+ async isInstalled(skillId: string): Promise<boolean> {
43
+ const skillFile = this.getSkillFilePath(skillId);
44
+ return fs.pathExists(skillFile);
45
+ }
46
+
47
+ async install(skillId: string, sourceDir: string): Promise<void> {
48
+ const targetDir = this.getSkillPath(skillId);
49
+ const targetFile = this.getSkillFilePath(skillId);
50
+
51
+ await fs.ensureDir(targetDir);
52
+
53
+ const sourceFile = path.join(sourceDir, 'SKILL.md');
54
+ if (!(await fs.pathExists(sourceFile))) {
55
+ throw new Error(`SKILL.md not found in ${sourceDir}`);
56
+ }
57
+
58
+ await fs.copy(sourceFile, targetFile, { overwrite: true });
59
+ }
60
+
61
+ async uninstall(skillId: string): Promise<void> {
62
+ const targetDir = this.getSkillPath(skillId);
63
+ if (await fs.pathExists(targetDir)) {
64
+ await fs.remove(targetDir);
65
+ }
66
+ }
67
+
68
+ async listInstalled(): Promise<string[]> {
69
+ if (!(await fs.pathExists(this.skillDir))) {
70
+ return [];
71
+ }
72
+
73
+ const entries = await fs.readdir(this.skillDir, { withFileTypes: true });
74
+ const skills: string[] = [];
75
+
76
+ for (const entry of entries) {
77
+ if (entry.isDirectory()) {
78
+ const skillFile = path.join(this.skillDir, entry.name, 'SKILL.md');
79
+ if (await fs.pathExists(skillFile)) {
80
+ skills.push(entry.name);
81
+ }
82
+ }
83
+ }
84
+
85
+ return skills;
86
+ }
87
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * =============================================================================
3
+ * Claude Code Platform Adapter
4
+ * =============================================================================
5
+ *
6
+ * Handles skill installation for Claude Code CLI.
7
+ * Skills are installed to ~/.claude/skills/<skill-id>/
8
+ */
9
+
10
+ import path from 'path';
11
+ import os from 'os';
12
+ import fs from 'fs-extra';
13
+ import { BaseAdapter } from './base.js';
14
+
15
+ export class ClaudeAdapter extends BaseAdapter {
16
+ readonly id = 'claude';
17
+ readonly name = 'Claude Code';
18
+
19
+ get skillDir(): string {
20
+ return path.join(os.homedir(), '.claude', 'skills');
21
+ }
22
+
23
+ async isAvailable(): Promise<boolean> {
24
+ // Check for environment variable or directory
25
+ if (process.env.CLAUDE_CODE) return true;
26
+
27
+ // Check if .claude directory exists
28
+ const claudeDir = path.join(os.homedir(), '.claude');
29
+ return fs.pathExists(claudeDir);
30
+ }
31
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Platform adapters index
3
+ */
4
+
5
+ export { BaseAdapter } from './base.js';
6
+ export { OpenCodeAdapter } from './opencode.js';
7
+ export { ClaudeAdapter } from './claude.js';
8
+ export { VSCodeAdapter } from './vscode.js';
9
+ export { detectPlatforms, getPlatformAdapter, getAllAdapters, getAdapterByPlatform } from './registry.js';
@@ -0,0 +1,40 @@
1
+ /**
2
+ * =============================================================================
3
+ * OpenCode Platform Adapter
4
+ * =============================================================================
5
+ *
6
+ * Handles skill installation for OpenCode AI coding tool.
7
+ * Skills are installed to ~/.config/opencode/skills/<skill-id>/
8
+ */
9
+
10
+ import path from 'path';
11
+ import os from 'os';
12
+ import fs from 'fs-extra';
13
+ import { BaseAdapter } from './base.js';
14
+
15
+ export class OpenCodeAdapter extends BaseAdapter {
16
+ readonly id = 'opencode';
17
+ readonly name = 'OpenCode';
18
+
19
+ get skillDir(): string {
20
+ // Respect OPENCODE_CONFIG_DIR environment variable
21
+ const configDir = process.env.OPENCODE_CONFIG_DIR
22
+ || path.join(os.homedir(), '.config', 'opencode');
23
+ return path.join(configDir, 'skills');
24
+ }
25
+
26
+ async isAvailable(): Promise<boolean> {
27
+ // Check for environment variable or directory
28
+ if (process.env.OPENCODE) return true;
29
+
30
+ const configDir = process.env.OPENCODE_CONFIG_DIR
31
+ || path.join(os.homedir(), '.config', 'opencode');
32
+
33
+ try {
34
+ await fs.ensureDir(path.join(configDir, 'skills'));
35
+ return true;
36
+ } catch {
37
+ return false;
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * =============================================================================
3
+ * Platform Registry
4
+ * =============================================================================
5
+ *
6
+ * Central registry for platform adapters.
7
+ * Handles platform detection and selection.
8
+ */
9
+
10
+ import { OpenCodeAdapter } from './opencode.js';
11
+ import { ClaudeAdapter } from './claude.js';
12
+ import { VSCodeAdapter } from './vscode.js';
13
+ import type { PlatformAdapter } from '../types.js';
14
+ import type { Platform } from '../constants.js';
15
+
16
+ const adapters: Map<string, PlatformAdapter> = new Map();
17
+
18
+ /**
19
+ * Register all built-in platform adapters
20
+ */
21
+ function registerAdapters(): void {
22
+ const opencode = new OpenCodeAdapter();
23
+ const claude = new ClaudeAdapter();
24
+ const vscode = new VSCodeAdapter();
25
+
26
+ adapters.set(opencode.id, opencode);
27
+ adapters.set(claude.id, claude);
28
+ adapters.set(vscode.id, vscode);
29
+ }
30
+
31
+ // Register adapters on module load
32
+ registerAdapters();
33
+
34
+ /**
35
+ * Detect which platforms are available on the current system
36
+ */
37
+ export async function detectPlatforms(): Promise<PlatformAdapter[]> {
38
+ const available: PlatformAdapter[] = [];
39
+
40
+ for (const adapter of adapters.values()) {
41
+ if (await adapter.isAvailable()) {
42
+ available.push(adapter);
43
+ }
44
+ }
45
+
46
+ return available;
47
+ }
48
+
49
+ /**
50
+ * Get adapter for a specific platform
51
+ */
52
+ export function getPlatformAdapter(platformId: string): PlatformAdapter | undefined {
53
+ return adapters.get(platformId);
54
+ }
55
+
56
+ /**
57
+ * Get all registered adapters
58
+ */
59
+ export function getAllAdapters(): PlatformAdapter[] {
60
+ return Array.from(adapters.values());
61
+ }
62
+
63
+ /**
64
+ * Get adapter by platform type
65
+ */
66
+ export function getAdapterByPlatform(platform: Platform): PlatformAdapter | undefined {
67
+ const idMap: Record<Platform, string> = {
68
+ opencode: 'opencode',
69
+ claude: 'claude',
70
+ vscode: 'vscode',
71
+ cursor: 'opencode', // Cursor uses OpenCode-compatible structure
72
+ codex: 'opencode', // Codex uses OpenCode-compatible structure
73
+ antigravity: 'opencode', // Antigravity uses OpenCode-compatible structure
74
+ };
75
+
76
+ return adapters.get(idMap[platform]);
77
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * =============================================================================
3
+ * VSCode (Copilot) Platform Adapter
4
+ * =============================================================================
5
+ *
6
+ * Handles skill installation for VSCode GitHub Copilot Agent Skills.
7
+ * Skills are installed to ~/.copilot/skills/<skill-id>/
8
+ *
9
+ * Note: Also supports ~/.claude/skills/ for cross-compatibility.
10
+ */
11
+
12
+ import path from 'path';
13
+ import os from 'os';
14
+ import fs from 'fs-extra';
15
+ import { BaseAdapter } from './base.js';
16
+
17
+ export class VSCodeAdapter extends BaseAdapter {
18
+ readonly id = 'vscode';
19
+ readonly name = 'VSCode';
20
+
21
+ get skillDir(): string {
22
+ // Try ~/.copilot/skills first, fallback to ~/.claude/skills
23
+ return path.join(os.homedir(), '.copilot', 'skills');
24
+ }
25
+
26
+ async isAvailable(): Promise<boolean> {
27
+ // Check multiple possible locations
28
+ const possibleDirs = [
29
+ path.join(os.homedir(), '.copilot', 'skills'),
30
+ path.join(os.homedir(), '.claude', 'skills'),
31
+ ];
32
+
33
+ for (const dir of possibleDirs) {
34
+ try {
35
+ await fs.ensureDir(dir);
36
+ return true;
37
+ } catch {
38
+ continue;
39
+ }
40
+ }
41
+
42
+ return false;
43
+ }
44
+
45
+ async install(skillId: string, sourceDir: string): Promise<void> {
46
+ // Install to ~/.copilot/skills, but also create symlink in ~/.claude/skills
47
+ await super.install(skillId, sourceDir);
48
+
49
+ // Create cross-compatible symlink in ~/.claude/skills
50
+ const claudeSkillDir = path.join(os.homedir(), '.claude', 'skills');
51
+ const targetPath = this.getSkillPath(skillId);
52
+ const claudeTargetPath = path.join(claudeSkillDir, skillId);
53
+
54
+ try {
55
+ await fs.ensureDir(claudeSkillDir);
56
+ await fs.remove(claudeTargetPath);
57
+ await fs.symlink(targetPath, claudeTargetPath, 'junction');
58
+ } catch {
59
+ // Silently fail if symlink not possible (cross-platform compatibility)
60
+ }
61
+ }
62
+ }