agentinit 1.16.2 → 1.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -16945,6 +16945,13 @@ var init_marketplaceRegistry = __esm(() => {
16945
16945
  CUSTOM_MARKETPLACE_CACHE_TTL_MS = 3600000;
16946
16946
  });
16947
16947
 
16948
+ // dist/types/skills.js
16949
+ var SHARED_SKILLS_TARGET_ID, SHARED_SKILLS_TARGET_NAME;
16950
+ var init_skills = __esm(() => {
16951
+ SHARED_SKILLS_TARGET_ID = "agents";
16952
+ SHARED_SKILLS_TARGET_NAME = "AGENTS.md ecosystem";
16953
+ });
16954
+
16948
16955
  // dist/core/mcpFilter.js
16949
16956
  class MCPFilter {
16950
16957
  static filterForAgent(agent, servers) {
@@ -17048,6 +17055,11 @@ __export(exports_pluginManager, {
17048
17055
  return PluginManager;
17049
17056
  }
17050
17057
  },
17058
+ MultipleBundlePluginsError: () => {
17059
+ {
17060
+ return MultipleBundlePluginsError;
17061
+ }
17062
+ },
17051
17063
  MarketplacePluginNotFoundError: () => {
17052
17064
  {
17053
17065
  return MarketplacePluginNotFoundError;
@@ -17058,6 +17070,16 @@ import {resolve as resolve7, join as join4, basename as basename2, relative as r
17058
17070
  import {promises as fs22} from "fs";
17059
17071
  import {homedir as homedir4} from "os";
17060
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
+
17061
17083
  class MarketplacePluginNotFoundError extends Error {
17062
17084
  pluginName;
17063
17085
  marketplaceId;
@@ -17195,7 +17217,7 @@ class PluginManager {
17195
17217
  const candidates = new Set([source.pluginName, source.repo].filter((value) => !!value).flatMap((value) => [value, basename2(value)]));
17196
17218
  const matched = entries.find((entry) => candidates.has(entry.name) || candidates.has(basename2(entry.source)));
17197
17219
  if (!matched) {
17198
- throw new Error(`Repository "${pluginDir}" is a Claude marketplace bundle with multiple plugins. Select one of: ${entries.map((entry) => entry.name).join(", ")}.`);
17220
+ throw new MultipleBundlePluginsError(pluginDir, entries);
17199
17221
  }
17200
17222
  selectedEntry = matched;
17201
17223
  }
@@ -17272,6 +17294,9 @@ class PluginManager {
17272
17294
  throw new Error(`Local path not found: ${pluginDir}`);
17273
17295
  }
17274
17296
  }
17297
+ if (options2.pluginName) {
17298
+ effectiveSource = { ...effectiveSource, pluginName: options2.pluginName };
17299
+ }
17275
17300
  return {
17276
17301
  plugin: await this.loadPluginFromDirectory(pluginDir, effectiveSource, resolutionWarnings),
17277
17302
  effectiveSource,
@@ -18111,7 +18136,10 @@ ${body.trim()}
18111
18136
  };
18112
18137
  }
18113
18138
  async installPlugin(source, projectPath, options2 = {}) {
18114
- const context = this.takePreparedInstallContext(source, options2.from) || await this.loadPluginContext(source, { from: options2.from });
18139
+ const context = this.takePreparedInstallContext(source, options2.from) || await this.loadPluginContext(source, {
18140
+ from: options2.from,
18141
+ ...options2.pluginName ? { pluginName: options2.pluginName } : {}
18142
+ });
18115
18143
  try {
18116
18144
  const plugin = context.plugin;
18117
18145
  if (options2.list) {
@@ -18526,6 +18554,7 @@ import {promisify} from "util";
18526
18554
 
18527
18555
  class SkillsManager {
18528
18556
  agentManager;
18557
+ preparedSourceContexts = new Map;
18529
18558
  constructor(agentManager3) {
18530
18559
  this.agentManager = agentManager3 || new AgentManager;
18531
18560
  }
@@ -18668,7 +18697,7 @@ class SkillsManager {
18668
18697
  }
18669
18698
  }
18670
18699
  async discoverSkills(repoPath) {
18671
- const skills = [];
18700
+ const skills2 = [];
18672
18701
  const seen = new Set;
18673
18702
  for (const searchDir of SKILL_SEARCH_DIRS) {
18674
18703
  const fullDir = resolve8(repoPath, searchDir);
@@ -18679,7 +18708,7 @@ class SkillsManager {
18679
18708
  const parsed = await this.parseSkillMd(directSkillMd);
18680
18709
  if (parsed && !seen.has(parsed.name)) {
18681
18710
  seen.add(parsed.name);
18682
- skills.push({ ...parsed, path: resolve8(fullDir) });
18711
+ skills2.push({ ...parsed, path: resolve8(fullDir) });
18683
18712
  }
18684
18713
  }
18685
18714
  const directSkillMdLower = join5(fullDir, "skill.md");
@@ -18687,7 +18716,7 @@ class SkillsManager {
18687
18716
  const parsed = await this.parseSkillMd(directSkillMdLower);
18688
18717
  if (parsed && !seen.has(parsed.name)) {
18689
18718
  seen.add(parsed.name);
18690
- skills.push({ ...parsed, path: resolve8(fullDir) });
18719
+ skills2.push({ ...parsed, path: resolve8(fullDir) });
18691
18720
  }
18692
18721
  }
18693
18722
  if (!await isDirectory(fullDir))
@@ -18705,11 +18734,11 @@ class SkillsManager {
18705
18734
  const parsed = await this.parseSkillMd(skillFile);
18706
18735
  if (parsed && !seen.has(parsed.name)) {
18707
18736
  seen.add(parsed.name);
18708
- skills.push({ ...parsed, path: entryPath });
18737
+ skills2.push({ ...parsed, path: entryPath });
18709
18738
  }
18710
18739
  }
18711
18740
  }
18712
- return skills;
18741
+ return skills2;
18713
18742
  }
18714
18743
  async cloneRepo(url) {
18715
18744
  const tempDir = await fs24.mkdtemp(join5(tmpdir(), "agentinit-skills-"));
@@ -18740,12 +18769,13 @@ class SkillsManager {
18740
18769
  const marketplaceHints = marketplaces.length > 0 ? ` If you meant a marketplace skill, use "${marketplaces[0]}/${normalizedSource}" or "--from ${marketplaces[0]}".` : "";
18741
18770
  return new Error(`Local path not found: ${resolvedPath}. If you meant a local path, prefix it with "./".${marketplaceHints}`);
18742
18771
  }
18743
- async discoverMarketplaceSkills(source, projectPath) {
18772
+ async discoverMarketplaceSkills(source, projectPath, pluginName) {
18744
18773
  const { PluginManager: PluginManager2 } = await Promise.resolve().then(() => (init_pluginManager(), exports_pluginManager));
18745
18774
  const pluginManager = new PluginManager2(this.agentManager);
18746
18775
  const result = await pluginManager.installPlugin(source.pluginName || this.getMarketplaceSourceId(source), projectPath, {
18747
18776
  from: source.marketplace,
18748
- list: true
18777
+ list: true,
18778
+ ...pluginName ? { pluginName } : {}
18749
18779
  });
18750
18780
  const warnings = [...result.warnings];
18751
18781
  if (result.plugin.mcpServers.length > 0) {
@@ -18809,6 +18839,9 @@ class SkillsManager {
18809
18839
  async loadDiscoveredSkillsContext(source, projectPath, options2 = {}) {
18810
18840
  const request = this.resolveSourceRequest(source, options2);
18811
18841
  const resolved = request.source;
18842
+ if (options2.pluginName && resolved.type !== "marketplace") {
18843
+ resolved.pluginName = options2.pluginName;
18844
+ }
18812
18845
  let tempDir = null;
18813
18846
  const cleanup = async () => {
18814
18847
  await this.cleanupTempDir(tempDir);
@@ -18816,7 +18849,7 @@ class SkillsManager {
18816
18849
  };
18817
18850
  try {
18818
18851
  if (resolved.type === "marketplace") {
18819
- const discovered = await this.discoverMarketplaceSkills(resolved, projectPath);
18852
+ const discovered = await this.discoverMarketplaceSkills(resolved, projectPath, options2.pluginName);
18820
18853
  return {
18821
18854
  ...discovered,
18822
18855
  cleanup
@@ -18836,24 +18869,24 @@ class SkillsManager {
18836
18869
  }
18837
18870
  }
18838
18871
  const discoveryRoot = await this.resolveDiscoveryRoot(repoPath, resolved, source);
18839
- let skills = await this.discoverSkills(discoveryRoot);
18872
+ let skills2 = await this.discoverSkills(discoveryRoot);
18840
18873
  let pluginWarnings = [];
18841
- if (skills.length === 0) {
18874
+ if (skills2.length === 0) {
18842
18875
  const pluginBackedSkills = await this.discoverPortablePluginSkills(discoveryRoot, source, resolved, projectPath);
18843
18876
  if (pluginBackedSkills) {
18844
- skills = pluginBackedSkills.skills;
18877
+ skills2 = pluginBackedSkills.skills;
18845
18878
  pluginWarnings = pluginBackedSkills.warnings;
18846
18879
  }
18847
18880
  }
18848
18881
  if (request.implicitSkills.length > 0) {
18849
18882
  const names = new Set(request.implicitSkills.map((skill) => skill.toLowerCase()));
18850
- skills = skills.filter((skill) => names.has(skill.name.toLowerCase()));
18883
+ skills2 = skills2.filter((skill) => names.has(skill.name.toLowerCase()));
18851
18884
  }
18852
18885
  const warnings = [
18853
18886
  ...pluginWarnings,
18854
18887
  ...request.implicitSkills.length > 0 ? [`Resolved "${source}" from the default skills catalog ${DEFAULT_SKILLS_CATALOG.owner}/${DEFAULT_SKILLS_CATALOG.repo}. Use "./${source}" for a local path.`] : []
18855
18888
  ];
18856
- return { skills, warnings, cleanup };
18889
+ return { skills: skills2, warnings, cleanup };
18857
18890
  } catch (error) {
18858
18891
  await cleanup();
18859
18892
  throw error;
@@ -18870,6 +18903,37 @@ class SkillsManager {
18870
18903
  await context.cleanup();
18871
18904
  }
18872
18905
  }
18906
+ getPreparedSourceKey(source, projectPath, from) {
18907
+ return `${projectPath}\n${from || ""}\n${source}`;
18908
+ }
18909
+ async storePreparedSourceContext(source, projectPath, from, context) {
18910
+ const key = this.getPreparedSourceKey(source, projectPath, from);
18911
+ const existing = this.preparedSourceContexts.get(key);
18912
+ this.preparedSourceContexts.set(key, context);
18913
+ if (existing && existing !== context) {
18914
+ await existing.cleanup();
18915
+ }
18916
+ }
18917
+ takePreparedSourceContext(source, projectPath, from) {
18918
+ const key = this.getPreparedSourceKey(source, projectPath, from);
18919
+ const existing = this.preparedSourceContexts.get(key) || null;
18920
+ if (existing) {
18921
+ this.preparedSourceContexts.delete(key);
18922
+ }
18923
+ return existing;
18924
+ }
18925
+ async prepareSource(source, projectPath, options2 = {}) {
18926
+ const context = await this.loadDiscoveredSkillsContext(source, projectPath, options2);
18927
+ await this.storePreparedSourceContext(source, projectPath, options2.from, context);
18928
+ return {
18929
+ skills: context.skills,
18930
+ warnings: context.warnings
18931
+ };
18932
+ }
18933
+ async discardPreparedSource(source, projectPath, options2 = {}) {
18934
+ const context = this.takePreparedSourceContext(source, projectPath, options2.from);
18935
+ await context?.cleanup();
18936
+ }
18873
18937
  async getTargetAgents(projectPath, options2) {
18874
18938
  if (options2.agents && options2.agents.length > 0) {
18875
18939
  const agents = [];
@@ -18997,6 +19061,27 @@ class SkillsManager {
18997
19061
  }
18998
19062
  return plan;
18999
19063
  }
19064
+ async installSkillToCanonicalStore(skillPath, skillName, projectPath, options2 = {}) {
19065
+ const plan = this.getCanonicalInstallPlan(skillName, projectPath, options2);
19066
+ await this.cleanAndCreateDirectory(plan.path);
19067
+ await this.copyDir(skillPath, plan.path);
19068
+ return plan;
19069
+ }
19070
+ async installSkillFromContentToCanonicalStore(skillName, skillContent, projectPath, options2 = {}) {
19071
+ const plan = this.getCanonicalInstallPlan(skillName, projectPath, options2);
19072
+ await this.cleanAndCreateDirectory(plan.path);
19073
+ await fs24.writeFile(join5(plan.path, "SKILL.md"), skillContent, "utf8");
19074
+ return plan;
19075
+ }
19076
+ getCanonicalInstallPlan(skillName, projectPath, options2 = {}) {
19077
+ const normalizedSkillName = this.normalizeSkillName(skillName);
19078
+ const canonicalPath = this.resolveInstallPath(this.getCanonicalSkillsDir(projectPath, options2.global ?? false), normalizedSkillName);
19079
+ return {
19080
+ path: canonicalPath,
19081
+ canonicalPath,
19082
+ mode: "symlink"
19083
+ };
19084
+ }
19000
19085
  normalizeSkillName(skillName) {
19001
19086
  const normalized = skillName.trim();
19002
19087
  if (!normalized) {
@@ -19032,45 +19117,60 @@ class SkillsManager {
19032
19117
  await fs24.cp(src, dest, { recursive: true, dereference: true });
19033
19118
  }
19034
19119
  async addFromSource(source, projectPath, options2 = {}) {
19035
- const context = await this.loadDiscoveredSkillsContext(source, projectPath, {
19036
- ...options2.from !== undefined ? { from: options2.from } : {}
19120
+ const context = this.takePreparedSourceContext(source, projectPath, options2.from) || await this.loadDiscoveredSkillsContext(source, projectPath, {
19121
+ ...options2.from !== undefined ? { from: options2.from } : {},
19122
+ ...options2.pluginName !== undefined ? { pluginName: options2.pluginName } : {}
19037
19123
  });
19038
19124
  try {
19039
- let skills = context.skills;
19040
- if (skills.length === 0) {
19125
+ let skills2 = context.skills;
19126
+ if (skills2.length === 0) {
19041
19127
  return { installed: [], skipped: [], warnings: context.warnings };
19042
19128
  }
19043
19129
  if (options2.skills && options2.skills.length > 0) {
19044
19130
  const names = new Set(options2.skills.map((skill) => skill.toLowerCase()));
19045
- skills = skills.filter((skill) => names.has(skill.name.toLowerCase()));
19131
+ skills2 = skills2.filter((skill) => names.has(skill.name.toLowerCase()));
19046
19132
  }
19133
+ const installToSharedStore = options2.agents?.includes(SHARED_SKILLS_TARGET_ID) ?? false;
19047
19134
  const agents = await this.getTargetAgents(projectPath, options2);
19048
- if (agents.length === 0) {
19135
+ if (agents.length === 0 && !installToSharedStore) {
19049
19136
  return {
19050
19137
  installed: [],
19051
- skipped: skills.map((skill) => ({ skill, reason: "No target agents found" })),
19138
+ skipped: skills2.map((skill) => ({ skill, reason: "No target agents found" })),
19052
19139
  warnings: context.warnings
19053
19140
  };
19054
19141
  }
19055
19142
  const result = { installed: [], skipped: [], warnings: context.warnings };
19056
19143
  const installableAgents = [];
19144
+ if (installToSharedStore) {
19145
+ for (const skill of skills2) {
19146
+ try {
19147
+ const installOptions = {
19148
+ ...options2.global !== undefined ? { global: options2.global } : {}
19149
+ };
19150
+ const installed = skill.generatedContent ? await this.installSkillFromContentToCanonicalStore(skill.name, skill.generatedContent, projectPath, installOptions) : await this.installSkillToCanonicalStore(skill.path, skill.name, projectPath, installOptions);
19151
+ result.installed.push({ skill, agent: SHARED_SKILLS_TARGET_ID, ...installed });
19152
+ } catch (error) {
19153
+ result.skipped.push({ skill, reason: error.message });
19154
+ }
19155
+ }
19156
+ }
19057
19157
  for (const agent of agents) {
19058
19158
  if (!agent.supportsSkills()) {
19059
- for (const skill of skills) {
19159
+ for (const skill of skills2) {
19060
19160
  result.skipped.push({ skill, reason: `${agent.name} does not support skills` });
19061
19161
  }
19062
19162
  continue;
19063
19163
  }
19064
19164
  const skillsDir = agent.getSkillsDir(projectPath, options2.global);
19065
19165
  if (!skillsDir) {
19066
- for (const skill of skills) {
19166
+ for (const skill of skills2) {
19067
19167
  result.skipped.push({ skill, reason: `No skills directory for ${agent.name}` });
19068
19168
  }
19069
19169
  continue;
19070
19170
  }
19071
19171
  installableAgents.push(agent);
19072
19172
  }
19073
- for (const skill of skills) {
19173
+ for (const skill of skills2) {
19074
19174
  for (const agent of installableAgents) {
19075
19175
  try {
19076
19176
  const installOptions = {
@@ -19149,6 +19249,43 @@ class SkillsManager {
19149
19249
  }
19150
19250
  }
19151
19251
  }
19252
+ const includeSharedTarget = !options2.agents || options2.agents.includes(SHARED_SKILLS_TARGET_ID);
19253
+ if (includeSharedTarget) {
19254
+ const scopes = options2.global ? ["global"] : ["project", "global"];
19255
+ const referencedCanonicalPaths = new Set(installed.map((entry) => entry.canonicalPath).filter((value) => !!value).map((value) => resolve8(value)));
19256
+ for (const scope of scopes) {
19257
+ const canonicalDir = this.getCanonicalSkillsDir(projectPath, scope === "global");
19258
+ if (!await fileExists(canonicalDir))
19259
+ continue;
19260
+ const entries = await listFiles(canonicalDir);
19261
+ for (const entry of entries) {
19262
+ const entryPath = join5(canonicalDir, entry);
19263
+ if (!await isDirectory(entryPath))
19264
+ continue;
19265
+ const resolvedEntryPath = resolve8(entryPath);
19266
+ if (referencedCanonicalPaths.has(resolvedEntryPath))
19267
+ continue;
19268
+ const skillMdPath = join5(entryPath, "SKILL.md");
19269
+ const skillMdPathLower = join5(entryPath, "skill.md");
19270
+ const skillFile = await fileExists(skillMdPath) ? skillMdPath : await fileExists(skillMdPathLower) ? skillMdPathLower : null;
19271
+ if (!skillFile)
19272
+ continue;
19273
+ const parsed = await this.parseSkillMd(skillFile);
19274
+ if (!parsed)
19275
+ continue;
19276
+ installed.push({
19277
+ name: parsed.name,
19278
+ description: parsed.description,
19279
+ path: entryPath,
19280
+ canonicalPath: resolvedEntryPath,
19281
+ agent: SHARED_SKILLS_TARGET_ID,
19282
+ scope,
19283
+ isSymlink: false,
19284
+ mode: "symlink"
19285
+ });
19286
+ }
19287
+ }
19288
+ }
19152
19289
  return installed;
19153
19290
  }
19154
19291
  async remove(skillNames, projectPath, options2 = {}) {
@@ -19159,11 +19296,19 @@ class SkillsManager {
19159
19296
  const skipped = [];
19160
19297
  const namesLower = new Set(skillNames.map((n) => n.toLowerCase()));
19161
19298
  const targetAgentIds = new Set(agents.map((agent) => agent.id));
19299
+ if (options2.agents?.includes(SHARED_SKILLS_TARGET_ID) || options2.agents === undefined) {
19300
+ targetAgentIds.add(SHARED_SKILLS_TARGET_ID);
19301
+ }
19162
19302
  const installed = await this.listInstalledForAgents(projectPath, allAgents, options2);
19163
- const scopedInstalled = installed.filter((entry) => options2.global ? entry.scope === "global" : entry.scope === "project");
19303
+ const sharedTargetInstalled = options2.agents?.includes(SHARED_SKILLS_TARGET_ID) ? await this.listInstalledForAgents(projectPath, [], options2) : [];
19304
+ const installedEntries = Array.from(new Map([...installed, ...sharedTargetInstalled].map((entry) => [
19305
+ `${entry.agent}:${entry.scope}:${entry.path}:${entry.name}`,
19306
+ entry
19307
+ ])).values());
19308
+ const scopedInstalled = installedEntries.filter((entry) => options2.global ? entry.scope === "global" : entry.scope === "project");
19164
19309
  const targetedEntries = scopedInstalled.filter((entry) => targetAgentIds.has(entry.agent) && namesLower.has(entry.name.toLowerCase()));
19165
19310
  const targetedKeys = new Set(targetedEntries.map((entry) => `${entry.agent}:${entry.scope}:${entry.path}:${entry.name}`));
19166
- const remainingEntries = installed.filter((entry) => !targetedKeys.has(`${entry.agent}:${entry.scope}:${entry.path}:${entry.name}`));
19311
+ const remainingEntries = installedEntries.filter((entry) => !targetedKeys.has(`${entry.agent}:${entry.scope}:${entry.path}:${entry.name}`));
19167
19312
  const removedPaths = new Set;
19168
19313
  const removedCanonicalPaths = new Set;
19169
19314
  for (const entry of targetedEntries) {
@@ -19223,6 +19368,7 @@ var init_skillsManager = __esm(() => {
19223
19368
  init_fs();
19224
19369
  init_agentManager();
19225
19370
  init_marketplaceRegistry();
19371
+ init_skills();
19226
19372
  execFileAsync = promisify(execFile);
19227
19373
  DEFAULT_SKILLS_CATALOG = {
19228
19374
  owner: "vercel-labs",
@@ -39992,7 +40138,7 @@ init_fs();
39992
40138
  import {dirname as dirname8, join as join9} from "path";
39993
40139
  async function discoverProjectSkills(projectPath, skillsManager4) {
39994
40140
  const sources = [];
39995
- const skills = new Map;
40141
+ const skills2 = new Map;
39996
40142
  for (const sourceDir of PROJECT_SKILL_SOURCE_DIRS) {
39997
40143
  const absoluteSourceDir = join9(projectPath, sourceDir);
39998
40144
  if (!await fileExists(absoluteSourceDir)) {
@@ -40002,23 +40148,23 @@ async function discoverProjectSkills(projectPath, skillsManager4) {
40002
40148
  const discovered = await skillsManager4.discoverSkills(absoluteSourceDir);
40003
40149
  for (const skill of discovered) {
40004
40150
  const key = skill.name.toLowerCase();
40005
- if (!skills.has(key)) {
40006
- skills.set(key, skill);
40151
+ if (!skills2.has(key)) {
40152
+ skills2.set(key, skill);
40007
40153
  }
40008
40154
  }
40009
40155
  }
40010
40156
  return {
40011
40157
  sources,
40012
- skills: [...skills.values()]
40158
+ skills: [...skills2.values()]
40013
40159
  };
40014
40160
  }
40015
40161
  async function applyProjectSkills(projectPath, targetAgentIds, managedState2, options2 = {}) {
40016
40162
  const agentManager6 = new AgentManager;
40017
40163
  const skillsManager4 = new SkillsManager(agentManager6);
40018
- const { sources, skills } = await discoverProjectSkills(projectPath, skillsManager4);
40164
+ const { sources, skills: skills2 } = await discoverProjectSkills(projectPath, skillsManager4);
40019
40165
  const installed = [];
40020
40166
  const skipped = [];
40021
- if (skills.length === 0) {
40167
+ if (skills2.length === 0) {
40022
40168
  return {
40023
40169
  discovered: 0,
40024
40170
  sources,
@@ -40029,22 +40175,22 @@ async function applyProjectSkills(projectPath, targetAgentIds, managedState2, op
40029
40175
  const targetAgents = targetAgentIds.map((id) => agentManager6.getAgentById(id)).filter((agent) => !!agent);
40030
40176
  if (targetAgents.length === 0) {
40031
40177
  return {
40032
- discovered: skills.length,
40178
+ discovered: skills2.length,
40033
40179
  sources,
40034
40180
  installed,
40035
- skipped: skills.map((skill) => ({ skill, reason: "No target agents found" }))
40181
+ skipped: skills2.map((skill) => ({ skill, reason: "No target agents found" }))
40036
40182
  };
40037
40183
  }
40038
40184
  for (const agent of targetAgents) {
40039
40185
  if (!agent.supportsSkills()) {
40040
- for (const skill of skills) {
40186
+ for (const skill of skills2) {
40041
40187
  skipped.push({ skill, reason: `${agent.name} does not support skills` });
40042
40188
  }
40043
40189
  continue;
40044
40190
  }
40045
40191
  const skillsDir = agent.getSkillsDir(projectPath, false);
40046
40192
  if (!skillsDir) {
40047
- for (const skill of skills) {
40193
+ for (const skill of skills2) {
40048
40194
  skipped.push({ skill, reason: `No skills directory for ${agent.name}` });
40049
40195
  }
40050
40196
  continue;
@@ -40055,7 +40201,7 @@ async function applyProjectSkills(projectPath, targetAgentIds, managedState2, op
40055
40201
  continue;
40056
40202
  if (!agent.getSkillsDir(projectPath, false))
40057
40203
  continue;
40058
- for (const skill of skills) {
40204
+ for (const skill of skills2) {
40059
40205
  try {
40060
40206
  const installOptions = {
40061
40207
  ...options2.copy !== undefined ? { copy: options2.copy } : {}
@@ -40079,7 +40225,7 @@ async function applyProjectSkills(projectPath, targetAgentIds, managedState2, op
40079
40225
  }
40080
40226
  }
40081
40227
  return {
40082
- discovered: skills.length,
40228
+ discovered: skills2.length,
40083
40229
  sources,
40084
40230
  installed,
40085
40231
  skipped
@@ -41079,12 +41225,14 @@ var import_prompts2 = __toESM(require_prompts3(), 1);
41079
41225
  import {homedir as homedir6} from "os";
41080
41226
  import {relative as relative7, resolve as resolve12} from "path";
41081
41227
  init_skillsManager();
41228
+ init_pluginManager();
41082
41229
  init_marketplaceRegistry();
41083
41230
  init_agentManager();
41231
+ init_skills();
41084
41232
  function registerSkillsCommand(program2) {
41085
41233
  const marketplaceHelp = getMarketplaceIds().join(", ");
41086
- const skills = program2.command("skills").description("Manage agent skills");
41087
- skills.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) => {
41234
+ 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) => {
41088
41236
  logger.titleBox("AgentInit Skills");
41089
41237
  const agentManager9 = new AgentManager;
41090
41238
  const skillsManager5 = new SkillsManager(agentManager9);
@@ -41097,11 +41245,64 @@ function registerSkillsCommand(program2) {
41097
41245
  spinner2.stop();
41098
41246
  displayDiscoveredSkills(result.skills, result.warnings);
41099
41247
  } catch (error) {
41100
- spinner2.fail("Failed to discover skills");
41101
- logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
41248
+ if (error instanceof MultipleBundlePluginsError) {
41249
+ spinner2.stop();
41250
+ const selected = await selectBundlePlugin(error, "list");
41251
+ if (!selected) {
41252
+ return;
41253
+ }
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"}`);
41265
+ }
41266
+ } else {
41267
+ spinner2.fail("Failed to discover skills");
41268
+ logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
41269
+ }
41102
41270
  }
41103
41271
  return;
41104
41272
  }
41273
+ const verifySpinner = ora("Verifying skill source...").start();
41274
+ let selectedPluginName;
41275
+ try {
41276
+ await skillsManager5.prepareSource(source, process.cwd(), {
41277
+ from: options2.from
41278
+ });
41279
+ verifySpinner.stop();
41280
+ } catch (error) {
41281
+ if (error instanceof MultipleBundlePluginsError && !options2.yes) {
41282
+ verifySpinner.stop();
41283
+ const selected = await selectBundlePlugin(error, "install");
41284
+ if (!selected) {
41285
+ return;
41286
+ }
41287
+ selectedPluginName = selected;
41288
+ const retrySpinner = ora("Verifying skill source...").start();
41289
+ try {
41290
+ await skillsManager5.prepareSource(source, process.cwd(), {
41291
+ from: options2.from,
41292
+ pluginName: selectedPluginName
41293
+ });
41294
+ retrySpinner.stop();
41295
+ } catch (retryError) {
41296
+ retrySpinner.fail("Failed to verify skill source");
41297
+ logger.error(`Error: ${retryError instanceof Error ? retryError.message : "Unknown error"}`);
41298
+ return;
41299
+ }
41300
+ } else {
41301
+ verifySpinner.fail("Failed to verify skill source");
41302
+ logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
41303
+ return;
41304
+ }
41305
+ }
41105
41306
  let targetAgents = options2.agent;
41106
41307
  let targetGlobal = options2.global;
41107
41308
  if (!targetAgents && !options2.yes) {
@@ -41110,6 +41311,9 @@ function registerSkillsCommand(program2) {
41110
41311
  global: options2.global
41111
41312
  });
41112
41313
  if (selection?.aborted) {
41314
+ await skillsManager5.discardPreparedSource(source, process.cwd(), {
41315
+ from: options2.from
41316
+ });
41113
41317
  return;
41114
41318
  }
41115
41319
  if (selection?.agents && selection.agents.length > 0) {
@@ -41123,6 +41327,7 @@ function registerSkillsCommand(program2) {
41123
41327
  ...targetAgents !== undefined ? { agents: targetAgents } : {},
41124
41328
  ...options2.skill !== undefined ? { skills: options2.skill } : {},
41125
41329
  ...options2.copy !== undefined ? { copy: options2.copy } : {},
41330
+ ...selectedPluginName !== undefined ? { pluginName: selectedPluginName } : {},
41126
41331
  ...options2.yes !== undefined ? { yes: options2.yes } : {}
41127
41332
  });
41128
41333
  const spinner = ora("Installing skills...").start();
@@ -41134,7 +41339,7 @@ function registerSkillsCommand(program2) {
41134
41339
  logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
41135
41340
  }
41136
41341
  });
41137
- skills.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) => {
41342
+ 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) => {
41138
41343
  logger.titleBox("AgentInit Skills");
41139
41344
  const agentManager9 = new AgentManager;
41140
41345
  const skillsManager5 = new SkillsManager(agentManager9);
@@ -41163,7 +41368,7 @@ function registerSkillsCommand(program2) {
41163
41368
  if (skill.mode === "symlink") {
41164
41369
  existing.mode = "symlink";
41165
41370
  }
41166
- existing.agents.add(agentManager9.getAgentById(skill.agent)?.name || skill.agent);
41371
+ existing.agents.add(formatSkillTargetName(agentManager9, skill.agent));
41167
41372
  bySkill.set(key, existing);
41168
41373
  }
41169
41374
  for (const skill of bySkill.values()) {
@@ -41174,7 +41379,7 @@ function registerSkillsCommand(program2) {
41174
41379
  logger.info(` Agents: ${[...skill.agents].join(", ")}`);
41175
41380
  }
41176
41381
  });
41177
- skills.command("remove [names...]").alias("rm").description("Remove installed skills by name").option("-g, --global", "Remove from global scope").option("-a, --agent <agents...>", "Target specific agent(s)").option("-y, --yes", "Skip confirmation prompts").action(async (names, options2) => {
41382
+ skills3.command("remove [names...]").alias("rm").description("Remove installed skills by name").option("-g, --global", "Remove from global scope").option("-a, --agent <agents...>", "Target specific agent(s)").option("-y, --yes", "Skip confirmation prompts").action(async (names, options2) => {
41178
41383
  logger.titleBox("AgentInit Skills");
41179
41384
  if (!names || names.length === 0) {
41180
41385
  if (!options2.yes) {
@@ -41210,6 +41415,22 @@ function registerSkillsCommand(program2) {
41210
41415
  }
41211
41416
  });
41212
41417
  }
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
+ }
41213
41434
  async function resolveInteractiveSkillTargets(skillsManager5, agentManager9, source, projectPath, options2) {
41214
41435
  let installGlobal = !!options2.global;
41215
41436
  if (!options2.global) {
@@ -41258,9 +41479,9 @@ async function resolveInteractiveSkillTargets(skillsManager5, agentManager9, sou
41258
41479
  instructions: false,
41259
41480
  min: 1,
41260
41481
  choices: availableGroups.map((group) => ({
41261
- title: `${group.displayDir} -> ${group.agentNames.join(", ")}${formatCompatibleAgents(group)}`,
41482
+ title: formatSkillGroupTitle(group),
41262
41483
  ...group.description ? { description: group.description } : {},
41263
- value: group.agents.map((agent) => agent.id),
41484
+ value: group.kind === "canonical-shared" ? [SHARED_SKILLS_TARGET_ID] : group.agents.map((agent) => agent.id),
41264
41485
  selected: shouldPreselectSkillGroup(group, installGlobal, detectedGroups.length > 0, recommendedAgentId)
41265
41486
  }))
41266
41487
  });
@@ -41309,15 +41530,23 @@ var buildSkillGroups = function(agents, projectPath, global3) {
41309
41530
  existing.push(agent);
41310
41531
  dirToAgents.set(skillsDir, existing);
41311
41532
  }
41312
- return Array.from(dirToAgents.entries()).map(([dir, groupedAgents]) => ({
41313
- dir,
41314
- displayDir: formatSkillsDir(projectPath, dir),
41315
- agents: groupedAgents,
41316
- agentNames: groupedAgents.map((agent) => agent.name),
41317
- compatibleAgents: [],
41318
- compatibleAgentNames: [],
41319
- kind: "native"
41320
- }));
41533
+ return Array.from(dirToAgents.entries()).map(([dir, groupedAgents]) => {
41534
+ const canonicalShared = resolve12(dir) === getCanonicalSkillsDirForScope(projectPath, !!global3) && groupedAgents.every((agent) => agent.getProjectSkillsStandard() === "agents");
41535
+ return {
41536
+ dir,
41537
+ displayDir: formatSkillsDir(projectPath, dir),
41538
+ agents: groupedAgents,
41539
+ agentNames: groupedAgents.map((agent) => agent.name),
41540
+ compatibleAgents: [],
41541
+ compatibleAgentNames: [],
41542
+ ...canonicalShared ? {
41543
+ description: `Install only into the shared AGENTS.md store. Compatible tools: ${groupedAgents.map((agent) => agent.name).join(", ")}.`,
41544
+ kind: "canonical-shared"
41545
+ } : {
41546
+ kind: "native"
41547
+ }
41548
+ };
41549
+ });
41321
41550
  };
41322
41551
  var prependCanonicalGlobalGroup = function(agentManager9, projectPath, groups) {
41323
41552
  const canonicalDir = getCanonicalGlobalSkillsDir();
@@ -41332,7 +41561,7 @@ var prependCanonicalGlobalGroup = function(agentManager9, projectPath, groups) {
41332
41561
  return [
41333
41562
  {
41334
41563
  ...existingCanonical,
41335
- description: existingCanonical.description || "Canonical shared skills store for the open AGENTS.md ecosystem.",
41564
+ description: existingCanonical.description || `Install only into the shared AGENTS.md store. Compatible tools: ${existingCanonical.agentNames.join(", ")}.`,
41336
41565
  kind: "canonical-shared"
41337
41566
  },
41338
41567
  ...remaining
@@ -41346,7 +41575,7 @@ var prependCanonicalGlobalGroup = function(agentManager9, projectPath, groups) {
41346
41575
  agentNames: sharedAgents.map((agent) => agent.name),
41347
41576
  compatibleAgents: [],
41348
41577
  compatibleAgentNames: [],
41349
- description: "Canonical shared skills store for the open AGENTS.md ecosystem.",
41578
+ description: `Install only into the shared AGENTS.md store. Compatible tools: ${sharedAgents.map((agent) => agent.name).join(", ")}.`,
41350
41579
  kind: "canonical-shared"
41351
41580
  },
41352
41581
  ...groups.map((group) => {
@@ -41384,12 +41613,15 @@ var formatPromptPath = function(path) {
41384
41613
  var getCanonicalGlobalSkillsDir = function() {
41385
41614
  return resolve12(homedir6(), ".agents/skills");
41386
41615
  };
41616
+ var getCanonicalSkillsDirForScope = function(projectPath, global3) {
41617
+ return global3 ? getCanonicalGlobalSkillsDir() : resolve12(projectPath, ".agents/skills");
41618
+ };
41387
41619
  var getCanonicalGlobalSkillsDisplayPath = function() {
41388
41620
  return formatPromptPath(getCanonicalGlobalSkillsDir());
41389
41621
  };
41390
41622
  var describeGlobalSkillGroup = function(group) {
41391
41623
  if (group.kind === "canonical-shared") {
41392
- return group.description;
41624
+ return group.description || `Install only into the shared AGENTS.md store. Compatible tools: ${group.agentNames.join(", ")}.`;
41393
41625
  }
41394
41626
  if (group.agents.every((agent) => agent.getProjectSkillsStandard() === "agents")) {
41395
41627
  return `Native agent directory linked to ${getCanonicalGlobalSkillsDisplayPath()} when symlinks are used.`;
@@ -41399,6 +41631,18 @@ var describeGlobalSkillGroup = function(group) {
41399
41631
  }
41400
41632
  return;
41401
41633
  };
41634
+ var formatSkillGroupTitle = function(group) {
41635
+ if (group.kind === "canonical-shared") {
41636
+ return `${group.displayDir} -> ${SHARED_SKILLS_TARGET_NAME}`;
41637
+ }
41638
+ return `${group.displayDir} -> ${group.agentNames.join(", ")}${formatCompatibleAgents(group)}`;
41639
+ };
41640
+ var formatSkillTargetName = function(agentManager9, agentId) {
41641
+ if (agentId === SHARED_SKILLS_TARGET_ID) {
41642
+ return SHARED_SKILLS_TARGET_NAME;
41643
+ }
41644
+ return agentManager9.getAgentById(agentId)?.name || agentId;
41645
+ };
41402
41646
  var shouldPreselectSkillGroup = function(group, installGlobal, hasDetectedGroups, recommendedAgentId) {
41403
41647
  const includesRecommendedAgent = !!recommendedAgentId && group.agents.some((agent) => agent.id === recommendedAgentId);
41404
41648
  if (!installGlobal) {
@@ -41451,18 +41695,18 @@ var buildSkillsAddCommand = function(source, from, extraArgs) {
41451
41695
  args.push(...extraArgs);
41452
41696
  return args.join(" ");
41453
41697
  };
41454
- var displayDiscoveredSkills = function(skills, warnings) {
41455
- if (skills.length === 0) {
41698
+ var displayDiscoveredSkills = function(skills3, warnings) {
41699
+ if (skills3.length === 0) {
41456
41700
  logger.info("No skills found in the source.");
41457
41701
  for (const warning of warnings) {
41458
41702
  logger.warn(warning);
41459
41703
  }
41460
41704
  return;
41461
41705
  }
41462
- logger.info(`Found ${green(String(skills.length))} skill(s):\n`);
41706
+ logger.info(`Found ${green(String(skills3.length))} skill(s):\n`);
41463
41707
  logger.info(" Name Description");
41464
41708
  logger.info(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
41465
- for (const skill of skills) {
41709
+ for (const skill of skills3) {
41466
41710
  const name = skill.name.padEnd(18);
41467
41711
  logger.info(` ${green(name)} ${skill.description}`);
41468
41712
  }
@@ -41503,7 +41747,7 @@ var displayInstallResult = function(result, spinner, agentManager9, skillsManage
41503
41747
  agents: new Set,
41504
41748
  skills: new Set
41505
41749
  };
41506
- existing.agents.add(agentManager9.getAgentById(item.agent)?.name || item.agent);
41750
+ existing.agents.add(formatSkillTargetName(agentManager9, item.agent));
41507
41751
  existing.skills.add(item.skill.name);
41508
41752
  byPath.set(path, existing);
41509
41753
  }
@@ -42335,11 +42579,11 @@ function registerPluginsCommand(program2) {
42335
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) => {
42336
42580
  logger.titleBox("AgentInit Plugins");
42337
42581
  const agentManager12 = new AgentManager;
42338
- const pluginManager2 = new PluginManager(agentManager12);
42582
+ const pluginManager3 = new PluginManager(agentManager12);
42339
42583
  if (options2.list) {
42340
42584
  const spinner2 = ora("Fetching plugin...").start();
42341
42585
  try {
42342
- const preview2 = await pluginManager2.inspectPlugin(source, {
42586
+ const preview2 = await pluginManager3.inspectPlugin(source, {
42343
42587
  from: options2.from
42344
42588
  });
42345
42589
  spinner2.stop();
@@ -42366,8 +42610,49 @@ function registerPluginsCommand(program2) {
42366
42610
  }
42367
42611
  renderPluginWarnings(preview2, process.cwd());
42368
42612
  } catch (error) {
42369
- spinner2.fail("Failed to fetch plugin");
42370
- logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
42613
+ if (error instanceof MultipleBundlePluginsError) {
42614
+ spinner2.stop();
42615
+ const selected = await selectBundlePlugin2(error, "preview");
42616
+ if (!selected) {
42617
+ return;
42618
+ }
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}`);
42636
+ }
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}]`);
42642
+ }
42643
+ }
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
+ }
42652
+ } else {
42653
+ spinner2.fail("Failed to fetch plugin");
42654
+ logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
42655
+ }
42371
42656
  }
42372
42657
  return;
42373
42658
  }
@@ -42375,24 +42660,48 @@ function registerPluginsCommand(program2) {
42375
42660
  let targetGlobal = options2.global;
42376
42661
  let preview = null;
42377
42662
  let previewRendered = false;
42663
+ let selectedPluginName;
42378
42664
  if (!agentIds && !options2.yes) {
42379
42665
  const previewSpinner = ora("Inspecting plugin...").start();
42380
42666
  try {
42381
- preview = await pluginManager2.preparePluginInstall(source, {
42667
+ preview = await pluginManager3.preparePluginInstall(source, {
42382
42668
  from: options2.from
42383
42669
  });
42384
42670
  previewSpinner.stop();
42385
42671
  renderPluginWarnings(preview, process.cwd());
42386
42672
  previewRendered = true;
42387
42673
  } catch (error) {
42388
- previewSpinner.fail("Failed to inspect plugin");
42389
- logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
42390
- return;
42674
+ if (error instanceof MultipleBundlePluginsError) {
42675
+ previewSpinner.stop();
42676
+ const selected = await selectBundlePlugin2(error, "install");
42677
+ if (!selected) {
42678
+ return;
42679
+ }
42680
+ selectedPluginName = selected;
42681
+ const retrySpinner = ora("Inspecting plugin...").start();
42682
+ try {
42683
+ preview = await pluginManager3.preparePluginInstall(source, {
42684
+ from: options2.from,
42685
+ pluginName: selectedPluginName
42686
+ });
42687
+ retrySpinner.stop();
42688
+ renderPluginWarnings(preview, process.cwd());
42689
+ previewRendered = true;
42690
+ } catch (retryError) {
42691
+ retrySpinner.fail("Failed to inspect plugin");
42692
+ logger.error(`Error: ${retryError instanceof Error ? retryError.message : "Unknown error"}`);
42693
+ return;
42694
+ }
42695
+ } else {
42696
+ previewSpinner.fail("Failed to inspect plugin");
42697
+ logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
42698
+ return;
42699
+ }
42391
42700
  }
42392
42701
  try {
42393
- const selection = await interactiveAgentSelect(pluginManager2, agentManager12, process.cwd(), targetGlobal, preview);
42702
+ const selection = await interactiveAgentSelect(pluginManager3, agentManager12, process.cwd(), targetGlobal, preview);
42394
42703
  if (!selection || selection.aborted || !selection.agents || selection.agents.length === 0) {
42395
- await pluginManager2.discardPreparedPlugin(source, { from: options2.from });
42704
+ await pluginManager3.discardPreparedPlugin(source, { from: options2.from });
42396
42705
  logger.info("No agents selected. Aborting.");
42397
42706
  return;
42398
42707
  }
@@ -42407,12 +42716,13 @@ function registerPluginsCommand(program2) {
42407
42716
  }
42408
42717
  const spinner = ora("Installing plugin...").start();
42409
42718
  try {
42410
- const result = await pluginManager2.installPlugin(source, process.cwd(), {
42719
+ const result = await pluginManager3.installPlugin(source, process.cwd(), {
42411
42720
  from: options2.from,
42412
42721
  agents: agentIds,
42413
42722
  global: targetGlobal,
42414
42723
  copySkills: options2.copySkills,
42415
- yes: options2.yes
42724
+ yes: options2.yes,
42725
+ ...selectedPluginName ? { pluginName: selectedPluginName } : {}
42416
42726
  });
42417
42727
  const p = result.plugin;
42418
42728
  const totalSkills = result.skills.installed.length;
@@ -42444,13 +42754,48 @@ function registerPluginsCommand(program2) {
42444
42754
  }
42445
42755
  logger.success("Plugin installation complete.");
42446
42756
  } catch (error) {
42447
- spinner.fail("Failed to install plugin");
42448
- logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
42757
+ if (error instanceof MultipleBundlePluginsError && !options2.yes) {
42758
+ spinner.stop();
42759
+ const selected = await selectBundlePlugin2(error, "install");
42760
+ if (!selected) {
42761
+ return;
42762
+ }
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());
42780
+ return;
42781
+ }
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"}`);
42789
+ }
42790
+ } else {
42791
+ spinner.fail("Failed to install plugin");
42792
+ logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
42793
+ }
42449
42794
  }
42450
42795
  });
42451
42796
  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) => {
42452
42797
  logger.titleBox("AgentInit Plugin Search");
42453
- const pluginManager2 = new PluginManager;
42798
+ const pluginManager3 = new PluginManager;
42454
42799
  const registryId = options2.from || getConfiguredDefaultMarketplaceId();
42455
42800
  if (!registryId) {
42456
42801
  logger.info(`Please specify a marketplace with --from <marketplace>. Available: ${marketplaceHelp}`);
@@ -42461,7 +42806,7 @@ function registerPluginsCommand(program2) {
42461
42806
  }
42462
42807
  const spinner = ora(`Fetching ${registryId} marketplace...`).start();
42463
42808
  try {
42464
- const results = await pluginManager2.listMarketplacePlugins(registryId, query, options2.category);
42809
+ const results = await pluginManager3.listMarketplacePlugins(registryId, query, options2.category);
42465
42810
  spinner.stop();
42466
42811
  if (results.length === 0) {
42467
42812
  logger.info(query ? `No plugins matching "${query}".` : "No plugins found.");
@@ -42491,8 +42836,8 @@ function registerPluginsCommand(program2) {
42491
42836
  });
42492
42837
  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) => {
42493
42838
  logger.titleBox("AgentInit Installed Plugins");
42494
- const pluginManager2 = new PluginManager;
42495
- const installed = await pluginManager2.listPlugins(process.cwd(), {
42839
+ const pluginManager3 = new PluginManager;
42840
+ const installed = await pluginManager3.listPlugins(process.cwd(), {
42496
42841
  global: options2.global,
42497
42842
  agents: options2.agent
42498
42843
  });
@@ -42527,10 +42872,10 @@ function registerPluginsCommand(program2) {
42527
42872
  });
42528
42873
  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) => {
42529
42874
  logger.titleBox("AgentInit Remove Plugin");
42530
- const pluginManager2 = new PluginManager;
42875
+ const pluginManager3 = new PluginManager;
42531
42876
  const spinner = ora(`Removing plugin "${name}"...`).start();
42532
42877
  try {
42533
- const result = await pluginManager2.removePlugin(name, process.cwd(), {
42878
+ const result = await pluginManager3.removePlugin(name, process.cwd(), {
42534
42879
  global: options2.global,
42535
42880
  agents: options2.agent,
42536
42881
  yes: options2.yes
@@ -42552,6 +42897,22 @@ function registerPluginsCommand(program2) {
42552
42897
  }
42553
42898
  });
42554
42899
  }
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
+ }
42555
42916
  var formatPathForDisplay = function(pathValue, projectPath) {
42556
42917
  if (pathValue.startsWith(`${projectPath}/`)) {
42557
42918
  return relative8(projectPath, pathValue) || ".";
@@ -42841,9 +43202,9 @@ var getPluginGroupDescription = function(group, preview, projectPath) {
42841
43202
  const receiveVerb = otherAgents.length === 1 ? "receives" : "receive";
42842
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.`;
42843
43204
  };
42844
- async function interactiveAgentSelect(pluginManager2, agentManager12, projectPath, global3, preview) {
43205
+ async function interactiveAgentSelect(pluginManager3, agentManager12, projectPath, global3, preview) {
42845
43206
  let installGlobal = !!global3;
42846
- let groups = installGlobal ? buildGlobalPluginGroups(agentManager12, projectPath) : (await pluginManager2.groupAgentsBySkillsDir(projectPath, false)).map((group) => ({
43207
+ let groups = installGlobal ? buildGlobalPluginGroups(agentManager12, projectPath) : (await pluginManager3.groupAgentsBySkillsDir(projectPath, false)).map((group) => ({
42847
43208
  ...group,
42848
43209
  displayDir: group.dir
42849
43210
  }));