agentinit 1.17.0 → 1.17.2

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
@@ -17055,6 +17055,11 @@ __export(exports_pluginManager, {
17055
17055
  return PluginManager;
17056
17056
  }
17057
17057
  },
17058
+ MultipleBundlePluginsError: () => {
17059
+ {
17060
+ return MultipleBundlePluginsError;
17061
+ }
17062
+ },
17058
17063
  MarketplacePluginNotFoundError: () => {
17059
17064
  {
17060
17065
  return MarketplacePluginNotFoundError;
@@ -17065,6 +17070,16 @@ import {resolve as resolve7, join as join4, basename as basename2, relative as r
17065
17070
  import {promises as fs22} from "fs";
17066
17071
  import {homedir as homedir4} from "os";
17067
17072
 
17073
+ class MultipleBundlePluginsError extends Error {
17074
+ entries;
17075
+ constructor(pluginDir, entries) {
17076
+ const names = entries.map((e) => e.name).join(", ");
17077
+ super(`Repository "${pluginDir}" is a Claude marketplace bundle with multiple plugins. Select one of: ${names}.`);
17078
+ this.name = "MultipleBundlePluginsError";
17079
+ this.entries = entries;
17080
+ }
17081
+ }
17082
+
17068
17083
  class MarketplacePluginNotFoundError extends Error {
17069
17084
  pluginName;
17070
17085
  marketplaceId;
@@ -17189,7 +17204,11 @@ class PluginManager {
17189
17204
  } catch {
17190
17205
  throw new Error(`Invalid .claude-plugin/marketplace.json in ${pluginDir}`);
17191
17206
  }
17192
- 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
+ })) : [];
17193
17212
  if (entries.length === 0) {
17194
17213
  throw new Error(`No plugins declared in .claude-plugin/marketplace.json for ${pluginDir}`);
17195
17214
  }
@@ -17202,7 +17221,7 @@ class PluginManager {
17202
17221
  const candidates = new Set([source.pluginName, source.repo].filter((value) => !!value).flatMap((value) => [value, basename2(value)]));
17203
17222
  const matched = entries.find((entry) => candidates.has(entry.name) || candidates.has(basename2(entry.source)));
17204
17223
  if (!matched) {
17205
- throw new Error(`Repository "${pluginDir}" is a Claude marketplace bundle with multiple plugins. Select one of: ${entries.map((entry) => entry.name).join(", ")}.`);
17224
+ throw new MultipleBundlePluginsError(pluginDir, entries);
17206
17225
  }
17207
17226
  selectedEntry = matched;
17208
17227
  }
@@ -17279,6 +17298,9 @@ class PluginManager {
17279
17298
  throw new Error(`Local path not found: ${pluginDir}`);
17280
17299
  }
17281
17300
  }
17301
+ if (options2.pluginName) {
17302
+ effectiveSource = { ...effectiveSource, pluginName: options2.pluginName };
17303
+ }
17282
17304
  return {
17283
17305
  plugin: await this.loadPluginFromDirectory(pluginDir, effectiveSource, resolutionWarnings),
17284
17306
  effectiveSource,
@@ -18118,7 +18140,10 @@ ${body.trim()}
18118
18140
  };
18119
18141
  }
18120
18142
  async installPlugin(source, projectPath, options2 = {}) {
18121
- const context = this.takePreparedInstallContext(source, options2.from) || await this.loadPluginContext(source, { from: options2.from });
18143
+ const context = this.takePreparedInstallContext(source, options2.from) || await this.loadPluginContext(source, {
18144
+ from: options2.from,
18145
+ ...options2.pluginName ? { pluginName: options2.pluginName } : {}
18146
+ });
18122
18147
  try {
18123
18148
  const plugin = context.plugin;
18124
18149
  if (options2.list) {
@@ -18748,12 +18773,13 @@ class SkillsManager {
18748
18773
  const marketplaceHints = marketplaces.length > 0 ? ` If you meant a marketplace skill, use "${marketplaces[0]}/${normalizedSource}" or "--from ${marketplaces[0]}".` : "";
18749
18774
  return new Error(`Local path not found: ${resolvedPath}. If you meant a local path, prefix it with "./".${marketplaceHints}`);
18750
18775
  }
18751
- async discoverMarketplaceSkills(source, projectPath) {
18776
+ async discoverMarketplaceSkills(source, projectPath, pluginName) {
18752
18777
  const { PluginManager: PluginManager2 } = await Promise.resolve().then(() => (init_pluginManager(), exports_pluginManager));
18753
18778
  const pluginManager = new PluginManager2(this.agentManager);
18754
18779
  const result = await pluginManager.installPlugin(source.pluginName || this.getMarketplaceSourceId(source), projectPath, {
18755
18780
  from: source.marketplace,
18756
- list: true
18781
+ list: true,
18782
+ ...pluginName ? { pluginName } : {}
18757
18783
  });
18758
18784
  const warnings = [...result.warnings];
18759
18785
  if (result.plugin.mcpServers.length > 0) {
@@ -18817,6 +18843,9 @@ class SkillsManager {
18817
18843
  async loadDiscoveredSkillsContext(source, projectPath, options2 = {}) {
18818
18844
  const request = this.resolveSourceRequest(source, options2);
18819
18845
  const resolved = request.source;
18846
+ if (options2.pluginName && resolved.type !== "marketplace") {
18847
+ resolved.pluginName = options2.pluginName;
18848
+ }
18820
18849
  let tempDir = null;
18821
18850
  const cleanup = async () => {
18822
18851
  await this.cleanupTempDir(tempDir);
@@ -18824,7 +18853,7 @@ class SkillsManager {
18824
18853
  };
18825
18854
  try {
18826
18855
  if (resolved.type === "marketplace") {
18827
- const discovered = await this.discoverMarketplaceSkills(resolved, projectPath);
18856
+ const discovered = await this.discoverMarketplaceSkills(resolved, projectPath, options2.pluginName);
18828
18857
  return {
18829
18858
  ...discovered,
18830
18859
  cleanup
@@ -19093,7 +19122,8 @@ class SkillsManager {
19093
19122
  }
19094
19123
  async addFromSource(source, projectPath, options2 = {}) {
19095
19124
  const context = this.takePreparedSourceContext(source, projectPath, options2.from) || await this.loadDiscoveredSkillsContext(source, projectPath, {
19096
- ...options2.from !== undefined ? { from: options2.from } : {}
19125
+ ...options2.from !== undefined ? { from: options2.from } : {},
19126
+ ...options2.pluginName !== undefined ? { pluginName: options2.pluginName } : {}
19097
19127
  });
19098
19128
  try {
19099
19129
  let skills2 = context.skills;
@@ -41199,6 +41229,7 @@ var import_prompts2 = __toESM(require_prompts3(), 1);
41199
41229
  import {homedir as homedir6} from "os";
41200
41230
  import {relative as relative7, resolve as resolve12} from "path";
41201
41231
  init_skillsManager();
41232
+ init_pluginManager();
41202
41233
  init_marketplaceRegistry();
41203
41234
  init_agentManager();
41204
41235
  init_skills();
@@ -41210,29 +41241,73 @@ function registerSkillsCommand(program2) {
41210
41241
  const agentManager9 = new AgentManager;
41211
41242
  const skillsManager5 = new SkillsManager(agentManager9);
41212
41243
  if (options2.list) {
41213
- const spinner2 = ora("Discovering skills...").start();
41244
+ const spinner = ora("Discovering skills...").start();
41214
41245
  try {
41215
41246
  const result = await skillsManager5.discoverFromSource(source, process.cwd(), {
41216
41247
  from: options2.from
41217
41248
  });
41218
- spinner2.stop();
41249
+ spinner.stop();
41219
41250
  displayDiscoveredSkills(result.skills, result.warnings);
41220
41251
  } catch (error) {
41221
- spinner2.fail("Failed to discover skills");
41222
- logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
41252
+ if (error instanceof MultipleBundlePluginsError) {
41253
+ spinner.stop();
41254
+ const selected = await selectBundlePlugins(error, "list");
41255
+ if (!selected) {
41256
+ return;
41257
+ }
41258
+ for (const pluginName of selected) {
41259
+ const retrySpinner = ora(`Discovering skills from ${pluginName}...`).start();
41260
+ try {
41261
+ const result = await skillsManager5.discoverFromSource(source, process.cwd(), {
41262
+ from: options2.from,
41263
+ pluginName
41264
+ });
41265
+ retrySpinner.stop();
41266
+ displayDiscoveredSkills(result.skills, result.warnings);
41267
+ } catch (retryError) {
41268
+ retrySpinner.fail(`Failed to discover skills from ${pluginName}`);
41269
+ logger.error(`Error: ${retryError instanceof Error ? retryError.message : "Unknown error"}`);
41270
+ }
41271
+ }
41272
+ } else {
41273
+ spinner.fail("Failed to discover skills");
41274
+ logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
41275
+ }
41223
41276
  }
41224
41277
  return;
41225
41278
  }
41226
41279
  const verifySpinner = ora("Verifying skill source...").start();
41280
+ let selectedPluginNames;
41227
41281
  try {
41228
41282
  await skillsManager5.prepareSource(source, process.cwd(), {
41229
41283
  from: options2.from
41230
41284
  });
41231
41285
  verifySpinner.stop();
41232
41286
  } catch (error) {
41233
- verifySpinner.fail("Failed to verify skill source");
41234
- logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
41235
- return;
41287
+ if (error instanceof MultipleBundlePluginsError && !options2.yes) {
41288
+ verifySpinner.stop();
41289
+ const selected = await selectBundlePlugins(error, "install");
41290
+ if (!selected) {
41291
+ return;
41292
+ }
41293
+ selectedPluginNames = selected;
41294
+ const retrySpinner = ora("Verifying skill source...").start();
41295
+ try {
41296
+ await skillsManager5.prepareSource(source, process.cwd(), {
41297
+ from: options2.from,
41298
+ ...selectedPluginNames[0] ? { pluginName: selectedPluginNames[0] } : {}
41299
+ });
41300
+ retrySpinner.stop();
41301
+ } catch (retryError) {
41302
+ retrySpinner.fail("Failed to verify skill source");
41303
+ logger.error(`Error: ${retryError instanceof Error ? retryError.message : "Unknown error"}`);
41304
+ return;
41305
+ }
41306
+ } else {
41307
+ verifySpinner.fail("Failed to verify skill source");
41308
+ logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
41309
+ return;
41310
+ }
41236
41311
  }
41237
41312
  let targetAgents = options2.agent;
41238
41313
  let targetGlobal = options2.global;
@@ -41252,21 +41327,31 @@ function registerSkillsCommand(program2) {
41252
41327
  targetGlobal = selection.global;
41253
41328
  }
41254
41329
  }
41255
- const buildInstallOptions = (fromOverride) => ({
41256
- ...fromOverride !== undefined ? { from: fromOverride } : options2.from !== undefined ? { from: options2.from } : {},
41330
+ const buildInstallOptions = (pluginName) => ({
41331
+ ...options2.from !== undefined ? { from: options2.from } : {},
41257
41332
  ...targetGlobal !== undefined ? { global: targetGlobal } : {},
41258
41333
  ...targetAgents !== undefined ? { agents: targetAgents } : {},
41259
41334
  ...options2.skill !== undefined ? { skills: options2.skill } : {},
41260
41335
  ...options2.copy !== undefined ? { copy: options2.copy } : {},
41336
+ ...pluginName !== undefined ? { pluginName } : {},
41261
41337
  ...options2.yes !== undefined ? { yes: options2.yes } : {}
41262
41338
  });
41263
- const spinner = ora("Installing skills...").start();
41264
- try {
41265
- const result = await skillsManager5.addFromSource(source, process.cwd(), buildInstallOptions());
41266
- displayInstallResult(result, spinner, agentManager9, skillsManager5, source, { from: options2.from });
41267
- } catch (error) {
41268
- spinner.fail("Failed to install skills");
41269
- logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
41339
+ const pluginsToInstall = selectedPluginNames || [undefined];
41340
+ for (const pluginName of pluginsToInstall) {
41341
+ const spinner = ora(pluginName ? `Installing skills from ${pluginName}...` : "Installing skills...").start();
41342
+ try {
41343
+ if (pluginName && pluginName !== selectedPluginNames?.[0]) {
41344
+ await skillsManager5.prepareSource(source, process.cwd(), {
41345
+ from: options2.from,
41346
+ pluginName
41347
+ });
41348
+ }
41349
+ const result = await skillsManager5.addFromSource(source, process.cwd(), buildInstallOptions(pluginName));
41350
+ displayInstallResult(result, spinner, agentManager9, skillsManager5, source, { from: options2.from });
41351
+ } catch (error) {
41352
+ spinner.fail(pluginName ? `Failed to install skills from ${pluginName}` : "Failed to install skills");
41353
+ logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
41354
+ }
41270
41355
  }
41271
41356
  });
41272
41357
  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) => {
@@ -41345,6 +41430,26 @@ function registerSkillsCommand(program2) {
41345
41430
  }
41346
41431
  });
41347
41432
  }
41433
+ async function selectBundlePlugins(error, actionLabel) {
41434
+ logger.info(dim("Press Space to select, then Enter to confirm."));
41435
+ const response = await import_prompts2.default({
41436
+ type: "multiselect",
41437
+ name: "plugins",
41438
+ message: `This repository contains multiple plugins. Select which to ${actionLabel}:`,
41439
+ instructions: false,
41440
+ min: 1,
41441
+ choices: error.entries.map((entry) => ({
41442
+ title: entry.name,
41443
+ value: entry.name,
41444
+ ...entry.description ? { description: entry.description } : {}
41445
+ }))
41446
+ });
41447
+ if (!response.plugins || response.plugins.length === 0) {
41448
+ logger.info("Cancelled.");
41449
+ return null;
41450
+ }
41451
+ return response.plugins;
41452
+ }
41348
41453
  async function resolveInteractiveSkillTargets(skillsManager5, agentManager9, source, projectPath, options2) {
41349
41454
  let installGlobal = !!options2.global;
41350
41455
  if (!options2.global) {
@@ -42493,15 +42598,15 @@ function registerPluginsCommand(program2) {
42493
42598
  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) => {
42494
42599
  logger.titleBox("AgentInit Plugins");
42495
42600
  const agentManager12 = new AgentManager;
42496
- const pluginManager2 = new PluginManager(agentManager12);
42601
+ const pluginManager3 = new PluginManager(agentManager12);
42497
42602
  if (options2.list) {
42498
- const spinner2 = ora("Fetching plugin...").start();
42603
+ const spinner = ora("Fetching plugin...").start();
42499
42604
  try {
42500
- const preview2 = await pluginManager2.inspectPlugin(source, {
42605
+ const preview = await pluginManager3.inspectPlugin(source, {
42501
42606
  from: options2.from
42502
42607
  });
42503
- spinner2.stop();
42504
- const p = preview2.plugin;
42608
+ spinner.stop();
42609
+ const p = preview.plugin;
42505
42610
  console.log("");
42506
42611
  logger.info(`${bold(p.name)} ${dim(`v${p.version}`)} ${dim(`[${p.format} format]`)}`);
42507
42612
  if (p.description)
@@ -42522,35 +42627,110 @@ function registerPluginsCommand(program2) {
42522
42627
  if (p.skills.length === 0 && p.mcpServers.length === 0) {
42523
42628
  logger.info(" No portable components found (no skills or MCP servers).");
42524
42629
  }
42525
- renderPluginWarnings(preview2, process.cwd());
42630
+ renderPluginWarnings(preview, process.cwd());
42526
42631
  } catch (error) {
42527
- spinner2.fail("Failed to fetch plugin");
42528
- logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
42632
+ if (error instanceof MultipleBundlePluginsError) {
42633
+ spinner.stop();
42634
+ const selected = await selectBundlePlugins2(error, "preview");
42635
+ if (!selected) {
42636
+ return;
42637
+ }
42638
+ for (const pluginName of selected) {
42639
+ const retrySpinner = ora(`Fetching plugin ${pluginName}...`).start();
42640
+ try {
42641
+ const preview = await pluginManager3.inspectPlugin(source, {
42642
+ from: options2.from,
42643
+ pluginName
42644
+ });
42645
+ retrySpinner.stop();
42646
+ const p = preview.plugin;
42647
+ console.log("");
42648
+ logger.info(`${bold(p.name)} ${dim(`v${p.version}`)} ${dim(`[${p.format} format]`)}`);
42649
+ if (p.description)
42650
+ logger.info(` ${p.description}`);
42651
+ console.log("");
42652
+ if (p.skills.length > 0) {
42653
+ logger.info(` ${green("Skills")} (${p.skills.length}):`);
42654
+ for (const skill of p.skills) {
42655
+ logger.info(` ${green(skill.name)} - ${skill.description}`);
42656
+ }
42657
+ }
42658
+ if (p.mcpServers.length > 0) {
42659
+ logger.info(` ${cyan("MCP Servers")} (${p.mcpServers.length}):`);
42660
+ for (const mcp of p.mcpServers) {
42661
+ logger.info(` ${cyan(mcp.name)} [${mcp.type}]`);
42662
+ }
42663
+ }
42664
+ if (p.skills.length === 0 && p.mcpServers.length === 0) {
42665
+ logger.info(" No portable components found (no skills or MCP servers).");
42666
+ }
42667
+ renderPluginWarnings(preview, process.cwd());
42668
+ } catch (retryError) {
42669
+ retrySpinner.fail(`Failed to fetch plugin ${pluginName}`);
42670
+ logger.error(`Error: ${retryError instanceof Error ? retryError.message : "Unknown error"}`);
42671
+ }
42672
+ }
42673
+ } else {
42674
+ spinner.fail("Failed to fetch plugin");
42675
+ logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
42676
+ }
42529
42677
  }
42530
42678
  return;
42531
42679
  }
42532
42680
  let agentIds = options2.agent;
42533
42681
  let targetGlobal = options2.global;
42534
- let preview = null;
42682
+ let selectionPreview = null;
42535
42683
  let previewRendered = false;
42684
+ let selectedPluginNames;
42536
42685
  if (!agentIds && !options2.yes) {
42537
42686
  const previewSpinner = ora("Inspecting plugin...").start();
42538
42687
  try {
42539
- preview = await pluginManager2.preparePluginInstall(source, {
42688
+ const preview = await pluginManager3.preparePluginInstall(source, {
42540
42689
  from: options2.from
42541
42690
  });
42542
42691
  previewSpinner.stop();
42543
- renderPluginWarnings(preview, process.cwd());
42692
+ selectionPreview = buildPluginSelectionPreview([preview]);
42693
+ renderPreparedPluginWarnings([preview], process.cwd());
42544
42694
  previewRendered = true;
42545
42695
  } catch (error) {
42546
- previewSpinner.fail("Failed to inspect plugin");
42547
- logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
42548
- return;
42696
+ if (error instanceof MultipleBundlePluginsError) {
42697
+ previewSpinner.stop();
42698
+ const selected = await selectBundlePlugins2(error, "install");
42699
+ if (!selected) {
42700
+ return;
42701
+ }
42702
+ selectedPluginNames = selected;
42703
+ const retrySpinner = ora("Inspecting plugin...").start();
42704
+ try {
42705
+ const previewsByPlugin = new Map;
42706
+ const previewOrder = selectedPluginNames.length > 1 ? [...selectedPluginNames.slice(1), selectedPluginNames[0]] : selectedPluginNames;
42707
+ for (const pluginName of previewOrder) {
42708
+ const preparedPreview = await pluginManager3.preparePluginInstall(source, {
42709
+ from: options2.from,
42710
+ pluginName
42711
+ });
42712
+ previewsByPlugin.set(pluginName, preparedPreview);
42713
+ }
42714
+ const previews = selectedPluginNames.map((pluginName) => previewsByPlugin.get(pluginName)).filter((value) => !!value);
42715
+ retrySpinner.stop();
42716
+ selectionPreview = buildPluginSelectionPreview(previews);
42717
+ renderPreparedPluginWarnings(previews, process.cwd());
42718
+ previewRendered = true;
42719
+ } catch (retryError) {
42720
+ retrySpinner.fail("Failed to inspect plugin");
42721
+ logger.error(`Error: ${retryError instanceof Error ? retryError.message : "Unknown error"}`);
42722
+ return;
42723
+ }
42724
+ } else {
42725
+ previewSpinner.fail("Failed to inspect plugin");
42726
+ logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
42727
+ return;
42728
+ }
42549
42729
  }
42550
42730
  try {
42551
- const selection = await interactiveAgentSelect(pluginManager2, agentManager12, process.cwd(), targetGlobal, preview);
42731
+ const selection = await interactiveAgentSelect(pluginManager3, agentManager12, process.cwd(), targetGlobal, selectionPreview);
42552
42732
  if (!selection || selection.aborted || !selection.agents || selection.agents.length === 0) {
42553
- await pluginManager2.discardPreparedPlugin(source, { from: options2.from });
42733
+ await pluginManager3.discardPreparedPlugin(source, { from: options2.from });
42554
42734
  logger.info("No agents selected. Aborting.");
42555
42735
  return;
42556
42736
  }
@@ -42563,52 +42743,99 @@ function registerPluginsCommand(program2) {
42563
42743
  }
42564
42744
  }
42565
42745
  }
42566
- const spinner = ora("Installing plugin...").start();
42567
- try {
42568
- const result = await pluginManager2.installPlugin(source, process.cwd(), {
42569
- from: options2.from,
42570
- agents: agentIds,
42571
- global: targetGlobal,
42572
- copySkills: options2.copySkills,
42573
- yes: options2.yes
42574
- });
42575
- const p = result.plugin;
42576
- const totalSkills = result.skills.installed.length;
42577
- const totalMcp = result.mcpServers.applied.length;
42578
- const totalNative = result.nativePlugins.installed.length;
42579
- if (totalSkills === 0 && totalMcp === 0 && totalNative === 0) {
42580
- spinner.warn(`Plugin "${p.name}" has no portable components to install.`);
42581
- if (!previewRendered) {
42582
- renderPluginWarnings(result, process.cwd());
42746
+ const pluginsToInstall = selectedPluginNames || [undefined];
42747
+ for (const pluginName of pluginsToInstall) {
42748
+ const spinner = ora(pluginName ? `Installing plugin ${pluginName}...` : "Installing plugin...").start();
42749
+ try {
42750
+ if (pluginName && pluginName !== selectedPluginNames?.[0]) {
42751
+ await pluginManager3.preparePluginInstall(source, {
42752
+ from: options2.from,
42753
+ pluginName
42754
+ });
42583
42755
  }
42584
- return;
42585
- }
42586
- spinner.succeed(`Installed plugin ${green(bold(p.name))} ${dim(`v${p.version}`)}`);
42587
- renderInstalledComponents(result, agentManager12, process.cwd());
42588
- if (result.skills.skipped.length > 0 || result.mcpServers.skipped.length > 0 || result.nativePlugins.skipped.length > 0) {
42589
- console.log("");
42590
- for (const s of result.skills.skipped) {
42591
- logger.debug(`Skipped skill ${s.name}: ${s.reason}`);
42756
+ const result = await pluginManager3.installPlugin(source, process.cwd(), {
42757
+ from: options2.from,
42758
+ agents: agentIds,
42759
+ global: targetGlobal,
42760
+ copySkills: options2.copySkills,
42761
+ yes: options2.yes,
42762
+ ...pluginName ? { pluginName } : {}
42763
+ });
42764
+ const p = result.plugin;
42765
+ const totalSkills = result.skills.installed.length;
42766
+ const totalMcp = result.mcpServers.applied.length;
42767
+ const totalNative = result.nativePlugins.installed.length;
42768
+ if (totalSkills === 0 && totalMcp === 0 && totalNative === 0) {
42769
+ spinner.warn(`Plugin "${p.name}" has no portable components to install.`);
42770
+ if (!previewRendered) {
42771
+ renderPluginWarnings(result, process.cwd());
42772
+ }
42773
+ continue;
42592
42774
  }
42593
- for (const s of result.mcpServers.skipped) {
42594
- logger.debug(`Skipped MCP ${s.name}: ${s.reason}`);
42775
+ spinner.succeed(`Installed plugin ${green(bold(p.name))} ${dim(`v${p.version}`)}`);
42776
+ renderInstalledComponents(result, agentManager12, process.cwd());
42777
+ if (result.skills.skipped.length > 0 || result.mcpServers.skipped.length > 0 || result.nativePlugins.skipped.length > 0) {
42778
+ console.log("");
42779
+ for (const s of result.skills.skipped) {
42780
+ logger.debug(`Skipped skill ${s.name}: ${s.reason}`);
42781
+ }
42782
+ for (const s of result.mcpServers.skipped) {
42783
+ logger.debug(`Skipped MCP ${s.name}: ${s.reason}`);
42784
+ }
42785
+ for (const s of result.nativePlugins.skipped) {
42786
+ logger.warn(`Skipped native plugin payload for ${s.agent}: ${s.reason}`);
42787
+ }
42595
42788
  }
42596
- for (const s of result.nativePlugins.skipped) {
42597
- logger.warn(`Skipped native plugin payload for ${s.agent}: ${s.reason}`);
42789
+ if (!previewRendered) {
42790
+ renderPluginWarnings(result, process.cwd());
42791
+ }
42792
+ logger.success("Plugin installation complete.");
42793
+ } catch (error) {
42794
+ if (error instanceof MultipleBundlePluginsError && !options2.yes) {
42795
+ spinner.stop();
42796
+ const selected = await selectBundlePlugins2(error, "install");
42797
+ if (!selected) {
42798
+ return;
42799
+ }
42800
+ for (const selectedName of selected) {
42801
+ const retrySpinner = ora(`Installing plugin ${selectedName}...`).start();
42802
+ try {
42803
+ const result = await pluginManager3.installPlugin(source, process.cwd(), {
42804
+ from: options2.from,
42805
+ agents: agentIds,
42806
+ global: targetGlobal,
42807
+ copySkills: options2.copySkills,
42808
+ yes: options2.yes,
42809
+ pluginName: selectedName
42810
+ });
42811
+ const p = result.plugin;
42812
+ const totalSkills = result.skills.installed.length;
42813
+ const totalMcp = result.mcpServers.applied.length;
42814
+ const totalNative = result.nativePlugins.installed.length;
42815
+ if (totalSkills === 0 && totalMcp === 0 && totalNative === 0) {
42816
+ retrySpinner.warn(`Plugin "${p.name}" has no portable components to install.`);
42817
+ renderPluginWarnings(result, process.cwd());
42818
+ continue;
42819
+ }
42820
+ retrySpinner.succeed(`Installed plugin ${green(bold(p.name))} ${dim(`v${p.version}`)}`);
42821
+ renderInstalledComponents(result, agentManager12, process.cwd());
42822
+ renderPluginWarnings(result, process.cwd());
42823
+ logger.success("Plugin installation complete.");
42824
+ } catch (retryError) {
42825
+ retrySpinner.fail(`Failed to install plugin ${selectedName}`);
42826
+ logger.error(`Error: ${retryError instanceof Error ? retryError.message : "Unknown error"}`);
42827
+ }
42828
+ }
42829
+ } else {
42830
+ spinner.fail("Failed to install plugin");
42831
+ logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
42598
42832
  }
42599
42833
  }
42600
- if (!previewRendered) {
42601
- renderPluginWarnings(result, process.cwd());
42602
- }
42603
- logger.success("Plugin installation complete.");
42604
- } catch (error) {
42605
- spinner.fail("Failed to install plugin");
42606
- logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
42607
42834
  }
42608
42835
  });
42609
42836
  plugins.command("search [query]").description("Search marketplace plugins").option("--from <marketplace>", `Which marketplace to search (available: ${marketplaceHelp})`).option("--category <category>", `Filter by marketplace category (examples: ${marketplaceCategoryHelp})`).action(async (query, options2) => {
42610
42837
  logger.titleBox("AgentInit Plugin Search");
42611
- const pluginManager2 = new PluginManager;
42838
+ const pluginManager3 = new PluginManager;
42612
42839
  const registryId = options2.from || getConfiguredDefaultMarketplaceId();
42613
42840
  if (!registryId) {
42614
42841
  logger.info(`Please specify a marketplace with --from <marketplace>. Available: ${marketplaceHelp}`);
@@ -42619,7 +42846,7 @@ function registerPluginsCommand(program2) {
42619
42846
  }
42620
42847
  const spinner = ora(`Fetching ${registryId} marketplace...`).start();
42621
42848
  try {
42622
- const results = await pluginManager2.listMarketplacePlugins(registryId, query, options2.category);
42849
+ const results = await pluginManager3.listMarketplacePlugins(registryId, query, options2.category);
42623
42850
  spinner.stop();
42624
42851
  if (results.length === 0) {
42625
42852
  logger.info(query ? `No plugins matching "${query}".` : "No plugins found.");
@@ -42649,8 +42876,8 @@ function registerPluginsCommand(program2) {
42649
42876
  });
42650
42877
  plugins.command("list").alias("ls").description("List installed plugins").option("-a, --agent <agents...>", "Filter by specific agent(s)").option("-g, --global", "List global plugins").action(async (options2) => {
42651
42878
  logger.titleBox("AgentInit Installed Plugins");
42652
- const pluginManager2 = new PluginManager;
42653
- const installed = await pluginManager2.listPlugins(process.cwd(), {
42879
+ const pluginManager3 = new PluginManager;
42880
+ const installed = await pluginManager3.listPlugins(process.cwd(), {
42654
42881
  global: options2.global,
42655
42882
  agents: options2.agent
42656
42883
  });
@@ -42685,10 +42912,10 @@ function registerPluginsCommand(program2) {
42685
42912
  });
42686
42913
  plugins.command("remove <name>").alias("rm").description("Remove an installed plugin").option("-a, --agent <agents...>", "Target specific agent(s)").option("-g, --global", "Remove from global scope").option("-y, --yes", "Skip confirmation prompts").action(async (name, options2) => {
42687
42914
  logger.titleBox("AgentInit Remove Plugin");
42688
- const pluginManager2 = new PluginManager;
42915
+ const pluginManager3 = new PluginManager;
42689
42916
  const spinner = ora(`Removing plugin "${name}"...`).start();
42690
42917
  try {
42691
- const result = await pluginManager2.removePlugin(name, process.cwd(), {
42918
+ const result = await pluginManager3.removePlugin(name, process.cwd(), {
42692
42919
  global: options2.global,
42693
42920
  agents: options2.agent,
42694
42921
  yes: options2.yes
@@ -42710,6 +42937,26 @@ function registerPluginsCommand(program2) {
42710
42937
  }
42711
42938
  });
42712
42939
  }
42940
+ async function selectBundlePlugins2(error, actionLabel) {
42941
+ logger.info(dim("Press Space to select, then Enter to confirm."));
42942
+ const response = await import_prompts3.default({
42943
+ type: "multiselect",
42944
+ name: "plugins",
42945
+ message: `This repository contains multiple plugins. Select which to ${actionLabel}:`,
42946
+ instructions: false,
42947
+ min: 1,
42948
+ choices: error.entries.map((entry) => ({
42949
+ title: entry.name,
42950
+ value: entry.name,
42951
+ ...entry.description ? { description: entry.description } : {}
42952
+ }))
42953
+ });
42954
+ if (!response.plugins || response.plugins.length === 0) {
42955
+ logger.info("Cancelled.");
42956
+ return null;
42957
+ }
42958
+ return response.plugins;
42959
+ }
42713
42960
  var formatPathForDisplay = function(pathValue, projectPath) {
42714
42961
  if (pathValue.startsWith(`${projectPath}/`)) {
42715
42962
  return relative8(projectPath, pathValue) || ".";
@@ -42723,16 +42970,48 @@ var formatPathForDisplay = function(pathValue, projectPath) {
42723
42970
  var getAgentLabel = function(agentIds, agentManager12) {
42724
42971
  return agentIds.map((agentId) => agentManager12.getAgentById(agentId)?.name || agentId).join(", ");
42725
42972
  };
42973
+ var buildPluginSelectionPreview = function(previews) {
42974
+ const nativeAgentIds = new Set;
42975
+ const nativeFeatures = new Set;
42976
+ const nativeInstallPaths = new Set;
42977
+ for (const preview of previews) {
42978
+ if (!preview.nativePreview) {
42979
+ continue;
42980
+ }
42981
+ nativeAgentIds.add(preview.nativePreview.agent);
42982
+ nativeInstallPaths.add(preview.nativePreview.installPath);
42983
+ for (const feature of preview.nativePreview.features) {
42984
+ nativeFeatures.add(feature);
42985
+ }
42986
+ }
42987
+ return {
42988
+ selectedCount: previews.length,
42989
+ skillCount: previews.reduce((total, preview) => total + preview.plugin.skills.length, 0),
42990
+ mcpServerCount: previews.reduce((total, preview) => total + preview.plugin.mcpServers.length, 0),
42991
+ nativeAgentIds: [...nativeAgentIds],
42992
+ nativeFeatures: [...nativeFeatures],
42993
+ nativeInstallPaths: [...nativeInstallPaths]
42994
+ };
42995
+ };
42726
42996
  var getPortableComponentSummary = function(preview) {
42727
42997
  const parts = [];
42728
- if (preview.plugin.skills.length > 0) {
42729
- parts.push(`${preview.plugin.skills.length} skill(s)`);
42998
+ if (preview.skillCount > 0) {
42999
+ parts.push(`${preview.skillCount} skill(s)`);
42730
43000
  }
42731
- if (preview.plugin.mcpServers.length > 0) {
42732
- parts.push(`${preview.plugin.mcpServers.length} MCP server(s)`);
43001
+ if (preview.mcpServerCount > 0) {
43002
+ parts.push(`${preview.mcpServerCount} MCP server(s)`);
42733
43003
  }
42734
43004
  return parts.length > 0 ? parts.join(", ") : "No portable components";
42735
43005
  };
43006
+ var renderPreparedPluginWarnings = function(previews, projectPath) {
43007
+ for (const preview of previews) {
43008
+ if (previews.length > 1) {
43009
+ console.log("");
43010
+ logger.info(`${bold(preview.plugin.name)} ${dim(`v${preview.plugin.version}`)}`);
43011
+ }
43012
+ renderPluginWarnings(preview, projectPath);
43013
+ }
43014
+ };
42736
43015
  var getSourceWarnings = function(warnings) {
42737
43016
  const items = [];
42738
43017
  for (const warning of warnings) {
@@ -42975,33 +43254,37 @@ var shouldPreselectPluginGroup = function(group, installGlobal, preview) {
42975
43254
  if (group.kind === "canonical-shared") {
42976
43255
  return true;
42977
43256
  }
42978
- if (preview.nativePreview) {
42979
- return group.agents.some((agent) => agent.id === preview.nativePreview?.agent);
43257
+ if (preview.nativeAgentIds.length > 0) {
43258
+ return group.agents.some((agent) => preview.nativeAgentIds.includes(agent.id));
42980
43259
  }
42981
43260
  return false;
42982
43261
  };
42983
43262
  var getPluginGroupDescription = function(group, preview, projectPath) {
42984
43263
  const portableSummary = getPortableComponentSummary(preview);
42985
- if (!preview.nativePreview) {
43264
+ if (preview.nativeAgentIds.length === 0) {
42986
43265
  return portableSummary;
42987
43266
  }
42988
- const containsClaudeCode = group.agents.some((agent) => agent.id === "claude");
43267
+ const containsClaudeCode = group.agents.some((agent) => preview.nativeAgentIds.includes(agent.id));
42989
43268
  if (!containsClaudeCode) {
42990
- return `${portableSummary}. Skills will be installed here, but Claude-specific components will not be fully available for these agents.`;
43269
+ return `${portableSummary}. Some selected plugins also include Claude-specific components that will not be fully available for these agents.`;
42991
43270
  }
42992
- const otherAgents = group.agents.filter((agent) => agent.id !== "claude").map((agent) => agent.name);
42993
- const installPath = formatPathForDisplay(preview.nativePreview.installPath, projectPath);
43271
+ const otherAgents = group.agents.filter((agent) => !preview.nativeAgentIds.includes(agent.id)).map((agent) => agent.name);
43272
+ const installPath = preview.nativeInstallPaths.length === 1 ? formatPathForDisplay(preview.nativeInstallPaths[0], projectPath) : `~/.claude/plugins (${preview.nativeInstallPaths.length} plugin-specific install paths)`;
43273
+ const nativeSummary = preview.nativeFeatures.length > 0 ? ` Native components: ${preview.nativeFeatures.join(", ")}.` : "";
42994
43274
  if (otherAgents.length === 0) {
42995
- return `${portableSummary}. Full plugin support is available in Claude Code; the native plugin installs at ${installPath}.`;
43275
+ return `${portableSummary}. Full plugin support is available in Claude Code; native components install at ${installPath}.${nativeSummary}`;
42996
43276
  }
42997
43277
  const otherAgentsLabel = otherAgents.join(", ");
42998
43278
  const shareVerb = otherAgents.length === 1 ? "shares" : "share";
42999
43279
  const receiveVerb = otherAgents.length === 1 ? "receives" : "receive";
43000
- 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.`;
43280
+ 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.`;
43001
43281
  };
43002
- async function interactiveAgentSelect(pluginManager2, agentManager12, projectPath, global3, preview) {
43282
+ async function interactiveAgentSelect(pluginManager3, agentManager12, projectPath, global3, preview) {
43283
+ if (!preview) {
43284
+ return { aborted: true };
43285
+ }
43003
43286
  let installGlobal = !!global3;
43004
- let groups = installGlobal ? buildGlobalPluginGroups(agentManager12, projectPath) : (await pluginManager2.groupAgentsBySkillsDir(projectPath, false)).map((group) => ({
43287
+ let groups = installGlobal ? buildGlobalPluginGroups(agentManager12, projectPath) : (await pluginManager3.groupAgentsBySkillsDir(projectPath, false)).map((group) => ({
43005
43288
  ...group,
43006
43289
  displayDir: group.dir
43007
43290
  }));