plugins 1.3.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/README.md +22 -22
- package/dist/index.js +168 -30
- package/package.json +17 -2
package/README.md
CHANGED
|
@@ -42,31 +42,31 @@ npx plugins targets
|
|
|
42
42
|
|
|
43
43
|
## Commands
|
|
44
44
|
|
|
45
|
-
| Command
|
|
46
|
-
|
|
47
|
-
| `plugins add <source>`
|
|
48
|
-
| `plugins discover <source>` | Inspect plugins without installing (dry run)
|
|
49
|
-
| `plugins targets`
|
|
45
|
+
| Command | Description |
|
|
46
|
+
| --------------------------- | ----------------------------------------------------- |
|
|
47
|
+
| `plugins add <source>` | Discover and install plugins from a source |
|
|
48
|
+
| `plugins discover <source>` | Inspect plugins without installing (dry run) |
|
|
49
|
+
| `plugins targets` | List available agent tools and their detection status |
|
|
50
50
|
|
|
51
51
|
If no subcommand is given, `plugins <source>` defaults to `add`.
|
|
52
52
|
|
|
53
53
|
## Flags
|
|
54
54
|
|
|
55
|
-
| Flag
|
|
56
|
-
|
|
57
|
-
| `--target` | `-t`
|
|
58
|
-
| `--scope`
|
|
59
|
-
| `--yes`
|
|
60
|
-
| `--help`
|
|
55
|
+
| Flag | Short | Default | Description |
|
|
56
|
+
| ---------- | ----- | ----------- | ---------------------------------------------------------- |
|
|
57
|
+
| `--target` | `-t` | auto-detect | Install to a specific agent tool (`claude-code`, `cursor`) |
|
|
58
|
+
| `--scope` | `-s` | `user` | Installation scope: `user`, `project`, or `local` |
|
|
59
|
+
| `--yes` | `-y` | `false` | Skip the confirmation prompt |
|
|
60
|
+
| `--help` | `-h` | | Show usage information |
|
|
61
61
|
|
|
62
62
|
## Supported targets
|
|
63
63
|
|
|
64
64
|
The CLI auto-detects which agent tools are installed and installs to all of them.
|
|
65
65
|
|
|
66
|
-
| Target
|
|
67
|
-
|
|
68
|
-
| [Claude Code](https://code.claude.com) | `claude` binary on PATH
|
|
69
|
-
| [Cursor](https://cursor.com)
|
|
66
|
+
| Target | Detection |
|
|
67
|
+
| -------------------------------------- | ------------------------------------ |
|
|
68
|
+
| [Claude Code](https://code.claude.com) | `claude` binary on PATH |
|
|
69
|
+
| [Cursor](https://cursor.com) | `cursor` + `claude` binaries on PATH |
|
|
70
70
|
|
|
71
71
|
## How it works
|
|
72
72
|
|
|
@@ -90,12 +90,12 @@ The CLI translates the vendor-neutral `.plugin/` format into target-specific for
|
|
|
90
90
|
|
|
91
91
|
## Environment variables
|
|
92
92
|
|
|
93
|
-
| Variable
|
|
94
|
-
|
|
95
|
-
| `DISABLE_TELEMETRY` | Disable anonymous install telemetry
|
|
96
|
-
| `DO_NOT_TRACK`
|
|
97
|
-
| `NO_COLOR`
|
|
98
|
-
| `FORCE_COLOR`
|
|
93
|
+
| Variable | Purpose |
|
|
94
|
+
| ------------------- | -------------------------------------------------------------------------------- |
|
|
95
|
+
| `DISABLE_TELEMETRY` | Disable anonymous install telemetry |
|
|
96
|
+
| `DO_NOT_TRACK` | Disable anonymous install telemetry ([standard](https://consoledonottrack.com/)) |
|
|
97
|
+
| `NO_COLOR` | Disable color output |
|
|
98
|
+
| `FORCE_COLOR` | Force color output |
|
|
99
99
|
|
|
100
100
|
## Development
|
|
101
101
|
|
|
@@ -109,4 +109,4 @@ Zero runtime dependencies. Built with [tsup](https://tsup.egoist.dev/) as a sing
|
|
|
109
109
|
|
|
110
110
|
## License
|
|
111
111
|
|
|
112
|
-
[Apache 2.0](
|
|
112
|
+
[Apache 2.0](./LICENSE)
|
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
|
}
|
|
@@ -773,7 +825,10 @@ async function installToPluginCache(plugins, scope, repoPath, source) {
|
|
|
773
825
|
marketplaceSource = { source: "github", repo: githubRepo };
|
|
774
826
|
} else if (isRemoteSource(source)) {
|
|
775
827
|
const gitUrl = normalizeGitUrl(source);
|
|
776
|
-
marketplaceSource = {
|
|
828
|
+
marketplaceSource = {
|
|
829
|
+
source: "git",
|
|
830
|
+
url: gitUrl.endsWith(".git") ? gitUrl : gitUrl + ".git"
|
|
831
|
+
};
|
|
777
832
|
} else {
|
|
778
833
|
marketplaceSource = { source: "directory", path: repoPath };
|
|
779
834
|
}
|
|
@@ -787,16 +842,25 @@ async function installToPluginCache(plugins, scope, repoPath, source) {
|
|
|
787
842
|
}
|
|
788
843
|
barEmpty();
|
|
789
844
|
const installedPath = join3(pluginsDir, "installed_plugins.json");
|
|
790
|
-
let installedData = {
|
|
845
|
+
let installedData = {
|
|
846
|
+
version: 2,
|
|
847
|
+
plugins: {}
|
|
848
|
+
};
|
|
791
849
|
if (existsSync2(installedPath)) {
|
|
792
850
|
try {
|
|
793
|
-
|
|
851
|
+
const parsed = JSON.parse(await readFile2(installedPath, "utf-8"));
|
|
852
|
+
installedData.version = parsed.version ?? 2;
|
|
853
|
+
installedData.plugins = parsed.plugins ?? {};
|
|
794
854
|
} catch {
|
|
795
855
|
}
|
|
796
856
|
}
|
|
797
857
|
let gitSha;
|
|
798
858
|
try {
|
|
799
|
-
gitSha = execSync2("git rev-parse HEAD", {
|
|
859
|
+
gitSha = execSync2("git rev-parse HEAD", {
|
|
860
|
+
cwd: repoPath,
|
|
861
|
+
encoding: "utf-8",
|
|
862
|
+
stdio: "pipe"
|
|
863
|
+
}).trim();
|
|
800
864
|
} catch {
|
|
801
865
|
}
|
|
802
866
|
for (const plugin of plugins) {
|
|
@@ -834,7 +898,9 @@ async function installToPluginCache(plugins, scope, repoPath, source) {
|
|
|
834
898
|
}
|
|
835
899
|
}
|
|
836
900
|
if (settingsCorrupted) {
|
|
837
|
-
warn(
|
|
901
|
+
warn(
|
|
902
|
+
"Could not parse ~/.claude/settings.json \u2014 skipping enabledPlugins update to avoid overwriting existing settings."
|
|
903
|
+
);
|
|
838
904
|
barLine(c.dim("You may need to manually enable the plugins in Claude Code settings."));
|
|
839
905
|
} else {
|
|
840
906
|
const enabled = settings.enabledPlugins ?? {};
|
|
@@ -867,7 +933,11 @@ async function installToCursorExtensions(plugins, scope, repoPath, source) {
|
|
|
867
933
|
}
|
|
868
934
|
let gitSha;
|
|
869
935
|
try {
|
|
870
|
-
gitSha = execSync2("git rev-parse HEAD", {
|
|
936
|
+
gitSha = execSync2("git rev-parse HEAD", {
|
|
937
|
+
cwd: repoPath,
|
|
938
|
+
encoding: "utf-8",
|
|
939
|
+
stdio: "pipe"
|
|
940
|
+
}).trim();
|
|
871
941
|
} catch {
|
|
872
942
|
}
|
|
873
943
|
for (const plugin of plugins) {
|
|
@@ -881,9 +951,7 @@ async function installToCursorExtensions(plugins, scope, repoPath, source) {
|
|
|
881
951
|
await cp(plugin.path, destDir, { recursive: true });
|
|
882
952
|
barDebug(c.dim(`Copied to ${destDir}`));
|
|
883
953
|
const identifier = `${marketplaceName}.${plugin.name}`;
|
|
884
|
-
extensions = extensions.filter(
|
|
885
|
-
(e) => e?.identifier?.id !== identifier
|
|
886
|
-
);
|
|
954
|
+
extensions = extensions.filter((e) => e?.identifier?.id !== identifier);
|
|
887
955
|
const uriPath = "/" + destDir.replace(/\\/g, "/");
|
|
888
956
|
extensions.push({
|
|
889
957
|
identifier: { id: identifier },
|
|
@@ -917,7 +985,11 @@ async function installToCodex(plugins, scope, repoPath, source) {
|
|
|
917
985
|
}
|
|
918
986
|
let gitSha;
|
|
919
987
|
try {
|
|
920
|
-
gitSha = execSync2("git rev-parse HEAD", {
|
|
988
|
+
gitSha = execSync2("git rev-parse HEAD", {
|
|
989
|
+
cwd: repoPath,
|
|
990
|
+
encoding: "utf-8",
|
|
991
|
+
stdio: "pipe"
|
|
992
|
+
}).trim();
|
|
921
993
|
} catch {
|
|
922
994
|
}
|
|
923
995
|
const versionKey = gitSha ?? "local";
|
|
@@ -1031,7 +1103,12 @@ async function enrichForCodex(plugin) {
|
|
|
1031
1103
|
};
|
|
1032
1104
|
if (manifest.homepage) iface.websiteURL = manifest.homepage;
|
|
1033
1105
|
else if (manifest.repository) iface.websiteURL = manifest.repository;
|
|
1034
|
-
const assetCandidates = [
|
|
1106
|
+
const assetCandidates = [
|
|
1107
|
+
"assets/app-icon.png",
|
|
1108
|
+
"assets/icon.png",
|
|
1109
|
+
"assets/logo.png",
|
|
1110
|
+
"assets/logo.svg"
|
|
1111
|
+
];
|
|
1035
1112
|
for (const candidate of assetCandidates) {
|
|
1036
1113
|
if (existsSync2(join3(plugin.path, candidate))) {
|
|
1037
1114
|
iface.logo = `./${candidate}`;
|
|
@@ -1076,6 +1153,23 @@ async function prepareForClaudeCode(plugins, repoPath, marketplaceName) {
|
|
|
1076
1153
|
await preparePluginDirForVendor(plugin, ".claude-plugin", "CLAUDE_PLUGIN_ROOT");
|
|
1077
1154
|
}
|
|
1078
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
|
+
}
|
|
1079
1173
|
async function preparePluginDirForVendor(plugin, vendorDir, envVar) {
|
|
1080
1174
|
const pluginPath = plugin.path;
|
|
1081
1175
|
const openPluginDir = join3(pluginPath, ".plugin");
|
|
@@ -1131,7 +1225,9 @@ async function translateEnvVars(pluginPath, pluginName, envVar) {
|
|
|
1131
1225
|
if (changed) {
|
|
1132
1226
|
await writeFile(filePath, content);
|
|
1133
1227
|
barDebug(
|
|
1134
|
-
c.dim(
|
|
1228
|
+
c.dim(
|
|
1229
|
+
`${pluginName}: translated plugin root \u2192 \${${envVar}} in ${filePath.split("/").pop()}`
|
|
1230
|
+
)
|
|
1135
1231
|
);
|
|
1136
1232
|
}
|
|
1137
1233
|
}
|
|
@@ -1183,6 +1279,29 @@ function normalizeGitUrl(source) {
|
|
|
1183
1279
|
}
|
|
1184
1280
|
return source;
|
|
1185
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
|
+
}
|
|
1186
1305
|
|
|
1187
1306
|
// lib/telemetry.ts
|
|
1188
1307
|
var TELEMETRY_URL = "https://plugins-telemetry.labs.vercel.dev/t";
|
|
@@ -1294,14 +1413,14 @@ async function cmdDiscover(source) {
|
|
|
1294
1413
|
if (remotePlugins.length > 0) {
|
|
1295
1414
|
if (values.remote) {
|
|
1296
1415
|
barEmpty();
|
|
1297
|
-
step(
|
|
1416
|
+
step(
|
|
1417
|
+
`${c.bold(String(remotePlugins.length))} remote plugin(s) ${c.dim("(hosted in external repos)")}`
|
|
1418
|
+
);
|
|
1298
1419
|
barEmpty();
|
|
1299
1420
|
printRemotePluginTable(remotePlugins);
|
|
1300
1421
|
} else {
|
|
1301
1422
|
barEmpty();
|
|
1302
|
-
barLine(
|
|
1303
|
-
c.dim(`${remotePlugins.length} remote plugin(s) not shown. Run:`)
|
|
1304
|
-
);
|
|
1423
|
+
barLine(c.dim(`${remotePlugins.length} remote plugin(s) not shown. Run:`));
|
|
1305
1424
|
barLine(` ${c.cyan(`npx plugins discover ${source} --remote`)}`);
|
|
1306
1425
|
}
|
|
1307
1426
|
printMissingPaths(missingPaths);
|
|
@@ -1343,9 +1462,7 @@ async function cmdInstall(source, opts) {
|
|
|
1343
1462
|
barEmpty();
|
|
1344
1463
|
step("No plugins found.");
|
|
1345
1464
|
if (remotePlugins.length > 0) {
|
|
1346
|
-
barLine(
|
|
1347
|
-
c.dim(`${remotePlugins.length} remote plugin(s) not shown. Run:`)
|
|
1348
|
-
);
|
|
1465
|
+
barLine(c.dim(`${remotePlugins.length} remote plugin(s) not shown. Run:`));
|
|
1349
1466
|
barLine(` ${c.cyan(`npx plugins discover ${source} --remote`)}`);
|
|
1350
1467
|
printMissingPaths(missingPaths);
|
|
1351
1468
|
}
|
|
@@ -1387,9 +1504,7 @@ async function cmdInstall(source, opts) {
|
|
|
1387
1504
|
printPluginTable(plugins);
|
|
1388
1505
|
if (remotePlugins.length > 0) {
|
|
1389
1506
|
barEmpty();
|
|
1390
|
-
barLine(
|
|
1391
|
-
c.dim(`+ ${remotePlugins.length} remote plugin(s) not included. Run:`)
|
|
1392
|
-
);
|
|
1507
|
+
barLine(c.dim(`+ ${remotePlugins.length} remote plugin(s) not included. Run:`));
|
|
1393
1508
|
barLine(` ${c.cyan(`npx plugins discover ${source} --remote`)}`);
|
|
1394
1509
|
printMissingPaths(missingPaths);
|
|
1395
1510
|
}
|
|
@@ -1422,9 +1537,7 @@ async function cmdInstall(source, opts) {
|
|
|
1422
1537
|
}
|
|
1423
1538
|
selectedPlugins = plugins.filter((p) => selected.includes(p.name));
|
|
1424
1539
|
if (remotePlugins.length > 0) {
|
|
1425
|
-
barLine(
|
|
1426
|
-
c.dim(`+ ${remotePlugins.length} remote plugin(s) not included. Run:`)
|
|
1427
|
-
);
|
|
1540
|
+
barLine(c.dim(`+ ${remotePlugins.length} remote plugin(s) not included. Run:`));
|
|
1428
1541
|
barLine(` ${c.cyan(`npx plugins discover ${source} --remote`)}`);
|
|
1429
1542
|
printMissingPaths(missingPaths);
|
|
1430
1543
|
}
|
|
@@ -1434,9 +1547,29 @@ async function cmdInstall(source, opts) {
|
|
|
1434
1547
|
barEmpty();
|
|
1435
1548
|
}
|
|
1436
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);
|
|
1437
1555
|
for (const target of installTargets) {
|
|
1438
1556
|
await installPlugins(selectedPlugins, target, scope, repoPath, source);
|
|
1439
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
|
+
}
|
|
1440
1573
|
track({
|
|
1441
1574
|
event: "install",
|
|
1442
1575
|
source,
|
|
@@ -1451,9 +1584,12 @@ async function cmdInstall(source, opts) {
|
|
|
1451
1584
|
}
|
|
1452
1585
|
function pluginComponents(p) {
|
|
1453
1586
|
const parts = [];
|
|
1454
|
-
if (p.skills.length)
|
|
1455
|
-
|
|
1456
|
-
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"}`);
|
|
1457
1593
|
if (p.rules.length) parts.push(`${p.rules.length} ${p.rules.length === 1 ? "rule" : "rules"}`);
|
|
1458
1594
|
if (p.hasHooks) parts.push("hooks");
|
|
1459
1595
|
if (p.hasMcp) parts.push("mcp");
|
|
@@ -1471,7 +1607,9 @@ function printPluginTable(plugins) {
|
|
|
1471
1607
|
const name = p.name.padEnd(nameWidth);
|
|
1472
1608
|
const comp = compStrs[i];
|
|
1473
1609
|
const desc = truncate(p.description ?? "", descWidth);
|
|
1474
|
-
barLine(
|
|
1610
|
+
barLine(
|
|
1611
|
+
`${c.bold(name)} ${comp ? c.cyan(comp.padEnd(compWidth)) : " ".repeat(compWidth)} ${c.dim(desc)}`
|
|
1612
|
+
);
|
|
1475
1613
|
}
|
|
1476
1614
|
}
|
|
1477
1615
|
function printRemotePluginTable(plugins) {
|
package/package.json
CHANGED
|
@@ -1,20 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "plugins",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Install open-plugin format plugins into agent tools",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"packageManager": "pnpm@10.28.1",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=18"
|
|
9
|
+
},
|
|
6
10
|
"bin": {
|
|
7
11
|
"plugins": "dist/index.js"
|
|
8
12
|
},
|
|
9
13
|
"files": [
|
|
10
14
|
"dist"
|
|
11
15
|
],
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/vercel-labs/plugins.git"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/vercel-labs/plugins#readme",
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/vercel-labs/plugins/issues"
|
|
23
|
+
},
|
|
12
24
|
"scripts": {
|
|
13
25
|
"build": "tsup",
|
|
14
26
|
"start": "node dist/index.js",
|
|
15
|
-
"test": "tsx --test test/*.test.ts"
|
|
27
|
+
"test": "tsx --test test/*.test.ts",
|
|
28
|
+
"format:check": "prettier --check \"index.ts\" \"lib/**/*.ts\" \"test/**/*.ts\"",
|
|
29
|
+
"publish:snapshot": "npm version prerelease --preid=snapshot --no-git-tag-version && npm publish --tag snapshot"
|
|
16
30
|
},
|
|
17
31
|
"devDependencies": {
|
|
32
|
+
"prettier": "^3",
|
|
18
33
|
"tsx": "^4.20.6",
|
|
19
34
|
"tsup": "^8",
|
|
20
35
|
"typescript": "^5"
|