vskill 0.5.45 → 0.5.47
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/commands/add.js +5 -25
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/cleanup.js +10 -11
- package/dist/commands/cleanup.js.map +1 -1
- package/dist/commands/init.js +11 -15
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/remove.js +9 -14
- package/dist/commands/remove.js.map +1 -1
- package/dist/eval/verdict.d.ts +2 -1
- package/dist/eval/verdict.js +15 -2
- package/dist/eval/verdict.js.map +1 -1
- package/dist/eval-ui/assets/index-B5TJCTjp.js +73 -0
- package/dist/eval-ui/index.html +1 -1
- package/dist/installer/migrate.d.ts +16 -0
- package/dist/installer/migrate.js +32 -1
- package/dist/installer/migrate.js.map +1 -1
- package/dist/security/platform-security.js +23 -5
- package/dist/security/platform-security.js.map +1 -1
- package/dist/settings/index.d.ts +1 -1
- package/dist/settings/index.js +1 -1
- package/dist/settings/index.js.map +1 -1
- package/dist/settings/settings.d.ts +4 -16
- package/dist/settings/settings.js +15 -57
- package/dist/settings/settings.js.map +1 -1
- package/dist/utils/claude-plugin.d.ts +35 -0
- package/dist/utils/claude-plugin.js +58 -0
- package/dist/utils/claude-plugin.js.map +1 -0
- package/package.json +1 -1
- package/scripts/preuninstall.cjs +6 -5
- package/dist/eval-ui/assets/index-CsWzYuTb.js +0 -73
package/dist/eval-ui/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>Skill Studio</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-B5TJCTjp.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="/assets/index-CGNHEtf7.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
@@ -32,3 +32,19 @@ export declare function migrateStaleSkillFiles(skillsDir: string): MigrationResu
|
|
|
32
32
|
* Also recurses one level into namespace directories (e.g., sw/).
|
|
33
33
|
*/
|
|
34
34
|
export declare function ensureSkillMdNaming(skillsDir: string): NamingResult;
|
|
35
|
+
/**
|
|
36
|
+
* Remove stale double-nested skill directories left by pre-fix installations.
|
|
37
|
+
*
|
|
38
|
+
* Before the double-nesting fix (ec19dde, 2026-03-18), installing a plugin
|
|
39
|
+
* whose single skill shared its name would create:
|
|
40
|
+
* {skillsDir}/{name}/{name}/SKILL.md (incorrect)
|
|
41
|
+
* instead of:
|
|
42
|
+
* {skillsDir}/{name}/SKILL.md (correct)
|
|
43
|
+
*
|
|
44
|
+
* When called AFTER writing the correct SKILL.md, this function detects and
|
|
45
|
+
* removes the stale nested directory.
|
|
46
|
+
*
|
|
47
|
+
* @param skillDir The directory that should contain SKILL.md directly,
|
|
48
|
+
* e.g. `~/.claude/skills/nanobanana/`
|
|
49
|
+
*/
|
|
50
|
+
export declare function cleanStaleNesting(skillDir: string): void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
2
|
// Migrate stale flat .md skill files to {name}/SKILL.md subdirectory structure
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
|
-
import { readdirSync, readFileSync, writeFileSync, mkdirSync, unlinkSync, existsSync, lstatSync, } from "node:fs";
|
|
4
|
+
import { readdirSync, readFileSync, writeFileSync, mkdirSync, unlinkSync, rmSync, existsSync, lstatSync, } from "node:fs";
|
|
5
5
|
import { join, basename } from "node:path";
|
|
6
6
|
import { ensureFrontmatter } from "./frontmatter.js";
|
|
7
7
|
/**
|
|
@@ -164,6 +164,37 @@ function enforceSkillMdInDir(dir, result) {
|
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Remove stale double-nested skill directories left by pre-fix installations.
|
|
169
|
+
*
|
|
170
|
+
* Before the double-nesting fix (ec19dde, 2026-03-18), installing a plugin
|
|
171
|
+
* whose single skill shared its name would create:
|
|
172
|
+
* {skillsDir}/{name}/{name}/SKILL.md (incorrect)
|
|
173
|
+
* instead of:
|
|
174
|
+
* {skillsDir}/{name}/SKILL.md (correct)
|
|
175
|
+
*
|
|
176
|
+
* When called AFTER writing the correct SKILL.md, this function detects and
|
|
177
|
+
* removes the stale nested directory.
|
|
178
|
+
*
|
|
179
|
+
* @param skillDir The directory that should contain SKILL.md directly,
|
|
180
|
+
* e.g. `~/.claude/skills/nanobanana/`
|
|
181
|
+
*/
|
|
182
|
+
export function cleanStaleNesting(skillDir) {
|
|
183
|
+
const name = basename(skillDir);
|
|
184
|
+
const nested = join(skillDir, name);
|
|
185
|
+
try {
|
|
186
|
+
const stat = lstatSync(nested);
|
|
187
|
+
if (!stat.isDirectory() || stat.isSymbolicLink())
|
|
188
|
+
return;
|
|
189
|
+
// Only remove the nested dir when the parent already has the correct SKILL.md
|
|
190
|
+
if (existsSync(join(skillDir, "SKILL.md"))) {
|
|
191
|
+
rmSync(nested, { recursive: true, force: true });
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
// Nested dir doesn't exist — nothing to clean
|
|
196
|
+
}
|
|
197
|
+
}
|
|
167
198
|
/**
|
|
168
199
|
* Migrate stale flat .md files within a single directory level.
|
|
169
200
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/installer/migrate.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/installer/migrate.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
// Platform security check — queries external SAST scan results (best-effort)
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
4
|
const BASE_URL = "https://verified-skill.com";
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// Runtime validation helpers
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
const VALID_STATUSES = new Set(["PASS", "FAIL", "PENDING", "TIMED_OUT"]);
|
|
9
|
+
const VALID_VERDICTS = new Set(["PASS", "FAIL", "CONCERNS", "PENDING"]);
|
|
10
|
+
const VALID_OVERALL = new Set(["PASS", "FAIL", "PENDING", "TIMED_OUT", "CERTIFIED"]);
|
|
11
|
+
function validateEnum(value, allowed, fallback) {
|
|
12
|
+
const upper = value.toUpperCase();
|
|
13
|
+
return allowed.has(upper) ? upper : fallback;
|
|
14
|
+
}
|
|
15
|
+
function safeNumber(value, fallback) {
|
|
16
|
+
const n = Number(value ?? fallback);
|
|
17
|
+
return isNaN(n) ? fallback : n;
|
|
18
|
+
}
|
|
5
19
|
/**
|
|
6
20
|
* Check external SAST scan results from the platform API.
|
|
7
21
|
* Returns null on any network/API error (best-effort, non-fatal).
|
|
@@ -9,7 +23,7 @@ const BASE_URL = "https://verified-skill.com";
|
|
|
9
23
|
export async function checkPlatformSecurity(skillName) {
|
|
10
24
|
try {
|
|
11
25
|
const url = `${BASE_URL}/api/v1/skills/${skillName.split("/").map(encodeURIComponent).join("/")}/security`;
|
|
12
|
-
const res = await fetch(url);
|
|
26
|
+
const res = await fetch(url, { signal: AbortSignal.timeout(10_000) });
|
|
13
27
|
if (!res.ok) {
|
|
14
28
|
console.warn(`[platform-security] HTTP ${res.status} for ${skillName}`);
|
|
15
29
|
return null;
|
|
@@ -17,14 +31,18 @@ export async function checkPlatformSecurity(skillName) {
|
|
|
17
31
|
const data = (await res.json());
|
|
18
32
|
const providers = (data.providers || []).map((p) => ({
|
|
19
33
|
provider: String(p.provider || ""),
|
|
20
|
-
status: (String(p.status || "PENDING")),
|
|
21
|
-
verdict:
|
|
22
|
-
criticalCount:
|
|
34
|
+
status: validateEnum(String(p.status || "PENDING"), VALID_STATUSES, "PENDING"),
|
|
35
|
+
verdict: p.verdict == null ? null : validateEnum(String(p.verdict), VALID_VERDICTS, "PENDING"),
|
|
36
|
+
criticalCount: safeNumber(p.criticalCount, 0),
|
|
23
37
|
}));
|
|
38
|
+
// Empty providers = no scan data available — report as PENDING, not all-clear
|
|
39
|
+
const overallVerdict = providers.length === 0
|
|
40
|
+
? "PENDING"
|
|
41
|
+
: validateEnum(String(data.overallVerdict || "PENDING"), VALID_OVERALL, "PENDING");
|
|
24
42
|
const hasCritical = providers.some((p) => p.status === "FAIL" && p.criticalCount > 0);
|
|
25
43
|
return {
|
|
26
44
|
hasCritical,
|
|
27
|
-
overallVerdict
|
|
45
|
+
overallVerdict,
|
|
28
46
|
providers,
|
|
29
47
|
reportUrl: String(data.reportUrl || ""),
|
|
30
48
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-security.js","sourceRoot":"","sources":["../../src/security/platform-security.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,6EAA6E;AAC7E,8EAA8E;AAE9E,MAAM,QAAQ,GAAG,4BAA4B,CAAC;AAgB9C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,SAAiB;IAEjB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,GAAG,QAAQ,kBAAkB,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC;QAC3G,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"platform-security.js","sourceRoot":"","sources":["../../src/security/platform-security.ts"],"names":[],"mappings":"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"}
|
package/dist/settings/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export type { SettingsOptions } from "./settings.js";
|
|
2
|
-
export {
|
|
2
|
+
export { isPluginEnabled, listEnabledPlugins, purgeStalePlugins, } from "./settings.js";
|
package/dist/settings/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { isPluginEnabled, listEnabledPlugins, purgeStalePlugins, } from "./settings.js";
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/settings/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/settings/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,eAAe,CAAC"}
|
|
@@ -2,18 +2,6 @@ export interface SettingsOptions {
|
|
|
2
2
|
scope: "user" | "project";
|
|
3
3
|
projectDir?: string;
|
|
4
4
|
}
|
|
5
|
-
/**
|
|
6
|
-
* Enable a plugin in settings.json.
|
|
7
|
-
*/
|
|
8
|
-
export declare function enablePlugin(pluginId: string, opts: SettingsOptions): void;
|
|
9
|
-
/**
|
|
10
|
-
* Disable a plugin in settings.json (set to false).
|
|
11
|
-
*/
|
|
12
|
-
export declare function disablePlugin(pluginId: string, opts: SettingsOptions): void;
|
|
13
|
-
/**
|
|
14
|
-
* Remove a plugin entry entirely from settings.json (vs. setting to false).
|
|
15
|
-
*/
|
|
16
|
-
export declare function removePlugin(pluginId: string, opts: SettingsOptions): void;
|
|
17
5
|
/**
|
|
18
6
|
* Check if a plugin is enabled in settings.json.
|
|
19
7
|
*/
|
|
@@ -23,15 +11,15 @@ export declare function isPluginEnabled(pluginId: string, opts: SettingsOptions)
|
|
|
23
11
|
*/
|
|
24
12
|
export declare function listEnabledPlugins(opts: SettingsOptions): string[];
|
|
25
13
|
/**
|
|
26
|
-
*
|
|
14
|
+
* Identify enabledPlugins entries not backed by a lockfile entry.
|
|
27
15
|
*
|
|
28
16
|
* Plugin IDs use `<skillName>@<marketplace>` format.
|
|
29
17
|
* A plugin is stale when no lockfile skill matches by name AND marketplace.
|
|
30
18
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
19
|
+
* Returns the list of stale plugin IDs — callers are responsible for
|
|
20
|
+
* uninstalling them via `claudePluginUninstall()`.
|
|
33
21
|
*
|
|
34
|
-
* @returns Array of
|
|
22
|
+
* @returns Array of stale plugin IDs
|
|
35
23
|
*/
|
|
36
24
|
export declare function purgeStalePlugins(opts: SettingsOptions, lockfileSkills: Record<string, {
|
|
37
25
|
marketplace?: string;
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
|
-
// Claude Code settings.json
|
|
2
|
+
// Claude Code settings.json — READ-ONLY access
|
|
3
|
+
//
|
|
4
|
+
// This module only reads settings.json. All writes must go through the
|
|
5
|
+
// claude CLI (claude plugin install/uninstall). Direct filesystem writes
|
|
6
|
+
// to settings.json bypass Claude Code's atomicity guarantees and can cause
|
|
7
|
+
// race conditions when Claude Code holds the file in memory.
|
|
3
8
|
// ---------------------------------------------------------------------------
|
|
4
|
-
import { readFileSync,
|
|
5
|
-
import { join
|
|
9
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
10
|
+
import { join } from "node:path";
|
|
6
11
|
import { homedir } from "node:os";
|
|
7
12
|
/**
|
|
8
13
|
* Resolves the path to settings.json based on scope.
|
|
@@ -30,49 +35,6 @@ function readSettings(opts) {
|
|
|
30
35
|
return {};
|
|
31
36
|
}
|
|
32
37
|
}
|
|
33
|
-
/**
|
|
34
|
-
* Writes settings.json, creating parent directories if needed.
|
|
35
|
-
*/
|
|
36
|
-
function writeSettings(settings, opts) {
|
|
37
|
-
const p = settingsPath(opts);
|
|
38
|
-
const dir = dirname(p);
|
|
39
|
-
if (!existsSync(dir)) {
|
|
40
|
-
mkdirSync(dir, { recursive: true });
|
|
41
|
-
}
|
|
42
|
-
writeFileSync(p, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Enable a plugin in settings.json.
|
|
46
|
-
*/
|
|
47
|
-
export function enablePlugin(pluginId, opts) {
|
|
48
|
-
const settings = readSettings(opts);
|
|
49
|
-
if (!settings.enabledPlugins) {
|
|
50
|
-
settings.enabledPlugins = {};
|
|
51
|
-
}
|
|
52
|
-
settings.enabledPlugins[pluginId] = true;
|
|
53
|
-
writeSettings(settings, opts);
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Disable a plugin in settings.json (set to false).
|
|
57
|
-
*/
|
|
58
|
-
export function disablePlugin(pluginId, opts) {
|
|
59
|
-
const settings = readSettings(opts);
|
|
60
|
-
if (!settings.enabledPlugins) {
|
|
61
|
-
settings.enabledPlugins = {};
|
|
62
|
-
}
|
|
63
|
-
settings.enabledPlugins[pluginId] = false;
|
|
64
|
-
writeSettings(settings, opts);
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Remove a plugin entry entirely from settings.json (vs. setting to false).
|
|
68
|
-
*/
|
|
69
|
-
export function removePlugin(pluginId, opts) {
|
|
70
|
-
const settings = readSettings(opts);
|
|
71
|
-
if (settings.enabledPlugins) {
|
|
72
|
-
delete settings.enabledPlugins[pluginId];
|
|
73
|
-
}
|
|
74
|
-
writeSettings(settings, opts);
|
|
75
|
-
}
|
|
76
38
|
/**
|
|
77
39
|
* Check if a plugin is enabled in settings.json.
|
|
78
40
|
*/
|
|
@@ -92,21 +54,21 @@ export function listEnabledPlugins(opts) {
|
|
|
92
54
|
.map(([k]) => k);
|
|
93
55
|
}
|
|
94
56
|
/**
|
|
95
|
-
*
|
|
57
|
+
* Identify enabledPlugins entries not backed by a lockfile entry.
|
|
96
58
|
*
|
|
97
59
|
* Plugin IDs use `<skillName>@<marketplace>` format.
|
|
98
60
|
* A plugin is stale when no lockfile skill matches by name AND marketplace.
|
|
99
61
|
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
62
|
+
* Returns the list of stale plugin IDs — callers are responsible for
|
|
63
|
+
* uninstalling them via `claudePluginUninstall()`.
|
|
102
64
|
*
|
|
103
|
-
* @returns Array of
|
|
65
|
+
* @returns Array of stale plugin IDs
|
|
104
66
|
*/
|
|
105
67
|
export function purgeStalePlugins(opts, lockfileSkills) {
|
|
106
68
|
const settings = readSettings(opts);
|
|
107
69
|
if (!settings.enabledPlugins)
|
|
108
70
|
return [];
|
|
109
|
-
const
|
|
71
|
+
const stale = [];
|
|
110
72
|
for (const pluginId of Object.keys(settings.enabledPlugins)) {
|
|
111
73
|
const atIdx = pluginId.lastIndexOf("@");
|
|
112
74
|
if (atIdx === -1)
|
|
@@ -115,13 +77,9 @@ export function purgeStalePlugins(opts, lockfileSkills) {
|
|
|
115
77
|
const marketplace = pluginId.slice(atIdx + 1);
|
|
116
78
|
const lockEntry = lockfileSkills[skillName];
|
|
117
79
|
if (!lockEntry || lockEntry.marketplace !== marketplace) {
|
|
118
|
-
|
|
119
|
-
delete settings.enabledPlugins[pluginId];
|
|
80
|
+
stale.push(pluginId);
|
|
120
81
|
}
|
|
121
82
|
}
|
|
122
|
-
|
|
123
|
-
writeSettings(settings, opts);
|
|
124
|
-
}
|
|
125
|
-
return purged;
|
|
83
|
+
return stale;
|
|
126
84
|
}
|
|
127
85
|
//# sourceMappingURL=settings.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/settings/settings.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/settings/settings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Uninstall a marketplace plugin via the claude CLI.
|
|
3
|
+
*
|
|
4
|
+
* Delegates to: claude plugin uninstall --scope <scope> -- <pluginId>
|
|
5
|
+
*
|
|
6
|
+
* This is the only sanctioned way to remove entries from settings.json's
|
|
7
|
+
* enabledPlugins field and the associated plugin cache.
|
|
8
|
+
*
|
|
9
|
+
* **Note**: `scope: "project"` operates on the project in `process.cwd()`.
|
|
10
|
+
* Callers must ensure they are in the correct working directory, or pass
|
|
11
|
+
* a `cwd` option to override.
|
|
12
|
+
*
|
|
13
|
+
* @throws if the claude binary is not found — callers should wrap in try/catch
|
|
14
|
+
* when the plugin may not have been installed via the claude CLI
|
|
15
|
+
*/
|
|
16
|
+
export declare function claudePluginUninstall(pluginId: string, scope?: "user" | "project" | "local", opts?: {
|
|
17
|
+
cwd?: string;
|
|
18
|
+
}): void;
|
|
19
|
+
/**
|
|
20
|
+
* Detect and uninstall stale plugins from both user and project scopes.
|
|
21
|
+
*
|
|
22
|
+
* Combines `purgeStalePlugins()` (read-only detection) with
|
|
23
|
+
* `claudePluginUninstall()` (CLI-delegated removal) in a single call.
|
|
24
|
+
*
|
|
25
|
+
* @returns Array of `{ id, scope, ok }` for each stale plugin processed
|
|
26
|
+
*/
|
|
27
|
+
export declare function uninstallStalePlugins(lockfileSkills: Record<string, {
|
|
28
|
+
marketplace?: string;
|
|
29
|
+
}>, opts?: {
|
|
30
|
+
log?: (msg: string) => void;
|
|
31
|
+
}): Array<{
|
|
32
|
+
id: string;
|
|
33
|
+
scope: "user" | "project";
|
|
34
|
+
ok: boolean;
|
|
35
|
+
}>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Claude CLI plugin management delegation
|
|
3
|
+
//
|
|
4
|
+
// All mutations to ~/.claude/settings.json (enabledPlugins) and the plugin
|
|
5
|
+
// cache must go through the claude CLI, never via direct filesystem writes.
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
import { execFileSync } from "node:child_process";
|
|
8
|
+
import { resolveCliBinary } from "./resolve-binary.js";
|
|
9
|
+
import { purgeStalePlugins } from "../settings/index.js";
|
|
10
|
+
/**
|
|
11
|
+
* Uninstall a marketplace plugin via the claude CLI.
|
|
12
|
+
*
|
|
13
|
+
* Delegates to: claude plugin uninstall --scope <scope> -- <pluginId>
|
|
14
|
+
*
|
|
15
|
+
* This is the only sanctioned way to remove entries from settings.json's
|
|
16
|
+
* enabledPlugins field and the associated plugin cache.
|
|
17
|
+
*
|
|
18
|
+
* **Note**: `scope: "project"` operates on the project in `process.cwd()`.
|
|
19
|
+
* Callers must ensure they are in the correct working directory, or pass
|
|
20
|
+
* a `cwd` option to override.
|
|
21
|
+
*
|
|
22
|
+
* @throws if the claude binary is not found — callers should wrap in try/catch
|
|
23
|
+
* when the plugin may not have been installed via the claude CLI
|
|
24
|
+
*/
|
|
25
|
+
export function claudePluginUninstall(pluginId, scope = "user", opts) {
|
|
26
|
+
const claude = resolveCliBinary("claude");
|
|
27
|
+
execFileSync(claude, ["plugin", "uninstall", "--scope", scope, "--", pluginId], { stdio: "pipe", ...(opts?.cwd ? { cwd: opts.cwd } : {}) });
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Detect and uninstall stale plugins from both user and project scopes.
|
|
31
|
+
*
|
|
32
|
+
* Combines `purgeStalePlugins()` (read-only detection) with
|
|
33
|
+
* `claudePluginUninstall()` (CLI-delegated removal) in a single call.
|
|
34
|
+
*
|
|
35
|
+
* @returns Array of `{ id, scope, ok }` for each stale plugin processed
|
|
36
|
+
*/
|
|
37
|
+
export function uninstallStalePlugins(lockfileSkills, opts) {
|
|
38
|
+
const log = opts?.log ?? console.log;
|
|
39
|
+
const staleUser = purgeStalePlugins({ scope: "user" }, lockfileSkills);
|
|
40
|
+
const staleProject = purgeStalePlugins({ scope: "project", projectDir: process.cwd() }, lockfileSkills);
|
|
41
|
+
const allStale = [
|
|
42
|
+
...staleUser.map((id) => ({ id, scope: "user" })),
|
|
43
|
+
...staleProject.map((id) => ({ id, scope: "project" })),
|
|
44
|
+
];
|
|
45
|
+
const results = [];
|
|
46
|
+
for (const { id, scope } of allStale) {
|
|
47
|
+
try {
|
|
48
|
+
claudePluginUninstall(id, scope);
|
|
49
|
+
results.push({ id, scope, ok: true });
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
log(` ${id} (skipped — not registered via CLI)`);
|
|
53
|
+
results.push({ id, scope, ok: false });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return results;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=claude-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-plugin.js","sourceRoot":"","sources":["../../src/utils/claude-plugin.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,0CAA0C;AAC1C,EAAE;AACF,2EAA2E;AAC3E,4EAA4E;AAC5E,8EAA8E;AAE9E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEzD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAgB,EAChB,QAAsC,MAAM,EAC5C,IAAuB;IAEvB,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC1C,YAAY,CACV,MAAM,EACN,CAAC,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,EACzD,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAC3D,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CACnC,cAAwD,EACxD,IAAsC;IAEtC,MAAM,GAAG,GAAG,IAAI,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACrC,MAAM,SAAS,GAAG,iBAAiB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC;IACvE,MAAM,YAAY,GAAG,iBAAiB,CACpC,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,EAC/C,cAAc,CACf,CAAC;IACF,MAAM,QAAQ,GAAG;QACf,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAe,EAAE,CAAC,CAAC;QAC1D,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,SAAkB,EAAE,CAAC,CAAC;KACjE,CAAC;IAEF,MAAM,OAAO,GAAkE,EAAE,CAAC;IAClF,KAAK,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,QAAQ,EAAE,CAAC;QACrC,IAAI,CAAC;YACH,qBAAqB,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,CAAC;QAAC,MAAM,CAAC;YACP,GAAG,CAAC,KAAK,EAAE,qCAAqC,CAAC,CAAC;YAClD,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/package.json
CHANGED
package/scripts/preuninstall.cjs
CHANGED
|
@@ -46,12 +46,13 @@ if (remaining.length > 0) {
|
|
|
46
46
|
console.log("Or manually delete the directories listed above.\n");
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
// Clean
|
|
50
|
-
|
|
49
|
+
// Clean only the vskill-owned marketplace subdirectory from the plugin cache.
|
|
50
|
+
// Never delete the entire cache — other tools may share ~/.claude/plugins/cache/.
|
|
51
|
+
const vskillCacheDir = path.join(home, ".claude", "plugins", "cache", "specweave");
|
|
51
52
|
try {
|
|
52
|
-
if (fs.existsSync(
|
|
53
|
-
fs.rmSync(
|
|
54
|
-
console.log("vskill: Cleaned plugin cache at " +
|
|
53
|
+
if (fs.existsSync(vskillCacheDir)) {
|
|
54
|
+
fs.rmSync(vskillCacheDir, { recursive: true, force: true });
|
|
55
|
+
console.log("vskill: Cleaned plugin cache at " + vskillCacheDir);
|
|
55
56
|
}
|
|
56
57
|
} catch {
|
|
57
58
|
// Ignore cleanup errors
|