mcpick 0.0.10 → 0.0.11

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/dist/index.js CHANGED
@@ -8,6 +8,7 @@ import { manage_cache } from './commands/manage-cache.js';
8
8
  import { restore_config } from './commands/restore.js';
9
9
  import { write_claude_config } from './core/config.js';
10
10
  import { list_profiles, load_profile, save_profile, } from './core/profile.js';
11
+ import { write_claude_settings } from './core/settings.js';
11
12
  function parse_args() {
12
13
  const args = process.argv.slice(2);
13
14
  const result = {};
@@ -29,10 +30,17 @@ function parse_args() {
29
30
  async function apply_profile(name) {
30
31
  intro(`MCPick - Loading profile: ${name}`);
31
32
  try {
32
- const profile_config = await load_profile(name);
33
- await write_claude_config(profile_config);
34
- const server_count = Object.keys(profile_config.mcpServers || {}).length;
35
- log.success(`Profile '${name}' applied (${server_count} servers)`);
33
+ const profile = await load_profile(name);
34
+ await write_claude_config(profile.config);
35
+ const server_count = Object.keys(profile.config.mcpServers || {}).length;
36
+ const parts = [`${server_count} servers`];
37
+ if (profile.enabledPlugins) {
38
+ await write_claude_settings({
39
+ enabledPlugins: profile.enabledPlugins,
40
+ });
41
+ parts.push(`${Object.keys(profile.enabledPlugins).length} plugins`);
42
+ }
43
+ log.success(`Profile '${name}' applied (${parts.join(', ')})`);
36
44
  outro('Done!');
37
45
  }
38
46
  catch (error) {
@@ -62,8 +70,12 @@ async function show_profiles() {
62
70
  async function create_profile(name) {
63
71
  intro(`MCPick - Saving profile: ${name}`);
64
72
  try {
65
- const server_count = await save_profile(name);
66
- log.success(`Profile '${name}' saved (${server_count} servers)`);
73
+ const counts = await save_profile(name);
74
+ const parts = [`${counts.serverCount} servers`];
75
+ if (counts.pluginCount > 0) {
76
+ parts.push(`${counts.pluginCount} plugins`);
77
+ }
78
+ log.success(`Profile '${name}' saved (${parts.join(', ')})`);
67
79
  outro('Done!');
68
80
  }
69
81
  catch (error) {
@@ -85,18 +97,31 @@ async function handle_load_profile() {
85
97
  }
86
98
  const profile_name = await select({
87
99
  message: 'Select a profile to load:',
88
- options: profiles.map((p) => ({
89
- value: p.name,
90
- label: p.name,
91
- hint: `${p.serverCount} servers`,
92
- })),
100
+ options: profiles.map((p) => {
101
+ const parts = [`${p.serverCount} servers`];
102
+ if (p.pluginCount > 0) {
103
+ parts.push(`${p.pluginCount} plugins`);
104
+ }
105
+ return {
106
+ value: p.name,
107
+ label: p.name,
108
+ hint: parts.join(', '),
109
+ };
110
+ }),
93
111
  });
94
112
  if (isCancel(profile_name))
95
113
  return;
96
- const profile_config = await load_profile(profile_name);
97
- await write_claude_config(profile_config);
98
- const server_count = Object.keys(profile_config.mcpServers || {}).length;
99
- log.success(`Profile '${profile_name}' applied (${server_count} servers)`);
114
+ const profile = await load_profile(profile_name);
115
+ await write_claude_config(profile.config);
116
+ const server_count = Object.keys(profile.config.mcpServers || {}).length;
117
+ const parts = [`${server_count} servers`];
118
+ if (profile.enabledPlugins) {
119
+ await write_claude_settings({
120
+ enabledPlugins: profile.enabledPlugins,
121
+ });
122
+ parts.push(`${Object.keys(profile.enabledPlugins).length} plugins`);
123
+ }
124
+ log.success(`Profile '${profile_name}' applied (${parts.join(', ')})`);
100
125
  }
101
126
  async function handle_save_profile() {
102
127
  const name = await text({
@@ -113,8 +138,12 @@ async function handle_save_profile() {
113
138
  });
114
139
  if (isCancel(name))
115
140
  return;
116
- const server_count = await save_profile(name);
117
- log.success(`Profile '${name}' saved (${server_count} servers)`);
141
+ const counts = await save_profile(name);
142
+ const parts = [`${counts.serverCount} servers`];
143
+ if (counts.pluginCount > 0) {
144
+ parts.push(`${counts.pluginCount} plugins`);
145
+ }
146
+ log.success(`Profile '${name}' saved (${parts.join(', ')})`);
118
147
  }
119
148
  async function main() {
120
149
  const args = parse_args();
@@ -146,8 +175,8 @@ async function main() {
146
175
  },
147
176
  {
148
177
  value: 'edit-plugins',
149
- label: 'Enable / Disable plugins',
150
- hint: 'Toggle Claude Code plugins on/off',
178
+ label: 'Manage plugins',
179
+ hint: 'Toggle, install, uninstall, or update plugins',
151
180
  },
152
181
  {
153
182
  value: 'manage-cache',
@@ -115,6 +115,75 @@ export async function remove_mcp_via_cli(name) {
115
115
  };
116
116
  }
117
117
  }
118
+ /**
119
+ * Install a plugin via Claude CLI
120
+ */
121
+ export async function install_plugin_via_cli(key, scope = 'user') {
122
+ const cli_available = await check_claude_cli();
123
+ if (!cli_available) {
124
+ return {
125
+ success: false,
126
+ error: 'Claude CLI not found. Please install Claude Code CLI.',
127
+ };
128
+ }
129
+ try {
130
+ await execAsync(`claude plugin install ${shell_escape(key)} --scope ${scope}`);
131
+ return { success: true };
132
+ }
133
+ catch (error) {
134
+ const message = error instanceof Error ? error.message : 'Unknown error';
135
+ return {
136
+ success: false,
137
+ error: `Failed to install plugin: ${message}`,
138
+ };
139
+ }
140
+ }
141
+ /**
142
+ * Uninstall a plugin via Claude CLI
143
+ */
144
+ export async function uninstall_plugin_via_cli(key, scope = 'user') {
145
+ const cli_available = await check_claude_cli();
146
+ if (!cli_available) {
147
+ return {
148
+ success: false,
149
+ error: 'Claude CLI not found. Please install Claude Code CLI.',
150
+ };
151
+ }
152
+ try {
153
+ await execAsync(`claude plugin uninstall ${shell_escape(key)} --scope ${scope}`);
154
+ return { success: true };
155
+ }
156
+ catch (error) {
157
+ const message = error instanceof Error ? error.message : 'Unknown error';
158
+ return {
159
+ success: false,
160
+ error: `Failed to uninstall plugin: ${message}`,
161
+ };
162
+ }
163
+ }
164
+ /**
165
+ * Update a plugin via Claude CLI
166
+ */
167
+ export async function update_plugin_via_cli(key, scope = 'user') {
168
+ const cli_available = await check_claude_cli();
169
+ if (!cli_available) {
170
+ return {
171
+ success: false,
172
+ error: 'Claude CLI not found. Please install Claude Code CLI.',
173
+ };
174
+ }
175
+ try {
176
+ await execAsync(`claude plugin update ${shell_escape(key)} --scope ${scope}`);
177
+ return { success: true };
178
+ }
179
+ catch (error) {
180
+ const message = error instanceof Error ? error.message : 'Unknown error';
181
+ return {
182
+ success: false,
183
+ error: `Failed to update plugin: ${message}`,
184
+ };
185
+ }
186
+ }
118
187
  /**
119
188
  * Get the scope description for display
120
189
  */
@@ -45,7 +45,7 @@ export function get_profile_path(name) {
45
45
  const filename = name.endsWith('.json') ? name : `${name}.json`;
46
46
  return join(get_profiles_dir(), filename);
47
47
  }
48
- export function get_backup_filename() {
48
+ function format_backup_timestamp() {
49
49
  const now = new Date();
50
50
  const year = now.getFullYear();
51
51
  const month = String(now.getMonth() + 1).padStart(2, '0');
@@ -53,7 +53,13 @@ export function get_backup_filename() {
53
53
  const hour = String(now.getHours()).padStart(2, '0');
54
54
  const minute = String(now.getMinutes()).padStart(2, '0');
55
55
  const second = String(now.getSeconds()).padStart(2, '0');
56
- return `mcp-servers-${year}-${month}-${day}-${hour}${minute}${second}.json`;
56
+ return `${year}-${month}-${day}-${hour}${minute}${second}`;
57
+ }
58
+ export function get_backup_filename() {
59
+ return `mcp-servers-${format_backup_timestamp()}.json`;
60
+ }
61
+ export function get_plugin_backup_filename() {
62
+ return `plugins-${format_backup_timestamp()}.json`;
57
63
  }
58
64
  export async function ensure_directory_exists(dir_path) {
59
65
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcpick",
3
- "version": "0.0.10",
3
+ "version": "0.0.11",
4
4
  "description": "Dynamic MCP server and plugin configuration manager for Claude Code",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",