mcpick 0.0.14 → 0.0.15
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/CHANGELOG.md +8 -0
- package/dist/cli/commands/cache.js +10 -3
- package/dist/cli/commands/dev.js +3 -4
- package/dist/cli/commands/marketplace.js +162 -0
- package/dist/cli/commands/plugins.js +20 -0
- package/dist/cli/commands/reload.js +36 -0
- package/dist/cli/index.js +2 -0
- package/dist/core/dev-override.js +3 -3
- package/dist/core/plugin-cache.js +95 -5
- package/dist/index.js +2 -0
- package/dist/utils/claude-cli.js +95 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineCommand } from 'citty';
|
|
2
|
-
import { clean_orphaned_versions, clear_plugin_caches, get_cached_plugins_info, link_local_plugin, list_linked_plugins, read_installed_plugins, refresh_all_marketplaces, unlink_local_plugin, } from '../../core/plugin-cache.js';
|
|
2
|
+
import { clean_orphaned_versions, clear_plugin_caches, get_cached_plugins_info, link_local_plugin, list_linked_plugins, read_installed_plugins, refresh_all_marketplaces, scan_all_cache_keys, unlink_local_plugin, } from '../../core/plugin-cache.js';
|
|
3
3
|
import { error, output } from '../output.js';
|
|
4
4
|
const status = defineCommand({
|
|
5
5
|
meta: {
|
|
@@ -65,7 +65,13 @@ const clear = defineCommand({
|
|
|
65
65
|
},
|
|
66
66
|
async run({ args }) {
|
|
67
67
|
const installed = await read_installed_plugins();
|
|
68
|
-
const
|
|
68
|
+
const installed_keys = Object.keys(installed.plugins);
|
|
69
|
+
// When --all, also scan disk for marketplace-sourced caches
|
|
70
|
+
// not tracked in installed_plugins.json
|
|
71
|
+
const scanned_keys = args.all ? await scan_all_cache_keys() : [];
|
|
72
|
+
const all_keys = [
|
|
73
|
+
...new Set([...installed_keys, ...scanned_keys]),
|
|
74
|
+
];
|
|
69
75
|
if (all_keys.length === 0) {
|
|
70
76
|
if (args.json) {
|
|
71
77
|
output({ cleared: [], errors: [] }, true);
|
|
@@ -77,7 +83,8 @@ const clear = defineCommand({
|
|
|
77
83
|
}
|
|
78
84
|
let keys_to_clear;
|
|
79
85
|
if (args.plugin) {
|
|
80
|
-
if (!installed.plugins[args.plugin]
|
|
86
|
+
if (!installed.plugins[args.plugin] &&
|
|
87
|
+
!scanned_keys.includes(args.plugin)) {
|
|
81
88
|
error(`Plugin '${args.plugin}' not found in cache. Run 'mcpick cache status' to see cached plugins.`);
|
|
82
89
|
}
|
|
83
90
|
keys_to_clear = [args.plugin];
|
package/dist/cli/commands/dev.js
CHANGED
|
@@ -36,9 +36,7 @@ const apply = defineCommand({
|
|
|
36
36
|
if (scope && !['local', 'project', 'user'].includes(scope)) {
|
|
37
37
|
error(`Invalid scope: ${scope}. Use local, project, or user.`);
|
|
38
38
|
}
|
|
39
|
-
const cmd_args = args.args
|
|
40
|
-
? args.args.split(',')
|
|
41
|
-
: [];
|
|
39
|
+
const cmd_args = args.args ? args.args.split(',') : [];
|
|
42
40
|
const result = await apply_dev_override(args.name, args.command, cmd_args, scope);
|
|
43
41
|
if (args.json) {
|
|
44
42
|
output(result, true);
|
|
@@ -82,7 +80,8 @@ const restore = defineCommand({
|
|
|
82
80
|
output(result, true);
|
|
83
81
|
}
|
|
84
82
|
else {
|
|
85
|
-
if (result.restored.length === 0 &&
|
|
83
|
+
if (result.restored.length === 0 &&
|
|
84
|
+
result.errors.length === 0) {
|
|
86
85
|
console.log('No dev overrides to restore.');
|
|
87
86
|
}
|
|
88
87
|
else {
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { defineCommand } from 'citty';
|
|
2
|
+
import { marketplace_add_via_cli, marketplace_list_via_cli, marketplace_remove_via_cli, marketplace_update_via_cli, } from '../../utils/claude-cli.js';
|
|
3
|
+
import { error, output } from '../output.js';
|
|
4
|
+
const list = defineCommand({
|
|
5
|
+
meta: {
|
|
6
|
+
name: 'list',
|
|
7
|
+
description: 'List configured marketplaces',
|
|
8
|
+
},
|
|
9
|
+
args: {
|
|
10
|
+
json: {
|
|
11
|
+
type: 'boolean',
|
|
12
|
+
description: 'Output as JSON',
|
|
13
|
+
default: false,
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
async run({ args }) {
|
|
17
|
+
const result = await marketplace_list_via_cli();
|
|
18
|
+
if (!result.success) {
|
|
19
|
+
error(result.error || 'Unknown error');
|
|
20
|
+
}
|
|
21
|
+
if (args.json) {
|
|
22
|
+
// Try to parse CLI JSON output, fallback to raw
|
|
23
|
+
try {
|
|
24
|
+
const parsed = JSON.parse(result.stdout || '[]');
|
|
25
|
+
output(parsed, true);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
output({ marketplaces: result.stdout }, true);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
console.log(result.stdout || 'No marketplaces configured.');
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
const add = defineCommand({
|
|
37
|
+
meta: {
|
|
38
|
+
name: 'add',
|
|
39
|
+
description: 'Add a marketplace from URL, path, or GitHub repo',
|
|
40
|
+
},
|
|
41
|
+
args: {
|
|
42
|
+
source: {
|
|
43
|
+
type: 'positional',
|
|
44
|
+
description: 'Marketplace source (GitHub repo, URL, or local path)',
|
|
45
|
+
required: true,
|
|
46
|
+
},
|
|
47
|
+
scope: {
|
|
48
|
+
type: 'string',
|
|
49
|
+
description: 'Scope: user, project, or local (default: user)',
|
|
50
|
+
default: 'user',
|
|
51
|
+
},
|
|
52
|
+
json: {
|
|
53
|
+
type: 'boolean',
|
|
54
|
+
description: 'Output as JSON',
|
|
55
|
+
default: false,
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
async run({ args }) {
|
|
59
|
+
const scope = args.scope;
|
|
60
|
+
if (!['user', 'project', 'local'].includes(scope)) {
|
|
61
|
+
error(`Invalid scope: ${scope}. Use user, project, or local.`);
|
|
62
|
+
}
|
|
63
|
+
const result = await marketplace_add_via_cli(args.source, scope);
|
|
64
|
+
if (args.json) {
|
|
65
|
+
output({
|
|
66
|
+
added: args.source,
|
|
67
|
+
scope,
|
|
68
|
+
success: result.success,
|
|
69
|
+
error: result.error,
|
|
70
|
+
}, true);
|
|
71
|
+
}
|
|
72
|
+
else if (result.success) {
|
|
73
|
+
console.log(`Marketplace added: ${args.source} (scope: ${scope})`);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
error(result.error || 'Unknown error');
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
const remove = defineCommand({
|
|
81
|
+
meta: {
|
|
82
|
+
name: 'remove',
|
|
83
|
+
description: 'Remove a marketplace',
|
|
84
|
+
},
|
|
85
|
+
args: {
|
|
86
|
+
name: {
|
|
87
|
+
type: 'positional',
|
|
88
|
+
description: 'Marketplace name to remove',
|
|
89
|
+
required: true,
|
|
90
|
+
},
|
|
91
|
+
json: {
|
|
92
|
+
type: 'boolean',
|
|
93
|
+
description: 'Output as JSON',
|
|
94
|
+
default: false,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
async run({ args }) {
|
|
98
|
+
const result = await marketplace_remove_via_cli(args.name);
|
|
99
|
+
if (args.json) {
|
|
100
|
+
output({
|
|
101
|
+
removed: args.name,
|
|
102
|
+
success: result.success,
|
|
103
|
+
error: result.error,
|
|
104
|
+
}, true);
|
|
105
|
+
}
|
|
106
|
+
else if (result.success) {
|
|
107
|
+
console.log(`Marketplace removed: ${args.name}`);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
error(result.error || 'Unknown error');
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
const update = defineCommand({
|
|
115
|
+
meta: {
|
|
116
|
+
name: 'update',
|
|
117
|
+
description: 'Update marketplace(s) from source',
|
|
118
|
+
},
|
|
119
|
+
args: {
|
|
120
|
+
name: {
|
|
121
|
+
type: 'positional',
|
|
122
|
+
description: 'Marketplace name to update (omit to update all)',
|
|
123
|
+
required: false,
|
|
124
|
+
},
|
|
125
|
+
json: {
|
|
126
|
+
type: 'boolean',
|
|
127
|
+
description: 'Output as JSON',
|
|
128
|
+
default: false,
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
async run({ args }) {
|
|
132
|
+
const result = await marketplace_update_via_cli(args.name || undefined);
|
|
133
|
+
if (args.json) {
|
|
134
|
+
output({
|
|
135
|
+
updated: args.name || 'all',
|
|
136
|
+
success: result.success,
|
|
137
|
+
error: result.error,
|
|
138
|
+
}, true);
|
|
139
|
+
}
|
|
140
|
+
else if (result.success) {
|
|
141
|
+
console.log(args.name
|
|
142
|
+
? `Marketplace updated: ${args.name}`
|
|
143
|
+
: 'All marketplaces updated.');
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
error(result.error || 'Unknown error');
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
export default defineCommand({
|
|
151
|
+
meta: {
|
|
152
|
+
name: 'marketplace',
|
|
153
|
+
description: 'Manage Claude Code plugin marketplaces',
|
|
154
|
+
},
|
|
155
|
+
subCommands: {
|
|
156
|
+
list,
|
|
157
|
+
add,
|
|
158
|
+
remove,
|
|
159
|
+
update,
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
//# sourceMappingURL=marketplace.js.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { defineCommand } from 'citty';
|
|
2
|
+
import { parse_plugin_key, read_known_marketplaces, } from '../../core/plugin-cache.js';
|
|
2
3
|
import { build_enabled_plugins, get_all_plugins, read_claude_settings, write_claude_settings, } from '../../core/settings.js';
|
|
3
4
|
import { install_plugin_via_cli, uninstall_plugin_via_cli, update_plugin_via_cli, } from '../../utils/claude-cli.js';
|
|
4
5
|
import { error, output } from '../output.js';
|
|
@@ -144,6 +145,25 @@ const uninstall = defineCommand({
|
|
|
144
145
|
},
|
|
145
146
|
async run({ args }) {
|
|
146
147
|
const scope = args.scope;
|
|
148
|
+
// Check if this is a marketplace-managed plugin
|
|
149
|
+
const { marketplace } = parse_plugin_key(args.plugin);
|
|
150
|
+
const known = await read_known_marketplaces();
|
|
151
|
+
if (known[marketplace]) {
|
|
152
|
+
const msg = `'${args.plugin}' is managed by marketplace '${marketplace}'.\n` +
|
|
153
|
+
`To remove the marketplace: mcpick marketplace remove ${marketplace}\n` +
|
|
154
|
+
`Or via Claude CLI: claude plugin marketplace remove ${marketplace}`;
|
|
155
|
+
if (args.json) {
|
|
156
|
+
output({
|
|
157
|
+
success: false,
|
|
158
|
+
error: msg,
|
|
159
|
+
marketplace_managed: true,
|
|
160
|
+
}, true);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
error(msg);
|
|
164
|
+
}
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
147
167
|
const result = await uninstall_plugin_via_cli(args.plugin, scope);
|
|
148
168
|
if (args.json) {
|
|
149
169
|
output(result, true);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { defineCommand } from 'citty';
|
|
2
|
+
import { output } from '../output.js';
|
|
3
|
+
export default defineCommand({
|
|
4
|
+
meta: {
|
|
5
|
+
name: 'reload',
|
|
6
|
+
description: 'Reload plugins in Claude Code',
|
|
7
|
+
},
|
|
8
|
+
args: {
|
|
9
|
+
json: {
|
|
10
|
+
type: 'boolean',
|
|
11
|
+
description: 'Output as JSON',
|
|
12
|
+
default: false,
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
async run({ args }) {
|
|
16
|
+
const info = {
|
|
17
|
+
supported: false,
|
|
18
|
+
message: 'Claude Code does not expose a programmatic reload API.',
|
|
19
|
+
instructions: [
|
|
20
|
+
'Run /reload-plugins inside an active Claude Code session',
|
|
21
|
+
'Or restart your Claude Code session to pick up changes',
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
if (args.json) {
|
|
25
|
+
output(info, true);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
console.log(info.message);
|
|
29
|
+
console.log('\nTo reload plugins:');
|
|
30
|
+
for (const instruction of info.instructions) {
|
|
31
|
+
console.log(` - ${instruction}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
//# sourceMappingURL=reload.js.map
|
package/dist/cli/index.js
CHANGED
|
@@ -16,6 +16,8 @@ const main = defineCommand({
|
|
|
16
16
|
plugins: () => import('./commands/plugins.js').then((m) => m.default),
|
|
17
17
|
cache: () => import('./commands/cache.js').then((m) => m.default),
|
|
18
18
|
dev: () => import('./commands/dev.js').then((m) => m.default),
|
|
19
|
+
marketplace: () => import('./commands/marketplace.js').then((m) => m.default),
|
|
20
|
+
reload: () => import('./commands/reload.js').then((m) => m.default),
|
|
19
21
|
},
|
|
20
22
|
});
|
|
21
23
|
export const run = () => runMain(main);
|
|
@@ -82,8 +82,7 @@ async function write_server_to_scope(name, server, scope) {
|
|
|
82
82
|
if (!existing.mcpServers) {
|
|
83
83
|
existing.mcpServers = {};
|
|
84
84
|
}
|
|
85
|
-
existing.mcpServers[name] =
|
|
86
|
-
server;
|
|
85
|
+
existing.mcpServers[name] = server;
|
|
87
86
|
return existing;
|
|
88
87
|
});
|
|
89
88
|
}
|
|
@@ -100,7 +99,8 @@ async function write_server_to_scope(name, server, scope) {
|
|
|
100
99
|
if (!projects[cwd].mcpServers) {
|
|
101
100
|
projects[cwd].mcpServers = {};
|
|
102
101
|
}
|
|
103
|
-
projects[cwd].mcpServers[name] =
|
|
102
|
+
projects[cwd].mcpServers[name] =
|
|
103
|
+
server;
|
|
104
104
|
return existing;
|
|
105
105
|
});
|
|
106
106
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { exec } from 'node:child_process';
|
|
2
|
-
import { lstat, readdir, readFile, readlink, rename, rm, symlink } from 'node:fs/promises';
|
|
2
|
+
import { lstat, readdir, readFile, readlink, rename, rm, symlink, } from 'node:fs/promises';
|
|
3
3
|
import { join, resolve } from 'node:path';
|
|
4
4
|
import { promisify } from 'node:util';
|
|
5
5
|
import { atomic_json_write } from '../utils/atomic-write.js';
|
|
@@ -50,6 +50,51 @@ async function get_marketplace_head_sha(marketplace_path) {
|
|
|
50
50
|
return null;
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Recover a marketplace clone stuck on a deleted branch.
|
|
55
|
+
* Resets the fetch refspec, fetches all branches, and checks out the default branch.
|
|
56
|
+
*/
|
|
57
|
+
async function recover_deleted_branch(dir) {
|
|
58
|
+
const q = JSON.stringify(dir);
|
|
59
|
+
try {
|
|
60
|
+
// Reset narrow refspec to fetch all branches
|
|
61
|
+
await execAsync(`git -C ${q} remote set-branches origin '*'`, {
|
|
62
|
+
timeout: 10_000,
|
|
63
|
+
});
|
|
64
|
+
await execAsync(`git -C ${q} fetch origin`, {
|
|
65
|
+
timeout: 30_000,
|
|
66
|
+
});
|
|
67
|
+
// Detect default branch
|
|
68
|
+
let default_branch = 'main';
|
|
69
|
+
try {
|
|
70
|
+
const { stdout } = await execAsync(`git -C ${q} symbolic-ref refs/remotes/origin/HEAD`, { timeout: 5_000 });
|
|
71
|
+
const match = stdout
|
|
72
|
+
.trim()
|
|
73
|
+
.match(/refs\/remotes\/origin\/(.+)/);
|
|
74
|
+
if (match)
|
|
75
|
+
default_branch = match[1];
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// symbolic-ref not set — try main, then master
|
|
79
|
+
try {
|
|
80
|
+
await execAsync(`git -C ${q} rev-parse --verify origin/main`, { timeout: 5_000 });
|
|
81
|
+
default_branch = 'main';
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
default_branch = 'master';
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
await execAsync(`git -C ${q} checkout ${default_branch}`, {
|
|
88
|
+
timeout: 10_000,
|
|
89
|
+
});
|
|
90
|
+
await execAsync(`git -C ${q} reset --hard origin/${default_branch}`, { timeout: 10_000 });
|
|
91
|
+
return { recovered: true };
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
const msg = err instanceof Error ? err.message : 'Unknown error';
|
|
95
|
+
return { recovered: false, error: msg };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
53
98
|
export async function refresh_marketplace(name, marketplace) {
|
|
54
99
|
const dir = marketplace.installLocation;
|
|
55
100
|
try {
|
|
@@ -58,9 +103,16 @@ export async function refresh_marketplace(name, marketplace) {
|
|
|
58
103
|
});
|
|
59
104
|
return { success: true };
|
|
60
105
|
}
|
|
61
|
-
catch
|
|
62
|
-
|
|
63
|
-
|
|
106
|
+
catch {
|
|
107
|
+
// Fast-forward failed — attempt recovery from deleted branch
|
|
108
|
+
const recovery = await recover_deleted_branch(dir);
|
|
109
|
+
if (recovery.recovered) {
|
|
110
|
+
return { success: true };
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
success: false,
|
|
114
|
+
error: `${name}: recovery failed: ${recovery.error}`,
|
|
115
|
+
};
|
|
64
116
|
}
|
|
65
117
|
}
|
|
66
118
|
export async function refresh_all_marketplaces() {
|
|
@@ -155,6 +207,42 @@ export async function get_cached_plugins_info() {
|
|
|
155
207
|
}
|
|
156
208
|
return results;
|
|
157
209
|
}
|
|
210
|
+
// --- Cache scanning ---
|
|
211
|
+
/**
|
|
212
|
+
* Scan the cache directory on disk to find all plugin keys,
|
|
213
|
+
* including marketplace-sourced plugins not tracked in installed_plugins.json.
|
|
214
|
+
*/
|
|
215
|
+
export async function scan_all_cache_keys() {
|
|
216
|
+
const cache_dir = get_plugin_cache_dir();
|
|
217
|
+
const keys = [];
|
|
218
|
+
try {
|
|
219
|
+
const marketplaces = await readdir(cache_dir, {
|
|
220
|
+
withFileTypes: true,
|
|
221
|
+
});
|
|
222
|
+
for (const mkt of marketplaces) {
|
|
223
|
+
if (!mkt.isDirectory() && !mkt.isSymbolicLink())
|
|
224
|
+
continue;
|
|
225
|
+
const mkt_path = join(cache_dir, mkt.name);
|
|
226
|
+
try {
|
|
227
|
+
const plugins = await readdir(mkt_path, {
|
|
228
|
+
withFileTypes: true,
|
|
229
|
+
});
|
|
230
|
+
for (const plugin of plugins) {
|
|
231
|
+
if (!plugin.isDirectory() && !plugin.isSymbolicLink())
|
|
232
|
+
continue;
|
|
233
|
+
keys.push(`${plugin.name}@${mkt.name}`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
// Skip unreadable marketplace dirs
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
// Cache dir doesn't exist
|
|
243
|
+
}
|
|
244
|
+
return keys;
|
|
245
|
+
}
|
|
158
246
|
// --- Cache clearing ---
|
|
159
247
|
function is_safe_cache_path(path) {
|
|
160
248
|
const cache_dir = resolve(get_plugin_cache_dir());
|
|
@@ -377,7 +465,9 @@ export async function list_linked_plugins() {
|
|
|
377
465
|
const cache_dir = get_plugin_cache_dir();
|
|
378
466
|
const links = [];
|
|
379
467
|
try {
|
|
380
|
-
const marketplaces = await readdir(cache_dir, {
|
|
468
|
+
const marketplaces = await readdir(cache_dir, {
|
|
469
|
+
withFileTypes: true,
|
|
470
|
+
});
|
|
381
471
|
for (const mkt of marketplaces) {
|
|
382
472
|
if (!mkt.isDirectory() && !mkt.isSymbolicLink())
|
|
383
473
|
continue;
|
package/dist/index.js
CHANGED
package/dist/utils/claude-cli.js
CHANGED
|
@@ -189,6 +189,101 @@ export async function update_plugin_via_cli(key, scope = 'user') {
|
|
|
189
189
|
};
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* Add a marketplace via Claude CLI
|
|
194
|
+
*/
|
|
195
|
+
export async function marketplace_add_via_cli(source, scope = 'user') {
|
|
196
|
+
const cli_available = await check_claude_cli();
|
|
197
|
+
if (!cli_available) {
|
|
198
|
+
return {
|
|
199
|
+
success: false,
|
|
200
|
+
error: 'Claude CLI not found. Please install Claude Code CLI.',
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
try {
|
|
204
|
+
await execAsync(`claude plugin marketplace add ${shell_escape(source)} --scope ${scope}`);
|
|
205
|
+
return { success: true };
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
209
|
+
return {
|
|
210
|
+
success: false,
|
|
211
|
+
error: `Failed to add marketplace: ${message}`,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Remove a marketplace via Claude CLI
|
|
217
|
+
*/
|
|
218
|
+
export async function marketplace_remove_via_cli(name) {
|
|
219
|
+
const cli_available = await check_claude_cli();
|
|
220
|
+
if (!cli_available) {
|
|
221
|
+
return {
|
|
222
|
+
success: false,
|
|
223
|
+
error: 'Claude CLI not found. Please install Claude Code CLI.',
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
try {
|
|
227
|
+
await execAsync(`claude plugin marketplace remove ${shell_escape(name)}`);
|
|
228
|
+
return { success: true };
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
232
|
+
return {
|
|
233
|
+
success: false,
|
|
234
|
+
error: `Failed to remove marketplace: ${message}`,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Update marketplace(s) via Claude CLI
|
|
240
|
+
*/
|
|
241
|
+
export async function marketplace_update_via_cli(name) {
|
|
242
|
+
const cli_available = await check_claude_cli();
|
|
243
|
+
if (!cli_available) {
|
|
244
|
+
return {
|
|
245
|
+
success: false,
|
|
246
|
+
error: 'Claude CLI not found. Please install Claude Code CLI.',
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
try {
|
|
250
|
+
const cmd = name
|
|
251
|
+
? `claude plugin marketplace update ${shell_escape(name)}`
|
|
252
|
+
: 'claude plugin marketplace update';
|
|
253
|
+
await execAsync(cmd);
|
|
254
|
+
return { success: true };
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
258
|
+
return {
|
|
259
|
+
success: false,
|
|
260
|
+
error: `Failed to update marketplace: ${message}`,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* List marketplaces via Claude CLI
|
|
266
|
+
*/
|
|
267
|
+
export async function marketplace_list_via_cli() {
|
|
268
|
+
const cli_available = await check_claude_cli();
|
|
269
|
+
if (!cli_available) {
|
|
270
|
+
return {
|
|
271
|
+
success: false,
|
|
272
|
+
error: 'Claude CLI not found. Please install Claude Code CLI.',
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
try {
|
|
276
|
+
const { stdout } = await execAsync('claude plugin marketplace list');
|
|
277
|
+
return { success: true, stdout: stdout.trim() };
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
281
|
+
return {
|
|
282
|
+
success: false,
|
|
283
|
+
error: `Failed to list marketplaces: ${message}`,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
}
|
|
192
287
|
/**
|
|
193
288
|
* Get the scope description for display
|
|
194
289
|
*/
|