agentinit 1.17.1 → 1.18.0

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/cli.js CHANGED
@@ -17204,7 +17204,11 @@ class PluginManager {
17204
17204
  } catch {
17205
17205
  throw new Error(`Invalid .claude-plugin/marketplace.json in ${pluginDir}`);
17206
17206
  }
17207
- const entries = Array.isArray(manifest.plugins) ? manifest.plugins.filter((entry) => typeof entry?.name === "string" && typeof entry?.source === "string") : [];
17207
+ const entries = Array.isArray(manifest.plugins) ? manifest.plugins.filter((entry) => typeof entry?.name === "string" && typeof entry?.source === "string").map((entry) => ({
17208
+ name: entry.name,
17209
+ source: entry.source,
17210
+ ...typeof entry.description === "string" ? { description: entry.description } : {}
17211
+ })) : [];
17208
17212
  if (entries.length === 0) {
17209
17213
  throw new Error(`No plugins declared in .claude-plugin/marketplace.json for ${pluginDir}`);
17210
17214
  }
@@ -41221,9 +41225,73 @@ var BUILT_IN_MARKETPLACE_IDS = new Set(MARKETPLACES.map((marketplace) => marketp
41221
41225
  var BUILT_IN_VERIFIED_REPOS = new Set(getBuiltInVerifiedGithubRepos());
41222
41226
 
41223
41227
  // dist/commands/skills.js
41224
- var import_prompts2 = __toESM(require_prompts3(), 1);
41228
+ var import_prompts3 = __toESM(require_prompts3(), 1);
41225
41229
  import {homedir as homedir6} from "os";
41226
41230
  import {relative as relative7, resolve as resolve12} from "path";
41231
+
41232
+ // dist/utils/promptUtils.js
41233
+ var import_prompts2 = __toESM(require_prompts3(), 1);
41234
+ import {createRequire as createRequire2} from "module";
41235
+ function enableUppercaseToggleAllForMultiselectPrompt() {
41236
+ if (uppercaseToggleAllPatched) {
41237
+ return;
41238
+ }
41239
+ uppercaseToggleAllPatched = true;
41240
+ try {
41241
+ const MultiselectPrompt = require2("prompts/lib/elements/multiselect");
41242
+ const prototype = MultiselectPrompt?.prototype;
41243
+ if (!prototype || typeof prototype._ !== "function" || prototype.__agentinitUppercaseToggleAllPatched) {
41244
+ return;
41245
+ }
41246
+ const originalHandler = prototype._;
41247
+ prototype._ = function agentinitMultiselectHandler(input, key) {
41248
+ return originalHandler.call(this, input === "A" ? "a" : input, key);
41249
+ };
41250
+ Object.defineProperty(prototype, "__agentinitUppercaseToggleAllPatched", {
41251
+ value: true,
41252
+ configurable: false,
41253
+ enumerable: false,
41254
+ writable: false
41255
+ });
41256
+ } catch {
41257
+ }
41258
+ }
41259
+ async function promptMultiselect(options2) {
41260
+ enableUppercaseToggleAllForMultiselectPrompt();
41261
+ return import_prompts2.default({
41262
+ ...options2,
41263
+ type: "multiselect",
41264
+ instructions: options2.instructions ?? false,
41265
+ hint: options2.hint ?? MULTISELECT_TOGGLE_ALL_HINT
41266
+ });
41267
+ }
41268
+ async function selectBundlePlugins(entries, actionLabel, options2 = {}) {
41269
+ if (options2.selectAll) {
41270
+ logger.info("Selecting all bundled plugins (--all).");
41271
+ return entries.map((entry) => entry.name);
41272
+ }
41273
+ logger.info(dim(MULTISELECT_TOGGLE_ALL_HINT));
41274
+ const response = await promptMultiselect({
41275
+ name: "plugins",
41276
+ message: `This repository contains multiple plugins. Select which to ${actionLabel}:`,
41277
+ min: 1,
41278
+ choices: entries.map((entry) => ({
41279
+ title: entry.name,
41280
+ value: entry.name,
41281
+ ...entry.description ? { description: entry.description } : {}
41282
+ }))
41283
+ });
41284
+ if (!response.plugins || response.plugins.length === 0) {
41285
+ logger.info("Cancelled.");
41286
+ return null;
41287
+ }
41288
+ return response.plugins;
41289
+ }
41290
+ var require2 = createRequire2(import.meta.url);
41291
+ var MULTISELECT_TOGGLE_ALL_HINT = "Press Space to select, A to select or deselect all, then Enter to confirm.";
41292
+ var uppercaseToggleAllPatched = false;
41293
+
41294
+ // dist/commands/skills.js
41227
41295
  init_skillsManager();
41228
41296
  init_pluginManager();
41229
41297
  init_marketplaceRegistry();
@@ -41232,64 +41300,66 @@ init_skills();
41232
41300
  function registerSkillsCommand(program2) {
41233
41301
  const marketplaceHelp = getMarketplaceIds().join(", ");
41234
41302
  const skills3 = program2.command("skills").description("Manage agent skills");
41235
- skills3.command("add <source>").description("Add skills from a marketplace, GitHub repo, or local path").option("--from <marketplace>", `Marketplace source override (available: ${marketplaceHelp})`).option("-g, --global", "Install skills globally").option("-a, --agent <agents...>", "Target specific agent(s)").option("-s, --skill <names...>", "Install only specific skills by name").option("-l, --list", "List available skills from the source without installing").option("--copy", "Copy skill files instead of symlinking").option("-y, --yes", "Skip prompts and auto-detect project-configured agents only").action(async (source, options2) => {
41303
+ skills3.command("add <source>").description("Add skills from a marketplace, GitHub repo, or local path").option("--from <marketplace>", `Marketplace source override (available: ${marketplaceHelp})`).option("-g, --global", "Install skills globally").option("-a, --agent <agents...>", "Target specific agent(s)").option("-s, --skill <names...>", "Install only specific skills by name").option("-l, --list", "List available skills from the source without installing").option("--all", "Select all bundled plugins when the source contains multiple plugins").option("--copy", "Copy skill files instead of symlinking").option("-y, --yes", "Skip prompts and auto-detect project-configured agents only").action(async (source, options2) => {
41236
41304
  logger.titleBox("AgentInit Skills");
41237
41305
  const agentManager9 = new AgentManager;
41238
41306
  const skillsManager5 = new SkillsManager(agentManager9);
41239
41307
  if (options2.list) {
41240
- const spinner2 = ora("Discovering skills...").start();
41308
+ const spinner = ora("Discovering skills...").start();
41241
41309
  try {
41242
41310
  const result = await skillsManager5.discoverFromSource(source, process.cwd(), {
41243
41311
  from: options2.from
41244
41312
  });
41245
- spinner2.stop();
41313
+ spinner.stop();
41246
41314
  displayDiscoveredSkills(result.skills, result.warnings);
41247
41315
  } catch (error) {
41248
41316
  if (error instanceof MultipleBundlePluginsError) {
41249
- spinner2.stop();
41250
- const selected = await selectBundlePlugin(error, "list");
41317
+ spinner.stop();
41318
+ const selected = await selectBundlePlugins(error.entries, "list", { selectAll: options2.all });
41251
41319
  if (!selected) {
41252
41320
  return;
41253
41321
  }
41254
- const retrySpinner = ora("Discovering skills...").start();
41255
- try {
41256
- const result = await skillsManager5.discoverFromSource(source, process.cwd(), {
41257
- from: options2.from,
41258
- pluginName: selected
41259
- });
41260
- retrySpinner.stop();
41261
- displayDiscoveredSkills(result.skills, result.warnings);
41262
- } catch (retryError) {
41263
- retrySpinner.fail("Failed to discover skills");
41264
- logger.error(`Error: ${retryError instanceof Error ? retryError.message : "Unknown error"}`);
41322
+ for (const pluginName of selected) {
41323
+ const retrySpinner = ora(`Discovering skills from ${pluginName}...`).start();
41324
+ try {
41325
+ const result = await skillsManager5.discoverFromSource(source, process.cwd(), {
41326
+ from: options2.from,
41327
+ pluginName
41328
+ });
41329
+ retrySpinner.stop();
41330
+ displayDiscoveredSkills(result.skills, result.warnings);
41331
+ } catch (retryError) {
41332
+ retrySpinner.fail(`Failed to discover skills from ${pluginName}`);
41333
+ logger.error(`Error: ${retryError instanceof Error ? retryError.message : "Unknown error"}`);
41334
+ }
41265
41335
  }
41266
41336
  } else {
41267
- spinner2.fail("Failed to discover skills");
41337
+ spinner.fail("Failed to discover skills");
41268
41338
  logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
41269
41339
  }
41270
41340
  }
41271
41341
  return;
41272
41342
  }
41273
41343
  const verifySpinner = ora("Verifying skill source...").start();
41274
- let selectedPluginName;
41344
+ let selectedPluginNames;
41275
41345
  try {
41276
41346
  await skillsManager5.prepareSource(source, process.cwd(), {
41277
41347
  from: options2.from
41278
41348
  });
41279
41349
  verifySpinner.stop();
41280
41350
  } catch (error) {
41281
- if (error instanceof MultipleBundlePluginsError && !options2.yes) {
41351
+ if (error instanceof MultipleBundlePluginsError && (options2.all || !options2.yes)) {
41282
41352
  verifySpinner.stop();
41283
- const selected = await selectBundlePlugin(error, "install");
41353
+ const selected = await selectBundlePlugins(error.entries, "install", { selectAll: options2.all });
41284
41354
  if (!selected) {
41285
41355
  return;
41286
41356
  }
41287
- selectedPluginName = selected;
41357
+ selectedPluginNames = selected;
41288
41358
  const retrySpinner = ora("Verifying skill source...").start();
41289
41359
  try {
41290
41360
  await skillsManager5.prepareSource(source, process.cwd(), {
41291
41361
  from: options2.from,
41292
- pluginName: selectedPluginName
41362
+ ...selectedPluginNames[0] ? { pluginName: selectedPluginNames[0] } : {}
41293
41363
  });
41294
41364
  retrySpinner.stop();
41295
41365
  } catch (retryError) {
@@ -41321,22 +41391,31 @@ function registerSkillsCommand(program2) {
41321
41391
  targetGlobal = selection.global;
41322
41392
  }
41323
41393
  }
41324
- const buildInstallOptions = (fromOverride) => ({
41325
- ...fromOverride !== undefined ? { from: fromOverride } : options2.from !== undefined ? { from: options2.from } : {},
41394
+ const buildInstallOptions = (pluginName) => ({
41395
+ ...options2.from !== undefined ? { from: options2.from } : {},
41326
41396
  ...targetGlobal !== undefined ? { global: targetGlobal } : {},
41327
41397
  ...targetAgents !== undefined ? { agents: targetAgents } : {},
41328
41398
  ...options2.skill !== undefined ? { skills: options2.skill } : {},
41329
41399
  ...options2.copy !== undefined ? { copy: options2.copy } : {},
41330
- ...selectedPluginName !== undefined ? { pluginName: selectedPluginName } : {},
41400
+ ...pluginName !== undefined ? { pluginName } : {},
41331
41401
  ...options2.yes !== undefined ? { yes: options2.yes } : {}
41332
41402
  });
41333
- const spinner = ora("Installing skills...").start();
41334
- try {
41335
- const result = await skillsManager5.addFromSource(source, process.cwd(), buildInstallOptions());
41336
- displayInstallResult(result, spinner, agentManager9, skillsManager5, source, { from: options2.from });
41337
- } catch (error) {
41338
- spinner.fail("Failed to install skills");
41339
- logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
41403
+ const pluginsToInstall = selectedPluginNames || [undefined];
41404
+ for (const pluginName of pluginsToInstall) {
41405
+ const spinner = ora(pluginName ? `Installing skills from ${pluginName}...` : "Installing skills...").start();
41406
+ try {
41407
+ if (pluginName && pluginName !== selectedPluginNames?.[0]) {
41408
+ await skillsManager5.prepareSource(source, process.cwd(), {
41409
+ from: options2.from,
41410
+ pluginName
41411
+ });
41412
+ }
41413
+ const result = await skillsManager5.addFromSource(source, process.cwd(), buildInstallOptions(pluginName));
41414
+ displayInstallResult(result, spinner, agentManager9, skillsManager5, source, { from: options2.from });
41415
+ } catch (error) {
41416
+ spinner.fail(pluginName ? `Failed to install skills from ${pluginName}` : "Failed to install skills");
41417
+ logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
41418
+ }
41340
41419
  }
41341
41420
  });
41342
41421
  skills3.command("list").alias("ls").description("List installed skills").option("-g, --global", "List only global skills").option("-a, --agent <agents...>", "Filter by specific agent(s)").action(async (options2) => {
@@ -41415,26 +41494,10 @@ function registerSkillsCommand(program2) {
41415
41494
  }
41416
41495
  });
41417
41496
  }
41418
- async function selectBundlePlugin(error, actionLabel) {
41419
- const response = await import_prompts2.default({
41420
- type: "select",
41421
- name: "plugin",
41422
- message: `This repository contains multiple plugins. Select one to ${actionLabel}:`,
41423
- choices: error.entries.map((entry) => ({
41424
- title: entry.name,
41425
- value: entry.name
41426
- }))
41427
- });
41428
- if (!response.plugin) {
41429
- logger.info("Cancelled.");
41430
- return null;
41431
- }
41432
- return response.plugin;
41433
- }
41434
41497
  async function resolveInteractiveSkillTargets(skillsManager5, agentManager9, source, projectPath, options2) {
41435
41498
  let installGlobal = !!options2.global;
41436
41499
  if (!options2.global) {
41437
- const response2 = await import_prompts2.default({
41500
+ const response2 = await import_prompts3.default({
41438
41501
  type: "select",
41439
41502
  name: "scope",
41440
41503
  message: "Where should the skill be installed?",
@@ -41472,11 +41535,9 @@ async function resolveInteractiveSkillTargets(skillsManager5, agentManager9, sou
41472
41535
  logger.warn("No project agent files with skills support were detected in this project.");
41473
41536
  logger.info("Select project agent directories manually. Run `agentinit init` if you want future installs to auto-detect.");
41474
41537
  }
41475
- const response = await import_prompts2.default({
41476
- type: "multiselect",
41538
+ const response = await promptMultiselect({
41477
41539
  name: "groups",
41478
41540
  message: installGlobal ? "Select which global agent skills directories to install into:" : detectedGroups.length > 0 ? "Select which project agent skills directories to install into:" : "Select which project agent skills directories to install into manually:",
41479
- instructions: false,
41480
41541
  min: 1,
41481
41542
  choices: availableGroups.map((group) => ({
41482
41543
  title: formatSkillGroupTitle(group),
@@ -42566,7 +42627,7 @@ function registerRulesCommand(program2) {
42566
42627
  }
42567
42628
 
42568
42629
  // dist/commands/plugins.js
42569
- var import_prompts3 = __toESM(require_prompts3(), 1);
42630
+ var import_prompts4 = __toESM(require_prompts3(), 1);
42570
42631
  import {homedir as homedir7} from "os";
42571
42632
  import {dirname as dirname9, relative as relative8, resolve as resolve13} from "path";
42572
42633
  init_pluginManager();
@@ -42576,18 +42637,18 @@ function registerPluginsCommand(program2) {
42576
42637
  const marketplaceHelp = new PluginManager().getMarketplaceIds().join(", ");
42577
42638
  const marketplaceCategoryHelp = getMarketplaceCategories().join(", ");
42578
42639
  const plugins = program2.command("plugins").description("Install agent-agnostic plugins from any marketplace or source");
42579
- plugins.command("install <source>").description("Install a plugin from <marketplace>/<name>, a GitHub repo, or a local path").option("--from <marketplace>", `Marketplace source override (available: ${marketplaceHelp})`).option("-a, --agent <agents...>", "Target specific agent(s)").option("-g, --global", "Install globally").option("--copy-skills", "Copy plugin skills instead of using canonical symlink installs").option("-l, --list", "Preview plugin contents without installing").option("-y, --yes", "Skip confirmation prompts, auto-detect project-configured agents").action(async (source, options2) => {
42640
+ plugins.command("install <source>").description("Install a plugin from <marketplace>/<name>, a GitHub repo, or a local path").option("--from <marketplace>", `Marketplace source override (available: ${marketplaceHelp})`).option("-a, --agent <agents...>", "Target specific agent(s)").option("-g, --global", "Install globally").option("--copy-skills", "Copy plugin skills instead of using canonical symlink installs").option("--all", "Select all bundled plugins when the source contains multiple plugins").option("-l, --list", "Preview plugin contents without installing").option("-y, --yes", "Skip confirmation prompts, auto-detect project-configured agents").action(async (source, options2) => {
42580
42641
  logger.titleBox("AgentInit Plugins");
42581
42642
  const agentManager12 = new AgentManager;
42582
42643
  const pluginManager3 = new PluginManager(agentManager12);
42583
42644
  if (options2.list) {
42584
- const spinner2 = ora("Fetching plugin...").start();
42645
+ const spinner = ora("Fetching plugin...").start();
42585
42646
  try {
42586
- const preview2 = await pluginManager3.inspectPlugin(source, {
42647
+ const preview = await pluginManager3.inspectPlugin(source, {
42587
42648
  from: options2.from
42588
42649
  });
42589
- spinner2.stop();
42590
- const p = preview2.plugin;
42650
+ spinner.stop();
42651
+ const p = preview.plugin;
42591
42652
  console.log("");
42592
42653
  logger.info(`${bold(p.name)} ${dim(`v${p.version}`)} ${dim(`[${p.format} format]`)}`);
42593
42654
  if (p.description)
@@ -42608,49 +42669,51 @@ function registerPluginsCommand(program2) {
42608
42669
  if (p.skills.length === 0 && p.mcpServers.length === 0) {
42609
42670
  logger.info(" No portable components found (no skills or MCP servers).");
42610
42671
  }
42611
- renderPluginWarnings(preview2, process.cwd());
42672
+ renderPluginWarnings(preview, process.cwd());
42612
42673
  } catch (error) {
42613
42674
  if (error instanceof MultipleBundlePluginsError) {
42614
- spinner2.stop();
42615
- const selected = await selectBundlePlugin2(error, "preview");
42675
+ spinner.stop();
42676
+ const selected = await selectBundlePlugins(error.entries, "preview", { selectAll: options2.all });
42616
42677
  if (!selected) {
42617
42678
  return;
42618
42679
  }
42619
- const retrySpinner = ora("Fetching plugin...").start();
42620
- try {
42621
- const preview2 = await pluginManager3.inspectPlugin(source, {
42622
- from: options2.from,
42623
- pluginName: selected
42624
- });
42625
- retrySpinner.stop();
42626
- const p = preview2.plugin;
42627
- console.log("");
42628
- logger.info(`${bold(p.name)} ${dim(`v${p.version}`)} ${dim(`[${p.format} format]`)}`);
42629
- if (p.description)
42630
- logger.info(` ${p.description}`);
42631
- console.log("");
42632
- if (p.skills.length > 0) {
42633
- logger.info(` ${green("Skills")} (${p.skills.length}):`);
42634
- for (const skill of p.skills) {
42635
- logger.info(` ${green(skill.name)} - ${skill.description}`);
42680
+ for (const pluginName of selected) {
42681
+ const retrySpinner = ora(`Fetching plugin ${pluginName}...`).start();
42682
+ try {
42683
+ const preview = await pluginManager3.inspectPlugin(source, {
42684
+ from: options2.from,
42685
+ pluginName
42686
+ });
42687
+ retrySpinner.stop();
42688
+ const p = preview.plugin;
42689
+ console.log("");
42690
+ logger.info(`${bold(p.name)} ${dim(`v${p.version}`)} ${dim(`[${p.format} format]`)}`);
42691
+ if (p.description)
42692
+ logger.info(` ${p.description}`);
42693
+ console.log("");
42694
+ if (p.skills.length > 0) {
42695
+ logger.info(` ${green("Skills")} (${p.skills.length}):`);
42696
+ for (const skill of p.skills) {
42697
+ logger.info(` ${green(skill.name)} - ${skill.description}`);
42698
+ }
42636
42699
  }
42637
- }
42638
- if (p.mcpServers.length > 0) {
42639
- logger.info(` ${cyan("MCP Servers")} (${p.mcpServers.length}):`);
42640
- for (const mcp of p.mcpServers) {
42641
- logger.info(` ${cyan(mcp.name)} [${mcp.type}]`);
42700
+ if (p.mcpServers.length > 0) {
42701
+ logger.info(` ${cyan("MCP Servers")} (${p.mcpServers.length}):`);
42702
+ for (const mcp of p.mcpServers) {
42703
+ logger.info(` ${cyan(mcp.name)} [${mcp.type}]`);
42704
+ }
42642
42705
  }
42706
+ if (p.skills.length === 0 && p.mcpServers.length === 0) {
42707
+ logger.info(" No portable components found (no skills or MCP servers).");
42708
+ }
42709
+ renderPluginWarnings(preview, process.cwd());
42710
+ } catch (retryError) {
42711
+ retrySpinner.fail(`Failed to fetch plugin ${pluginName}`);
42712
+ logger.error(`Error: ${retryError instanceof Error ? retryError.message : "Unknown error"}`);
42643
42713
  }
42644
- if (p.skills.length === 0 && p.mcpServers.length === 0) {
42645
- logger.info(" No portable components found (no skills or MCP servers).");
42646
- }
42647
- renderPluginWarnings(preview2, process.cwd());
42648
- } catch (retryError) {
42649
- retrySpinner.fail("Failed to fetch plugin");
42650
- logger.error(`Error: ${retryError instanceof Error ? retryError.message : "Unknown error"}`);
42651
42714
  }
42652
42715
  } else {
42653
- spinner2.fail("Failed to fetch plugin");
42716
+ spinner.fail("Failed to fetch plugin");
42654
42717
  logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
42655
42718
  }
42656
42719
  }
@@ -42658,34 +42721,42 @@ function registerPluginsCommand(program2) {
42658
42721
  }
42659
42722
  let agentIds = options2.agent;
42660
42723
  let targetGlobal = options2.global;
42661
- let preview = null;
42724
+ let selectionPreview = null;
42662
42725
  let previewRendered = false;
42663
- let selectedPluginName;
42726
+ let selectedPluginNames;
42664
42727
  if (!agentIds && !options2.yes) {
42665
42728
  const previewSpinner = ora("Inspecting plugin...").start();
42666
42729
  try {
42667
- preview = await pluginManager3.preparePluginInstall(source, {
42730
+ const preview = await pluginManager3.preparePluginInstall(source, {
42668
42731
  from: options2.from
42669
42732
  });
42670
42733
  previewSpinner.stop();
42671
- renderPluginWarnings(preview, process.cwd());
42734
+ selectionPreview = buildPluginSelectionPreview([preview]);
42735
+ renderPreparedPluginWarnings([preview], process.cwd());
42672
42736
  previewRendered = true;
42673
42737
  } catch (error) {
42674
42738
  if (error instanceof MultipleBundlePluginsError) {
42675
42739
  previewSpinner.stop();
42676
- const selected = await selectBundlePlugin2(error, "install");
42740
+ const selected = await selectBundlePlugins(error.entries, "install", { selectAll: options2.all });
42677
42741
  if (!selected) {
42678
42742
  return;
42679
42743
  }
42680
- selectedPluginName = selected;
42744
+ selectedPluginNames = selected;
42681
42745
  const retrySpinner = ora("Inspecting plugin...").start();
42682
42746
  try {
42683
- preview = await pluginManager3.preparePluginInstall(source, {
42684
- from: options2.from,
42685
- pluginName: selectedPluginName
42686
- });
42747
+ const previewsByPlugin = new Map;
42748
+ const previewOrder = selectedPluginNames.length > 1 ? [...selectedPluginNames.slice(1), selectedPluginNames[0]] : selectedPluginNames;
42749
+ for (const pluginName of previewOrder) {
42750
+ const preparedPreview = await pluginManager3.preparePluginInstall(source, {
42751
+ from: options2.from,
42752
+ pluginName
42753
+ });
42754
+ previewsByPlugin.set(pluginName, preparedPreview);
42755
+ }
42756
+ const previews = selectedPluginNames.map((pluginName) => previewsByPlugin.get(pluginName)).filter((value) => !!value);
42687
42757
  retrySpinner.stop();
42688
- renderPluginWarnings(preview, process.cwd());
42758
+ selectionPreview = buildPluginSelectionPreview(previews);
42759
+ renderPreparedPluginWarnings(previews, process.cwd());
42689
42760
  previewRendered = true;
42690
42761
  } catch (retryError) {
42691
42762
  retrySpinner.fail("Failed to inspect plugin");
@@ -42699,7 +42770,7 @@ function registerPluginsCommand(program2) {
42699
42770
  }
42700
42771
  }
42701
42772
  try {
42702
- const selection = await interactiveAgentSelect(pluginManager3, agentManager12, process.cwd(), targetGlobal, preview);
42773
+ const selection = await interactiveAgentSelect(pluginManager3, agentManager12, process.cwd(), targetGlobal, selectionPreview);
42703
42774
  if (!selection || selection.aborted || !selection.agents || selection.agents.length === 0) {
42704
42775
  await pluginManager3.discardPreparedPlugin(source, { from: options2.from });
42705
42776
  logger.info("No agents selected. Aborting.");
@@ -42714,82 +42785,93 @@ function registerPluginsCommand(program2) {
42714
42785
  }
42715
42786
  }
42716
42787
  }
42717
- const spinner = ora("Installing plugin...").start();
42718
- try {
42719
- const result = await pluginManager3.installPlugin(source, process.cwd(), {
42720
- from: options2.from,
42721
- agents: agentIds,
42722
- global: targetGlobal,
42723
- copySkills: options2.copySkills,
42724
- yes: options2.yes,
42725
- ...selectedPluginName ? { pluginName: selectedPluginName } : {}
42726
- });
42727
- const p = result.plugin;
42728
- const totalSkills = result.skills.installed.length;
42729
- const totalMcp = result.mcpServers.applied.length;
42730
- const totalNative = result.nativePlugins.installed.length;
42731
- if (totalSkills === 0 && totalMcp === 0 && totalNative === 0) {
42732
- spinner.warn(`Plugin "${p.name}" has no portable components to install.`);
42733
- if (!previewRendered) {
42734
- renderPluginWarnings(result, process.cwd());
42735
- }
42736
- return;
42737
- }
42738
- spinner.succeed(`Installed plugin ${green(bold(p.name))} ${dim(`v${p.version}`)}`);
42739
- renderInstalledComponents(result, agentManager12, process.cwd());
42740
- if (result.skills.skipped.length > 0 || result.mcpServers.skipped.length > 0 || result.nativePlugins.skipped.length > 0) {
42741
- console.log("");
42742
- for (const s of result.skills.skipped) {
42743
- logger.debug(`Skipped skill ${s.name}: ${s.reason}`);
42788
+ const pluginsToInstall = selectedPluginNames || [undefined];
42789
+ for (const pluginName of pluginsToInstall) {
42790
+ const spinner = ora(pluginName ? `Installing plugin ${pluginName}...` : "Installing plugin...").start();
42791
+ try {
42792
+ if (pluginName && pluginName !== selectedPluginNames?.[0]) {
42793
+ await pluginManager3.preparePluginInstall(source, {
42794
+ from: options2.from,
42795
+ pluginName
42796
+ });
42744
42797
  }
42745
- for (const s of result.mcpServers.skipped) {
42746
- logger.debug(`Skipped MCP ${s.name}: ${s.reason}`);
42798
+ const result = await pluginManager3.installPlugin(source, process.cwd(), {
42799
+ from: options2.from,
42800
+ agents: agentIds,
42801
+ global: targetGlobal,
42802
+ copySkills: options2.copySkills,
42803
+ yes: options2.yes,
42804
+ ...pluginName ? { pluginName } : {}
42805
+ });
42806
+ const p = result.plugin;
42807
+ const totalSkills = result.skills.installed.length;
42808
+ const totalMcp = result.mcpServers.applied.length;
42809
+ const totalNative = result.nativePlugins.installed.length;
42810
+ if (totalSkills === 0 && totalMcp === 0 && totalNative === 0) {
42811
+ spinner.warn(`Plugin "${p.name}" has no portable components to install.`);
42812
+ if (!previewRendered) {
42813
+ renderPluginWarnings(result, process.cwd());
42814
+ }
42815
+ continue;
42747
42816
  }
42748
- for (const s of result.nativePlugins.skipped) {
42749
- logger.warn(`Skipped native plugin payload for ${s.agent}: ${s.reason}`);
42817
+ spinner.succeed(`Installed plugin ${green(bold(p.name))} ${dim(`v${p.version}`)}`);
42818
+ renderInstalledComponents(result, agentManager12, process.cwd());
42819
+ if (result.skills.skipped.length > 0 || result.mcpServers.skipped.length > 0 || result.nativePlugins.skipped.length > 0) {
42820
+ console.log("");
42821
+ for (const s of result.skills.skipped) {
42822
+ logger.debug(`Skipped skill ${s.name}: ${s.reason}`);
42823
+ }
42824
+ for (const s of result.mcpServers.skipped) {
42825
+ logger.debug(`Skipped MCP ${s.name}: ${s.reason}`);
42826
+ }
42827
+ for (const s of result.nativePlugins.skipped) {
42828
+ logger.warn(`Skipped native plugin payload for ${s.agent}: ${s.reason}`);
42829
+ }
42750
42830
  }
42751
- }
42752
- if (!previewRendered) {
42753
- renderPluginWarnings(result, process.cwd());
42754
- }
42755
- logger.success("Plugin installation complete.");
42756
- } catch (error) {
42757
- if (error instanceof MultipleBundlePluginsError && !options2.yes) {
42758
- spinner.stop();
42759
- const selected = await selectBundlePlugin2(error, "install");
42760
- if (!selected) {
42761
- return;
42831
+ if (!previewRendered) {
42832
+ renderPluginWarnings(result, process.cwd());
42762
42833
  }
42763
- const retrySpinner = ora("Installing plugin...").start();
42764
- try {
42765
- const result = await pluginManager3.installPlugin(source, process.cwd(), {
42766
- from: options2.from,
42767
- agents: agentIds,
42768
- global: targetGlobal,
42769
- copySkills: options2.copySkills,
42770
- yes: options2.yes,
42771
- pluginName: selected
42772
- });
42773
- const p = result.plugin;
42774
- const totalSkills = result.skills.installed.length;
42775
- const totalMcp = result.mcpServers.applied.length;
42776
- const totalNative = result.nativePlugins.installed.length;
42777
- if (totalSkills === 0 && totalMcp === 0 && totalNative === 0) {
42778
- retrySpinner.warn(`Plugin "${p.name}" has no portable components to install.`);
42779
- renderPluginWarnings(result, process.cwd());
42834
+ logger.success("Plugin installation complete.");
42835
+ } catch (error) {
42836
+ if (error instanceof MultipleBundlePluginsError && (options2.all || !options2.yes)) {
42837
+ spinner.stop();
42838
+ const selected = await selectBundlePlugins(error.entries, "install", { selectAll: options2.all });
42839
+ if (!selected) {
42780
42840
  return;
42781
42841
  }
42782
- retrySpinner.succeed(`Installed plugin ${green(bold(p.name))} ${dim(`v${p.version}`)}`);
42783
- renderInstalledComponents(result, agentManager12, process.cwd());
42784
- renderPluginWarnings(result, process.cwd());
42785
- logger.success("Plugin installation complete.");
42786
- } catch (retryError) {
42787
- retrySpinner.fail("Failed to install plugin");
42788
- logger.error(`Error: ${retryError instanceof Error ? retryError.message : "Unknown error"}`);
42842
+ for (const selectedName of selected) {
42843
+ const retrySpinner = ora(`Installing plugin ${selectedName}...`).start();
42844
+ try {
42845
+ const result = await pluginManager3.installPlugin(source, process.cwd(), {
42846
+ from: options2.from,
42847
+ agents: agentIds,
42848
+ global: targetGlobal,
42849
+ copySkills: options2.copySkills,
42850
+ yes: options2.yes,
42851
+ pluginName: selectedName
42852
+ });
42853
+ const p = result.plugin;
42854
+ const totalSkills = result.skills.installed.length;
42855
+ const totalMcp = result.mcpServers.applied.length;
42856
+ const totalNative = result.nativePlugins.installed.length;
42857
+ if (totalSkills === 0 && totalMcp === 0 && totalNative === 0) {
42858
+ retrySpinner.warn(`Plugin "${p.name}" has no portable components to install.`);
42859
+ renderPluginWarnings(result, process.cwd());
42860
+ continue;
42861
+ }
42862
+ retrySpinner.succeed(`Installed plugin ${green(bold(p.name))} ${dim(`v${p.version}`)}`);
42863
+ renderInstalledComponents(result, agentManager12, process.cwd());
42864
+ renderPluginWarnings(result, process.cwd());
42865
+ logger.success("Plugin installation complete.");
42866
+ } catch (retryError) {
42867
+ retrySpinner.fail(`Failed to install plugin ${selectedName}`);
42868
+ logger.error(`Error: ${retryError instanceof Error ? retryError.message : "Unknown error"}`);
42869
+ }
42870
+ }
42871
+ } else {
42872
+ spinner.fail("Failed to install plugin");
42873
+ logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
42789
42874
  }
42790
- } else {
42791
- spinner.fail("Failed to install plugin");
42792
- logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
42793
42875
  }
42794
42876
  }
42795
42877
  });
@@ -42897,22 +42979,6 @@ function registerPluginsCommand(program2) {
42897
42979
  }
42898
42980
  });
42899
42981
  }
42900
- async function selectBundlePlugin2(error, actionLabel) {
42901
- const response = await import_prompts3.default({
42902
- type: "select",
42903
- name: "plugin",
42904
- message: `This repository contains multiple plugins. Select one to ${actionLabel}:`,
42905
- choices: error.entries.map((entry) => ({
42906
- title: entry.name,
42907
- value: entry.name
42908
- }))
42909
- });
42910
- if (!response.plugin) {
42911
- logger.info("Cancelled.");
42912
- return null;
42913
- }
42914
- return response.plugin;
42915
- }
42916
42982
  var formatPathForDisplay = function(pathValue, projectPath) {
42917
42983
  if (pathValue.startsWith(`${projectPath}/`)) {
42918
42984
  return relative8(projectPath, pathValue) || ".";
@@ -42926,16 +42992,48 @@ var formatPathForDisplay = function(pathValue, projectPath) {
42926
42992
  var getAgentLabel = function(agentIds, agentManager12) {
42927
42993
  return agentIds.map((agentId) => agentManager12.getAgentById(agentId)?.name || agentId).join(", ");
42928
42994
  };
42995
+ var buildPluginSelectionPreview = function(previews) {
42996
+ const nativeAgentIds = new Set;
42997
+ const nativeFeatures = new Set;
42998
+ const nativeInstallPaths = new Set;
42999
+ for (const preview of previews) {
43000
+ if (!preview.nativePreview) {
43001
+ continue;
43002
+ }
43003
+ nativeAgentIds.add(preview.nativePreview.agent);
43004
+ nativeInstallPaths.add(preview.nativePreview.installPath);
43005
+ for (const feature of preview.nativePreview.features) {
43006
+ nativeFeatures.add(feature);
43007
+ }
43008
+ }
43009
+ return {
43010
+ selectedCount: previews.length,
43011
+ skillCount: previews.reduce((total, preview) => total + preview.plugin.skills.length, 0),
43012
+ mcpServerCount: previews.reduce((total, preview) => total + preview.plugin.mcpServers.length, 0),
43013
+ nativeAgentIds: [...nativeAgentIds],
43014
+ nativeFeatures: [...nativeFeatures],
43015
+ nativeInstallPaths: [...nativeInstallPaths]
43016
+ };
43017
+ };
42929
43018
  var getPortableComponentSummary = function(preview) {
42930
43019
  const parts = [];
42931
- if (preview.plugin.skills.length > 0) {
42932
- parts.push(`${preview.plugin.skills.length} skill(s)`);
43020
+ if (preview.skillCount > 0) {
43021
+ parts.push(`${preview.skillCount} skill(s)`);
42933
43022
  }
42934
- if (preview.plugin.mcpServers.length > 0) {
42935
- parts.push(`${preview.plugin.mcpServers.length} MCP server(s)`);
43023
+ if (preview.mcpServerCount > 0) {
43024
+ parts.push(`${preview.mcpServerCount} MCP server(s)`);
42936
43025
  }
42937
43026
  return parts.length > 0 ? parts.join(", ") : "No portable components";
42938
43027
  };
43028
+ var renderPreparedPluginWarnings = function(previews, projectPath) {
43029
+ for (const preview of previews) {
43030
+ if (previews.length > 1) {
43031
+ console.log("");
43032
+ logger.info(`${bold(preview.plugin.name)} ${dim(`v${preview.plugin.version}`)}`);
43033
+ }
43034
+ renderPluginWarnings(preview, projectPath);
43035
+ }
43036
+ };
42939
43037
  var getSourceWarnings = function(warnings) {
42940
43038
  const items = [];
42941
43039
  for (const warning of warnings) {
@@ -43178,31 +43276,35 @@ var shouldPreselectPluginGroup = function(group, installGlobal, preview) {
43178
43276
  if (group.kind === "canonical-shared") {
43179
43277
  return true;
43180
43278
  }
43181
- if (preview.nativePreview) {
43182
- return group.agents.some((agent) => agent.id === preview.nativePreview?.agent);
43279
+ if (preview.nativeAgentIds.length > 0) {
43280
+ return group.agents.some((agent) => preview.nativeAgentIds.includes(agent.id));
43183
43281
  }
43184
43282
  return false;
43185
43283
  };
43186
43284
  var getPluginGroupDescription = function(group, preview, projectPath) {
43187
43285
  const portableSummary = getPortableComponentSummary(preview);
43188
- if (!preview.nativePreview) {
43286
+ if (preview.nativeAgentIds.length === 0) {
43189
43287
  return portableSummary;
43190
43288
  }
43191
- const containsClaudeCode = group.agents.some((agent) => agent.id === "claude");
43289
+ const containsClaudeCode = group.agents.some((agent) => preview.nativeAgentIds.includes(agent.id));
43192
43290
  if (!containsClaudeCode) {
43193
- return `${portableSummary}. Skills will be installed here, but Claude-specific components will not be fully available for these agents.`;
43291
+ return `${portableSummary}. Some selected plugins also include Claude-specific components that will not be fully available for these agents.`;
43194
43292
  }
43195
- const otherAgents = group.agents.filter((agent) => agent.id !== "claude").map((agent) => agent.name);
43196
- const installPath = formatPathForDisplay(preview.nativePreview.installPath, projectPath);
43293
+ const otherAgents = group.agents.filter((agent) => !preview.nativeAgentIds.includes(agent.id)).map((agent) => agent.name);
43294
+ const installPath = preview.nativeInstallPaths.length === 1 ? formatPathForDisplay(preview.nativeInstallPaths[0], projectPath) : `~/.claude/plugins (${preview.nativeInstallPaths.length} plugin-specific install paths)`;
43295
+ const nativeSummary = preview.nativeFeatures.length > 0 ? ` Native components: ${preview.nativeFeatures.join(", ")}.` : "";
43197
43296
  if (otherAgents.length === 0) {
43198
- return `${portableSummary}. Full plugin support is available in Claude Code; the native plugin installs at ${installPath}.`;
43297
+ return `${portableSummary}. Full plugin support is available in Claude Code; native components install at ${installPath}.${nativeSummary}`;
43199
43298
  }
43200
43299
  const otherAgentsLabel = otherAgents.join(", ");
43201
43300
  const shareVerb = otherAgents.length === 1 ? "shares" : "share";
43202
43301
  const receiveVerb = otherAgents.length === 1 ? "receives" : "receive";
43203
- return `${portableSummary}. Full plugin support is available in Claude Code; the native plugin installs at ${installPath}. ${otherAgentsLabel} ${shareVerb} this skills directory but only ${receiveVerb} the installed skills.`;
43302
+ return `${portableSummary}. Full plugin support is available in Claude Code; native components install at ${installPath}.${nativeSummary} ${otherAgentsLabel} ${shareVerb} this skills directory but only ${receiveVerb} the installed skills.`;
43204
43303
  };
43205
43304
  async function interactiveAgentSelect(pluginManager3, agentManager12, projectPath, global3, preview) {
43305
+ if (!preview) {
43306
+ return { aborted: true };
43307
+ }
43206
43308
  let installGlobal = !!global3;
43207
43309
  let groups = installGlobal ? buildGlobalPluginGroups(agentManager12, projectPath) : (await pluginManager3.groupAgentsBySkillsDir(projectPath, false)).map((group) => ({
43208
43310
  ...group,
@@ -43210,7 +43312,7 @@ async function interactiveAgentSelect(pluginManager3, agentManager12, projectPat
43210
43312
  }));
43211
43313
  if (groups.length === 0 && !installGlobal) {
43212
43314
  logger.warn("No agents with skills support detected in this project.");
43213
- const scopeResponse = await import_prompts3.default({
43315
+ const scopeResponse = await import_prompts4.default({
43214
43316
  type: "select",
43215
43317
  name: "scope",
43216
43318
  message: "Install this plugin globally instead?",
@@ -43236,11 +43338,9 @@ async function interactiveAgentSelect(pluginManager3, agentManager12, projectPat
43236
43338
  logger.warn("No supported agents expose a skills directory.");
43237
43339
  return { aborted: true };
43238
43340
  }
43239
- const response = await import_prompts3.default({
43240
- type: "multiselect",
43341
+ const response = await promptMultiselect({
43241
43342
  name: "groups",
43242
43343
  message: installGlobal ? "Select which global agents should receive this plugin:" : "Select which agents should receive this plugin:",
43243
- instructions: false,
43244
43344
  min: 1,
43245
43345
  choices: groups.map((group) => {
43246
43346
  const compatible = group.compatibleAgentNames.length > 0 ? dim(` (also compatible: ${group.compatibleAgentNames.join(", ")})`) : "";