@birdie_moblie/plugin-marketplace-cli 1.0.0
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 +71 -0
- package/dist/adapters/claude.d.ts +41 -0
- package/dist/adapters/claude.js +89 -0
- package/dist/adapters/claude.js.map +1 -0
- package/dist/adapters/codex.d.ts +54 -0
- package/dist/adapters/codex.js +96 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/cli.d.ts +13 -0
- package/dist/cli.js +58 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/build.d.ts +9 -0
- package/dist/commands/build.js +37 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/index-gen.d.ts +9 -0
- package/dist/commands/index-gen.js +72 -0
- package/dist/commands/index-gen.js.map +1 -0
- package/dist/commands/init-repo.d.ts +7 -0
- package/dist/commands/init-repo.js +116 -0
- package/dist/commands/init-repo.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.js +101 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/release-local.d.ts +8 -0
- package/dist/commands/release-local.js +106 -0
- package/dist/commands/release-local.js.map +1 -0
- package/dist/commands/validate.d.ts +9 -0
- package/dist/commands/validate.js +150 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/schema/plugin-yaml.d.ts +59 -0
- package/dist/schema/plugin-yaml.js +140 -0
- package/dist/schema/plugin-yaml.js.map +1 -0
- package/dist/utils/helpers.d.ts +47 -0
- package/dist/utils/helpers.js +117 -0
- package/dist/utils/helpers.js.map +1 -0
- package/package.json +33 -0
package/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# @birdie_moblie/plugin-marketplace-cli
|
|
2
|
+
|
|
3
|
+
CLI for maintaining plugin marketplace repositories compatible with Claude Code and Codex.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install --save-dev @birdie_moblie/plugin-marketplace-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Commands
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
plugin-marketplace init-repo [name] --organization "Team Name"
|
|
15
|
+
plugin-marketplace init <plugin-name> --type <skill|mcp|hook>
|
|
16
|
+
plugin-marketplace validate [plugin-name] --all
|
|
17
|
+
plugin-marketplace build [plugin-name] --all
|
|
18
|
+
plugin-marketplace index
|
|
19
|
+
plugin-marketplace release-local
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Use `--root <dir>` to operate on a marketplace repository from another directory:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
plugin-marketplace --root /path/to/repo validate --all
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Without `--root`, the CLI searches upward from the current working directory for `marketplace.yaml`.
|
|
29
|
+
|
|
30
|
+
## Repository Layout
|
|
31
|
+
|
|
32
|
+
```text
|
|
33
|
+
.
|
|
34
|
+
├── marketplace.yaml
|
|
35
|
+
├── plugins/
|
|
36
|
+
│ └── my-plugin/
|
|
37
|
+
│ ├── plugin.yaml
|
|
38
|
+
│ └── skills/
|
|
39
|
+
├── .claude-plugin/marketplace.json
|
|
40
|
+
├── .agents/plugins/marketplace.json
|
|
41
|
+
└── marketplace.json
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`plugin.yaml` is the source of truth for each plugin. Generated manifest files must be committed when the repository itself is used as a marketplace source:
|
|
45
|
+
|
|
46
|
+
- `.claude-plugin/marketplace.json`
|
|
47
|
+
- `.agents/plugins/marketplace.json`
|
|
48
|
+
- `plugins/**/.claude-plugin/plugin.json`
|
|
49
|
+
- `plugins/**/.codex-plugin/plugin.json`
|
|
50
|
+
- `plugins/**/.mcp.json`
|
|
51
|
+
- `plugins/**/hooks/hooks.json`
|
|
52
|
+
- `marketplace.json`
|
|
53
|
+
- `plugins/CATALOG.md`
|
|
54
|
+
|
|
55
|
+
## Suggested Scripts
|
|
56
|
+
|
|
57
|
+
`plugin-marketplace init-repo` writes these scripts into new repositories:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"scripts": {
|
|
62
|
+
"mp": "plugin-marketplace",
|
|
63
|
+
"validate:plugins": "plugin-marketplace validate --all",
|
|
64
|
+
"build:plugins": "plugin-marketplace build --all",
|
|
65
|
+
"build:index": "plugin-marketplace index",
|
|
66
|
+
"build:all": "npm run build:plugins && npm run build:index",
|
|
67
|
+
"ci:local": "npm run validate:plugins && npm run build:all",
|
|
68
|
+
"release:local": "npm run ci:local && plugin-marketplace release-local"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code 适配器
|
|
3
|
+
*
|
|
4
|
+
* 从 plugin.yaml 生成 .claude-plugin/plugin.json 和相关配置文件。
|
|
5
|
+
*
|
|
6
|
+
* Claude Code 插件结构约定:
|
|
7
|
+
* - .claude-plugin/plugin.json — manifest
|
|
8
|
+
* - skills/<name>/SKILL.md — skill 文件(已在源码中维护,无需生成)
|
|
9
|
+
* - hooks/hooks.json — hook 配置(如果有 hooks 组件)
|
|
10
|
+
* - .mcp.json — MCP server 配置(如果有 mcp 组件)
|
|
11
|
+
*/
|
|
12
|
+
import type { PluginYaml } from '../schema/plugin-yaml.js';
|
|
13
|
+
export interface ClaudeManifest {
|
|
14
|
+
name: string;
|
|
15
|
+
version: string;
|
|
16
|
+
description: string;
|
|
17
|
+
author: {
|
|
18
|
+
name: string;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export interface ClaudeHooksConfig {
|
|
22
|
+
hooks: Record<string, Array<{
|
|
23
|
+
matcher: string;
|
|
24
|
+
hooks: Array<{
|
|
25
|
+
type: 'command';
|
|
26
|
+
command: string;
|
|
27
|
+
timeout?: number;
|
|
28
|
+
}>;
|
|
29
|
+
}>>;
|
|
30
|
+
}
|
|
31
|
+
export interface ClaudeMcpConfig {
|
|
32
|
+
mcpServers: Record<string, {
|
|
33
|
+
command: string;
|
|
34
|
+
args?: string[];
|
|
35
|
+
env?: Record<string, string>;
|
|
36
|
+
}>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 将 Claude Code 兼容的文件写入插件目录
|
|
40
|
+
*/
|
|
41
|
+
export declare function generateClaude(config: PluginYaml, pluginDir: string): void;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code 适配器
|
|
3
|
+
*
|
|
4
|
+
* 从 plugin.yaml 生成 .claude-plugin/plugin.json 和相关配置文件。
|
|
5
|
+
*
|
|
6
|
+
* Claude Code 插件结构约定:
|
|
7
|
+
* - .claude-plugin/plugin.json — manifest
|
|
8
|
+
* - skills/<name>/SKILL.md — skill 文件(已在源码中维护,无需生成)
|
|
9
|
+
* - hooks/hooks.json — hook 配置(如果有 hooks 组件)
|
|
10
|
+
* - .mcp.json — MCP server 配置(如果有 mcp 组件)
|
|
11
|
+
*/
|
|
12
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
13
|
+
import { join } from 'node:path';
|
|
14
|
+
/**
|
|
15
|
+
* 生成 Claude Code 的 .claude-plugin/plugin.json
|
|
16
|
+
*/
|
|
17
|
+
function buildManifest(config) {
|
|
18
|
+
return {
|
|
19
|
+
name: config.name,
|
|
20
|
+
version: config.version,
|
|
21
|
+
description: config.description,
|
|
22
|
+
author: { name: config.author.name },
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 生成 Claude Code 的 hooks/hooks.json(如果有 hooks 组件)
|
|
27
|
+
*/
|
|
28
|
+
function buildHooksConfig(config) {
|
|
29
|
+
const hooks = config.components.hooks;
|
|
30
|
+
if (!hooks || hooks.length === 0)
|
|
31
|
+
return null;
|
|
32
|
+
const hooksMap = {};
|
|
33
|
+
for (const hook of hooks) {
|
|
34
|
+
const entry = {
|
|
35
|
+
matcher: hook.pattern || '*',
|
|
36
|
+
hooks: [
|
|
37
|
+
{
|
|
38
|
+
type: 'command',
|
|
39
|
+
command: hook.command,
|
|
40
|
+
...(hook.timeout ? { timeout: hook.timeout } : {}),
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
if (!hooksMap[hook.event]) {
|
|
45
|
+
hooksMap[hook.event] = [];
|
|
46
|
+
}
|
|
47
|
+
hooksMap[hook.event].push(entry);
|
|
48
|
+
}
|
|
49
|
+
return { hooks: hooksMap };
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 生成 Claude Code 的 .mcp.json(如果有 mcp 组件)
|
|
53
|
+
*/
|
|
54
|
+
function buildMcpConfig(config) {
|
|
55
|
+
const mcps = config.components.mcp;
|
|
56
|
+
if (!mcps || mcps.length === 0)
|
|
57
|
+
return null;
|
|
58
|
+
const servers = {};
|
|
59
|
+
for (const mcp of mcps) {
|
|
60
|
+
servers[mcp.name] = {
|
|
61
|
+
command: mcp.command,
|
|
62
|
+
...(mcp.args ? { args: mcp.args } : {}),
|
|
63
|
+
...(mcp.env ? { env: mcp.env } : {}),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return { mcpServers: servers };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* 将 Claude Code 兼容的文件写入插件目录
|
|
70
|
+
*/
|
|
71
|
+
export function generateClaude(config, pluginDir) {
|
|
72
|
+
// 1. .claude-plugin/plugin.json
|
|
73
|
+
const claudeDir = join(pluginDir, '.claude-plugin');
|
|
74
|
+
mkdirSync(claudeDir, { recursive: true });
|
|
75
|
+
writeFileSync(join(claudeDir, 'plugin.json'), JSON.stringify(buildManifest(config), null, 2) + '\n');
|
|
76
|
+
// 2. hooks/hooks.json
|
|
77
|
+
const hooksConfig = buildHooksConfig(config);
|
|
78
|
+
if (hooksConfig) {
|
|
79
|
+
const hooksDir = join(pluginDir, 'hooks');
|
|
80
|
+
mkdirSync(hooksDir, { recursive: true });
|
|
81
|
+
writeFileSync(join(hooksDir, 'hooks.json'), JSON.stringify(hooksConfig, null, 2) + '\n');
|
|
82
|
+
}
|
|
83
|
+
// 3. .mcp.json
|
|
84
|
+
const mcpConfig = buildMcpConfig(config);
|
|
85
|
+
if (mcpConfig) {
|
|
86
|
+
writeFileSync(join(pluginDir, '.mcp.json'), JSON.stringify(mcpConfig, null, 2) + '\n');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/adapters/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex 适配器
|
|
3
|
+
*
|
|
4
|
+
* 从 plugin.yaml 生成 .codex-plugin/plugin.json 和 marketplace.json 条目。
|
|
5
|
+
*
|
|
6
|
+
* Codex 插件结构约定:
|
|
7
|
+
* - .codex-plugin/plugin.json — manifest(比 Claude Code 多 interface 字段)
|
|
8
|
+
* - skills/ — skill 文件(同上,无需生成)
|
|
9
|
+
* - .mcp.json — MCP 配置(格式与 Claude Code 相同)
|
|
10
|
+
*/
|
|
11
|
+
import type { PluginYaml } from '../schema/plugin-yaml.js';
|
|
12
|
+
export interface CodexManifest {
|
|
13
|
+
name: string;
|
|
14
|
+
version: string;
|
|
15
|
+
description: string;
|
|
16
|
+
author: {
|
|
17
|
+
name: string;
|
|
18
|
+
email: string;
|
|
19
|
+
url: string;
|
|
20
|
+
};
|
|
21
|
+
interface: {
|
|
22
|
+
displayName: string;
|
|
23
|
+
shortDescription: string;
|
|
24
|
+
longDescription: string;
|
|
25
|
+
category: string;
|
|
26
|
+
developerName: string;
|
|
27
|
+
};
|
|
28
|
+
skills?: string;
|
|
29
|
+
mcpServers?: string;
|
|
30
|
+
hooks?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface CodexMarketplaceEntry {
|
|
33
|
+
name: string;
|
|
34
|
+
source: {
|
|
35
|
+
source: 'local';
|
|
36
|
+
path: string;
|
|
37
|
+
};
|
|
38
|
+
interface: {
|
|
39
|
+
displayName: string;
|
|
40
|
+
};
|
|
41
|
+
policy: {
|
|
42
|
+
installation: 'AVAILABLE';
|
|
43
|
+
authentication: 'ON_INSTALL';
|
|
44
|
+
};
|
|
45
|
+
category: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 生成 marketplace.json 中的一个条目
|
|
49
|
+
*/
|
|
50
|
+
export declare function buildMarketplaceEntry(config: PluginYaml, relativePath: string): CodexMarketplaceEntry;
|
|
51
|
+
/**
|
|
52
|
+
* 将 Codex 兼容的文件写入插件目录
|
|
53
|
+
*/
|
|
54
|
+
export declare function generateCodex(config: PluginYaml, pluginDir: string): void;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex 适配器
|
|
3
|
+
*
|
|
4
|
+
* 从 plugin.yaml 生成 .codex-plugin/plugin.json 和 marketplace.json 条目。
|
|
5
|
+
*
|
|
6
|
+
* Codex 插件结构约定:
|
|
7
|
+
* - .codex-plugin/plugin.json — manifest(比 Claude Code 多 interface 字段)
|
|
8
|
+
* - skills/ — skill 文件(同上,无需生成)
|
|
9
|
+
* - .mcp.json — MCP 配置(格式与 Claude Code 相同)
|
|
10
|
+
*/
|
|
11
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
import { toTitleCase } from '../utils/helpers.js';
|
|
14
|
+
/**
|
|
15
|
+
* 生成 Codex 的 .codex-plugin/plugin.json
|
|
16
|
+
*
|
|
17
|
+
* 如果 plugin.yaml 中没有显式指定 platform.codex.interface,
|
|
18
|
+
* 则从 name 和 description 自动推导。
|
|
19
|
+
*/
|
|
20
|
+
function buildManifest(config) {
|
|
21
|
+
const iface = config.platform?.codex?.interface;
|
|
22
|
+
const manifest = {
|
|
23
|
+
name: config.name,
|
|
24
|
+
version: config.version,
|
|
25
|
+
description: config.description,
|
|
26
|
+
author: {
|
|
27
|
+
name: config.author.name,
|
|
28
|
+
email: config.author.email || '',
|
|
29
|
+
url: config.author.url || '',
|
|
30
|
+
},
|
|
31
|
+
interface: {
|
|
32
|
+
displayName: iface?.displayName || toTitleCase(config.name),
|
|
33
|
+
shortDescription: iface?.shortDescription || config.description,
|
|
34
|
+
longDescription: iface?.longDescription || config.description,
|
|
35
|
+
category: iface?.category || config.category || 'General',
|
|
36
|
+
developerName: iface?.developerName || config.author.name,
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
// skills 引用
|
|
40
|
+
const skills = config.components.skills;
|
|
41
|
+
if (skills && skills.length > 0) {
|
|
42
|
+
manifest.skills = './skills/';
|
|
43
|
+
}
|
|
44
|
+
// MCP 引用
|
|
45
|
+
const mcps = config.components.mcp;
|
|
46
|
+
if (mcps && mcps.length > 0) {
|
|
47
|
+
manifest.mcpServers = './.mcp.json';
|
|
48
|
+
}
|
|
49
|
+
// Hooks 引用
|
|
50
|
+
const hooks = config.components.hooks;
|
|
51
|
+
if (hooks && hooks.length > 0) {
|
|
52
|
+
manifest.hooks = './hooks/hooks.json';
|
|
53
|
+
}
|
|
54
|
+
return manifest;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* 生成 marketplace.json 中的一个条目
|
|
58
|
+
*/
|
|
59
|
+
export function buildMarketplaceEntry(config, relativePath) {
|
|
60
|
+
const iface = config.platform?.codex?.interface;
|
|
61
|
+
return {
|
|
62
|
+
name: config.name,
|
|
63
|
+
source: { source: 'local', path: relativePath },
|
|
64
|
+
interface: {
|
|
65
|
+
displayName: iface?.displayName || toTitleCase(config.name),
|
|
66
|
+
},
|
|
67
|
+
policy: {
|
|
68
|
+
installation: 'AVAILABLE',
|
|
69
|
+
authentication: 'ON_INSTALL',
|
|
70
|
+
},
|
|
71
|
+
category: iface?.category || config.category || 'General',
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* 将 Codex 兼容的文件写入插件目录
|
|
76
|
+
*/
|
|
77
|
+
export function generateCodex(config, pluginDir) {
|
|
78
|
+
// .codex-plugin/plugin.json
|
|
79
|
+
const codexDir = join(pluginDir, '.codex-plugin');
|
|
80
|
+
mkdirSync(codexDir, { recursive: true });
|
|
81
|
+
writeFileSync(join(codexDir, 'plugin.json'), JSON.stringify(buildManifest(config), null, 2) + '\n');
|
|
82
|
+
// .mcp.json(Codex 的 MCP 格式与 Claude Code 相同)
|
|
83
|
+
const mcps = config.components.mcp;
|
|
84
|
+
if (mcps && mcps.length > 0) {
|
|
85
|
+
const servers = {};
|
|
86
|
+
for (const mcp of mcps) {
|
|
87
|
+
servers[mcp.name] = {
|
|
88
|
+
command: mcp.command,
|
|
89
|
+
...(mcp.args ? { args: mcp.args } : {}),
|
|
90
|
+
...(mcp.env ? { env: mcp.env } : {}),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
writeFileSync(join(pluginDir, '.mcp.json'), JSON.stringify({ mcpServers: servers }, null, 2) + '\n');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=codex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/adapters/codex.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* plugin-marketplace CLI — Plugin Marketplace 管理工具
|
|
4
|
+
*
|
|
5
|
+
* 命令:
|
|
6
|
+
* plugin-marketplace init-repo [name] 创建新插件仓库
|
|
7
|
+
* plugin-marketplace init <name> 创建新插件
|
|
8
|
+
* plugin-marketplace validate [name] 验证插件格式
|
|
9
|
+
* plugin-marketplace build [name] 生成双平台 manifest
|
|
10
|
+
* plugin-marketplace index 生成 marketplace 索引
|
|
11
|
+
* plugin-marketplace release-local 组装本地发布包
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* plugin-marketplace CLI — Plugin Marketplace 管理工具
|
|
4
|
+
*
|
|
5
|
+
* 命令:
|
|
6
|
+
* plugin-marketplace init-repo [name] 创建新插件仓库
|
|
7
|
+
* plugin-marketplace init <name> 创建新插件
|
|
8
|
+
* plugin-marketplace validate [name] 验证插件格式
|
|
9
|
+
* plugin-marketplace build [name] 生成双平台 manifest
|
|
10
|
+
* plugin-marketplace index 生成 marketplace 索引
|
|
11
|
+
* plugin-marketplace release-local 组装本地发布包
|
|
12
|
+
*/
|
|
13
|
+
import { Command } from 'commander';
|
|
14
|
+
import { runInitRepo } from './commands/init-repo.js';
|
|
15
|
+
import { runInit } from './commands/init.js';
|
|
16
|
+
import { runValidate } from './commands/validate.js';
|
|
17
|
+
import { runBuild } from './commands/build.js';
|
|
18
|
+
import { runIndexGen } from './commands/index-gen.js';
|
|
19
|
+
import { runReleaseLocal } from './commands/release-local.js';
|
|
20
|
+
const program = new Command();
|
|
21
|
+
function rootOption() {
|
|
22
|
+
return program.opts().root;
|
|
23
|
+
}
|
|
24
|
+
program
|
|
25
|
+
.name('plugin-marketplace')
|
|
26
|
+
.description('Plugin Marketplace CLI — 管理兼容 Claude Code 和 Codex 的插件仓库')
|
|
27
|
+
.version('1.0.0')
|
|
28
|
+
.option('--root <dir>', '插件仓库根目录;默认从当前目录向上查找 marketplace.yaml');
|
|
29
|
+
program
|
|
30
|
+
.command('init-repo [name]')
|
|
31
|
+
.description('创建新的 plugin marketplace 仓库')
|
|
32
|
+
.option('--organization <name>', 'Marketplace owner / organization 名称')
|
|
33
|
+
.action((name, options) => runInitRepo(name, { ...options, root: rootOption() }));
|
|
34
|
+
program
|
|
35
|
+
.command('init <name>')
|
|
36
|
+
.description('创建新插件骨架')
|
|
37
|
+
.option('-t, --type <type>', '插件类型: skill, mcp, hook', 'skill')
|
|
38
|
+
.action((name, options) => runInit(name, { ...options, root: rootOption() }));
|
|
39
|
+
program
|
|
40
|
+
.command('validate [name]')
|
|
41
|
+
.description('验证插件格式')
|
|
42
|
+
.option('-a, --all', '验证所有插件')
|
|
43
|
+
.action((name, options) => runValidate(name, { ...options, root: rootOption() }));
|
|
44
|
+
program
|
|
45
|
+
.command('build [name]')
|
|
46
|
+
.description('从 plugin.yaml 生成双平台 manifest')
|
|
47
|
+
.option('-a, --all', '构建所有插件')
|
|
48
|
+
.action((name, options) => runBuild(name, { ...options, root: rootOption() }));
|
|
49
|
+
program
|
|
50
|
+
.command('index')
|
|
51
|
+
.description('生成 marketplace 索引文件')
|
|
52
|
+
.action(() => runIndexGen({ root: rootOption() }));
|
|
53
|
+
program
|
|
54
|
+
.command('release-local')
|
|
55
|
+
.description('组装本地发布包')
|
|
56
|
+
.action(() => runReleaseLocal({ root: rootOption() }));
|
|
57
|
+
program.parse();
|
|
58
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,SAAS,UAAU;IACjB,OAAO,OAAO,CAAC,IAAI,EAAqB,CAAC,IAAI,CAAC;AAChD,CAAC;AAED,OAAO;KACJ,IAAI,CAAC,oBAAoB,CAAC;KAC1B,WAAW,CAAC,yDAAyD,CAAC;KACtE,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,cAAc,EAAE,sCAAsC,CAAC,CAAC;AAElE,OAAO;KACJ,OAAO,CAAC,kBAAkB,CAAC;KAC3B,WAAW,CAAC,4BAA4B,CAAC;KACzC,MAAM,CAAC,uBAAuB,EAAE,qCAAqC,CAAC;KACtE,MAAM,CAAC,CAAC,IAAwB,EAAE,OAAkC,EAAE,EAAE,CACvE,WAAW,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,CACtD,CAAC;AAEJ,OAAO;KACJ,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,SAAS,CAAC;KACtB,MAAM,CAAC,mBAAmB,EAAE,wBAAwB,EAAE,OAAO,CAAC;KAC9D,MAAM,CAAC,CAAC,IAAY,EAAE,OAAyB,EAAE,EAAE,CAClD,OAAO,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,CAClD,CAAC;AAEJ,OAAO;KACJ,OAAO,CAAC,iBAAiB,CAAC;KAC1B,WAAW,CAAC,QAAQ,CAAC;KACrB,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC;KAC7B,MAAM,CAAC,CAAC,IAAwB,EAAE,OAAyB,EAAE,EAAE,CAC9D,WAAW,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,CACtD,CAAC;AAEJ,OAAO;KACJ,OAAO,CAAC,cAAc,CAAC;KACvB,WAAW,CAAC,8BAA8B,CAAC;KAC3C,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC;KAC7B,MAAM,CAAC,CAAC,IAAwB,EAAE,OAAyB,EAAE,EAAE,CAC9D,QAAQ,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,CACnD,CAAC;AAEJ,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,qBAAqB,CAAC;KAClC,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;AAErD,OAAO;KACJ,OAAO,CAAC,eAAe,CAAC;KACxB,WAAW,CAAC,SAAS,CAAC;KACtB,MAAM,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;AAEzD,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* build 命令 — 从 plugin.yaml 生成双平台 manifest
|
|
3
|
+
*
|
|
4
|
+
* 用法:mp build [name] 或 mp build --all
|
|
5
|
+
*/
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import { loadPluginYaml, listPluginNames, resolveRepoContext, } from '../utils/helpers.js';
|
|
9
|
+
import { generateClaude } from '../adapters/claude.js';
|
|
10
|
+
import { generateCodex } from '../adapters/codex.js';
|
|
11
|
+
function buildOne(context, name) {
|
|
12
|
+
const pluginDir = join(context.pluginsDir, name);
|
|
13
|
+
const config = loadPluginYaml(pluginDir);
|
|
14
|
+
generateClaude(config, pluginDir);
|
|
15
|
+
generateCodex(config, pluginDir);
|
|
16
|
+
console.log(chalk.green(` ✓ ${name}`));
|
|
17
|
+
}
|
|
18
|
+
export function runBuild(name, options) {
|
|
19
|
+
const context = resolveRepoContext(options.root);
|
|
20
|
+
const names = options.all ? listPluginNames(context) : name ? [name] : [];
|
|
21
|
+
if (names.length === 0) {
|
|
22
|
+
console.error(chalk.red('✗ 请指定插件名或使用 --all'));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
console.log(chalk.blue(`⟳ 构建 ${names.length} 个插件的平台 manifest...\n`));
|
|
26
|
+
for (const n of names) {
|
|
27
|
+
try {
|
|
28
|
+
buildOne(context, n);
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
console.error(chalk.red(` ✗ ${n}: ${err.message}`));
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
console.log(chalk.green(`\n✓ 构建完成`));
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAEL,cAAc,EACd,eAAe,EACf,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,SAAS,QAAQ,CAAC,OAA0B,EAAE,IAAY;IACxD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IAEzC,cAAc,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAClC,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAEjC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,QAAQ,CACtB,IAAwB,EACxB,OAAwC;IAExC,MAAM,OAAO,GAAG,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAE1E,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC;QAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,KAAK,CAAC,MAAM,uBAAuB,CAAC,CAAC,CAAC;IAErE,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC;YACH,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QACvB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,KAAM,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* index-gen 命令 — 生成 marketplace 索引文件
|
|
3
|
+
*
|
|
4
|
+
* Claude Code: 生成 .claude-plugin/marketplace.json
|
|
5
|
+
* Codex: 生成 .agents/plugins/marketplace.json,并保留根 marketplace.json 兼容镜像
|
|
6
|
+
*/
|
|
7
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
import { loadAllPlugins, loadMarketplaceMetadata, resolveRepoContext, toTitleCase, } from '../utils/helpers.js';
|
|
11
|
+
import { buildMarketplaceEntry } from '../adapters/codex.js';
|
|
12
|
+
function writeJson(path, value) {
|
|
13
|
+
mkdirSync(join(path, '..'), { recursive: true });
|
|
14
|
+
writeFileSync(path, JSON.stringify(value, null, 2) + '\n');
|
|
15
|
+
}
|
|
16
|
+
export function runIndexGen(options = {}) {
|
|
17
|
+
console.log(chalk.blue('⟳ 生成 marketplace 索引...\n'));
|
|
18
|
+
const context = resolveRepoContext(options.root);
|
|
19
|
+
const plugins = loadAllPlugins(context);
|
|
20
|
+
const marketplace = loadMarketplaceMetadata(context);
|
|
21
|
+
if (plugins.length === 0) {
|
|
22
|
+
console.log(chalk.yellow(' ⚠ 没有找到插件'));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const marketplaceDisplayName = toTitleCase(marketplace.name);
|
|
26
|
+
const ownerName = marketplace.organization || marketplaceDisplayName;
|
|
27
|
+
// ── Claude Code marketplace ──
|
|
28
|
+
const claudeMarketplace = {
|
|
29
|
+
name: marketplace.name,
|
|
30
|
+
owner: {
|
|
31
|
+
name: ownerName,
|
|
32
|
+
},
|
|
33
|
+
...(marketplace.description ? { description: marketplace.description } : {}),
|
|
34
|
+
plugins: plugins.map(({ name, config }) => ({
|
|
35
|
+
name: config.name,
|
|
36
|
+
source: `./plugins/${name}`,
|
|
37
|
+
description: config.description,
|
|
38
|
+
version: config.version,
|
|
39
|
+
author: {
|
|
40
|
+
name: config.author.name,
|
|
41
|
+
...(config.author.email ? { email: config.author.email } : {}),
|
|
42
|
+
},
|
|
43
|
+
...(config.category ? { category: config.category } : {}),
|
|
44
|
+
...(config.tags?.length ? { tags: config.tags } : {}),
|
|
45
|
+
})),
|
|
46
|
+
};
|
|
47
|
+
writeJson(join(context.rootDir, '.claude-plugin/marketplace.json'), claudeMarketplace);
|
|
48
|
+
console.log(chalk.green(' ✓ .claude-plugin/marketplace.json (Claude Code)'));
|
|
49
|
+
// ── Codex marketplace ──
|
|
50
|
+
const codexEntries = plugins.map(({ name, config }) => buildMarketplaceEntry(config, `./plugins/${name}`));
|
|
51
|
+
const codexMarketplace = {
|
|
52
|
+
name: marketplace.name,
|
|
53
|
+
interface: {
|
|
54
|
+
displayName: marketplaceDisplayName,
|
|
55
|
+
},
|
|
56
|
+
plugins: codexEntries,
|
|
57
|
+
};
|
|
58
|
+
writeJson(join(context.rootDir, '.agents/plugins/marketplace.json'), codexMarketplace);
|
|
59
|
+
console.log(chalk.green(' ✓ .agents/plugins/marketplace.json (Codex)'));
|
|
60
|
+
// ── 根目录兼容镜像 ──
|
|
61
|
+
writeJson(join(context.rootDir, 'marketplace.json'), codexMarketplace);
|
|
62
|
+
console.log(chalk.green(' ✓ marketplace.json (compatibility mirror)'));
|
|
63
|
+
// ── 人类可读目录 ──
|
|
64
|
+
const pluginList = plugins
|
|
65
|
+
.map(({ name, config }) => `- **${name}** (v${config.version}): ${config.description}`)
|
|
66
|
+
.join('\n');
|
|
67
|
+
const catalogMd = `# Plugin Catalog\n\n${pluginList}\n\n_Auto-generated. Do not edit manually._\n`;
|
|
68
|
+
writeFileSync(join(context.pluginsDir, 'CATALOG.md'), catalogMd);
|
|
69
|
+
console.log(chalk.green(' ✓ plugins/CATALOG.md'));
|
|
70
|
+
console.log(chalk.green(`\n✓ 索引生成完成 (${plugins.length} 个插件)`));
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=index-gen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-gen.js","sourceRoot":"","sources":["../../src/commands/index-gen.ts"],"names":[],"mappings":"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"}
|