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 +7 -0
- package/dist/commands/edit-plugins.js +56 -0
- package/dist/core/settings.js +59 -0
- package/dist/index.js +9 -0
- package/dist/utils/paths.js +3 -0
- package/package.json +4 -4
- package/dist/commands/launch.js +0 -21
package/CHANGELOG.md
CHANGED
|
@@ -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;
|
package/dist/utils/paths.js
CHANGED
|
@@ -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.
|
|
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.
|
|
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": "^
|
|
28
|
+
"@types/node": "^25.0.1",
|
|
29
29
|
"prettier": "^3.7.4",
|
|
30
30
|
"typescript": "^5.9.3"
|
|
31
31
|
},
|
package/dist/commands/launch.js
DELETED
|
@@ -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
|