mcpick 0.0.15 → 0.0.17

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 CHANGED
@@ -1,5 +1,21 @@
1
1
  # mcpick
2
2
 
3
+ ## 0.0.17
4
+
5
+ ### Patch Changes
6
+
7
+ - 54fe401: feat: plugin hook management with per-hook disable/enable
8
+ and update guard
9
+
10
+ ## 0.0.16
11
+
12
+ ### Patch Changes
13
+
14
+ - b671135: fix: validate marketplace repos upfront, remove unsupported
15
+ --scope flag
16
+ - fed8311: feat: TUI marketplace management, plugin browse, CLI parity
17
+ commands
18
+
3
19
  ## 0.0.15
4
20
 
5
21
  ### Patch Changes
@@ -0,0 +1,60 @@
1
+ import { defineCommand } from 'citty';
2
+ import { mcp_add_json_via_cli } from '../../utils/claude-cli.js';
3
+ import { error, output } from '../output.js';
4
+ export default defineCommand({
5
+ meta: {
6
+ name: 'add-json',
7
+ description: 'Add an MCP server from a JSON configuration string',
8
+ },
9
+ args: {
10
+ name: {
11
+ type: 'positional',
12
+ description: 'Server name',
13
+ required: true,
14
+ },
15
+ config: {
16
+ type: 'positional',
17
+ description: 'JSON configuration string',
18
+ required: true,
19
+ },
20
+ scope: {
21
+ type: 'string',
22
+ description: 'Scope: local, project, or user (default: local)',
23
+ default: 'local',
24
+ },
25
+ json: {
26
+ type: 'boolean',
27
+ description: 'Output as JSON',
28
+ default: false,
29
+ },
30
+ },
31
+ async run({ args }) {
32
+ const scope = args.scope;
33
+ if (!['local', 'project', 'user'].includes(scope)) {
34
+ error(`Invalid scope: ${scope}. Use local, project, or user.`);
35
+ }
36
+ // Validate the JSON is parseable
37
+ try {
38
+ JSON.parse(args.config);
39
+ }
40
+ catch {
41
+ error('Invalid JSON configuration. Provide a valid JSON string.');
42
+ }
43
+ const result = await mcp_add_json_via_cli(args.name, args.config, scope);
44
+ if (args.json) {
45
+ output({
46
+ added: args.name,
47
+ scope,
48
+ success: result.success,
49
+ error: result.error,
50
+ }, true);
51
+ }
52
+ else if (result.success) {
53
+ console.log(`Added '${args.name}' from JSON (scope: ${scope})`);
54
+ }
55
+ else {
56
+ error(result.error || 'Unknown error');
57
+ }
58
+ },
59
+ });
60
+ //# sourceMappingURL=add-json.js.map
@@ -0,0 +1,45 @@
1
+ import { defineCommand } from 'citty';
2
+ import { mcp_get_via_cli } from '../../utils/claude-cli.js';
3
+ import { error, output } from '../output.js';
4
+ export default defineCommand({
5
+ meta: {
6
+ name: 'get',
7
+ description: 'Get details about an MCP server',
8
+ },
9
+ args: {
10
+ name: {
11
+ type: 'positional',
12
+ description: 'Server name',
13
+ required: true,
14
+ },
15
+ json: {
16
+ type: 'boolean',
17
+ description: 'Output as JSON',
18
+ default: false,
19
+ },
20
+ },
21
+ async run({ args }) {
22
+ const result = await mcp_get_via_cli(args.name);
23
+ if (args.json) {
24
+ try {
25
+ const parsed = JSON.parse(result.stdout || '{}');
26
+ output(parsed, true);
27
+ }
28
+ catch {
29
+ output({
30
+ name: args.name,
31
+ success: result.success,
32
+ output: result.stdout,
33
+ error: result.error,
34
+ }, true);
35
+ }
36
+ }
37
+ else if (result.success) {
38
+ console.log(result.stdout || 'No details available.');
39
+ }
40
+ else {
41
+ error(result.error || 'Unknown error');
42
+ }
43
+ },
44
+ });
45
+ //# sourceMappingURL=get.js.map
@@ -0,0 +1,314 @@
1
+ import { defineCommand } from 'citty';
2
+ import { check_restored_hooks, disable_plugin_hook, enable_plugin_hook, read_disabled_hooks, redisable_restored_hooks, } from '../../core/hook-state.js';
3
+ import { add_hook, get_all_hooks, remove_hook, } from '../../core/settings.js';
4
+ import { error, output } from '../output.js';
5
+ const list = defineCommand({
6
+ meta: {
7
+ name: 'list',
8
+ description: 'List all configured hooks (settings + plugins + disabled)',
9
+ },
10
+ args: {
11
+ scope: {
12
+ type: 'string',
13
+ description: 'Filter by source: user, project, project-local, or plugin',
14
+ },
15
+ json: {
16
+ type: 'boolean',
17
+ description: 'Output as JSON',
18
+ default: false,
19
+ },
20
+ },
21
+ async run({ args }) {
22
+ const hooks = await get_all_hooks();
23
+ const disabled = await read_disabled_hooks();
24
+ const filtered = args.scope
25
+ ? hooks.filter((h) => h.source === args.scope || h.scope === args.scope)
26
+ : hooks;
27
+ if (args.json) {
28
+ output({ active: filtered, disabled }, true);
29
+ }
30
+ else {
31
+ if (filtered.length === 0 && disabled.length === 0) {
32
+ console.log('No hooks configured.');
33
+ return;
34
+ }
35
+ if (filtered.length > 0) {
36
+ for (let i = 0; i < filtered.length; i++) {
37
+ const h = filtered[i];
38
+ const detail = h.handler.command ||
39
+ h.handler.url ||
40
+ h.handler.prompt ||
41
+ '(unknown)';
42
+ const matcher_str = h.matcher ? ` [${h.matcher}]` : '';
43
+ const source = h.source === 'plugin'
44
+ ? `plugin: ${h.plugin_key}`
45
+ : h.scope;
46
+ console.log(`${i}: [${source}] ${h.event}${matcher_str} → ${h.handler.type}: ${detail}`);
47
+ }
48
+ }
49
+ if (disabled.length > 0) {
50
+ console.log('\nDisabled:');
51
+ for (let i = 0; i < disabled.length; i++) {
52
+ const d = disabled[i];
53
+ const detail = d.original_handler.command ||
54
+ d.original_handler.url ||
55
+ d.original_handler.prompt ||
56
+ '(unknown)';
57
+ const matcher_str = d.matcher ? ` [${d.matcher}]` : '';
58
+ console.log(`${i}: [${d.plugin_key}] ${d.event}${matcher_str} → ${d.original_handler.type}: ${detail}`);
59
+ }
60
+ }
61
+ }
62
+ },
63
+ });
64
+ const disable = defineCommand({
65
+ meta: {
66
+ name: 'disable',
67
+ description: 'Disable a hook by index (use "hooks list" to see indices)',
68
+ },
69
+ args: {
70
+ index: {
71
+ type: 'positional',
72
+ description: 'Hook index from "hooks list" (0-based)',
73
+ required: true,
74
+ },
75
+ json: {
76
+ type: 'boolean',
77
+ description: 'Output as JSON',
78
+ default: false,
79
+ },
80
+ },
81
+ async run({ args }) {
82
+ const hooks = await get_all_hooks();
83
+ const idx = parseInt(args.index, 10);
84
+ if (isNaN(idx) || idx < 0 || idx >= hooks.length) {
85
+ error(`Invalid index: ${args.index}. Run "mcpick hooks list" to see available hooks (0-${hooks.length - 1}).`);
86
+ }
87
+ const entry = hooks[idx];
88
+ if (entry.source === 'plugin') {
89
+ await disable_plugin_hook(entry);
90
+ if (args.json) {
91
+ output({
92
+ disabled: true,
93
+ event: entry.event,
94
+ plugin_key: entry.plugin_key,
95
+ }, true);
96
+ }
97
+ else {
98
+ console.log(`Disabled: ${entry.event} from ${entry.plugin_key}`);
99
+ console.log('Restart Claude Code for changes to take effect.');
100
+ }
101
+ }
102
+ else {
103
+ // Settings hook — remove it
104
+ await remove_hook(entry);
105
+ if (args.json) {
106
+ output({
107
+ removed: true,
108
+ event: entry.event,
109
+ scope: entry.scope,
110
+ }, true);
111
+ }
112
+ else {
113
+ console.log(`Removed: ${entry.event} (${entry.scope})`);
114
+ }
115
+ }
116
+ },
117
+ });
118
+ const enable = defineCommand({
119
+ meta: {
120
+ name: 'enable',
121
+ description: 'Re-enable a disabled hook by index (use "hooks list" to see disabled hooks)',
122
+ },
123
+ args: {
124
+ index: {
125
+ type: 'positional',
126
+ description: 'Disabled hook index from "hooks list" (0-based)',
127
+ required: true,
128
+ },
129
+ json: {
130
+ type: 'boolean',
131
+ description: 'Output as JSON',
132
+ default: false,
133
+ },
134
+ },
135
+ async run({ args }) {
136
+ const disabled = await read_disabled_hooks();
137
+ const idx = parseInt(args.index, 10);
138
+ if (isNaN(idx) || idx < 0 || idx >= disabled.length) {
139
+ error(`Invalid index: ${args.index}. Run "mcpick hooks list" to see disabled hooks (0-${disabled.length - 1}).`);
140
+ }
141
+ const entry = disabled[idx];
142
+ await enable_plugin_hook(entry);
143
+ if (args.json) {
144
+ output({
145
+ enabled: true,
146
+ event: entry.event,
147
+ plugin_key: entry.plugin_key,
148
+ }, true);
149
+ }
150
+ else {
151
+ console.log(`Re-enabled: ${entry.event} for ${entry.plugin_key}`);
152
+ console.log('Restart Claude Code for changes to take effect.');
153
+ }
154
+ },
155
+ });
156
+ const add = defineCommand({
157
+ meta: {
158
+ name: 'add',
159
+ description: 'Add a new settings-based hook',
160
+ },
161
+ args: {
162
+ event: {
163
+ type: 'positional',
164
+ description: 'Hook event type (e.g. UserPromptSubmit, PreToolUse)',
165
+ required: true,
166
+ },
167
+ handler_type: {
168
+ type: 'positional',
169
+ description: 'Handler type: command, prompt, http, or agent',
170
+ required: true,
171
+ },
172
+ value: {
173
+ type: 'positional',
174
+ description: 'Handler value (command string, prompt text, URL, or agent prompt)',
175
+ required: true,
176
+ },
177
+ matcher: {
178
+ type: 'string',
179
+ description: 'Matcher pattern (e.g. Bash, Edit|Write) — only for tool/session events',
180
+ },
181
+ scope: {
182
+ type: 'string',
183
+ description: 'Scope: user, project, or project-local (default: user)',
184
+ default: 'user',
185
+ },
186
+ json: {
187
+ type: 'boolean',
188
+ description: 'Output as JSON',
189
+ default: false,
190
+ },
191
+ },
192
+ async run({ args }) {
193
+ const scope = args.scope;
194
+ if (!['user', 'project', 'project-local'].includes(scope)) {
195
+ error(`Invalid scope: ${scope}. Use user, project, or project-local.`);
196
+ }
197
+ const handler_type = args.handler_type;
198
+ if (!['command', 'prompt', 'http', 'agent'].includes(handler_type)) {
199
+ error(`Invalid handler type: ${handler_type}. Use command, prompt, http, or agent.`);
200
+ }
201
+ const handler = { type: handler_type };
202
+ if (handler_type === 'command')
203
+ handler.command = args.value;
204
+ else if (handler_type === 'prompt')
205
+ handler.prompt = args.value;
206
+ else if (handler_type === 'http')
207
+ handler.url = args.value;
208
+ else if (handler_type === 'agent')
209
+ handler.prompt = args.value;
210
+ await add_hook(scope, args.event, args.matcher || undefined, handler);
211
+ if (args.json) {
212
+ output({
213
+ added: true,
214
+ event: args.event,
215
+ handler_type,
216
+ scope,
217
+ matcher: args.matcher || null,
218
+ }, true);
219
+ }
220
+ else {
221
+ console.log(`Hook added: ${args.event} → ${handler_type} (${scope})`);
222
+ }
223
+ },
224
+ });
225
+ const remove = defineCommand({
226
+ meta: {
227
+ name: 'remove',
228
+ description: 'Remove a settings hook by index (use "hooks list" to see indices)',
229
+ },
230
+ args: {
231
+ index: {
232
+ type: 'positional',
233
+ description: 'Hook index from "hooks list" (0-based)',
234
+ required: true,
235
+ },
236
+ json: {
237
+ type: 'boolean',
238
+ description: 'Output as JSON',
239
+ default: false,
240
+ },
241
+ },
242
+ async run({ args }) {
243
+ const hooks = await get_all_hooks();
244
+ const settings_hooks = hooks.filter((h) => h.source !== 'plugin');
245
+ const idx = parseInt(args.index, 10);
246
+ if (isNaN(idx) || idx < 0 || idx >= settings_hooks.length) {
247
+ error(`Invalid index: ${args.index}. Use "mcpick hooks list" to see settings hooks.`);
248
+ }
249
+ const entry = settings_hooks[idx];
250
+ await remove_hook(entry);
251
+ if (args.json) {
252
+ output({
253
+ removed: true,
254
+ event: entry.event,
255
+ scope: entry.scope,
256
+ }, true);
257
+ }
258
+ else {
259
+ const detail = entry.handler.command ||
260
+ entry.handler.url ||
261
+ entry.handler.prompt ||
262
+ '(unknown)';
263
+ console.log(`Removed: [${entry.scope}] ${entry.event} → ${entry.handler.type}: ${detail}`);
264
+ }
265
+ },
266
+ });
267
+ const check = defineCommand({
268
+ meta: {
269
+ name: 'check',
270
+ description: 'Check if marketplace updates restored any disabled hooks',
271
+ },
272
+ args: {
273
+ fix: {
274
+ type: 'boolean',
275
+ description: 'Automatically re-disable restored hooks',
276
+ default: false,
277
+ },
278
+ json: {
279
+ type: 'boolean',
280
+ description: 'Output as JSON',
281
+ default: false,
282
+ },
283
+ },
284
+ async run({ args }) {
285
+ const restored = await check_restored_hooks();
286
+ if (args.json) {
287
+ output({ restored: restored.length, hooks: restored }, true);
288
+ return;
289
+ }
290
+ if (restored.length === 0) {
291
+ console.log('No disabled hooks were restored. All good.');
292
+ return;
293
+ }
294
+ console.log(`${restored.length} disabled hook(s) were restored:`);
295
+ for (const r of restored) {
296
+ console.log(` ${r.plugin_key}: ${r.event}`);
297
+ }
298
+ if (args.fix) {
299
+ const result = await redisable_restored_hooks(restored);
300
+ console.log(`Re-disabled ${result.success} hook(s).${result.failed > 0 ? ` Failed: ${result.failed}` : ''}`);
301
+ }
302
+ else {
303
+ console.log('Run with --fix to re-disable, or use "mcpick hooks disable".');
304
+ }
305
+ },
306
+ });
307
+ export default defineCommand({
308
+ meta: {
309
+ name: 'hooks',
310
+ description: 'Manage hooks (settings + plugin). Disable individual plugin hooks, add/remove settings hooks.',
311
+ },
312
+ subCommands: { list, disable, enable, add, remove, check },
313
+ });
314
+ //# sourceMappingURL=hooks.js.map
@@ -1,4 +1,6 @@
1
1
  import { defineCommand } from 'citty';
2
+ import { check_restored_hooks, redisable_restored_hooks, } from '../../core/hook-state.js';
3
+ import { read_marketplace_manifest } from '../../core/plugin-cache.js';
2
4
  import { marketplace_add_via_cli, marketplace_list_via_cli, marketplace_remove_via_cli, marketplace_update_via_cli, } from '../../utils/claude-cli.js';
3
5
  import { error, output } from '../output.js';
4
6
  const list = defineCommand({
@@ -36,7 +38,7 @@ const list = defineCommand({
36
38
  const add = defineCommand({
37
39
  meta: {
38
40
  name: 'add',
39
- description: 'Add a marketplace from URL, path, or GitHub repo',
41
+ description: 'Add a plugin marketplace (a catalog of installable plugins)',
40
42
  },
41
43
  args: {
42
44
  source: {
@@ -44,11 +46,6 @@ const add = defineCommand({
44
46
  description: 'Marketplace source (GitHub repo, URL, or local path)',
45
47
  required: true,
46
48
  },
47
- scope: {
48
- type: 'string',
49
- description: 'Scope: user, project, or local (default: user)',
50
- default: 'user',
51
- },
52
49
  json: {
53
50
  type: 'boolean',
54
51
  description: 'Output as JSON',
@@ -56,27 +53,72 @@ const add = defineCommand({
56
53
  },
57
54
  },
58
55
  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);
56
+ const result = await marketplace_add_via_cli(args.source);
64
57
  if (args.json) {
58
+ // Try to include available plugins in JSON output
59
+ let available_plugins = [];
60
+ if (result.success) {
61
+ const manifests = await find_marketplace_plugins(args.source);
62
+ available_plugins = manifests;
63
+ }
65
64
  output({
66
65
  added: args.source,
67
- scope,
68
66
  success: result.success,
69
67
  error: result.error,
68
+ available_plugins,
70
69
  }, true);
71
70
  }
72
71
  else if (result.success) {
73
- console.log(`Marketplace added: ${args.source} (scope: ${scope})`);
72
+ console.log(`Marketplace added: ${args.source}`);
73
+ await show_available_plugins(args.source);
74
74
  }
75
75
  else {
76
76
  error(result.error || 'Unknown error');
77
77
  }
78
78
  },
79
79
  });
80
+ /**
81
+ * Try to find and display available plugins from a newly added marketplace.
82
+ * The marketplace name in the filesystem may differ from the source string,
83
+ * so we try common derivations.
84
+ */
85
+ async function find_marketplace_plugins(source) {
86
+ // Try the source as-is, then extract repo name from various formats
87
+ const candidates = [];
88
+ // Extract repo name from owner/repo, URLs, etc.
89
+ const repo_match = source.match(/([^/]+?)(?:\.git)?$/);
90
+ if (repo_match) {
91
+ candidates.push(repo_match[1].toLowerCase());
92
+ candidates.push(repo_match[1]);
93
+ }
94
+ // Try the full source as a name
95
+ candidates.push(source);
96
+ for (const name of candidates) {
97
+ const manifest = await read_marketplace_manifest(name);
98
+ if (manifest?.plugins?.length) {
99
+ return manifest.plugins.map((p) => {
100
+ const desc = p.description
101
+ ? ` - ${p.description}`
102
+ : '';
103
+ return `${p.name}${desc}`;
104
+ });
105
+ }
106
+ }
107
+ return [];
108
+ }
109
+ async function show_available_plugins(source) {
110
+ const plugins = await find_marketplace_plugins(source);
111
+ if (plugins.length > 0) {
112
+ console.log(`\nAvailable plugins (${plugins.length}):`);
113
+ for (const p of plugins) {
114
+ console.log(` - ${p}`);
115
+ }
116
+ console.log('\nInstall with: mcpick plugins install <name>@<marketplace>');
117
+ }
118
+ else {
119
+ console.log('\nTo browse and install plugins: mcpick plugins install <name>@<marketplace>');
120
+ }
121
+ }
80
122
  const remove = defineCommand({
81
123
  meta: {
82
124
  name: 'remove',
@@ -141,6 +183,13 @@ const update = defineCommand({
141
183
  console.log(args.name
142
184
  ? `Marketplace updated: ${args.name}`
143
185
  : 'All marketplaces updated.');
186
+ // Check if update restored any disabled hooks
187
+ const restored = await check_restored_hooks();
188
+ if (restored.length > 0) {
189
+ console.log(`\nWarning: ${restored.length} disabled hook(s) were restored by the update.`);
190
+ const redisable_result = await redisable_restored_hooks(restored);
191
+ console.log(`Re-disabled ${redisable_result.success} hook(s).${redisable_result.failed > 0 ? ` Failed: ${redisable_result.failed}` : ''}`);
192
+ }
144
193
  }
145
194
  else {
146
195
  error(result.error || 'Unknown error');
@@ -150,7 +199,7 @@ const update = defineCommand({
150
199
  export default defineCommand({
151
200
  meta: {
152
201
  name: 'marketplace',
153
- description: 'Manage Claude Code plugin marketplaces',
202
+ description: 'Manage plugin marketplaces (catalogs of installable plugins). Add a marketplace first, then install plugins from it with: mcpick plugins install <name>@<marketplace>',
154
203
  },
155
204
  subCommands: {
156
205
  list,
@@ -1,7 +1,7 @@
1
1
  import { defineCommand } from 'citty';
2
2
  import { parse_plugin_key, read_known_marketplaces, } from '../../core/plugin-cache.js';
3
3
  import { build_enabled_plugins, get_all_plugins, read_claude_settings, write_claude_settings, } from '../../core/settings.js';
4
- import { install_plugin_via_cli, uninstall_plugin_via_cli, update_plugin_via_cli, } from '../../utils/claude-cli.js';
4
+ import { install_plugin_via_cli, uninstall_plugin_via_cli, update_plugin_via_cli, validate_plugin_via_cli, } from '../../utils/claude-cli.js';
5
5
  import { error, output } from '../output.js';
6
6
  const list = defineCommand({
7
7
  meta: {
@@ -212,11 +212,54 @@ const update = defineCommand({
212
212
  }
213
213
  },
214
214
  });
215
+ const validate = defineCommand({
216
+ meta: {
217
+ name: 'validate',
218
+ description: 'Validate a plugin or marketplace manifest',
219
+ },
220
+ args: {
221
+ path: {
222
+ type: 'positional',
223
+ description: 'Path to plugin or marketplace manifest',
224
+ required: true,
225
+ },
226
+ json: {
227
+ type: 'boolean',
228
+ description: 'Output as JSON',
229
+ default: false,
230
+ },
231
+ },
232
+ async run({ args }) {
233
+ const result = await validate_plugin_via_cli(args.path);
234
+ if (args.json) {
235
+ output({
236
+ path: args.path,
237
+ valid: result.success,
238
+ output: result.stdout,
239
+ error: result.error,
240
+ }, true);
241
+ }
242
+ else if (result.success) {
243
+ console.log(result.stdout || 'Validation passed.');
244
+ }
245
+ else {
246
+ error(result.error || 'Validation failed');
247
+ }
248
+ },
249
+ });
215
250
  export default defineCommand({
216
251
  meta: {
217
252
  name: 'plugins',
218
253
  description: 'Manage Claude Code plugins',
219
254
  },
220
- subCommands: { list, enable, disable, install, uninstall, update },
255
+ subCommands: {
256
+ list,
257
+ enable,
258
+ disable,
259
+ install,
260
+ uninstall,
261
+ update,
262
+ validate,
263
+ },
221
264
  });
222
265
  //# sourceMappingURL=plugins.js.map
@@ -0,0 +1,32 @@
1
+ import { defineCommand } from 'citty';
2
+ import { mcp_reset_project_choices_via_cli } from '../../utils/claude-cli.js';
3
+ import { error, output } from '../output.js';
4
+ export default defineCommand({
5
+ meta: {
6
+ name: 'reset-project-choices',
7
+ description: 'Reset all approved and rejected project-scoped MCP servers',
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 mcp_reset_project_choices_via_cli();
18
+ if (args.json) {
19
+ output({
20
+ success: result.success,
21
+ error: result.error,
22
+ }, true);
23
+ }
24
+ else if (result.success) {
25
+ console.log('Project MCP server choices have been reset.');
26
+ }
27
+ else {
28
+ error(result.error || 'Unknown error');
29
+ }
30
+ },
31
+ });
32
+ //# sourceMappingURL=reset-project-choices.js.map
package/dist/cli/index.js CHANGED
@@ -10,10 +10,14 @@ const main = defineCommand({
10
10
  disable: () => import('./commands/disable.js').then((m) => m.default),
11
11
  remove: () => import('./commands/remove.js').then((m) => m.default),
12
12
  add: () => import('./commands/add.js').then((m) => m.default),
13
+ 'add-json': () => import('./commands/add-json.js').then((m) => m.default),
14
+ get: () => import('./commands/get.js').then((m) => m.default),
15
+ 'reset-project-choices': () => import('./commands/reset-project-choices.js').then((m) => m.default),
13
16
  backup: () => import('./commands/backup.js').then((m) => m.default),
14
17
  restore: () => import('./commands/restore.js').then((m) => m.default),
15
18
  profile: () => import('./commands/profile.js').then((m) => m.default),
16
19
  plugins: () => import('./commands/plugins.js').then((m) => m.default),
20
+ hooks: () => import('./commands/hooks.js').then((m) => m.default),
17
21
  cache: () => import('./commands/cache.js').then((m) => m.default),
18
22
  dev: () => import('./commands/dev.js').then((m) => m.default),
19
23
  marketplace: () => import('./commands/marketplace.js').then((m) => m.default),