mcpick 0.0.17 → 0.0.19

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 (75) hide show
  1. package/.vscode/settings.json +5 -0
  2. package/CHANGELOG.md +15 -0
  3. package/dist/add-B9nVyh8T.js +113 -0
  4. package/dist/add-json-CXNDl3al.js +58 -0
  5. package/dist/atomic-write-BqEykHp9.js +26 -0
  6. package/dist/backup-DSDhHI5f.js +64 -0
  7. package/dist/cache-D6kd7qE8.js +226 -0
  8. package/dist/claude-cli-BeA-bmoW.js +394 -0
  9. package/dist/cli-DNNZjJYL.js +84 -0
  10. package/dist/clone-DLFLewBY.js +88 -0
  11. package/dist/config-DijVdEFn.js +176 -0
  12. package/dist/dev-DRJRNp7y.js +265 -0
  13. package/dist/disable-BA8tXPJN.js +39 -0
  14. package/dist/enable-Bdnnn_Cq.js +40 -0
  15. package/dist/get-BPjMXTMc.js +41 -0
  16. package/dist/hook-state-Di8lUsPr.js +171 -0
  17. package/dist/hooks-Bmn7pUZa.js +280 -0
  18. package/dist/index.js +1230 -303
  19. package/dist/list-B8YeDWt6.js +64 -0
  20. package/dist/marketplace-Br89Tg-Z.js +168 -0
  21. package/dist/output-BchYq0mR.js +15 -0
  22. package/dist/paths-BPISiJi4.js +124 -0
  23. package/dist/plugin-cache-Bby9Dxm9.js +405 -0
  24. package/dist/plugins-DHYJF5CP.js +212 -0
  25. package/dist/profile-CX97sMGp.js +120 -0
  26. package/dist/profile-DkY_lBEm.js +70 -0
  27. package/dist/redact-O35tjnRD.js +26 -0
  28. package/dist/registry-CfUKT7_C.js +92 -0
  29. package/dist/reload-CYDhkCVZ.js +31 -0
  30. package/dist/remove-DIPWYMpk.js +31 -0
  31. package/dist/reset-project-choices-DRM5KByw.js +28 -0
  32. package/dist/restore-DdMfUljI.js +84 -0
  33. package/dist/rolldown-runtime-CiIaOW0V.js +13 -0
  34. package/dist/settings-DEcWtzLE.js +201 -0
  35. package/dist/validation-xMlbgGCF.js +44 -0
  36. package/package.json +20 -19
  37. package/dist/cli/commands/add-json.js +0 -60
  38. package/dist/cli/commands/add.js +0 -135
  39. package/dist/cli/commands/backup.js +0 -83
  40. package/dist/cli/commands/cache.js +0 -296
  41. package/dist/cli/commands/dev.js +0 -161
  42. package/dist/cli/commands/disable.js +0 -36
  43. package/dist/cli/commands/enable.js +0 -39
  44. package/dist/cli/commands/get.js +0 -45
  45. package/dist/cli/commands/hooks.js +0 -314
  46. package/dist/cli/commands/list.js +0 -63
  47. package/dist/cli/commands/marketplace.js +0 -211
  48. package/dist/cli/commands/plugins.js +0 -265
  49. package/dist/cli/commands/profile.js +0 -134
  50. package/dist/cli/commands/reload.js +0 -36
  51. package/dist/cli/commands/remove.js +0 -35
  52. package/dist/cli/commands/reset-project-choices.js +0 -32
  53. package/dist/cli/commands/restore.js +0 -105
  54. package/dist/cli/index.js +0 -28
  55. package/dist/cli/output.js +0 -21
  56. package/dist/commands/add-server.js +0 -310
  57. package/dist/commands/backup.js +0 -60
  58. package/dist/commands/edit-config.js +0 -109
  59. package/dist/commands/edit-plugins.js +0 -201
  60. package/dist/commands/manage-cache.js +0 -155
  61. package/dist/commands/manage-hooks.js +0 -99
  62. package/dist/commands/manage-marketplace.js +0 -293
  63. package/dist/commands/restore.js +0 -118
  64. package/dist/core/config.js +0 -146
  65. package/dist/core/dev-override.js +0 -210
  66. package/dist/core/hook-state.js +0 -220
  67. package/dist/core/plugin-cache.js +0 -506
  68. package/dist/core/profile.js +0 -94
  69. package/dist/core/registry.js +0 -121
  70. package/dist/core/settings.js +0 -243
  71. package/dist/core/validation.js +0 -49
  72. package/dist/types.js +0 -2
  73. package/dist/utils/atomic-write.js +0 -27
  74. package/dist/utils/claude-cli.js +0 -483
  75. package/dist/utils/paths.js +0 -114
@@ -1,155 +0,0 @@
1
- import { confirm, isCancel, log, multiselect, note, select, } from '@clack/prompts';
2
- import { clean_orphaned_versions, clear_plugin_caches, get_cached_plugins_info, refresh_all_marketplaces, } from '../core/plugin-cache.js';
3
- function format_status_line(p) {
4
- const markers = [];
5
- if (p.isVersionStale) {
6
- markers.push(`version: ${p.installedVersion} → ${p.latestVersion}`);
7
- }
8
- if (p.isShaStale) {
9
- markers.push('commits behind');
10
- }
11
- if (p.orphanedVersions.length > 0) {
12
- markers.push(`${p.orphanedVersions.length} orphaned`);
13
- }
14
- const status = markers.length > 0
15
- ? `[stale: ${markers.join(', ')}]`
16
- : '[up to date]';
17
- return `${p.name}@${p.marketplace} v${p.installedVersion} ${status}`;
18
- }
19
- async function handle_status() {
20
- const plugins = await get_cached_plugins_info();
21
- if (plugins.length === 0) {
22
- log.info('No cached plugins found.');
23
- return;
24
- }
25
- const lines = plugins.map(format_status_line).join('\n');
26
- note(lines, 'Plugin Cache Status');
27
- }
28
- async function handle_clear() {
29
- const plugins = await get_cached_plugins_info();
30
- if (plugins.length === 0) {
31
- log.info('No cached plugins to clear.');
32
- return;
33
- }
34
- const selected = await multiselect({
35
- message: 'Select plugins to clear cache for:',
36
- options: plugins.map((p) => {
37
- const stale = p.isVersionStale || p.isShaStale;
38
- return {
39
- value: p.key,
40
- label: `${p.name}@${p.marketplace}`,
41
- hint: stale
42
- ? `v${p.installedVersion} → ${p.latestVersion ?? 'unknown'} (stale)`
43
- : `v${p.installedVersion}`,
44
- };
45
- }),
46
- initialValues: plugins
47
- .filter((p) => p.isVersionStale || p.isShaStale)
48
- .map((p) => p.key),
49
- });
50
- if (isCancel(selected) || selected.length === 0)
51
- return;
52
- const should_clear = await confirm({
53
- message: `Clear cache for ${selected.length} plugin(s)? This will also refresh the marketplace.`,
54
- });
55
- if (isCancel(should_clear) || !should_clear)
56
- return;
57
- const result = await clear_plugin_caches(selected);
58
- for (const key of result.cleared) {
59
- log.success(`Cleared: ${key}`);
60
- }
61
- for (const err of result.errors) {
62
- log.error(`Error: ${err}`);
63
- }
64
- if (result.cleared.length > 0) {
65
- note('Run /reload-plugins in Claude Code or restart your session to apply changes.', 'Next Steps');
66
- }
67
- }
68
- async function handle_clean_orphaned() {
69
- const should_clean = await confirm({
70
- message: 'Remove all orphaned plugin version directories?',
71
- });
72
- if (isCancel(should_clean) || !should_clean)
73
- return;
74
- const result = await clean_orphaned_versions();
75
- if (result.cleaned === 0) {
76
- log.info('No orphaned versions found.');
77
- }
78
- else {
79
- for (const p of result.paths) {
80
- log.success(`Removed: ${p}`);
81
- }
82
- log.info(`Cleaned ${result.cleaned} orphaned version(s).`);
83
- }
84
- }
85
- async function handle_refresh() {
86
- const should_refresh = await confirm({
87
- message: 'Refresh all marketplace clones (git pull)?',
88
- });
89
- if (isCancel(should_refresh) || !should_refresh)
90
- return;
91
- const results = await refresh_all_marketplaces();
92
- if (results.size === 0) {
93
- log.info('No marketplaces configured.');
94
- return;
95
- }
96
- for (const [name, result] of results) {
97
- if (result.success) {
98
- log.success(`${name}: refreshed`);
99
- }
100
- else {
101
- log.error(`${name}: ${result.error}`);
102
- }
103
- }
104
- }
105
- export async function manage_cache() {
106
- while (true) {
107
- const action = await select({
108
- message: 'Plugin cache management:',
109
- options: [
110
- {
111
- value: 'status',
112
- label: 'View cache status',
113
- hint: 'Show plugins with staleness info',
114
- },
115
- {
116
- value: 'clear',
117
- label: 'Clear plugin caches',
118
- hint: 'Refresh marketplace + clear selected caches',
119
- },
120
- {
121
- value: 'clean-orphaned',
122
- label: 'Clean orphaned versions',
123
- hint: 'Remove old version directories',
124
- },
125
- {
126
- value: 'refresh',
127
- label: 'Refresh marketplaces',
128
- hint: 'Git pull all marketplace clones',
129
- },
130
- {
131
- value: 'back',
132
- label: 'Back',
133
- hint: 'Return to main menu',
134
- },
135
- ],
136
- });
137
- if (isCancel(action) || action === 'back')
138
- return;
139
- switch (action) {
140
- case 'status':
141
- await handle_status();
142
- break;
143
- case 'clear':
144
- await handle_clear();
145
- break;
146
- case 'clean-orphaned':
147
- await handle_clean_orphaned();
148
- break;
149
- case 'refresh':
150
- await handle_refresh();
151
- break;
152
- }
153
- }
154
- }
155
- //# sourceMappingURL=manage-cache.js.map
@@ -1,99 +0,0 @@
1
- import { isCancel, log, multiselect, note } from '@clack/prompts';
2
- import { disable_plugin_hook, enable_plugin_hook, read_disabled_hooks, } from '../core/hook-state.js';
3
- import { get_all_hooks } from '../core/settings.js';
4
- function format_hook(entry) {
5
- const detail = entry.handler.command ||
6
- entry.handler.url ||
7
- entry.handler.prompt ||
8
- '(unknown)';
9
- const truncated = detail.length > 50 ? detail.substring(0, 47) + '...' : detail;
10
- return `${entry.event} → ${entry.handler.type}: ${truncated}`;
11
- }
12
- function format_source(entry) {
13
- if (entry.source === 'plugin' && entry.plugin_key) {
14
- return entry.plugin_key;
15
- }
16
- return entry.scope;
17
- }
18
- export async function manage_hooks() {
19
- // Get all active hooks + disabled hooks
20
- const active_hooks = await get_all_hooks();
21
- const disabled = await read_disabled_hooks();
22
- const items = [];
23
- // Active hooks
24
- for (let i = 0; i < active_hooks.length; i++) {
25
- const h = active_hooks[i];
26
- items.push({
27
- id: `active:${i}`,
28
- active_entry: h,
29
- label: format_hook(h),
30
- hint: format_source(h),
31
- });
32
- }
33
- // Disabled hooks
34
- for (let i = 0; i < disabled.length; i++) {
35
- const d = disabled[i];
36
- const detail = d.original_handler.command ||
37
- d.original_handler.url ||
38
- d.original_handler.prompt ||
39
- '(unknown)';
40
- const truncated = detail.length > 50 ? detail.substring(0, 47) + '...' : detail;
41
- items.push({
42
- id: `disabled:${i}`,
43
- disabled_index: i,
44
- label: `${d.event} → ${d.original_handler.type}: ${truncated}`,
45
- hint: `${d.plugin_key} (disabled)`,
46
- });
47
- }
48
- if (items.length === 0) {
49
- note('No hooks found (settings or plugins).');
50
- return;
51
- }
52
- // Currently enabled = active hooks
53
- const currently_enabled = items
54
- .filter((item) => item.active_entry)
55
- .map((item) => item.id);
56
- const selected = await multiselect({
57
- message: 'Toggle hooks on/off:',
58
- options: items.map((item) => ({
59
- value: item.id,
60
- label: item.label,
61
- hint: item.hint,
62
- })),
63
- initialValues: currently_enabled,
64
- required: false,
65
- });
66
- if (isCancel(selected))
67
- return;
68
- const selected_set = new Set(selected);
69
- let changes = 0;
70
- // Disable hooks that were deselected (active → disabled)
71
- for (const item of items) {
72
- if (!item.active_entry)
73
- continue;
74
- if (selected_set.has(item.id))
75
- continue;
76
- // Only plugin hooks can be disabled — settings hooks get removed
77
- if (item.active_entry.source === 'plugin') {
78
- await disable_plugin_hook(item.active_entry);
79
- changes++;
80
- }
81
- }
82
- // Enable hooks that were selected (disabled → active)
83
- for (const item of items) {
84
- if (item.disabled_index === undefined)
85
- continue;
86
- if (!selected_set.has(item.id))
87
- continue;
88
- await enable_plugin_hook(disabled[item.disabled_index]);
89
- changes++;
90
- }
91
- if (changes > 0) {
92
- log.success(`${changes} hook(s) updated.`);
93
- log.info('Restart Claude Code for changes to take effect.');
94
- }
95
- else {
96
- log.info('No changes.');
97
- }
98
- }
99
- //# sourceMappingURL=manage-hooks.js.map
@@ -1,293 +0,0 @@
1
- import { confirm, isCancel, log, multiselect, note, select, text, } from '@clack/prompts';
2
- import { check_restored_hooks, redisable_restored_hooks, } from '../core/hook-state.js';
3
- import { read_known_marketplaces, read_marketplace_manifest, } from '../core/plugin-cache.js';
4
- import { get_all_plugins, read_claude_settings, } from '../core/settings.js';
5
- import { install_plugin_via_cli, marketplace_add_via_cli, marketplace_remove_via_cli, marketplace_update_via_cli, uninstall_plugin_via_cli, } from '../utils/claude-cli.js';
6
- /**
7
- * Browse all available plugins across all marketplaces.
8
- * Shows a multiselect with installed plugins pre-selected — toggle to install/uninstall.
9
- */
10
- async function handle_browse() {
11
- const known = await read_known_marketplaces();
12
- const marketplace_names = Object.keys(known);
13
- if (marketplace_names.length === 0) {
14
- note('No marketplaces configured.\nAdd one first to browse plugins.');
15
- return;
16
- }
17
- // Build list of all available plugins across marketplaces
18
- const all_available = [];
19
- for (const mkt_name of marketplace_names) {
20
- const manifest = await read_marketplace_manifest(mkt_name);
21
- if (!manifest?.plugins?.length)
22
- continue;
23
- for (const p of manifest.plugins) {
24
- all_available.push({
25
- key: `${p.name}@${mkt_name}`,
26
- name: p.name,
27
- marketplace: mkt_name,
28
- description: p.description,
29
- });
30
- }
31
- }
32
- if (all_available.length === 0) {
33
- note('No plugins found in any marketplace.');
34
- return;
35
- }
36
- // Get currently installed plugins
37
- const settings = await read_claude_settings();
38
- const installed = get_all_plugins(settings);
39
- const installed_keys = new Set(installed.map((p) => `${p.name}@${p.marketplace}`));
40
- const selected = await multiselect({
41
- message: `Available plugins (${all_available.length}) — toggle to install/uninstall:`,
42
- options: all_available.map((p) => ({
43
- value: p.key,
44
- label: p.name,
45
- hint: `${p.marketplace}${p.description ? ` · ${p.description}` : ''}`,
46
- })),
47
- initialValues: all_available
48
- .filter((p) => installed_keys.has(p.key))
49
- .map((p) => p.key),
50
- required: false,
51
- });
52
- if (isCancel(selected))
53
- return;
54
- const selected_set = new Set(selected);
55
- // Determine what to install and uninstall
56
- const to_install = all_available.filter((p) => selected_set.has(p.key) && !installed_keys.has(p.key));
57
- const to_uninstall = all_available.filter((p) => !selected_set.has(p.key) && installed_keys.has(p.key));
58
- if (to_install.length === 0 && to_uninstall.length === 0) {
59
- log.info('No changes.');
60
- return;
61
- }
62
- // Install new plugins
63
- for (const p of to_install) {
64
- log.info(`Installing ${p.key}...`);
65
- const result = await install_plugin_via_cli(p.key);
66
- if (result.success) {
67
- log.success(`Installed: ${p.key}`);
68
- }
69
- else {
70
- log.error(`Failed: ${p.key} - ${result.error}`);
71
- }
72
- }
73
- // Uninstall deselected plugins
74
- for (const p of to_uninstall) {
75
- log.info(`Uninstalling ${p.key}...`);
76
- const result = await uninstall_plugin_via_cli(p.key);
77
- if (result.success) {
78
- log.success(`Uninstalled: ${p.key}`);
79
- }
80
- else {
81
- log.error(`Failed: ${p.key} - ${result.error}`);
82
- }
83
- }
84
- const parts = [];
85
- if (to_install.length > 0)
86
- parts.push(`${to_install.length} installed`);
87
- if (to_uninstall.length > 0)
88
- parts.push(`${to_uninstall.length} uninstalled`);
89
- note(parts.join(', '), 'Plugins updated');
90
- }
91
- async function handle_add() {
92
- const source = await text({
93
- message: 'Marketplace source:',
94
- placeholder: 'e.g. owner/repo or https://github.com/owner/repo',
95
- validate: (value) => {
96
- if (!value || value.trim().length === 0) {
97
- return 'Marketplace source is required';
98
- }
99
- },
100
- });
101
- if (isCancel(source))
102
- return;
103
- log.info(`Adding marketplace: ${source}`);
104
- const result = await marketplace_add_via_cli(source);
105
- if (!result.success) {
106
- log.error(result.error || 'Unknown error');
107
- return;
108
- }
109
- log.success(`Marketplace added: ${source}`);
110
- // Try to find and offer available plugins
111
- const marketplace_name = derive_marketplace_name(source);
112
- const manifest = marketplace_name
113
- ? await read_marketplace_manifest(marketplace_name)
114
- : null;
115
- if (!manifest?.plugins?.length) {
116
- log.info('Install plugins with: mcpick plugins install <name>@<marketplace>');
117
- return;
118
- }
119
- const should_install = await confirm({
120
- message: `${manifest.plugins.length} plugins available. Install now?`,
121
- });
122
- if (isCancel(should_install) || !should_install)
123
- return;
124
- const to_install = await multiselect({
125
- message: 'Select plugins to install:',
126
- options: manifest.plugins.map((p) => ({
127
- value: `${p.name}@${marketplace_name}`,
128
- label: p.name,
129
- hint: p.description,
130
- })),
131
- required: false,
132
- });
133
- if (isCancel(to_install) || to_install.length === 0)
134
- return;
135
- for (const key of to_install) {
136
- log.info(`Installing ${key}...`);
137
- const install_result = await install_plugin_via_cli(key);
138
- if (install_result.success) {
139
- log.success(`Installed: ${key}`);
140
- }
141
- else {
142
- log.error(`Failed: ${key} - ${install_result.error}`);
143
- }
144
- }
145
- }
146
- function derive_marketplace_name(source) {
147
- const match = source.match(/([^/]+?)(?:\.git)?$/);
148
- return match ? match[1].toLowerCase() : null;
149
- }
150
- async function handle_remove() {
151
- const known = await read_known_marketplaces();
152
- const names = Object.keys(known);
153
- if (names.length === 0) {
154
- note('No marketplaces configured.');
155
- return;
156
- }
157
- const name = await select({
158
- message: 'Select marketplace to remove:',
159
- options: names.map((n) => ({
160
- value: n,
161
- label: n,
162
- hint: known[n].source.repo || known[n].source.url,
163
- })),
164
- });
165
- if (isCancel(name))
166
- return;
167
- const should_remove = await confirm({
168
- message: `Remove marketplace '${name}'? Its plugins will also be removed.`,
169
- });
170
- if (isCancel(should_remove) || !should_remove)
171
- return;
172
- const remove_result = await marketplace_remove_via_cli(name);
173
- if (remove_result.success) {
174
- log.success(`Marketplace removed: ${name}`);
175
- }
176
- else {
177
- log.error(remove_result.error || 'Unknown error');
178
- }
179
- }
180
- async function handle_update() {
181
- const known = await read_known_marketplaces();
182
- const names = Object.keys(known);
183
- if (names.length === 0) {
184
- note('No marketplaces configured.');
185
- return;
186
- }
187
- const choice = await select({
188
- message: 'What to update:',
189
- options: [
190
- { value: '__all__', label: 'All marketplaces' },
191
- ...names.map((n) => ({
192
- value: n,
193
- label: n,
194
- hint: known[n].source.repo || known[n].source.url,
195
- })),
196
- ],
197
- });
198
- if (isCancel(choice))
199
- return;
200
- if (choice === '__all__') {
201
- log.info('Updating all marketplaces...');
202
- const result = await marketplace_update_via_cli();
203
- if (result.success) {
204
- log.success('All marketplaces updated.');
205
- }
206
- else {
207
- log.error(result.error || 'Unknown error');
208
- }
209
- }
210
- else {
211
- log.info(`Updating ${choice}...`);
212
- const result = await marketplace_update_via_cli(choice);
213
- if (result.success) {
214
- log.success(`Marketplace updated: ${choice}`);
215
- }
216
- else {
217
- log.error(result.error || 'Unknown error');
218
- }
219
- }
220
- // Check if update restored any disabled hooks
221
- const restored = await check_restored_hooks();
222
- if (restored.length > 0) {
223
- log.warn(`${restored.length} disabled hook(s) were restored by the update.`);
224
- const should_redisable = await confirm({
225
- message: 'Re-disable these hooks?',
226
- });
227
- if (!isCancel(should_redisable) && should_redisable) {
228
- const redisable_result = await redisable_restored_hooks(restored);
229
- if (redisable_result.success > 0) {
230
- log.success(`Re-disabled ${redisable_result.success} hook(s).`);
231
- }
232
- if (redisable_result.failed > 0) {
233
- log.error(`Failed to re-disable ${redisable_result.failed} hook(s).`);
234
- }
235
- }
236
- }
237
- }
238
- export async function manage_marketplace() {
239
- while (true) {
240
- const action = await select({
241
- message: 'Marketplace & plugins:',
242
- options: [
243
- {
244
- value: 'browse',
245
- label: 'Browse & install plugins',
246
- hint: 'Toggle plugins on/off across all marketplaces',
247
- },
248
- {
249
- value: 'add',
250
- label: 'Add marketplace',
251
- hint: 'Add a plugin catalog, then install plugins from it',
252
- },
253
- {
254
- value: 'remove',
255
- label: 'Remove marketplace',
256
- hint: 'Remove a marketplace and its plugins',
257
- },
258
- {
259
- value: 'update',
260
- label: 'Update marketplace(s)',
261
- hint: 'Pull latest from source',
262
- },
263
- {
264
- value: 'back',
265
- label: 'Back',
266
- hint: 'Return to main menu',
267
- },
268
- ],
269
- });
270
- if (isCancel(action) || action === 'back')
271
- return;
272
- try {
273
- switch (action) {
274
- case 'browse':
275
- await handle_browse();
276
- break;
277
- case 'add':
278
- await handle_add();
279
- break;
280
- case 'remove':
281
- await handle_remove();
282
- break;
283
- case 'update':
284
- await handle_update();
285
- break;
286
- }
287
- }
288
- catch (err) {
289
- log.error(err instanceof Error ? err.message : 'Unknown error');
290
- }
291
- }
292
- }
293
- //# sourceMappingURL=manage-marketplace.js.map
@@ -1,118 +0,0 @@
1
- import { confirm, isCancel, log, note, select } from '@clack/prompts';
2
- import { readFile } from 'node:fs/promises';
3
- import { read_claude_config, write_claude_config, } from '../core/config.js';
4
- import { list_backups, list_plugin_backups, } from '../core/registry.js';
5
- import { write_claude_settings } from '../core/settings.js';
6
- export async function restore_config() {
7
- try {
8
- const restore_type = await select({
9
- message: 'What would you like to restore?',
10
- options: [
11
- {
12
- value: 'mcp',
13
- label: 'MCP servers',
14
- hint: 'Restore server configuration',
15
- },
16
- {
17
- value: 'plugins',
18
- label: 'Plugins',
19
- hint: 'Restore plugin enabled/disabled state',
20
- },
21
- ],
22
- });
23
- if (isCancel(restore_type))
24
- return;
25
- if (restore_type === 'mcp') {
26
- await restore_mcp();
27
- }
28
- else {
29
- await restore_plugins();
30
- }
31
- }
32
- catch (error) {
33
- throw new Error(`Failed to restore configuration: ${error instanceof Error ? error.message : 'Unknown error'}`);
34
- }
35
- }
36
- async function restore_mcp() {
37
- const backups = await list_backups();
38
- if (backups.length === 0) {
39
- note('No MCP server backups found.');
40
- return;
41
- }
42
- const backup_choices = backups.map((backup) => ({
43
- value: backup.path,
44
- label: `${backup.filename} (${backup.timestamp.toLocaleString()})`,
45
- hint: format_time_ago(backup.timestamp),
46
- }));
47
- const selected_backup_path = await select({
48
- message: 'Select backup to restore:',
49
- options: backup_choices,
50
- });
51
- if (isCancel(selected_backup_path))
52
- return;
53
- const should_restore = await confirm({
54
- message: 'This will replace your current MCP servers configuration. Continue?',
55
- });
56
- if (isCancel(should_restore) || !should_restore)
57
- return;
58
- const backup_content = await readFile(selected_backup_path, 'utf-8');
59
- const backup_data = JSON.parse(backup_content);
60
- const current_config = await read_claude_config();
61
- const updated_config = {
62
- ...current_config,
63
- mcpServers: backup_data.mcpServers || {},
64
- };
65
- await write_claude_config(updated_config);
66
- const server_count = Object.keys(backup_data.mcpServers || {}).length;
67
- log.success(`MCP servers restored (${server_count} servers)`);
68
- }
69
- async function restore_plugins() {
70
- const backups = await list_plugin_backups();
71
- if (backups.length === 0) {
72
- note('No plugin backups found.');
73
- return;
74
- }
75
- const backup_choices = backups.map((backup) => ({
76
- value: backup.path,
77
- label: `${backup.filename} (${backup.timestamp.toLocaleString()})`,
78
- hint: format_time_ago(backup.timestamp),
79
- }));
80
- const selected_backup_path = await select({
81
- message: 'Select plugin backup to restore:',
82
- options: backup_choices,
83
- });
84
- if (isCancel(selected_backup_path))
85
- return;
86
- const should_restore = await confirm({
87
- message: 'This will replace your current plugin configuration. Continue?',
88
- });
89
- if (isCancel(should_restore) || !should_restore)
90
- return;
91
- const backup_content = await readFile(selected_backup_path, 'utf-8');
92
- const backup_data = JSON.parse(backup_content);
93
- await write_claude_settings({
94
- enabledPlugins: backup_data.enabledPlugins || {},
95
- });
96
- const plugin_count = Object.keys(backup_data.enabledPlugins || {}).length;
97
- log.success(`Plugins restored (${plugin_count} plugins)`);
98
- }
99
- function format_time_ago(date) {
100
- const now = new Date();
101
- const diff = now.getTime() - date.getTime();
102
- const minutes = Math.floor(diff / 60000);
103
- const hours = Math.floor(minutes / 60);
104
- const days = Math.floor(hours / 24);
105
- if (days > 0) {
106
- return `${days} day${days > 1 ? 's' : ''} ago`;
107
- }
108
- else if (hours > 0) {
109
- return `${hours} hour${hours > 1 ? 's' : ''} ago`;
110
- }
111
- else if (minutes > 0) {
112
- return `${minutes} minute${minutes > 1 ? 's' : ''} ago`;
113
- }
114
- else {
115
- return 'just now';
116
- }
117
- }
118
- //# sourceMappingURL=restore.js.map