mcpick 0.0.18 → 0.0.20
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/.github/workflows/ci.yml +26 -0
- package/.vscode/settings.json +5 -0
- package/CHANGELOG.md +15 -0
- package/LICENSE +21 -0
- package/dist/add-BDyaBew0.js +113 -0
- package/dist/add-json-BjgzdeG-.js +58 -0
- package/dist/atomic-write-BqEykHp9.js +26 -0
- package/dist/backup-DSDhHI5f.js +64 -0
- package/dist/cache-D6kd7qE8.js +226 -0
- package/dist/claude-cli-DnmBJrjg.js +445 -0
- package/dist/cli-CsFfnWBo.js +84 -0
- package/dist/clone-DYKPEsar.js +88 -0
- package/dist/config-DijVdEFn.js +176 -0
- package/dist/dev-DRJRNp7y.js +265 -0
- package/dist/disable-xJXZfUR_.js +39 -0
- package/dist/enable-RrpcN6la.js +40 -0
- package/dist/get-Bb1eOOIZ.js +41 -0
- package/dist/hook-state-Di8lUsPr.js +171 -0
- package/dist/hooks-Bmn7pUZa.js +280 -0
- package/dist/index.js +1232 -305
- package/dist/list-B8YeDWt6.js +64 -0
- package/dist/marketplace-DcKk5dc1.js +168 -0
- package/dist/output-BchYq0mR.js +15 -0
- package/dist/paths-BPISiJi4.js +124 -0
- package/dist/plugin-cache-Bby9Dxm9.js +405 -0
- package/dist/plugins-Dc7DN6R_.js +212 -0
- package/dist/profile-CX97sMGp.js +120 -0
- package/dist/profile-DkY_lBEm.js +70 -0
- package/dist/redact-O35tjnRD.js +26 -0
- package/dist/registry-CfUKT7_C.js +92 -0
- package/dist/reload-CYDhkCVZ.js +31 -0
- package/dist/remove-D1owHLhG.js +31 -0
- package/dist/reset-project-choices-BfRSNN3m.js +28 -0
- package/dist/restore-DdMfUljI.js +84 -0
- package/dist/rolldown-runtime-CiIaOW0V.js +13 -0
- package/dist/settings-DEcWtzLE.js +201 -0
- package/dist/validation-xMlbgGCF.js +44 -0
- package/package.json +23 -22
- package/dist/cli/commands/add-json.js +0 -60
- package/dist/cli/commands/add.js +0 -135
- package/dist/cli/commands/backup.js +0 -83
- package/dist/cli/commands/cache.js +0 -296
- package/dist/cli/commands/clone.js +0 -108
- package/dist/cli/commands/dev.js +0 -167
- package/dist/cli/commands/disable.js +0 -36
- package/dist/cli/commands/enable.js +0 -39
- package/dist/cli/commands/get.js +0 -45
- package/dist/cli/commands/hooks.js +0 -314
- package/dist/cli/commands/list.js +0 -64
- package/dist/cli/commands/marketplace.js +0 -211
- package/dist/cli/commands/plugins.js +0 -265
- package/dist/cli/commands/profile.js +0 -134
- package/dist/cli/commands/reload.js +0 -36
- package/dist/cli/commands/remove.js +0 -35
- package/dist/cli/commands/reset-project-choices.js +0 -32
- package/dist/cli/commands/restore.js +0 -105
- package/dist/cli/index.js +0 -29
- package/dist/cli/output.js +0 -21
- package/dist/commands/add-server.js +0 -310
- package/dist/commands/backup.js +0 -60
- package/dist/commands/edit-config.js +0 -109
- package/dist/commands/edit-plugins.js +0 -201
- package/dist/commands/manage-cache.js +0 -155
- package/dist/commands/manage-hooks.js +0 -99
- package/dist/commands/manage-marketplace.js +0 -293
- package/dist/commands/restore.js +0 -118
- package/dist/core/config.js +0 -200
- package/dist/core/dev-override.js +0 -155
- package/dist/core/hook-state.js +0 -220
- package/dist/core/plugin-cache.js +0 -506
- package/dist/core/profile.js +0 -94
- package/dist/core/registry.js +0 -121
- package/dist/core/settings.js +0 -243
- package/dist/core/validation.js +0 -49
- package/dist/types.js +0 -2
- package/dist/utils/atomic-write.js +0 -27
- package/dist/utils/claude-cli.js +0 -485
- package/dist/utils/paths.js +0 -114
- package/dist/utils/redact.js +0 -28
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v6
|
|
14
|
+
|
|
15
|
+
- uses: pnpm/action-setup@v6
|
|
16
|
+
|
|
17
|
+
- uses: actions/setup-node@v6
|
|
18
|
+
with:
|
|
19
|
+
node-version-file: package.json
|
|
20
|
+
cache: pnpm
|
|
21
|
+
|
|
22
|
+
- run: pnpm install --frozen-lockfile
|
|
23
|
+
|
|
24
|
+
- run: pnpm run build
|
|
25
|
+
|
|
26
|
+
- run: pnpm run test
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# mcpick
|
|
2
2
|
|
|
3
|
+
## 0.0.20
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 00ea930: chore: add unit tests and CI workflow with GitHub Actions
|
|
8
|
+
- 37a62e1: feat: auto-show help instead of TUI in non-TTY environments for LLM agents
|
|
9
|
+
- fc1db54: fix: replace exec with execFile to eliminate shell injection on all platforms
|
|
10
|
+
|
|
11
|
+
## 0.0.19
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- 5ed618e: Migrate build tooling from tsc/prettier to vite-plus, fix all lint warnings
|
|
16
|
+
- 08997dc: feat: rewrite --help for LLM agents with workflow, concepts, and examples sections
|
|
17
|
+
|
|
3
18
|
## 0.0.18
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Scott Spence
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { n as validate_mcp_server } from "./validation-xMlbgGCF.js";
|
|
2
|
+
import { t as add_server_to_registry } from "./registry-CfUKT7_C.js";
|
|
3
|
+
import { t as add_mcp_via_cli } from "./claude-cli-DnmBJrjg.js";
|
|
4
|
+
import { n as output, t as error } from "./output-BchYq0mR.js";
|
|
5
|
+
import { defineCommand } from "citty";
|
|
6
|
+
//#region src/cli/commands/add.ts
|
|
7
|
+
var add_default = defineCommand({
|
|
8
|
+
meta: {
|
|
9
|
+
name: "add",
|
|
10
|
+
description: "Add a new MCP server to the registry and enable it"
|
|
11
|
+
},
|
|
12
|
+
args: {
|
|
13
|
+
name: {
|
|
14
|
+
type: "string",
|
|
15
|
+
description: "Server name",
|
|
16
|
+
required: true
|
|
17
|
+
},
|
|
18
|
+
command: {
|
|
19
|
+
type: "string",
|
|
20
|
+
description: "Command to run (for stdio transport)"
|
|
21
|
+
},
|
|
22
|
+
args: {
|
|
23
|
+
type: "string",
|
|
24
|
+
description: "Comma-separated arguments (e.g. \"npx,-y,mcp-sqlite\")"
|
|
25
|
+
},
|
|
26
|
+
url: {
|
|
27
|
+
type: "string",
|
|
28
|
+
description: "URL (for sse or http transport)"
|
|
29
|
+
},
|
|
30
|
+
type: {
|
|
31
|
+
type: "string",
|
|
32
|
+
description: "Transport type: stdio, sse, or http (default: stdio)",
|
|
33
|
+
default: "stdio"
|
|
34
|
+
},
|
|
35
|
+
env: {
|
|
36
|
+
type: "string",
|
|
37
|
+
description: "Environment variables as KEY=val,KEY=val"
|
|
38
|
+
},
|
|
39
|
+
headers: {
|
|
40
|
+
type: "string",
|
|
41
|
+
description: "HTTP headers as KEY=val,KEY=val"
|
|
42
|
+
},
|
|
43
|
+
description: {
|
|
44
|
+
type: "string",
|
|
45
|
+
description: "Server description"
|
|
46
|
+
},
|
|
47
|
+
scope: {
|
|
48
|
+
type: "string",
|
|
49
|
+
description: "Scope: local, project, or user (default: local)",
|
|
50
|
+
default: "local"
|
|
51
|
+
},
|
|
52
|
+
json: {
|
|
53
|
+
type: "boolean",
|
|
54
|
+
description: "Output as JSON",
|
|
55
|
+
default: false
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
async run({ args }) {
|
|
59
|
+
const scope = args.scope;
|
|
60
|
+
if (![
|
|
61
|
+
"local",
|
|
62
|
+
"project",
|
|
63
|
+
"user"
|
|
64
|
+
].includes(scope)) error(`Invalid scope: ${scope}. Use local, project, or user.`);
|
|
65
|
+
const transport = args.type;
|
|
66
|
+
if (![
|
|
67
|
+
"stdio",
|
|
68
|
+
"sse",
|
|
69
|
+
"http"
|
|
70
|
+
].includes(transport)) error(`Invalid type: ${transport}. Use stdio, sse, or http.`);
|
|
71
|
+
const server_data = { name: args.name };
|
|
72
|
+
if (transport === "stdio") {
|
|
73
|
+
if (!args.command) error("--command is required for stdio transport");
|
|
74
|
+
server_data.command = args.command;
|
|
75
|
+
if (args.args) server_data.args = args.args.split(",");
|
|
76
|
+
} else {
|
|
77
|
+
if (!args.url) error(`--url is required for ${transport} transport`);
|
|
78
|
+
server_data.type = transport;
|
|
79
|
+
server_data.url = args.url;
|
|
80
|
+
if (args.headers) server_data.headers = parse_key_value_pairs(args.headers);
|
|
81
|
+
}
|
|
82
|
+
if (args.env) server_data.env = parse_key_value_pairs(args.env);
|
|
83
|
+
if (args.description) server_data.description = args.description;
|
|
84
|
+
let server;
|
|
85
|
+
try {
|
|
86
|
+
server = validate_mcp_server(server_data);
|
|
87
|
+
} catch (err) {
|
|
88
|
+
error(`Invalid server config: ${err instanceof Error ? err.message : "validation failed"}`);
|
|
89
|
+
}
|
|
90
|
+
await add_server_to_registry(server);
|
|
91
|
+
const result = await add_mcp_via_cli(server, scope);
|
|
92
|
+
if (args.json) output({
|
|
93
|
+
added: server.name,
|
|
94
|
+
scope,
|
|
95
|
+
cli: result.success,
|
|
96
|
+
error: result.error
|
|
97
|
+
}, true);
|
|
98
|
+
else if (result.success) console.log(`Added '${server.name}' and enabled (scope: ${scope})`);
|
|
99
|
+
else console.log(`Added '${server.name}' to registry but CLI failed: ${result.error}`);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
function parse_key_value_pairs(input) {
|
|
103
|
+
const result = {};
|
|
104
|
+
for (const pair of input.split(",")) {
|
|
105
|
+
const eq = pair.indexOf("=");
|
|
106
|
+
if (eq > 0) result[pair.substring(0, eq)] = pair.substring(eq + 1);
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
export { add_default as default };
|
|
112
|
+
|
|
113
|
+
//# sourceMappingURL=add-BDyaBew0.js.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { u as mcp_add_json_via_cli } from "./claude-cli-DnmBJrjg.js";
|
|
2
|
+
import { n as output, t as error } from "./output-BchYq0mR.js";
|
|
3
|
+
import { defineCommand } from "citty";
|
|
4
|
+
//#region src/cli/commands/add-json.ts
|
|
5
|
+
var add_json_default = defineCommand({
|
|
6
|
+
meta: {
|
|
7
|
+
name: "add-json",
|
|
8
|
+
description: "Add an MCP server from a JSON configuration string"
|
|
9
|
+
},
|
|
10
|
+
args: {
|
|
11
|
+
name: {
|
|
12
|
+
type: "positional",
|
|
13
|
+
description: "Server name",
|
|
14
|
+
required: true
|
|
15
|
+
},
|
|
16
|
+
config: {
|
|
17
|
+
type: "positional",
|
|
18
|
+
description: "JSON configuration string",
|
|
19
|
+
required: true
|
|
20
|
+
},
|
|
21
|
+
scope: {
|
|
22
|
+
type: "string",
|
|
23
|
+
description: "Scope: local, project, or user (default: local)",
|
|
24
|
+
default: "local"
|
|
25
|
+
},
|
|
26
|
+
json: {
|
|
27
|
+
type: "boolean",
|
|
28
|
+
description: "Output as JSON",
|
|
29
|
+
default: false
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
async run({ args }) {
|
|
33
|
+
const scope = args.scope;
|
|
34
|
+
if (![
|
|
35
|
+
"local",
|
|
36
|
+
"project",
|
|
37
|
+
"user"
|
|
38
|
+
].includes(scope)) error(`Invalid scope: ${scope}. Use local, project, or user.`);
|
|
39
|
+
try {
|
|
40
|
+
JSON.parse(args.config);
|
|
41
|
+
} catch {
|
|
42
|
+
error("Invalid JSON configuration. Provide a valid JSON string.");
|
|
43
|
+
}
|
|
44
|
+
const result = await mcp_add_json_via_cli(args.name, args.config, scope);
|
|
45
|
+
if (args.json) output({
|
|
46
|
+
added: args.name,
|
|
47
|
+
scope,
|
|
48
|
+
success: result.success,
|
|
49
|
+
error: result.error
|
|
50
|
+
}, true);
|
|
51
|
+
else if (result.success) console.log(`Added '${args.name}' from JSON (scope: ${scope})`);
|
|
52
|
+
else error(result.error || "Unknown error");
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
//#endregion
|
|
56
|
+
export { add_json_default as default };
|
|
57
|
+
|
|
58
|
+
//# sourceMappingURL=add-json-BjgzdeG-.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { readFile, rename, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
//#region src/utils/atomic-write.ts
|
|
4
|
+
/**
|
|
5
|
+
* Atomically write a JSON file with fresh-read merging.
|
|
6
|
+
*
|
|
7
|
+
* 1. Re-reads the file right before writing to pick up concurrent changes
|
|
8
|
+
* 2. Applies the merge function to the freshest data
|
|
9
|
+
* 3. Writes to a temp file, then renames (atomic on same filesystem)
|
|
10
|
+
*/
|
|
11
|
+
async function atomic_json_write(file_path, merge) {
|
|
12
|
+
let existing = {};
|
|
13
|
+
try {
|
|
14
|
+
const content = await readFile(file_path, "utf-8");
|
|
15
|
+
existing = JSON.parse(content);
|
|
16
|
+
} catch {}
|
|
17
|
+
const merged = merge(existing);
|
|
18
|
+
const content = JSON.stringify(merged, null, 2);
|
|
19
|
+
const tmp_path = join(dirname(file_path), `.${Date.now()}.tmp`);
|
|
20
|
+
await writeFile(tmp_path, content, "utf-8");
|
|
21
|
+
await rename(tmp_path, file_path);
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { atomic_json_write as t };
|
|
25
|
+
|
|
26
|
+
//# sourceMappingURL=atomic-write-BqEykHp9.js.map
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { m as get_plugin_backup_filename, n as get_backup_filename, r as get_backups_dir, t as ensure_directory_exists } from "./paths-BPISiJi4.js";
|
|
2
|
+
import { s as read_claude_config } from "./config-DijVdEFn.js";
|
|
3
|
+
import { a as read_claude_settings } from "./settings-DEcWtzLE.js";
|
|
4
|
+
import { n as output } from "./output-BchYq0mR.js";
|
|
5
|
+
import { readdir, unlink, writeFile } from "node:fs/promises";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { defineCommand } from "citty";
|
|
8
|
+
//#region src/cli/commands/backup.ts
|
|
9
|
+
const MAX_BACKUPS = 10;
|
|
10
|
+
async function cleanup_old_backups(prefix) {
|
|
11
|
+
try {
|
|
12
|
+
const backups_dir = get_backups_dir();
|
|
13
|
+
const backup_files = (await readdir(backups_dir)).filter((f) => f.startsWith(prefix) && f.endsWith(".json")).sort().reverse();
|
|
14
|
+
if (backup_files.length > MAX_BACKUPS) for (const file of backup_files.slice(MAX_BACKUPS)) await unlink(join(backups_dir, file));
|
|
15
|
+
} catch {}
|
|
16
|
+
}
|
|
17
|
+
var backup_default = defineCommand({
|
|
18
|
+
meta: {
|
|
19
|
+
name: "backup",
|
|
20
|
+
description: "Create a timestamped backup of MCP servers and plugins"
|
|
21
|
+
},
|
|
22
|
+
args: { json: {
|
|
23
|
+
type: "boolean",
|
|
24
|
+
description: "Output as JSON",
|
|
25
|
+
default: false
|
|
26
|
+
} },
|
|
27
|
+
async run({ args }) {
|
|
28
|
+
const current_config = await read_claude_config();
|
|
29
|
+
const current_settings = await read_claude_settings();
|
|
30
|
+
const backups_dir = get_backups_dir();
|
|
31
|
+
await ensure_directory_exists(backups_dir);
|
|
32
|
+
const mcp_path = join(backups_dir, get_backup_filename());
|
|
33
|
+
const mcp_backup = { mcpServers: current_config.mcpServers || {} };
|
|
34
|
+
await writeFile(mcp_path, JSON.stringify(mcp_backup, null, 2), "utf-8");
|
|
35
|
+
const plugins = current_settings.enabledPlugins || {};
|
|
36
|
+
const plugin_count = Object.keys(plugins).length;
|
|
37
|
+
let plugin_path = null;
|
|
38
|
+
if (plugin_count > 0) {
|
|
39
|
+
plugin_path = join(backups_dir, get_plugin_backup_filename());
|
|
40
|
+
await writeFile(plugin_path, JSON.stringify({ enabledPlugins: plugins }, null, 2), "utf-8");
|
|
41
|
+
}
|
|
42
|
+
await cleanup_old_backups("mcp-servers-");
|
|
43
|
+
await cleanup_old_backups("plugins-");
|
|
44
|
+
const server_count = Object.keys(current_config.mcpServers || {}).length;
|
|
45
|
+
if (args.json) output({
|
|
46
|
+
mcp: {
|
|
47
|
+
path: mcp_path,
|
|
48
|
+
servers: server_count
|
|
49
|
+
},
|
|
50
|
+
plugins: plugin_path ? {
|
|
51
|
+
path: plugin_path,
|
|
52
|
+
plugins: plugin_count
|
|
53
|
+
} : null
|
|
54
|
+
}, true);
|
|
55
|
+
else {
|
|
56
|
+
console.log(`Backup created: ${mcp_path} (${server_count} servers)`);
|
|
57
|
+
if (plugin_path) console.log(`Plugin backup: ${plugin_path} (${plugin_count} plugins)`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
//#endregion
|
|
62
|
+
export { backup_default as default };
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=backup-DSDhHI5f.js.map
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { a as list_linked_plugins, c as read_installed_plugins, d as refresh_all_marketplaces, f as scan_all_cache_keys, i as link_local_plugin, n as clear_plugin_caches, p as unlink_local_plugin, r as get_cached_plugins_info, t as clean_orphaned_versions } from "./plugin-cache-Bby9Dxm9.js";
|
|
2
|
+
import { n as output, t as error } from "./output-BchYq0mR.js";
|
|
3
|
+
import { defineCommand } from "citty";
|
|
4
|
+
var cache_default = defineCommand({
|
|
5
|
+
meta: {
|
|
6
|
+
name: "cache",
|
|
7
|
+
description: "Manage plugin cache"
|
|
8
|
+
},
|
|
9
|
+
subCommands: {
|
|
10
|
+
status: defineCommand({
|
|
11
|
+
meta: {
|
|
12
|
+
name: "status",
|
|
13
|
+
description: "Show cached plugins with staleness info"
|
|
14
|
+
},
|
|
15
|
+
args: { json: {
|
|
16
|
+
type: "boolean",
|
|
17
|
+
description: "Output as JSON",
|
|
18
|
+
default: false
|
|
19
|
+
} },
|
|
20
|
+
async run({ args }) {
|
|
21
|
+
const plugins = await get_cached_plugins_info();
|
|
22
|
+
if (args.json) {
|
|
23
|
+
output(plugins, true);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (plugins.length === 0) {
|
|
27
|
+
console.log("No cached plugins found.");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
for (const p of plugins) {
|
|
31
|
+
const stale_markers = [];
|
|
32
|
+
if (p.isVersionStale) stale_markers.push(`version: ${p.installedVersion} → ${p.latestVersion}`);
|
|
33
|
+
if (p.isShaStale) stale_markers.push("commits behind");
|
|
34
|
+
if (p.orphanedVersions.length > 0) stale_markers.push(`${p.orphanedVersions.length} orphaned`);
|
|
35
|
+
const status_str = stale_markers.length > 0 ? ` [stale: ${stale_markers.join(", ")}]` : " [up to date]";
|
|
36
|
+
console.log(`${p.name}@${p.marketplace} v${p.installedVersion}${status_str}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}),
|
|
40
|
+
clear: defineCommand({
|
|
41
|
+
meta: {
|
|
42
|
+
name: "clear",
|
|
43
|
+
description: "Clear plugin caches (refreshes marketplace first)"
|
|
44
|
+
},
|
|
45
|
+
args: {
|
|
46
|
+
plugin: {
|
|
47
|
+
type: "positional",
|
|
48
|
+
description: "Plugin key (name@marketplace) — omit for all",
|
|
49
|
+
required: false
|
|
50
|
+
},
|
|
51
|
+
all: {
|
|
52
|
+
type: "boolean",
|
|
53
|
+
description: "Clear all plugin caches",
|
|
54
|
+
default: false
|
|
55
|
+
},
|
|
56
|
+
json: {
|
|
57
|
+
type: "boolean",
|
|
58
|
+
description: "Output as JSON",
|
|
59
|
+
default: false
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
async run({ args }) {
|
|
63
|
+
const installed = await read_installed_plugins();
|
|
64
|
+
const installed_keys = Object.keys(installed.plugins);
|
|
65
|
+
const scanned_keys = args.all ? await scan_all_cache_keys() : [];
|
|
66
|
+
const all_keys = [...new Set([...installed_keys, ...scanned_keys])];
|
|
67
|
+
if (all_keys.length === 0) {
|
|
68
|
+
if (args.json) output({
|
|
69
|
+
cleared: [],
|
|
70
|
+
errors: []
|
|
71
|
+
}, true);
|
|
72
|
+
else console.log("No cached plugins to clear.");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
let keys_to_clear;
|
|
76
|
+
if (args.plugin) {
|
|
77
|
+
if (!installed.plugins[args.plugin] && !scanned_keys.includes(args.plugin)) error(`Plugin '${args.plugin}' not found in cache. Run 'mcpick cache status' to see cached plugins.`);
|
|
78
|
+
keys_to_clear = [args.plugin];
|
|
79
|
+
} else if (args.all) keys_to_clear = all_keys;
|
|
80
|
+
else error("Specify a plugin key or use --all. Run \"mcpick cache status\" to see cached plugins.");
|
|
81
|
+
const result = await clear_plugin_caches(keys_to_clear);
|
|
82
|
+
if (args.json) output(result, true);
|
|
83
|
+
else {
|
|
84
|
+
for (const key of result.cleared) console.log(`Cleared: ${key}`);
|
|
85
|
+
for (const err of result.errors) console.error(`Error: ${err}`);
|
|
86
|
+
if (result.cleared.length > 0) console.log("\nRun /reload-plugins in Claude Code or restart your session.");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}),
|
|
90
|
+
"clean-orphaned": defineCommand({
|
|
91
|
+
meta: {
|
|
92
|
+
name: "clean-orphaned",
|
|
93
|
+
description: "Remove orphaned plugin version directories"
|
|
94
|
+
},
|
|
95
|
+
args: { json: {
|
|
96
|
+
type: "boolean",
|
|
97
|
+
description: "Output as JSON",
|
|
98
|
+
default: false
|
|
99
|
+
} },
|
|
100
|
+
async run({ args }) {
|
|
101
|
+
const result = await clean_orphaned_versions();
|
|
102
|
+
if (args.json) output(result, true);
|
|
103
|
+
else if (result.cleaned === 0) console.log("No orphaned versions found.");
|
|
104
|
+
else {
|
|
105
|
+
for (const p of result.paths) console.log(`Removed: ${p}`);
|
|
106
|
+
console.log(`\nCleaned ${result.cleaned} orphaned version(s).`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}),
|
|
110
|
+
refresh: defineCommand({
|
|
111
|
+
meta: {
|
|
112
|
+
name: "refresh",
|
|
113
|
+
description: "Refresh all marketplace clones (git pull)"
|
|
114
|
+
},
|
|
115
|
+
args: { json: {
|
|
116
|
+
type: "boolean",
|
|
117
|
+
description: "Output as JSON",
|
|
118
|
+
default: false
|
|
119
|
+
} },
|
|
120
|
+
async run({ args }) {
|
|
121
|
+
const results = await refresh_all_marketplaces();
|
|
122
|
+
if (args.json) {
|
|
123
|
+
output(Object.fromEntries(results), true);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (results.size === 0) {
|
|
127
|
+
console.log("No marketplaces configured.");
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
for (const [name, result] of results) if (result.success) console.log(`${name} refreshed`);
|
|
131
|
+
else console.error(`${name} failed: ${result.error}`);
|
|
132
|
+
}
|
|
133
|
+
}),
|
|
134
|
+
link: defineCommand({
|
|
135
|
+
meta: {
|
|
136
|
+
name: "link",
|
|
137
|
+
description: "Symlink a local directory into the plugin cache for dev"
|
|
138
|
+
},
|
|
139
|
+
args: {
|
|
140
|
+
path: {
|
|
141
|
+
type: "positional",
|
|
142
|
+
description: "Local path to the plugin/marketplace directory",
|
|
143
|
+
required: true
|
|
144
|
+
},
|
|
145
|
+
as: {
|
|
146
|
+
type: "string",
|
|
147
|
+
description: "Plugin key (name@marketplace) for the cache entry",
|
|
148
|
+
required: true
|
|
149
|
+
},
|
|
150
|
+
json: {
|
|
151
|
+
type: "boolean",
|
|
152
|
+
description: "Output as JSON",
|
|
153
|
+
default: false
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
async run({ args }) {
|
|
157
|
+
if (!args.as) error("--as is required. Specify plugin key as name@marketplace.");
|
|
158
|
+
if (!args.as.includes("@")) error("Plugin key must be in name@marketplace format (e.g. my-plugin@my-marketplace)");
|
|
159
|
+
const result = await link_local_plugin(args.path, args.as);
|
|
160
|
+
if (args.json) output(result, true);
|
|
161
|
+
else if (result.success) {
|
|
162
|
+
console.log(`Linked: ${result.key}`);
|
|
163
|
+
console.log(` ${result.symlinkPath} → ${result.targetPath}`);
|
|
164
|
+
console.log("\nRun /reload-plugins in Claude Code or restart your session.");
|
|
165
|
+
} else error(result.error || "Unknown error");
|
|
166
|
+
}
|
|
167
|
+
}),
|
|
168
|
+
unlink: defineCommand({
|
|
169
|
+
meta: {
|
|
170
|
+
name: "unlink",
|
|
171
|
+
description: "Remove a symlink from the plugin cache"
|
|
172
|
+
},
|
|
173
|
+
args: {
|
|
174
|
+
key: {
|
|
175
|
+
type: "positional",
|
|
176
|
+
description: "Plugin key (name@marketplace)",
|
|
177
|
+
required: true
|
|
178
|
+
},
|
|
179
|
+
json: {
|
|
180
|
+
type: "boolean",
|
|
181
|
+
description: "Output as JSON",
|
|
182
|
+
default: false
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
async run({ args }) {
|
|
186
|
+
const result = await unlink_local_plugin(args.key);
|
|
187
|
+
if (args.json) output(result, true);
|
|
188
|
+
else if (result.success) {
|
|
189
|
+
console.log(`Unlinked: ${args.key}`);
|
|
190
|
+
if (result.restored) console.log(" Original cache directory restored from backup.");
|
|
191
|
+
console.log("\nRun /reload-plugins in Claude Code or restart your session.");
|
|
192
|
+
} else error(result.error || "Unknown error");
|
|
193
|
+
}
|
|
194
|
+
}),
|
|
195
|
+
links: defineCommand({
|
|
196
|
+
meta: {
|
|
197
|
+
name: "links",
|
|
198
|
+
description: "List all symlinked plugin cache entries"
|
|
199
|
+
},
|
|
200
|
+
args: { json: {
|
|
201
|
+
type: "boolean",
|
|
202
|
+
description: "Output as JSON",
|
|
203
|
+
default: false
|
|
204
|
+
} },
|
|
205
|
+
async run({ args }) {
|
|
206
|
+
const linked = await list_linked_plugins();
|
|
207
|
+
if (args.json) {
|
|
208
|
+
output(linked, true);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (linked.length === 0) {
|
|
212
|
+
console.log("No linked plugins.");
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
for (const l of linked) {
|
|
216
|
+
console.log(`${l.key}`);
|
|
217
|
+
console.log(` ${l.symlinkPath} → ${l.targetPath}`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
})
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
//#endregion
|
|
224
|
+
export { cache_default as default };
|
|
225
|
+
|
|
226
|
+
//# sourceMappingURL=cache-D6kd7qE8.js.map
|