plugins 1.3.1-snapshot.0 → 1.3.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.
- package/dist/index.js +132 -19
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -540,7 +540,9 @@ async function multiSelect(title, options, maxVisible = 8) {
|
|
|
540
540
|
if (state === "active") {
|
|
541
541
|
const blockCursor = isColorSupported ? `\x1B[7m \x1B[0m` : "_";
|
|
542
542
|
lines.push(`${c.gray(S.bar)} ${c.dim("Search:")} ${query}${blockCursor}`);
|
|
543
|
-
lines.push(
|
|
543
|
+
lines.push(
|
|
544
|
+
`${c.gray(S.bar)} ${c.dim("\u2191\u2193 move, space toggle, a all, n none, enter confirm")}`
|
|
545
|
+
);
|
|
544
546
|
lines.push(`${c.gray(S.bar)}`);
|
|
545
547
|
const visibleStart = Math.max(
|
|
546
548
|
0,
|
|
@@ -689,6 +691,15 @@ var cachePopulated = false;
|
|
|
689
691
|
async function installPlugins(plugins, target, scope, repoPath, source) {
|
|
690
692
|
switch (target.id) {
|
|
691
693
|
case "claude-code": {
|
|
694
|
+
const officialRef = getOfficialPluginRef(source);
|
|
695
|
+
if (officialRef) {
|
|
696
|
+
const ok = await installViaClaudeCli(officialRef, scope);
|
|
697
|
+
if (ok) {
|
|
698
|
+
cachePopulated = true;
|
|
699
|
+
break;
|
|
700
|
+
}
|
|
701
|
+
barDebug(c.dim("Falling back to direct file-based install"));
|
|
702
|
+
}
|
|
692
703
|
const workspace = await stageInstallWorkspace(plugins, repoPath, target.id);
|
|
693
704
|
await installToClaudeCode(workspace.plugins, scope, workspace.repoPath, source);
|
|
694
705
|
break;
|
|
@@ -727,6 +738,47 @@ async function stageInstallWorkspace(plugins, repoPath, targetId, stagingBaseDir
|
|
|
727
738
|
plugins: stagedPlugins
|
|
728
739
|
};
|
|
729
740
|
}
|
|
741
|
+
var OFFICIAL_MARKETPLACE_SOURCE = "anthropics/claude-plugins-official";
|
|
742
|
+
function getOfficialPluginRef(source) {
|
|
743
|
+
let repo = null;
|
|
744
|
+
const shorthand = source.match(/^([\w.-]+\/[\w.-]+?)(?:\.git)?$/);
|
|
745
|
+
if (shorthand) repo = shorthand[1].toLowerCase();
|
|
746
|
+
if (!repo) {
|
|
747
|
+
const https = source.match(/^https?:\/\/github\.com\/([\w.-]+\/[\w.-]+?)(?:\.git)?$/);
|
|
748
|
+
if (https) repo = https[1].toLowerCase();
|
|
749
|
+
}
|
|
750
|
+
if (!repo) {
|
|
751
|
+
const ssh = source.match(/^git@github\.com:([\w.-]+\/[\w.-]+?)(?:\.git)?$/);
|
|
752
|
+
if (ssh) repo = ssh[1].toLowerCase();
|
|
753
|
+
}
|
|
754
|
+
if (repo === "vercel/vercel-plugin") {
|
|
755
|
+
return "vercel@claude-plugins-official";
|
|
756
|
+
}
|
|
757
|
+
return null;
|
|
758
|
+
}
|
|
759
|
+
async function installViaClaudeCli(pluginRef, scope) {
|
|
760
|
+
const claude = findClaudeOrNull();
|
|
761
|
+
if (!claude) return false;
|
|
762
|
+
try {
|
|
763
|
+
step("Registering official Claude marketplace");
|
|
764
|
+
execSync2(`${claude} plugin marketplace add ${OFFICIAL_MARKETPLACE_SOURCE}`, {
|
|
765
|
+
stdio: "pipe",
|
|
766
|
+
timeout: 12e4
|
|
767
|
+
});
|
|
768
|
+
stepDone("Official marketplace registered");
|
|
769
|
+
step(`Installing ${c.cyan(pluginRef)} via Claude CLI`);
|
|
770
|
+
execSync2(`${claude} plugin install "${pluginRef}" --scope ${scope}`, {
|
|
771
|
+
stdio: "pipe",
|
|
772
|
+
timeout: 12e4
|
|
773
|
+
});
|
|
774
|
+
stepDone(`Installed ${c.cyan(pluginRef)} via Claude CLI`);
|
|
775
|
+
return true;
|
|
776
|
+
} catch (err) {
|
|
777
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
778
|
+
barDebug(c.dim(`Claude CLI install failed: ${msg}`));
|
|
779
|
+
return false;
|
|
780
|
+
}
|
|
781
|
+
}
|
|
730
782
|
async function installToClaudeCode(plugins, scope, repoPath, source) {
|
|
731
783
|
await installToPluginCache(plugins, scope, repoPath, source);
|
|
732
784
|
}
|
|
@@ -796,7 +848,9 @@ async function installToPluginCache(plugins, scope, repoPath, source) {
|
|
|
796
848
|
};
|
|
797
849
|
if (existsSync2(installedPath)) {
|
|
798
850
|
try {
|
|
799
|
-
|
|
851
|
+
const parsed = JSON.parse(await readFile2(installedPath, "utf-8"));
|
|
852
|
+
installedData.version = parsed.version ?? 2;
|
|
853
|
+
installedData.plugins = parsed.plugins ?? {};
|
|
800
854
|
} catch {
|
|
801
855
|
}
|
|
802
856
|
}
|
|
@@ -1099,6 +1153,23 @@ async function prepareForClaudeCode(plugins, repoPath, marketplaceName) {
|
|
|
1099
1153
|
await preparePluginDirForVendor(plugin, ".claude-plugin", "CLAUDE_PLUGIN_ROOT");
|
|
1100
1154
|
}
|
|
1101
1155
|
}
|
|
1156
|
+
function findClaudeOrNull() {
|
|
1157
|
+
try {
|
|
1158
|
+
const path = execSync2("which claude", { encoding: "utf-8", stdio: "pipe" }).trim();
|
|
1159
|
+
if (path) return path;
|
|
1160
|
+
} catch {
|
|
1161
|
+
}
|
|
1162
|
+
const home = homedir2();
|
|
1163
|
+
const candidates = [
|
|
1164
|
+
join3(home, ".local", "bin", "claude"),
|
|
1165
|
+
join3(home, ".bun", "bin", "claude"),
|
|
1166
|
+
"/usr/local/bin/claude"
|
|
1167
|
+
];
|
|
1168
|
+
for (const candidate of candidates) {
|
|
1169
|
+
if (existsSync2(candidate)) return candidate;
|
|
1170
|
+
}
|
|
1171
|
+
return null;
|
|
1172
|
+
}
|
|
1102
1173
|
async function preparePluginDirForVendor(plugin, vendorDir, envVar) {
|
|
1103
1174
|
const pluginPath = plugin.path;
|
|
1104
1175
|
const openPluginDir = join3(pluginPath, ".plugin");
|
|
@@ -1208,6 +1279,29 @@ function normalizeGitUrl(source) {
|
|
|
1208
1279
|
}
|
|
1209
1280
|
return source;
|
|
1210
1281
|
}
|
|
1282
|
+
async function isMarketplaceNew(marketplaceName) {
|
|
1283
|
+
const knownPath = join3(homedir2(), ".claude", "plugins", "known_marketplaces.json");
|
|
1284
|
+
if (!existsSync2(knownPath)) return true;
|
|
1285
|
+
try {
|
|
1286
|
+
const data = JSON.parse(await readFile2(knownPath, "utf-8"));
|
|
1287
|
+
return !data[marketplaceName];
|
|
1288
|
+
} catch {
|
|
1289
|
+
return true;
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
async function setAutoUpdate(marketplaceName, enabled) {
|
|
1293
|
+
const knownPath = join3(homedir2(), ".claude", "plugins", "known_marketplaces.json");
|
|
1294
|
+
if (!existsSync2(knownPath)) return;
|
|
1295
|
+
let data = {};
|
|
1296
|
+
try {
|
|
1297
|
+
data = JSON.parse(await readFile2(knownPath, "utf-8"));
|
|
1298
|
+
} catch {
|
|
1299
|
+
return;
|
|
1300
|
+
}
|
|
1301
|
+
if (!data[marketplaceName]) return;
|
|
1302
|
+
data[marketplaceName].autoUpdate = enabled;
|
|
1303
|
+
await writeFile(knownPath, JSON.stringify(data, null, 2));
|
|
1304
|
+
}
|
|
1211
1305
|
|
|
1212
1306
|
// lib/telemetry.ts
|
|
1213
1307
|
var TELEMETRY_URL = "https://plugins-telemetry.labs.vercel.dev/t";
|
|
@@ -1319,14 +1413,14 @@ async function cmdDiscover(source) {
|
|
|
1319
1413
|
if (remotePlugins.length > 0) {
|
|
1320
1414
|
if (values.remote) {
|
|
1321
1415
|
barEmpty();
|
|
1322
|
-
step(
|
|
1416
|
+
step(
|
|
1417
|
+
`${c.bold(String(remotePlugins.length))} remote plugin(s) ${c.dim("(hosted in external repos)")}`
|
|
1418
|
+
);
|
|
1323
1419
|
barEmpty();
|
|
1324
1420
|
printRemotePluginTable(remotePlugins);
|
|
1325
1421
|
} else {
|
|
1326
1422
|
barEmpty();
|
|
1327
|
-
barLine(
|
|
1328
|
-
c.dim(`${remotePlugins.length} remote plugin(s) not shown. Run:`)
|
|
1329
|
-
);
|
|
1423
|
+
barLine(c.dim(`${remotePlugins.length} remote plugin(s) not shown. Run:`));
|
|
1330
1424
|
barLine(` ${c.cyan(`npx plugins discover ${source} --remote`)}`);
|
|
1331
1425
|
}
|
|
1332
1426
|
printMissingPaths(missingPaths);
|
|
@@ -1368,9 +1462,7 @@ async function cmdInstall(source, opts) {
|
|
|
1368
1462
|
barEmpty();
|
|
1369
1463
|
step("No plugins found.");
|
|
1370
1464
|
if (remotePlugins.length > 0) {
|
|
1371
|
-
barLine(
|
|
1372
|
-
c.dim(`${remotePlugins.length} remote plugin(s) not shown. Run:`)
|
|
1373
|
-
);
|
|
1465
|
+
barLine(c.dim(`${remotePlugins.length} remote plugin(s) not shown. Run:`));
|
|
1374
1466
|
barLine(` ${c.cyan(`npx plugins discover ${source} --remote`)}`);
|
|
1375
1467
|
printMissingPaths(missingPaths);
|
|
1376
1468
|
}
|
|
@@ -1412,9 +1504,7 @@ async function cmdInstall(source, opts) {
|
|
|
1412
1504
|
printPluginTable(plugins);
|
|
1413
1505
|
if (remotePlugins.length > 0) {
|
|
1414
1506
|
barEmpty();
|
|
1415
|
-
barLine(
|
|
1416
|
-
c.dim(`+ ${remotePlugins.length} remote plugin(s) not included. Run:`)
|
|
1417
|
-
);
|
|
1507
|
+
barLine(c.dim(`+ ${remotePlugins.length} remote plugin(s) not included. Run:`));
|
|
1418
1508
|
barLine(` ${c.cyan(`npx plugins discover ${source} --remote`)}`);
|
|
1419
1509
|
printMissingPaths(missingPaths);
|
|
1420
1510
|
}
|
|
@@ -1447,9 +1537,7 @@ async function cmdInstall(source, opts) {
|
|
|
1447
1537
|
}
|
|
1448
1538
|
selectedPlugins = plugins.filter((p) => selected.includes(p.name));
|
|
1449
1539
|
if (remotePlugins.length > 0) {
|
|
1450
|
-
barLine(
|
|
1451
|
-
c.dim(`+ ${remotePlugins.length} remote plugin(s) not included. Run:`)
|
|
1452
|
-
);
|
|
1540
|
+
barLine(c.dim(`+ ${remotePlugins.length} remote plugin(s) not included. Run:`));
|
|
1453
1541
|
barLine(` ${c.cyan(`npx plugins discover ${source} --remote`)}`);
|
|
1454
1542
|
printMissingPaths(missingPaths);
|
|
1455
1543
|
}
|
|
@@ -1459,9 +1547,29 @@ async function cmdInstall(source, opts) {
|
|
|
1459
1547
|
barEmpty();
|
|
1460
1548
|
}
|
|
1461
1549
|
const scope = opts.scope ?? "user";
|
|
1550
|
+
const marketplaceName = selectedPlugins[0]?.marketplace ?? deriveMarketplaceName(source);
|
|
1551
|
+
const willInstallToClaude = installTargets.some(
|
|
1552
|
+
(t) => t.id === "claude-code" || t.id === "cursor" && process.platform !== "win32"
|
|
1553
|
+
);
|
|
1554
|
+
const isNew = willInstallToClaude && await isMarketplaceNew(marketplaceName);
|
|
1462
1555
|
for (const target of installTargets) {
|
|
1463
1556
|
await installPlugins(selectedPlugins, target, scope, repoPath, source);
|
|
1464
1557
|
}
|
|
1558
|
+
const installedViaOfficialCli = !!getOfficialPluginRef(source);
|
|
1559
|
+
if (isNew && willInstallToClaude && !installedViaOfficialCli) {
|
|
1560
|
+
let enableAutoUpdate = true;
|
|
1561
|
+
if (!opts.yes && process.stdin.isTTY) {
|
|
1562
|
+
barEmpty();
|
|
1563
|
+
const response = await readLine(
|
|
1564
|
+
`${c.cyan(S.stepActive)} Enable auto-updates? ${c.dim("[Y/n]")} `
|
|
1565
|
+
);
|
|
1566
|
+
enableAutoUpdate = response.trim().toLowerCase() !== "n";
|
|
1567
|
+
}
|
|
1568
|
+
if (enableAutoUpdate) {
|
|
1569
|
+
await setAutoUpdate(marketplaceName, true);
|
|
1570
|
+
stepDone("Auto-updates enabled");
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1465
1573
|
track({
|
|
1466
1574
|
event: "install",
|
|
1467
1575
|
source,
|
|
@@ -1476,9 +1584,12 @@ async function cmdInstall(source, opts) {
|
|
|
1476
1584
|
}
|
|
1477
1585
|
function pluginComponents(p) {
|
|
1478
1586
|
const parts = [];
|
|
1479
|
-
if (p.skills.length)
|
|
1480
|
-
|
|
1481
|
-
if (p.
|
|
1587
|
+
if (p.skills.length)
|
|
1588
|
+
parts.push(`${p.skills.length} ${p.skills.length === 1 ? "skill" : "skills"}`);
|
|
1589
|
+
if (p.commands.length)
|
|
1590
|
+
parts.push(`${p.commands.length} ${p.commands.length === 1 ? "cmd" : "cmds"}`);
|
|
1591
|
+
if (p.agents.length)
|
|
1592
|
+
parts.push(`${p.agents.length} ${p.agents.length === 1 ? "agent" : "agents"}`);
|
|
1482
1593
|
if (p.rules.length) parts.push(`${p.rules.length} ${p.rules.length === 1 ? "rule" : "rules"}`);
|
|
1483
1594
|
if (p.hasHooks) parts.push("hooks");
|
|
1484
1595
|
if (p.hasMcp) parts.push("mcp");
|
|
@@ -1496,7 +1607,9 @@ function printPluginTable(plugins) {
|
|
|
1496
1607
|
const name = p.name.padEnd(nameWidth);
|
|
1497
1608
|
const comp = compStrs[i];
|
|
1498
1609
|
const desc = truncate(p.description ?? "", descWidth);
|
|
1499
|
-
barLine(
|
|
1610
|
+
barLine(
|
|
1611
|
+
`${c.bold(name)} ${comp ? c.cyan(comp.padEnd(compWidth)) : " ".repeat(compWidth)} ${c.dim(desc)}`
|
|
1612
|
+
);
|
|
1500
1613
|
}
|
|
1501
1614
|
}
|
|
1502
1615
|
function printRemotePluginTable(plugins) {
|