mcpick 0.0.8 → 0.0.9

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,12 @@
1
1
  # mcpick
2
2
 
3
+ ## 0.0.9
4
+
5
+ ### Patch Changes
6
+
7
+ - d4f4b5c: Add plugin toggle support - enable/disable Claude Code
8
+ plugins from the mcpick menu
9
+
3
10
  ## 0.0.8
4
11
 
5
12
  ### Patch Changes
@@ -0,0 +1,56 @@
1
+ import { log, multiselect, note } from '@clack/prompts';
2
+ import { build_enabled_plugins, get_all_plugins, read_claude_settings, write_claude_settings, } from '../core/settings.js';
3
+ export async function edit_plugins() {
4
+ try {
5
+ const settings = await read_claude_settings();
6
+ const plugins = get_all_plugins(settings);
7
+ if (plugins.length === 0) {
8
+ note('No plugins found in ~/.claude/settings.json.\n' +
9
+ 'Install plugins via Claude Code: /plugin');
10
+ return;
11
+ }
12
+ const plugin_choices = plugins.map((plugin) => ({
13
+ value: `${plugin.name}@${plugin.marketplace}`,
14
+ label: plugin.name,
15
+ hint: plugin.marketplace,
16
+ }));
17
+ const currently_enabled = plugins
18
+ .filter((p) => p.enabled)
19
+ .map((p) => `${p.name}@${p.marketplace}`);
20
+ const selected = await multiselect({
21
+ message: 'Select plugins to enable:',
22
+ options: plugin_choices,
23
+ initialValues: currently_enabled,
24
+ required: false,
25
+ });
26
+ if (typeof selected === 'symbol') {
27
+ return;
28
+ }
29
+ const selected_set = new Set(selected);
30
+ const updated_plugins = plugins.map((plugin) => ({
31
+ ...plugin,
32
+ enabled: selected_set.has(`${plugin.name}@${plugin.marketplace}`),
33
+ }));
34
+ const enabled_plugins = build_enabled_plugins(updated_plugins);
35
+ await write_claude_settings({ enabledPlugins: enabled_plugins });
36
+ const enabled_count = updated_plugins.filter((p) => p.enabled).length;
37
+ const disabled_count = updated_plugins.filter((p) => !p.enabled).length;
38
+ note(`Plugins updated!\n` +
39
+ `Enabled: ${enabled_count}, Disabled: ${disabled_count}`);
40
+ // Show what changed
41
+ const newly_enabled = updated_plugins.filter((p) => p.enabled &&
42
+ !currently_enabled.includes(`${p.name}@${p.marketplace}`));
43
+ const newly_disabled = updated_plugins.filter((p) => !p.enabled &&
44
+ currently_enabled.includes(`${p.name}@${p.marketplace}`));
45
+ if (newly_enabled.length > 0) {
46
+ log.success(`Enabled: ${newly_enabled.map((p) => p.name).join(', ')}`);
47
+ }
48
+ if (newly_disabled.length > 0) {
49
+ log.warn(`Disabled: ${newly_disabled.map((p) => p.name).join(', ')}`);
50
+ }
51
+ }
52
+ catch (error) {
53
+ throw new Error(`Failed to edit plugins: ${error instanceof Error ? error.message : 'Unknown error'}`);
54
+ }
55
+ }
56
+ //# sourceMappingURL=edit-plugins.js.map
@@ -0,0 +1,59 @@
1
+ import { access, readFile, writeFile } from 'node:fs/promises';
2
+ import { get_claude_settings_path } from '../utils/paths.js';
3
+ export async function read_claude_settings() {
4
+ const settings_path = get_claude_settings_path();
5
+ try {
6
+ await access(settings_path);
7
+ const content = await readFile(settings_path, 'utf-8');
8
+ return JSON.parse(content);
9
+ }
10
+ catch (error) {
11
+ if (error instanceof Error &&
12
+ 'code' in error &&
13
+ error.code === 'ENOENT') {
14
+ return {};
15
+ }
16
+ throw error;
17
+ }
18
+ }
19
+ export async function write_claude_settings(updates) {
20
+ const settings_path = get_claude_settings_path();
21
+ let existing = {};
22
+ try {
23
+ const content = await readFile(settings_path, 'utf-8');
24
+ existing = JSON.parse(content);
25
+ }
26
+ catch {
27
+ // Start with empty if file doesn't exist
28
+ }
29
+ // Merge only the keys we're updating
30
+ for (const [key, value] of Object.entries(updates)) {
31
+ existing[key] = value;
32
+ }
33
+ await writeFile(settings_path, JSON.stringify(existing, null, 2), 'utf-8');
34
+ }
35
+ /**
36
+ * Parse enabledPlugins into structured list.
37
+ * Keys are in format "plugin-name@marketplace-name"
38
+ */
39
+ export function get_all_plugins(settings) {
40
+ const enabled_plugins = settings.enabledPlugins || {};
41
+ return Object.entries(enabled_plugins).map(([key, enabled]) => {
42
+ const at_index = key.lastIndexOf('@');
43
+ const name = at_index > 0 ? key.substring(0, at_index) : key;
44
+ const marketplace = at_index > 0 ? key.substring(at_index + 1) : 'unknown';
45
+ return { name, marketplace, enabled };
46
+ });
47
+ }
48
+ /**
49
+ * Build the enabledPlugins record from a list of PluginInfo
50
+ */
51
+ export function build_enabled_plugins(plugins) {
52
+ const result = {};
53
+ for (const plugin of plugins) {
54
+ const key = `${plugin.name}@${plugin.marketplace}`;
55
+ result[key] = plugin.enabled;
56
+ }
57
+ return result;
58
+ }
59
+ //# sourceMappingURL=settings.js.map
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ import { cancel, intro, isCancel, log, outro, select, text, } from '@clack/promp
3
3
  import { add_server } from './commands/add-server.js';
4
4
  import { backup_config } from './commands/backup.js';
5
5
  import { edit_config } from './commands/edit-config.js';
6
+ import { edit_plugins } from './commands/edit-plugins.js';
6
7
  import { restore_config } from './commands/restore.js';
7
8
  import { write_claude_config } from './core/config.js';
8
9
  import { list_profiles, load_profile, save_profile, } from './core/profile.js';
@@ -142,6 +143,11 @@ async function main() {
142
143
  label: 'Enable / Disable MCP servers',
143
144
  hint: 'Toggle MCP servers on/off',
144
145
  },
146
+ {
147
+ value: 'edit-plugins',
148
+ label: 'Enable / Disable plugins',
149
+ hint: 'Toggle Claude Code plugins on/off',
150
+ },
145
151
  {
146
152
  value: 'backup',
147
153
  label: 'Backup config',
@@ -182,6 +188,9 @@ async function main() {
182
188
  case 'edit-config':
183
189
  await edit_config();
184
190
  break;
191
+ case 'edit-plugins':
192
+ await edit_plugins();
193
+ break;
185
194
  case 'backup':
186
195
  await backup_config();
187
196
  break;
@@ -25,6 +25,9 @@ export function get_claude_config_path() {
25
25
  }
26
26
  return join(parentDir, '.claude.json');
27
27
  }
28
+ export function get_claude_settings_path() {
29
+ return join(get_base_dir().baseDir, 'settings.json');
30
+ }
28
31
  export function get_mcpick_dir() {
29
32
  return join(get_base_dir().baseDir, 'mcpick');
30
33
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mcpick",
3
- "version": "0.0.8",
4
- "description": "Dynamic MCP server configuration manager for Claude Code",
3
+ "version": "0.0.9",
4
+ "description": "Dynamic MCP server and plugin configuration manager for Claude Code",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "bin": {
@@ -20,12 +20,12 @@
20
20
  "author": "",
21
21
  "license": "MIT",
22
22
  "dependencies": {
23
- "@clack/prompts": "^0.11.0",
23
+ "@clack/prompts": "^1.0.0",
24
24
  "valibot": "^1.2.0"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@changesets/cli": "^2.29.8",
28
- "@types/node": "^24.10.1",
28
+ "@types/node": "^25.0.1",
29
29
  "prettier": "^3.7.4",
30
30
  "typescript": "^5.9.3"
31
31
  },
@@ -1,21 +0,0 @@
1
- import { outro } from '@clack/prompts';
2
- import { execSync } from 'node:child_process';
3
- export async function launch_claude_code() {
4
- try {
5
- outro('Launching Claude Code...');
6
- // Replace the current process with claude using exec
7
- // This ensures the terminal stays valid and Claude gets full control
8
- execSync('claude', {
9
- stdio: 'inherit',
10
- });
11
- }
12
- catch (error) {
13
- if (error instanceof Error && 'status' in error) {
14
- // Claude exited normally, just return
15
- return;
16
- }
17
- // Only throw for actual errors (not exit codes)
18
- throw new Error(`Failed to launch Claude Code: ${error instanceof Error ? error.message : 'Unknown error'}`);
19
- }
20
- }
21
- //# sourceMappingURL=launch.js.map