skillvault 0.11.0 → 0.11.1

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.
Files changed (2) hide show
  1. package/dist/cli.js +88 -10
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -24,7 +24,7 @@ import { resolveScope, resolveRoots, } from './scope.js';
24
24
  import { loadCredentials, saveCredentials, loadProjectConfig, saveProjectConfig, } from './credentials.js';
25
25
  import { registerProject, unregisterProject, getCurrentProject, listProjects, } from './projects-registry.js';
26
26
  import { confirmInstall } from './prompts.js';
27
- const VERSION = '0.11.0';
27
+ const VERSION = '0.11.1';
28
28
  const HOME = process.env.HOME || process.env.USERPROFILE || '~';
29
29
  const API_URL = process.env.SKILLVAULT_API_URL || 'https://api.getskillvault.com';
30
30
  const CONFIG_DIR = join(HOME, '.skillvault');
@@ -1242,13 +1242,12 @@ function scrubSkillvaultHooks(settingsPath) {
1242
1242
  return removed;
1243
1243
  }
1244
1244
  /**
1245
- * Walk <roots.claudeDir>/skills/ and remove every stub whose manifest.json
1246
- * has an `encrypted: true` flag (the marker we set during install). Returns
1247
- * the list of removed skill names. Vault data is left in place so a future
1248
- * --invite or migrate can reuse it.
1245
+ * Walk a single skills directory and remove every stub whose manifest.json
1246
+ * has an `encrypted: true` flag or a `publisher_id` (the markers we set during
1247
+ * install). Returns the list of removed skill names. Pre-existing skills from
1248
+ * other tools (no manifest, or non-skillvault manifest) are left untouched.
1249
1249
  */
1250
- function removeAllSkillvaultStubs(roots) {
1251
- const skillsDir = join(roots.claudeDir, 'skills');
1250
+ function removeStubsFromDir(skillsDir) {
1252
1251
  if (!existsSync(skillsDir))
1253
1252
  return [];
1254
1253
  const removed = [];
@@ -1268,6 +1267,68 @@ function removeAllSkillvaultStubs(roots) {
1268
1267
  }
1269
1268
  return removed;
1270
1269
  }
1270
+ /**
1271
+ * Walk every directory where install would have written a stub and remove
1272
+ * the SkillVault-managed ones. For project mode this is just
1273
+ * <roots.claudeDir>/skills/. For global mode it also covers ~/.agents/skills/
1274
+ * and the agent-agnostic platform mirrors (Cursor, Windsurf, Codex). Vault
1275
+ * data in <roots.vaultDir> is left in place so a future --invite or
1276
+ * migrate-to-project can reuse it.
1277
+ */
1278
+ function removeAllSkillvaultStubs(roots) {
1279
+ const all = [];
1280
+ // Always: <roots.claudeDir>/skills/ (the install's primary stub location)
1281
+ all.push(...removeStubsFromDir(join(roots.claudeDir, 'skills')));
1282
+ // Global only: ~/.agents/skills/ + every detected platform mirror.
1283
+ // installSkillStubs writes to all of these in global mode, so the global
1284
+ // uninstall has to clean all of them up too.
1285
+ if (roots.scope === 'global') {
1286
+ all.push(...removeStubsFromDir(AGENTS_SKILLS_DIR));
1287
+ for (const platform of detectAgentPlatforms()) {
1288
+ all.push(...removeStubsFromDir(platform.dir));
1289
+ }
1290
+ }
1291
+ // Dedupe — the same skill_name can appear in multiple mirrors.
1292
+ return [...new Set(all)];
1293
+ }
1294
+ /**
1295
+ * Remove SkillVault entries from a shared skill-lock.json file, preserving
1296
+ * any entries that belong to other tools (e.g. skill-creator's
1297
+ * sourceType=github wallet skills coexist with our sourceType=skillvault
1298
+ * entries in ~/.agents/.skill-lock.json). If the file ends up with zero
1299
+ * entries, the whole file is deleted.
1300
+ */
1301
+ function pruneSkillvaultLockEntries(lockPath) {
1302
+ if (!existsSync(lockPath))
1303
+ return 0;
1304
+ try {
1305
+ const data = JSON.parse(readFileSync(lockPath, 'utf8'));
1306
+ if (!data.skills || typeof data.skills !== 'object')
1307
+ return 0;
1308
+ let removed = 0;
1309
+ for (const [name, entry] of Object.entries(data.skills)) {
1310
+ if (entry && typeof entry === 'object' && (entry.sourceType === 'skillvault' || entry.encrypted === true)) {
1311
+ delete data.skills[name];
1312
+ removed++;
1313
+ }
1314
+ }
1315
+ if (removed === 0)
1316
+ return 0;
1317
+ if (Object.keys(data.skills).length === 0) {
1318
+ try {
1319
+ rmSync(lockPath);
1320
+ }
1321
+ catch { }
1322
+ }
1323
+ else {
1324
+ writeFileSync(lockPath, JSON.stringify(data, null, 2), { mode: 0o600 });
1325
+ }
1326
+ return removed;
1327
+ }
1328
+ catch {
1329
+ return 0;
1330
+ }
1331
+ }
1271
1332
  /**
1272
1333
  * Uninstall a single SkillVault install at the given roots.
1273
1334
  *
@@ -1303,8 +1364,17 @@ function uninstallInstall(roots) {
1303
1364
  catch { }
1304
1365
  }
1305
1366
  else {
1306
- // Global install — preserve credentials.json + projects.json.
1307
- const PRESERVE = new Set(['credentials.json', 'projects.json']);
1367
+ // Global install — preserve customer identity + publisher CLI state.
1368
+ // credentials.json + projects.json are the customer-side files we
1369
+ // documented as always-preserved. config.json + grants-cache.json are
1370
+ // owned by the publisher CLI (skillvault-publisher) — the customer-
1371
+ // side uninstall has no business deleting publisher login state.
1372
+ const PRESERVE = new Set([
1373
+ 'credentials.json',
1374
+ 'projects.json',
1375
+ 'config.json', // publisher CLI session
1376
+ 'grants-cache.json', // publisher CLI grant cache
1377
+ ]);
1308
1378
  for (const entry of readdirSync(roots.configDir)) {
1309
1379
  if (PRESERVE.has(entry))
1310
1380
  continue;
@@ -1317,8 +1387,16 @@ function uninstallInstall(roots) {
1317
1387
  }
1318
1388
  }
1319
1389
  }
1320
- // Skill stubs in <roots.claudeDir>/skills/
1390
+ // Skill stubs in every location install would have written them: always
1391
+ // <roots.claudeDir>/skills/, and (global mode) ~/.agents/skills/ + each
1392
+ // detected platform mirror.
1321
1393
  summary.removedStubs = removeAllSkillvaultStubs(roots);
1394
+ // Prune SkillVault entries from the shared lock file. In global mode this
1395
+ // is ~/.agents/.skill-lock.json which can also hold non-skillvault entries
1396
+ // (e.g. from skill-creator), so we preserve other entries.
1397
+ if (roots.scope === 'global') {
1398
+ pruneSkillvaultLockEntries(AGENTS_LOCK_PATH);
1399
+ }
1322
1400
  // Hooks in settings.json
1323
1401
  summary.removedHooks = scrubSkillvaultHooks(roots.settingsPath);
1324
1402
  // Registry: drop the entry if this was a project install. Use the install
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillvault",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "SkillVault — secure skill distribution for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {