agentinit 1.12.1 → 1.13.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
@@ -16807,6 +16807,13 @@ var init_marketplaceRegistry = __esm(() => {
16807
16807
  repoUrl: "https://github.com/anthropics/claude-plugins-official.git",
16808
16808
  pluginDirs: ["plugins", "external_plugins"],
16809
16809
  cacheTtlMs: 3600000
16810
+ },
16811
+ {
16812
+ id: "openai",
16813
+ name: "OpenAI Skills",
16814
+ repoUrl: "https://github.com/openai/skills.git",
16815
+ pluginDirs: ["skills/.curated", "skills/.system", "skills/.experimental"],
16816
+ cacheTtlMs: 3600000
16810
16817
  }
16811
16818
  ];
16812
16819
  });
@@ -16913,12 +16920,36 @@ __export(exports_pluginManager, {
16913
16920
  {
16914
16921
  return PluginManager;
16915
16922
  }
16923
+ },
16924
+ MarketplacePluginNotFoundError: () => {
16925
+ {
16926
+ return MarketplacePluginNotFoundError;
16927
+ }
16916
16928
  }
16917
16929
  });
16918
- import {resolve as resolve7, join as join3, basename as basename2} from "path";
16930
+ import {resolve as resolve7, join as join3, basename as basename2, relative as relative2, dirname as dirname2} from "path";
16919
16931
  import {promises as fs18} from "fs";
16920
16932
  import {homedir as homedir3} from "os";
16921
16933
 
16934
+ class MarketplacePluginNotFoundError extends Error {
16935
+ pluginName;
16936
+ marketplaceId;
16937
+ marketplaceName;
16938
+ suggestions;
16939
+ constructor(pluginName, marketplaceId, marketplaceName, suggestions) {
16940
+ let msg = `Plugin "${pluginName}" not found in ${marketplaceName} marketplace.`;
16941
+ if (suggestions.length > 0) {
16942
+ msg += ` Did you mean: ${suggestions.join(", ")}?`;
16943
+ }
16944
+ super(msg);
16945
+ this.name = "MarketplacePluginNotFoundError";
16946
+ this.pluginName = pluginName;
16947
+ this.marketplaceId = marketplaceId;
16948
+ this.marketplaceName = marketplaceName;
16949
+ this.suggestions = suggestions;
16950
+ }
16951
+ }
16952
+
16922
16953
  class PluginManager {
16923
16954
  agentManager;
16924
16955
  skillsManager;
@@ -16926,6 +16957,245 @@ class PluginManager {
16926
16957
  this.agentManager = agentManager2 || new AgentManager;
16927
16958
  this.skillsManager = new SkillsManager(this.agentManager);
16928
16959
  }
16960
+ parseGitHubRepo(url) {
16961
+ const normalized = url.replace(/\.git$/, "");
16962
+ const match = normalized.match(/github\.com[:/]([^/]+)\/([^/]+)/i);
16963
+ if (!match) {
16964
+ return null;
16965
+ }
16966
+ const [, owner, repo] = match;
16967
+ if (!owner || !repo) {
16968
+ return null;
16969
+ }
16970
+ return {
16971
+ owner,
16972
+ repo
16973
+ };
16974
+ }
16975
+ deriveGitHubFallbackSource(source, marketplaceId) {
16976
+ const repoShorthandMatch = source.match(/^([a-zA-Z0-9._-]+)\/([a-zA-Z0-9._-]+)$/);
16977
+ if (repoShorthandMatch) {
16978
+ const [, owner, repo] = repoShorthandMatch;
16979
+ return {
16980
+ type: "github",
16981
+ url: `https://github.com/${owner}/${repo}.git`,
16982
+ owner,
16983
+ repo
16984
+ };
16985
+ }
16986
+ if (!marketplaceId || !/^[a-zA-Z0-9._-]+$/.test(source)) {
16987
+ return null;
16988
+ }
16989
+ const registry = this.getMarketplace(marketplaceId);
16990
+ const registryRepo = registry ? this.parseGitHubRepo(registry.repoUrl) : null;
16991
+ if (!registryRepo) {
16992
+ return null;
16993
+ }
16994
+ return {
16995
+ type: "github",
16996
+ url: `https://github.com/${registryRepo.owner}/${source}.git`,
16997
+ owner: registryRepo.owner,
16998
+ repo: source
16999
+ };
17000
+ }
17001
+ formatGitHubRepoUrl(source) {
17002
+ if (!source.owner || !source.repo) {
17003
+ return null;
17004
+ }
17005
+ return `https://github.com/${source.owner}/${source.repo}`;
17006
+ }
17007
+ async resolvePreparedPluginDir(pluginDir, source) {
17008
+ const claudeMarketplaceManifestPath = join3(pluginDir, ".claude-plugin", "marketplace.json");
17009
+ if (!await fileExists(claudeMarketplaceManifestPath)) {
17010
+ return { pluginDir, warnings: [] };
17011
+ }
17012
+ const manifestContent = await readFileIfExists(claudeMarketplaceManifestPath);
17013
+ if (!manifestContent) {
17014
+ return { pluginDir, warnings: [] };
17015
+ }
17016
+ let manifest;
17017
+ try {
17018
+ manifest = JSON.parse(manifestContent);
17019
+ } catch {
17020
+ throw new Error(`Invalid .claude-plugin/marketplace.json in ${pluginDir}`);
17021
+ }
17022
+ const entries = Array.isArray(manifest.plugins) ? manifest.plugins.filter((entry) => typeof entry?.name === "string" && typeof entry?.source === "string") : [];
17023
+ if (entries.length === 0) {
17024
+ throw new Error(`No plugins declared in .claude-plugin/marketplace.json for ${pluginDir}`);
17025
+ }
17026
+ const [firstEntry] = entries;
17027
+ if (!firstEntry) {
17028
+ throw new Error(`No plugins declared in .claude-plugin/marketplace.json for ${pluginDir}`);
17029
+ }
17030
+ let selectedEntry = firstEntry;
17031
+ if (entries.length > 1) {
17032
+ const candidates = new Set([source.pluginName, source.repo].filter((value) => !!value).flatMap((value) => [value, basename2(value)]));
17033
+ const matched = entries.find((entry) => candidates.has(entry.name) || candidates.has(basename2(entry.source)));
17034
+ if (!matched) {
17035
+ throw new Error(`Repository "${pluginDir}" is a Claude marketplace bundle with multiple plugins. Select one of: ${entries.map((entry) => entry.name).join(", ")}.`);
17036
+ }
17037
+ selectedEntry = matched;
17038
+ }
17039
+ const selectedPluginDir = resolve7(pluginDir, selectedEntry.source);
17040
+ const relativePath = relative2(resolve7(pluginDir), selectedPluginDir);
17041
+ if (relativePath.startsWith("..") || relativePath.includes("/../") || relativePath.includes("\\..\\")) {
17042
+ throw new Error(`Invalid bundled plugin source path "${selectedEntry.source}" in ${claudeMarketplaceManifestPath}`);
17043
+ }
17044
+ if (!await isDirectory(selectedPluginDir)) {
17045
+ throw new Error(`Bundled plugin path not found: ${selectedPluginDir}`);
17046
+ }
17047
+ const sourceLabel = this.formatGitHubRepoUrl(source) || pluginDir;
17048
+ return {
17049
+ pluginDir: selectedPluginDir,
17050
+ warnings: [
17051
+ `Source "${sourceLabel}" is a Claude Code marketplace bundle; using bundled plugin "${selectedEntry.name}".`
17052
+ ],
17053
+ claudeBundle: {
17054
+ bundleName: manifest.name || selectedEntry.name,
17055
+ pluginName: selectedEntry.name
17056
+ }
17057
+ };
17058
+ }
17059
+ async loadPluginFromDirectory(pluginDir, source, warnings = []) {
17060
+ const preparedPlugin = await this.resolvePreparedPluginDir(pluginDir, source);
17061
+ const parsedPlugin = await this.parsePlugin(preparedPlugin.pluginDir, source);
17062
+ return {
17063
+ ...parsedPlugin,
17064
+ warnings: [...warnings, ...preparedPlugin.warnings, ...parsedPlugin.warnings],
17065
+ resolvedPluginDir: preparedPlugin.pluginDir,
17066
+ ...preparedPlugin.claudeBundle ? { nativeClaudeBundle: preparedPlugin.claudeBundle } : {}
17067
+ };
17068
+ }
17069
+ slugifyPluginNamespace(value) {
17070
+ return value.trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "plugin";
17071
+ }
17072
+ async getClaudeNativeFeatureKinds(pluginDir, manifest) {
17073
+ const featureChecks = await Promise.all([
17074
+ (async () => !!manifest.commands || await isDirectory(join3(pluginDir, "commands")))(),
17075
+ (async () => !!manifest.hooks || await isDirectory(join3(pluginDir, "hooks")))(),
17076
+ (async () => !!manifest.agents || await isDirectory(join3(pluginDir, "agents")))(),
17077
+ isDirectory(join3(pluginDir, "prompts")),
17078
+ isDirectory(join3(pluginDir, "schemas")),
17079
+ isDirectory(join3(pluginDir, "scripts")),
17080
+ isDirectory(join3(pluginDir, "templates"))
17081
+ ]);
17082
+ return [
17083
+ ...featureChecks[0] ? ["commands"] : [],
17084
+ ...featureChecks[1] ? ["hooks"] : [],
17085
+ ...featureChecks[2] ? ["agents"] : [],
17086
+ ...featureChecks[3] ? ["prompts"] : [],
17087
+ ...featureChecks[4] ? ["schemas"] : [],
17088
+ ...featureChecks[5] ? ["scripts"] : [],
17089
+ ...featureChecks[6] ? ["templates"] : []
17090
+ ];
17091
+ }
17092
+ async getClaudeNativeInstallTarget(plugin, pluginDir) {
17093
+ if (plugin.format !== "claude") {
17094
+ return null;
17095
+ }
17096
+ const manifestContent = await readFileIfExists(join3(pluginDir, ".claude-plugin", "plugin.json"));
17097
+ if (!manifestContent) {
17098
+ return null;
17099
+ }
17100
+ let manifest;
17101
+ try {
17102
+ manifest = JSON.parse(manifestContent);
17103
+ } catch {
17104
+ return null;
17105
+ }
17106
+ const features = await this.getClaudeNativeFeatureKinds(pluginDir, manifest);
17107
+ if (features.length === 0) {
17108
+ return null;
17109
+ }
17110
+ const baseNamespace = plugin.nativeClaudeBundle?.bundleName || plugin.source.marketplace || (plugin.source.owner && plugin.source.repo ? `${plugin.source.owner}-${plugin.source.repo}` : plugin.name);
17111
+ const namespace = `agentinit-${this.slugifyPluginNamespace(baseNamespace)}`;
17112
+ const versionDir = this.slugifyPluginNamespace(plugin.version || "0.0.0");
17113
+ return {
17114
+ namespace,
17115
+ pluginKey: `${plugin.name}@${namespace}`,
17116
+ installPath: join3(homedir3(), ".claude", "plugins", "cache", namespace, plugin.name, versionDir),
17117
+ features
17118
+ };
17119
+ }
17120
+ async readClaudeInstalledPlugins() {
17121
+ const path = getClaudeInstalledPluginsPath();
17122
+ const content = await readFileIfExists(path);
17123
+ if (!content) {
17124
+ return { version: 2, plugins: {} };
17125
+ }
17126
+ try {
17127
+ const parsed = JSON.parse(content);
17128
+ if (!parsed || parsed.version !== 2 || typeof parsed.plugins !== "object" || parsed.plugins === null) {
17129
+ return { version: 2, plugins: {} };
17130
+ }
17131
+ return parsed;
17132
+ } catch {
17133
+ return { version: 2, plugins: {} };
17134
+ }
17135
+ }
17136
+ async saveClaudeInstalledPlugins(state) {
17137
+ await writeFile(getClaudeInstalledPluginsPath(), JSON.stringify(state, null, 2));
17138
+ }
17139
+ async installNativeClaudePlugin(plugin, pluginDir, agents) {
17140
+ const installed = [];
17141
+ const skipped = [];
17142
+ const warnings = [];
17143
+ const nativeTarget = await this.getClaudeNativeInstallTarget(plugin, pluginDir);
17144
+ if (!nativeTarget) {
17145
+ return { installed, skipped, warnings };
17146
+ }
17147
+ const hasClaudeTarget = agents.some((agent) => agent.id === "claude");
17148
+ const featureLabel = nativeTarget.features.join(", ");
17149
+ if (!hasClaudeTarget) {
17150
+ warnings.push(`Claude Code-native plugin components detected (${featureLabel}), but no Claude Code target was selected; skipped native install.`);
17151
+ return { installed, skipped, warnings };
17152
+ }
17153
+ warnings.push(`Claude Code-native plugin components detected (${featureLabel}); they will only work in Claude Code and install into ~/.claude/plugins.`);
17154
+ const claudeInstalled = await this.readClaudeInstalledPlugins();
17155
+ const conflictingKey = Object.keys(claudeInstalled.plugins).find((key) => key !== nativeTarget.pluginKey && key.startsWith(`${plugin.name}@`));
17156
+ if (conflictingKey) {
17157
+ skipped.push({
17158
+ agent: "claude",
17159
+ reason: `Claude plugin "${plugin.name}" is already installed as ${conflictingKey}; skipped native install to avoid duplicates.`
17160
+ });
17161
+ warnings.push(`Skipped native Claude plugin install because Claude already has "${plugin.name}" installed as ${conflictingKey}.`);
17162
+ return { installed, skipped, warnings };
17163
+ }
17164
+ await fs18.rm(nativeTarget.installPath, { recursive: true, force: true }).catch(() => {
17165
+ });
17166
+ await fs18.mkdir(dirname2(nativeTarget.installPath), { recursive: true });
17167
+ await fs18.cp(pluginDir, nativeTarget.installPath, { recursive: true, dereference: true });
17168
+ const now = new Date().toISOString();
17169
+ claudeInstalled.plugins[nativeTarget.pluginKey] = [{
17170
+ scope: "user",
17171
+ installPath: nativeTarget.installPath,
17172
+ version: plugin.version,
17173
+ installedAt: now,
17174
+ lastUpdated: now
17175
+ }];
17176
+ await this.saveClaudeInstalledPlugins(claudeInstalled);
17177
+ installed.push({
17178
+ agent: "claude",
17179
+ pluginKey: nativeTarget.pluginKey,
17180
+ installPath: nativeTarget.installPath
17181
+ });
17182
+ warnings.push("Reload plugins in Claude Code with /reload-plugins to activate native plugin components.");
17183
+ return { installed, skipped, warnings };
17184
+ }
17185
+ async removeNativeClaudePlugin(component) {
17186
+ const claudeInstalled = await this.readClaudeInstalledPlugins();
17187
+ const entries = claudeInstalled.plugins[component.pluginKey] || [];
17188
+ const remainingEntries = entries.filter((entry) => entry.installPath !== component.installPath);
17189
+ if (remainingEntries.length > 0) {
17190
+ claudeInstalled.plugins[component.pluginKey] = remainingEntries;
17191
+ } else {
17192
+ delete claudeInstalled.plugins[component.pluginKey];
17193
+ }
17194
+ await this.saveClaudeInstalledPlugins(claudeInstalled);
17195
+ await fs18.rm(component.installPath, { recursive: true, force: true }).catch(() => {
17196
+ });
17197
+ return true;
17198
+ }
16929
17199
  resolveSource(source, options2) {
16930
17200
  if (source.startsWith(".") || source.startsWith("/") || source.startsWith("~")) {
16931
17201
  return { type: "local", path: source };
@@ -17045,11 +17315,7 @@ class PluginManager {
17045
17315
  }
17046
17316
  const available = await this.listMarketplacePlugins(registryId);
17047
17317
  const suggestions = available.filter((p) => p.name.includes(name) || name.includes(p.name)).map((p) => p.name).slice(0, 5);
17048
- let msg = `Plugin "${name}" not found in ${registry.name} marketplace.`;
17049
- if (suggestions.length > 0) {
17050
- msg += ` Did you mean: ${suggestions.join(", ")}?`;
17051
- }
17052
- throw new Error(msg);
17318
+ throw new MarketplacePluginNotFoundError(name, registryId, registry.name, suggestions);
17053
17319
  }
17054
17320
  async listMarketplacePlugins(registryId, query, category) {
17055
17321
  const registry = this.getMarketplace(registryId);
@@ -17061,7 +17327,7 @@ class PluginManager {
17061
17327
  const fullDir = join3(cacheDir, dir);
17062
17328
  if (!await isDirectory(fullDir))
17063
17329
  continue;
17064
- const cat = dir === "plugins" ? "official" : dir === "external_plugins" ? "community" : dir;
17330
+ const cat = dir === "plugins" ? "official" : dir === "external_plugins" ? "community" : dir.startsWith("skills/.") ? dir.slice("skills/.".length) : dir;
17065
17331
  if (category && cat !== category)
17066
17332
  continue;
17067
17333
  const entries = await listFiles(fullDir);
@@ -17152,10 +17418,10 @@ class PluginManager {
17152
17418
  skills.push(...convertedSkills);
17153
17419
  const mcpServers = await this.parseMcpJson(pluginDir);
17154
17420
  if (await isDirectory(join3(pluginDir, "hooks")) || manifest.hooks) {
17155
- warnings.push("Hooks (hooks/) are Claude Code-specific and were not installed");
17421
+ warnings.push("Hooks (hooks/) are Claude Code-specific");
17156
17422
  }
17157
17423
  if (await isDirectory(join3(pluginDir, "agents")) || manifest.agents) {
17158
- warnings.push("Agent definitions (agents/) are Claude Code-specific and were not installed");
17424
+ warnings.push("Agent definitions (agents/) are Claude Code-specific");
17159
17425
  }
17160
17426
  return {
17161
17427
  name: manifest.name,
@@ -17307,10 +17573,35 @@ ${body.trim()}
17307
17573
  }
17308
17574
  async installPlugin(source, projectPath, options2 = {}) {
17309
17575
  const resolved = this.resolveSource(source, { from: options2.from });
17576
+ let effectiveSource = resolved;
17310
17577
  let pluginDir;
17311
17578
  let tempDir = null;
17579
+ const resolutionWarnings = [];
17312
17580
  if (resolved.type === "marketplace") {
17313
- pluginDir = await this.resolveMarketplacePlugin(resolved.pluginName, resolved.marketplace || "claude");
17581
+ try {
17582
+ pluginDir = await this.resolveMarketplacePlugin(resolved.pluginName, resolved.marketplace || "claude");
17583
+ } catch (error) {
17584
+ if (!(error instanceof MarketplacePluginNotFoundError)) {
17585
+ throw error;
17586
+ }
17587
+ const fallbackSource = this.deriveGitHubFallbackSource(source, resolved.marketplace);
17588
+ if (!fallbackSource || !fallbackSource.url) {
17589
+ throw error;
17590
+ }
17591
+ const fallbackUrl = this.formatGitHubRepoUrl(fallbackSource) || fallbackSource.url.replace(/\.git$/, "");
17592
+ resolutionWarnings.push(error.message);
17593
+ resolutionWarnings.push(`Marketplace lookup failed; trying unverified GitHub repository ${fallbackUrl} instead.`);
17594
+ try {
17595
+ tempDir = await this.skillsManager.cloneRepo(fallbackSource.url);
17596
+ } catch (fallbackError) {
17597
+ throw new Error(`${error.message} Tried unverified GitHub repository ${fallbackUrl} but failed: ${fallbackError instanceof Error ? fallbackError.message : "Unknown error"}`);
17598
+ }
17599
+ effectiveSource = {
17600
+ ...fallbackSource,
17601
+ ...resolved.pluginName ? { pluginName: resolved.pluginName } : {}
17602
+ };
17603
+ pluginDir = tempDir;
17604
+ }
17314
17605
  } else if (resolved.type === "github") {
17315
17606
  if (!resolved.url)
17316
17607
  throw new Error(`Invalid source: ${source}`);
@@ -17323,12 +17614,13 @@ ${body.trim()}
17323
17614
  }
17324
17615
  }
17325
17616
  try {
17326
- const plugin = await this.parsePlugin(pluginDir, resolved);
17617
+ const plugin = await this.loadPluginFromDirectory(pluginDir, effectiveSource, resolutionWarnings);
17327
17618
  if (options2.list) {
17328
17619
  return {
17329
17620
  plugin,
17330
17621
  skills: { installed: [], skipped: [] },
17331
17622
  mcpServers: { applied: [], skipped: [] },
17623
+ nativePlugins: { installed: [], skipped: [] },
17332
17624
  warnings: plugin.warnings
17333
17625
  };
17334
17626
  }
@@ -17338,25 +17630,29 @@ ${body.trim()}
17338
17630
  plugin,
17339
17631
  skills: { installed: [], skipped: plugin.skills.map((s) => ({ name: s.name, reason: "No target agents found" })) },
17340
17632
  mcpServers: { applied: [], skipped: plugin.mcpServers.map((s) => ({ name: s.name, reason: "No target agents found" })) },
17633
+ nativePlugins: { installed: [], skipped: [] },
17341
17634
  warnings: plugin.warnings
17342
17635
  };
17343
17636
  }
17344
17637
  const skillResult = await this.installPluginSkills(plugin, projectPath, agents, options2);
17345
17638
  const mcpResult = await this.applyPluginMcpServers(plugin, projectPath, agents, options2.global);
17346
- if (skillResult.installed.length > 0 || mcpResult.applied.length > 0) {
17639
+ const nativePluginResult = await this.installNativeClaudePlugin(plugin, plugin.resolvedPluginDir, agents);
17640
+ const installWarnings = [...plugin.warnings, ...nativePluginResult.warnings];
17641
+ if (skillResult.installed.length > 0 || mcpResult.applied.length > 0 || nativePluginResult.installed.length > 0) {
17347
17642
  const installed = {
17348
17643
  name: plugin.name,
17349
17644
  version: plugin.version,
17350
17645
  description: plugin.description,
17351
- source: resolved,
17646
+ source: effectiveSource,
17352
17647
  format: plugin.format,
17353
17648
  installedAt: new Date().toISOString(),
17354
17649
  scope: options2.global ? "global" : "project",
17355
17650
  components: {
17356
17651
  skills: skillResult.installed,
17357
- mcpServers: mcpResult.applied
17652
+ mcpServers: mcpResult.applied,
17653
+ nativePlugins: nativePluginResult.installed
17358
17654
  },
17359
- warnings: plugin.warnings
17655
+ warnings: installWarnings
17360
17656
  };
17361
17657
  await this.addToRegistry(installed, projectPath, options2.global);
17362
17658
  }
@@ -17364,7 +17660,8 @@ ${body.trim()}
17364
17660
  plugin,
17365
17661
  skills: skillResult,
17366
17662
  mcpServers: mcpResult,
17367
- warnings: plugin.warnings
17663
+ nativePlugins: nativePluginResult,
17664
+ warnings: installWarnings
17368
17665
  };
17369
17666
  } finally {
17370
17667
  if (tempDir) {
@@ -17521,7 +17818,7 @@ ${body.trim()}
17521
17818
  let plugins = registry.plugins;
17522
17819
  if (options2.agents && options2.agents.length > 0) {
17523
17820
  const agentSet = new Set(options2.agents);
17524
- plugins = plugins.filter((p) => p.components.skills.some((s) => agentSet.has(s.agent)) || p.components.mcpServers.some((m) => agentSet.has(m.agent)));
17821
+ plugins = plugins.filter((p) => p.components.skills.some((s) => agentSet.has(s.agent)) || p.components.mcpServers.some((m) => agentSet.has(m.agent)) || (p.components.nativePlugins || []).some((nativePlugin) => agentSet.has(nativePlugin.agent)));
17525
17822
  }
17526
17823
  return plugins;
17527
17824
  }
@@ -17531,7 +17828,8 @@ ${body.trim()}
17531
17828
  if (!plugin) {
17532
17829
  return { removed: false, details: [`Plugin "${name}" not found in registry`] };
17533
17830
  }
17534
- if (plugin.components.skills.length === 0 && plugin.components.mcpServers.length === 0) {
17831
+ const pluginNativeComponents = plugin.components.nativePlugins || [];
17832
+ if (plugin.components.skills.length === 0 && plugin.components.mcpServers.length === 0 && pluginNativeComponents.length === 0) {
17535
17833
  registry.plugins = registry.plugins.filter((p) => p.name !== name);
17536
17834
  await this.saveRegistry(registry, projectPath, options2.global);
17537
17835
  return {
@@ -17611,7 +17909,40 @@ ${body.trim()}
17611
17909
  ...retainedMcpServers,
17612
17910
  ...targetedMcpServers.filter((mcp) => !removedMcpKeys.has(`${mcp.agent}:${mcp.name}`))
17613
17911
  ];
17614
- if (removedSkillPaths.size === 0 && removedMcpKeys.size === 0) {
17912
+ const targetedNativePlugins = agentFilter ? pluginNativeComponents.filter((nativePlugin) => agentFilter.has(nativePlugin.agent)) : pluginNativeComponents;
17913
+ const retainedNativePlugins = agentFilter ? pluginNativeComponents.filter((nativePlugin) => !agentFilter.has(nativePlugin.agent)) : [];
17914
+ const otherScopeRegistry = await this.getRegistry(projectPath, !options2.global);
17915
+ const otherRegistryNativePlugins = otherScopeRegistry.plugins.flatMap((entry) => entry.components.nativePlugins || []);
17916
+ const otherPluginNativePlugins = registry.plugins.filter((entry) => entry.name !== plugin.name).flatMap((entry) => entry.components.nativePlugins || []);
17917
+ const remainingNativeRefs = [
17918
+ ...retainedNativePlugins,
17919
+ ...otherPluginNativePlugins,
17920
+ ...otherRegistryNativePlugins
17921
+ ];
17922
+ const removedNativeKeys = new Set;
17923
+ for (const nativePlugin of targetedNativePlugins) {
17924
+ const nativeKey = `${nativePlugin.agent}:${nativePlugin.pluginKey}:${nativePlugin.installPath}`;
17925
+ if (removedNativeKeys.has(nativeKey)) {
17926
+ continue;
17927
+ }
17928
+ const sharedNativeInstall = remainingNativeRefs.some((other) => other.installPath === nativePlugin.installPath || other.pluginKey === nativePlugin.pluginKey);
17929
+ if (sharedNativeInstall) {
17930
+ details.push(`Skipped shared native plugin payload: ${nativePlugin.pluginKey} (${nativePlugin.agent})`);
17931
+ continue;
17932
+ }
17933
+ try {
17934
+ await this.removeNativeClaudePlugin(nativePlugin);
17935
+ removedNativeKeys.add(nativeKey);
17936
+ details.push(`Removed native plugin payload: ${nativePlugin.pluginKey} (${nativePlugin.agent})`);
17937
+ } catch {
17938
+ details.push(`Could not remove native plugin payload: ${nativePlugin.pluginKey} (${nativePlugin.agent})`);
17939
+ }
17940
+ }
17941
+ const remainingNativePlugins = [
17942
+ ...retainedNativePlugins,
17943
+ ...targetedNativePlugins.filter((nativePlugin) => !removedNativeKeys.has(`${nativePlugin.agent}:${nativePlugin.pluginKey}:${nativePlugin.installPath}`))
17944
+ ];
17945
+ if (removedSkillPaths.size === 0 && removedMcpKeys.size === 0 && removedNativeKeys.size === 0) {
17615
17946
  if (agentFilter) {
17616
17947
  details.push(`No removable plugin components matched the requested agents for "${name}"`);
17617
17948
  }
@@ -17621,11 +17952,12 @@ ${body.trim()}
17621
17952
  ...plugin,
17622
17953
  components: {
17623
17954
  skills: remainingSkills,
17624
- mcpServers: remainingMcpServers
17955
+ mcpServers: remainingMcpServers,
17956
+ nativePlugins: remainingNativePlugins
17625
17957
  }
17626
17958
  };
17627
17959
  registry.plugins = registry.plugins.filter((p) => p.name !== name);
17628
- if (updatedPlugin.components.skills.length > 0 || updatedPlugin.components.mcpServers.length > 0) {
17960
+ if (updatedPlugin.components.skills.length > 0 || updatedPlugin.components.mcpServers.length > 0 || (updatedPlugin.components.nativePlugins || []).length > 0) {
17629
17961
  registry.plugins.push(updatedPlugin);
17630
17962
  details.push("Updated plugin registry");
17631
17963
  } else {
@@ -17635,7 +17967,7 @@ ${body.trim()}
17635
17967
  return { removed: true, details };
17636
17968
  }
17637
17969
  }
17638
- var import_gray_matter, getMarketplaceCacheDir, getRegistryPath;
17970
+ var import_gray_matter, getMarketplaceCacheDir, getRegistryPath, getClaudeInstalledPluginsPath;
17639
17971
  var init_pluginManager = __esm(() => {
17640
17972
  import_gray_matter = __toESM(require_gray_matter(), 1);
17641
17973
  init_fs();
@@ -17652,10 +17984,13 @@ var init_pluginManager = __esm(() => {
17652
17984
  }
17653
17985
  return join3(projectPath, ".agentinit", "plugins.json");
17654
17986
  };
17987
+ getClaudeInstalledPluginsPath = function() {
17988
+ return join3(homedir3(), ".claude", "plugins", "installed_plugins.json");
17989
+ };
17655
17990
  });
17656
17991
 
17657
17992
  // dist/core/skillsManager.js
17658
- import {resolve as resolve8, join as join4, relative as relative2} from "path";
17993
+ import {resolve as resolve8, join as join4, relative as relative3} from "path";
17659
17994
  import {promises as fs20} from "fs";
17660
17995
  import {homedir as homedir4, tmpdir} from "os";
17661
17996
  import {execFile} from "child_process";
@@ -17798,8 +18133,8 @@ class SkillsManager {
17798
18133
  return skills;
17799
18134
  }
17800
18135
  async cloneRepo(url) {
17801
- const tempDir = join4(tmpdir(), `agentinit-skills-${Date.now()}`);
17802
- await fs20.mkdir(tempDir, { recursive: true });
18136
+ const tempDir = await fs20.mkdtemp(join4(tmpdir(), "agentinit-skills-"));
18137
+ await fs20.rm(tempDir, { recursive: true, force: true });
17803
18138
  try {
17804
18139
  await execFileAsync("git", ["clone", "--depth", "1", url, tempDir], {
17805
18140
  timeout: 60000
@@ -17842,6 +18177,22 @@ class SkillsManager {
17842
18177
  warnings
17843
18178
  };
17844
18179
  }
18180
+ async discoverPortablePluginSkills(repoPath, sourceLabel, source, projectPath) {
18181
+ const { PluginManager: PluginManager2 } = await Promise.resolve().then(() => (init_pluginManager(), exports_pluginManager));
18182
+ const pluginManager = new PluginManager2(this.agentManager);
18183
+ const plugin = await pluginManager.loadPluginFromDirectory(repoPath, source);
18184
+ if (plugin.skills.length === 0 && plugin.mcpServers.length === 0 && plugin.warnings.length === 0) {
18185
+ return null;
18186
+ }
18187
+ const warnings = [...plugin.warnings];
18188
+ if (plugin.mcpServers.length > 0) {
18189
+ warnings.push(`Source "${sourceLabel}" also includes ${plugin.mcpServers.length} MCP server(s); use "agentinit plugins install ${sourceLabel}" to install them.`);
18190
+ }
18191
+ return {
18192
+ skills: plugin.skills,
18193
+ warnings
18194
+ };
18195
+ }
17845
18196
  async discoverFromSource(source, projectPath, options2 = {}) {
17846
18197
  const request = this.resolveSourceRequest(source, options2);
17847
18198
  const resolved = request.source;
@@ -17864,11 +18215,22 @@ class SkillsManager {
17864
18215
  }
17865
18216
  }
17866
18217
  let skills = await this.discoverSkills(repoPath);
18218
+ let pluginWarnings = [];
18219
+ if (skills.length === 0) {
18220
+ const pluginBackedSkills = await this.discoverPortablePluginSkills(repoPath, source, resolved, projectPath);
18221
+ if (pluginBackedSkills) {
18222
+ skills = pluginBackedSkills.skills;
18223
+ pluginWarnings = pluginBackedSkills.warnings;
18224
+ }
18225
+ }
17867
18226
  if (request.implicitSkills.length > 0) {
17868
18227
  const names = new Set(request.implicitSkills.map((skill) => skill.toLowerCase()));
17869
18228
  skills = skills.filter((skill) => names.has(skill.name.toLowerCase()));
17870
18229
  }
17871
- const warnings = 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.`] : [];
18230
+ const warnings = [
18231
+ ...pluginWarnings,
18232
+ ...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.`] : []
18233
+ ];
17872
18234
  return { skills, warnings };
17873
18235
  } finally {
17874
18236
  if (tempDir) {
@@ -18017,7 +18379,7 @@ class SkillsManager {
18017
18379
  resolveInstallPath(targetDir, skillName) {
18018
18380
  const resolvedTargetDir = resolve8(targetDir);
18019
18381
  const destPath = resolve8(resolvedTargetDir, skillName);
18020
- const relativePath = relative2(resolvedTargetDir, destPath);
18382
+ const relativePath = relative3(resolvedTargetDir, destPath);
18021
18383
  if (relativePath === "" || relativePath.startsWith("..") || relativePath.includes("/../") || relativePath.includes("\\..\\")) {
18022
18384
  throw new Error(`Refusing to install skill outside target directory: ${skillName}`);
18023
18385
  }
@@ -18032,7 +18394,7 @@ class SkillsManager {
18032
18394
  await fs20.mkdir(path, { recursive: true });
18033
18395
  }
18034
18396
  isWithinPath(basePath, targetPath) {
18035
- const relativePath = relative2(resolve8(basePath), resolve8(targetPath));
18397
+ const relativePath = relative3(resolve8(basePath), resolve8(targetPath));
18036
18398
  return relativePath === "" || !relativePath.startsWith("..") && !relativePath.includes("/../") && !relativePath.includes("\\..\\");
18037
18399
  }
18038
18400
  async copyDir(src, dest) {
@@ -18083,7 +18445,7 @@ class SkillsManager {
18083
18445
  ...options2.global !== undefined ? { global: options2.global } : {},
18084
18446
  ...options2.copy !== undefined ? { copy: options2.copy } : {}
18085
18447
  };
18086
- const installed = await this.installSkillForAgent(skill.path, skill.name, agent, projectPath, installOptions);
18448
+ const installed = skill.generatedContent ? await this.installSkillFromContentForAgent(skill.name, skill.generatedContent, agent, projectPath, installOptions) : await this.installSkillForAgent(skill.path, skill.name, agent, projectPath, installOptions);
18087
18449
  result.installed.push({ skill, agent: agent.id, ...installed });
18088
18450
  } catch (error) {
18089
18451
  result.skipped.push({ skill, reason: error.message });
@@ -19109,51 +19471,51 @@ var require_uri_all = __commonJS((exports, module) => {
19109
19471
  }
19110
19472
  return uriTokens.join("");
19111
19473
  }
19112
- function resolveComponents(base2, relative5) {
19474
+ function resolveComponents(base2, relative6) {
19113
19475
  var options2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
19114
19476
  var skipNormalization = arguments[3];
19115
19477
  var target = {};
19116
19478
  if (!skipNormalization) {
19117
19479
  base2 = parse4(serialize(base2, options2), options2);
19118
- relative5 = parse4(serialize(relative5, options2), options2);
19480
+ relative6 = parse4(serialize(relative6, options2), options2);
19119
19481
  }
19120
19482
  options2 = options2 || {};
19121
- if (!options2.tolerant && relative5.scheme) {
19122
- target.scheme = relative5.scheme;
19123
- target.userinfo = relative5.userinfo;
19124
- target.host = relative5.host;
19125
- target.port = relative5.port;
19126
- target.path = removeDotSegments(relative5.path || "");
19127
- target.query = relative5.query;
19483
+ if (!options2.tolerant && relative6.scheme) {
19484
+ target.scheme = relative6.scheme;
19485
+ target.userinfo = relative6.userinfo;
19486
+ target.host = relative6.host;
19487
+ target.port = relative6.port;
19488
+ target.path = removeDotSegments(relative6.path || "");
19489
+ target.query = relative6.query;
19128
19490
  } else {
19129
- if (relative5.userinfo !== undefined || relative5.host !== undefined || relative5.port !== undefined) {
19130
- target.userinfo = relative5.userinfo;
19131
- target.host = relative5.host;
19132
- target.port = relative5.port;
19133
- target.path = removeDotSegments(relative5.path || "");
19134
- target.query = relative5.query;
19491
+ if (relative6.userinfo !== undefined || relative6.host !== undefined || relative6.port !== undefined) {
19492
+ target.userinfo = relative6.userinfo;
19493
+ target.host = relative6.host;
19494
+ target.port = relative6.port;
19495
+ target.path = removeDotSegments(relative6.path || "");
19496
+ target.query = relative6.query;
19135
19497
  } else {
19136
- if (!relative5.path) {
19498
+ if (!relative6.path) {
19137
19499
  target.path = base2.path;
19138
- if (relative5.query !== undefined) {
19139
- target.query = relative5.query;
19500
+ if (relative6.query !== undefined) {
19501
+ target.query = relative6.query;
19140
19502
  } else {
19141
19503
  target.query = base2.query;
19142
19504
  }
19143
19505
  } else {
19144
- if (relative5.path.charAt(0) === "/") {
19145
- target.path = removeDotSegments(relative5.path);
19506
+ if (relative6.path.charAt(0) === "/") {
19507
+ target.path = removeDotSegments(relative6.path);
19146
19508
  } else {
19147
19509
  if ((base2.userinfo !== undefined || base2.host !== undefined || base2.port !== undefined) && !base2.path) {
19148
- target.path = "/" + relative5.path;
19510
+ target.path = "/" + relative6.path;
19149
19511
  } else if (!base2.path) {
19150
- target.path = relative5.path;
19512
+ target.path = relative6.path;
19151
19513
  } else {
19152
- target.path = base2.path.slice(0, base2.path.lastIndexOf("/") + 1) + relative5.path;
19514
+ target.path = base2.path.slice(0, base2.path.lastIndexOf("/") + 1) + relative6.path;
19153
19515
  }
19154
19516
  target.path = removeDotSegments(target.path);
19155
19517
  }
19156
- target.query = relative5.query;
19518
+ target.query = relative6.query;
19157
19519
  }
19158
19520
  target.userinfo = base2.userinfo;
19159
19521
  target.host = base2.host;
@@ -19161,7 +19523,7 @@ var require_uri_all = __commonJS((exports, module) => {
19161
19523
  }
19162
19524
  target.scheme = base2.scheme;
19163
19525
  }
19164
- target.fragment = relative5.fragment;
19526
+ target.fragment = relative6.fragment;
19165
19527
  return target;
19166
19528
  }
19167
19529
  function resolve12(baseURI, relativeURI, options2) {
@@ -38951,7 +39313,7 @@ async function detectCommand(options2) {
38951
39313
  }
38952
39314
 
38953
39315
  // dist/commands/sync.js
38954
- import {relative as relative4} from "path";
39316
+ import {relative as relative5} from "path";
38955
39317
 
38956
39318
  // dist/core/propagator.js
38957
39319
  var import_gray_matter3 = __toESM(require_gray_matter(), 1);
@@ -41932,7 +42294,7 @@ ${content}
41932
42294
  // dist/core/managedState.js
41933
42295
  init_fs();
41934
42296
  import {promises as fs24} from "fs";
41935
- import {dirname as dirname2, join as join5, relative as relative3, resolve as resolve10} from "path";
42297
+ import {dirname as dirname3, join as join5, relative as relative4, resolve as resolve10} from "path";
41936
42298
  var toPosixPath = function(value) {
41937
42299
  return value.replace(/\\/g, "/");
41938
42300
  };
@@ -41957,10 +42319,10 @@ async function copyDirectory(src, dest) {
41957
42319
  await copyDirectory(srcPath, destPath);
41958
42320
  } else if (entry.isSymbolicLink()) {
41959
42321
  const target = await fs24.readlink(srcPath);
41960
- await fs24.mkdir(dirname2(destPath), { recursive: true });
42322
+ await fs24.mkdir(dirname3(destPath), { recursive: true });
41961
42323
  await fs24.symlink(target, destPath);
41962
42324
  } else {
41963
- await fs24.mkdir(dirname2(destPath), { recursive: true });
42325
+ await fs24.mkdir(dirname3(destPath), { recursive: true });
41964
42326
  await fs24.copyFile(srcPath, destPath);
41965
42327
  }
41966
42328
  }
@@ -41970,7 +42332,7 @@ async function copyPath(src, dest) {
41970
42332
  if (!type2) {
41971
42333
  return;
41972
42334
  }
41973
- await fs24.mkdir(dirname2(dest), { recursive: true });
42335
+ await fs24.mkdir(dirname3(dest), { recursive: true });
41974
42336
  if (type2 === "symlink") {
41975
42337
  const target = await fs24.readlink(src);
41976
42338
  await fs24.symlink(target, dest);
@@ -42016,7 +42378,7 @@ class ManagedStateStore {
42016
42378
  }
42017
42379
  normalizeRelativePath(targetPath, preserveTrailingSlash = false) {
42018
42380
  const hasTrailingSlash = preserveTrailingSlash && /[\\/]$/.test(targetPath);
42019
- const relativePath = relative3(this.projectPath, resolve10(targetPath));
42381
+ const relativePath = relative4(this.projectPath, resolve10(targetPath));
42020
42382
  const normalizedPath = toPosixPath(relativePath);
42021
42383
  if (hasTrailingSlash && normalizedPath) {
42022
42384
  return normalizedPath.endsWith("/") ? normalizedPath : `${normalizedPath}/`;
@@ -42106,7 +42468,7 @@ class ManagedStateStore {
42106
42468
  if (!options2.dryRun) {
42107
42469
  await fs24.rm(absolutePath, { recursive: true, force: true }).catch(() => {
42108
42470
  });
42109
- await fs24.mkdir(dirname2(absolutePath), { recursive: true });
42471
+ await fs24.mkdir(dirname3(absolutePath), { recursive: true });
42110
42472
  await fs24.symlink(backupLinkTarget, absolutePath);
42111
42473
  }
42112
42474
  summary.restored++;
@@ -42193,7 +42555,7 @@ async function syncCommand(options2) {
42193
42555
  for (const change of result.changes) {
42194
42556
  const action = change.action === "created" ? "\u2795" : change.action === "updated" ? "\uD83D\uDCDD" : "\uD83D\uDCBE";
42195
42557
  const names = change.agents.map((id) => agentManager5.getAgentById(id)?.name || id).join(", ");
42196
- logger.info(` ${action} ${relative4(cwd, change.file) || change.file}`);
42558
+ logger.info(` ${action} ${relative5(cwd, change.file) || change.file}`);
42197
42559
  logger.info(` Agents: ${names}`);
42198
42560
  }
42199
42561
  if (options2.backup && result.changes.some((c) => c.action === "backed_up")) {
@@ -42222,7 +42584,7 @@ async function syncCommand(options2) {
42222
42584
  }
42223
42585
 
42224
42586
  // dist/commands/apply.js
42225
- import {relative as relative5} from "path";
42587
+ import {relative as relative6} from "path";
42226
42588
 
42227
42589
  // dist/types/index.js
42228
42590
  var MCPServerType;
@@ -42488,11 +42850,11 @@ class MCPParser {
42488
42850
  // dist/constants/mcp.js
42489
42851
  import {readFileSync} from "fs";
42490
42852
  import {fileURLToPath} from "url";
42491
- import {dirname as dirname3, join as join6} from "path";
42853
+ import {dirname as dirname4, join as join6} from "path";
42492
42854
  var getPackageVersion = function() {
42493
42855
  try {
42494
42856
  const __filename2 = fileURLToPath(import.meta.url);
42495
- const __dirname2 = dirname3(__filename2);
42857
+ const __dirname2 = dirname4(__filename2);
42496
42858
  const packageJsonPath = join6(__dirname2, "../../package.json");
42497
42859
  const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
42498
42860
  return packageJson.version || "1.0.0";
@@ -42524,11 +42886,11 @@ import {readFileSync as readFileSync3} from "fs";
42524
42886
 
42525
42887
  // dist/core/rulesTemplateLoader.js
42526
42888
  var toml = __toESM(require_toml(), 1);
42527
- import {resolve as resolve11, dirname as dirname4} from "path";
42889
+ import {resolve as resolve11, dirname as dirname5} from "path";
42528
42890
  import {fileURLToPath as fileURLToPath2} from "url";
42529
42891
  import {readFileSync as readFileSync2, readdirSync, existsSync} from "fs";
42530
42892
  var __filename2 = fileURLToPath2(import.meta.url);
42531
- var __dirname2 = dirname4(__filename2);
42893
+ var __dirname2 = dirname5(__filename2);
42532
42894
 
42533
42895
  class RulesTemplateLoader {
42534
42896
  templatesPath;
@@ -50764,10 +51126,10 @@ class MCPVerifier {
50764
51126
 
50765
51127
  // dist/core/gitignoreManager.js
50766
51128
  import {promises as fs27} from "fs";
50767
- import {dirname as dirname5, join as join7} from "path";
51129
+ import {dirname as dirname6, join as join7} from "path";
50768
51130
  var normalizeIgnorePath = function(projectPath, value) {
50769
- const relative5 = value.startsWith(projectPath) ? value.slice(projectPath.length + 1) : value;
50770
- const normalized = relative5.replace(/\\/g, "/").replace(/^\/+/, "");
51131
+ const relative6 = value.startsWith(projectPath) ? value.slice(projectPath.length + 1) : value;
51132
+ const normalized = relative6.replace(/\\/g, "/").replace(/^\/+/, "");
50771
51133
  if (!normalized) {
50772
51134
  return normalized;
50773
51135
  }
@@ -50832,7 +51194,7 @@ async function updateManagedIgnoreFile(projectPath, paths2, options2 = {}) {
50832
51194
  existingContent = "";
50833
51195
  }
50834
51196
  const updatedContent = updateManagedBlock(existingContent, normalizedPaths);
50835
- await fs27.mkdir(dirname5(ignoreFilePath), { recursive: true });
51197
+ await fs27.mkdir(dirname6(ignoreFilePath), { recursive: true });
50836
51198
  await fs27.writeFile(ignoreFilePath, updatedContent, "utf8");
50837
51199
  return ignoreFilePath;
50838
51200
  }
@@ -50874,7 +51236,7 @@ var END_MARKER = "# END AgentInit Generated Files";
50874
51236
  init_agentManager();
50875
51237
  init_skillsManager();
50876
51238
  init_fs();
50877
- import {dirname as dirname6, join as join8} from "path";
51239
+ import {dirname as dirname7, join as join8} from "path";
50878
51240
  async function discoverProjectSkills(projectPath, skillsManager4) {
50879
51241
  const sources = [];
50880
51242
  const skills = new Map;
@@ -50952,7 +51314,7 @@ async function applyProjectSkills(projectPath, targetAgentIds, managedState2, op
50952
51314
  await managedState2.trackGeneratedPath(generatedPath, {
50953
51315
  kind: "directory",
50954
51316
  source: "skills",
50955
- ignorePath: `${dirname6(generatedPath)}/`
51317
+ ignorePath: `${dirname7(generatedPath)}/`
50956
51318
  });
50957
51319
  }
50958
51320
  }
@@ -51063,7 +51425,7 @@ async function applyProjectCommand(options2) {
51063
51425
  if (change.action === "backed_up")
51064
51426
  return;
51065
51427
  const names = change.agents.map((id) => agentManager7.getAgentById(id)?.name || id).join(", ");
51066
- logger.info(` ${relative5(cwd, change.file) || change.file}`);
51428
+ logger.info(` ${relative6(cwd, change.file) || change.file}`);
51067
51429
  logger.info(` Agents: ${names}`);
51068
51430
  });
51069
51431
  }
@@ -51081,7 +51443,7 @@ async function applyProjectCommand(options2) {
51081
51443
  installsByPath.set(item.path, existing);
51082
51444
  }
51083
51445
  for (const [path, details] of installsByPath) {
51084
- logger.info(` ${relative5(cwd, path) || path}`);
51446
+ logger.info(` ${relative6(cwd, path) || path}`);
51085
51447
  logger.info(` Agents: ${[...details.agents].join(", ")}`);
51086
51448
  logger.info(` Skills: ${[...details.skills].join(", ")}`);
51087
51449
  }
@@ -51774,7 +52136,7 @@ async function revertCommand(options2) {
51774
52136
  // dist/commands/skills.js
51775
52137
  var import_prompts2 = __toESM(require_prompts3(), 1);
51776
52138
  import {homedir as homedir5} from "os";
51777
- import {relative as relative6, resolve as resolve12} from "path";
52139
+ import {relative as relative7, resolve as resolve12} from "path";
51778
52140
  init_skillsManager();
51779
52141
  init_marketplaceRegistry();
51780
52142
  init_agentManager();
@@ -51791,28 +52153,8 @@ function registerSkillsCommand(program2) {
51791
52153
  const result = await skillsManager5.discoverFromSource(source, process.cwd(), {
51792
52154
  from: options2.from
51793
52155
  });
51794
- const discoveredSkills = result.skills;
51795
52156
  spinner2.stop();
51796
- if (discoveredSkills.length === 0) {
51797
- logger.info("No skills found in the source.");
51798
- for (const warning of result.warnings) {
51799
- logger.warn(warning);
51800
- }
51801
- return;
51802
- }
51803
- logger.info(`Found ${green(String(discoveredSkills.length))} skill(s):\n`);
51804
- logger.info(" Name Description");
51805
- 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");
51806
- for (const skill of discoveredSkills) {
51807
- const name = skill.name.padEnd(18);
51808
- logger.info(` ${green(name)} ${skill.description}`);
51809
- }
51810
- if (result.warnings.length > 0) {
51811
- logger.info("");
51812
- for (const warning of result.warnings) {
51813
- logger.warn(warning);
51814
- }
51815
- }
52157
+ displayDiscoveredSkills(result.skills, result.warnings);
51816
52158
  } catch (error) {
51817
52159
  spinner2.fail("Failed to discover skills");
51818
52160
  logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -51834,73 +52176,18 @@ function registerSkillsCommand(program2) {
51834
52176
  targetGlobal = selection.global;
51835
52177
  }
51836
52178
  }
52179
+ const buildInstallOptions = (fromOverride) => ({
52180
+ ...fromOverride !== undefined ? { from: fromOverride } : options2.from !== undefined ? { from: options2.from } : {},
52181
+ ...targetGlobal !== undefined ? { global: targetGlobal } : {},
52182
+ ...targetAgents !== undefined ? { agents: targetAgents } : {},
52183
+ ...options2.skill !== undefined ? { skills: options2.skill } : {},
52184
+ ...options2.copy !== undefined ? { copy: options2.copy } : {},
52185
+ ...options2.yes !== undefined ? { yes: options2.yes } : {}
52186
+ });
51837
52187
  const spinner = ora("Installing skills...").start();
51838
52188
  try {
51839
- const installOptions = {
51840
- ...options2.from !== undefined ? { from: options2.from } : {},
51841
- ...targetGlobal !== undefined ? { global: targetGlobal } : {},
51842
- ...targetAgents !== undefined ? { agents: targetAgents } : {},
51843
- ...options2.skill !== undefined ? { skills: options2.skill } : {},
51844
- ...options2.copy !== undefined ? { copy: options2.copy } : {},
51845
- ...options2.yes !== undefined ? { yes: options2.yes } : {}
51846
- };
51847
- const result = await skillsManager5.addFromSource(source, process.cwd(), installOptions);
51848
- if (result.installed.length === 0 && result.skipped.length === 0) {
51849
- spinner.warn("No skills found in the source.");
51850
- for (const warning of result.warnings) {
51851
- logger.warn(warning);
51852
- }
51853
- return;
51854
- }
51855
- if (result.installed.length === 0 && result.skipped.length > 0 && result.skipped.every((skip) => skip.reason === "No target agents found")) {
51856
- spinner.warn("No target agents found.");
51857
- logNoTargetAgentsGuidance(skillsManager5, agentManager9, source, {
51858
- from: options2.from
51859
- });
51860
- if (result.warnings.length > 0) {
51861
- logger.info("");
51862
- for (const warning of result.warnings) {
51863
- logger.warn(warning);
51864
- }
51865
- }
51866
- return;
51867
- }
51868
- const uniqueInstallCount = new Set(result.installed.map((item) => `${item.path}:${item.skill.name}`)).size;
51869
- spinner.succeed(`Installed ${green(String(uniqueInstallCount))} skill(s)`);
51870
- const byPath = new Map;
51871
- for (const item of result.installed) {
51872
- const path = item.path;
51873
- const existing = byPath.get(path) || {
51874
- agents: new Set,
51875
- skills: new Set
51876
- };
51877
- existing.agents.add(agentManager9.getAgentById(item.agent)?.name || item.agent);
51878
- existing.skills.add(item.skill.name);
51879
- byPath.set(path, existing);
51880
- }
51881
- for (const [path, details] of byPath) {
51882
- logger.info(` ${relative6(process.cwd(), path) || path}`);
51883
- logger.info(` Agents: ${[...details.agents].join(", ")}`);
51884
- logger.info(` Skills: ${green(String(details.skills.size))} installed (${[...details.skills].join(", ")})`);
51885
- }
51886
- const copiedFallbacks = result.installed.filter((item) => item.symlinkFailed);
51887
- if (copiedFallbacks.length > 0) {
51888
- logger.warn(`Symlink creation failed for ${copiedFallbacks.length} install(s); copied the skill files instead.`);
51889
- }
51890
- if (result.skipped.length > 0) {
51891
- logger.info("");
51892
- logger.warn(`Skipped ${result.skipped.length} skill(s):`);
51893
- for (const skip of result.skipped) {
51894
- logger.info(` ${skip.skill.name}: ${skip.reason}`);
51895
- }
51896
- }
51897
- if (result.warnings.length > 0) {
51898
- logger.info("");
51899
- for (const warning of result.warnings) {
51900
- logger.warn(warning);
51901
- }
51902
- }
51903
- logger.success("Skills installation complete.");
52189
+ const result = await skillsManager5.addFromSource(source, process.cwd(), buildInstallOptions());
52190
+ displayInstallResult(result, spinner, agentManager9, skillsManager5, source, { from: options2.from });
51904
52191
  } catch (error) {
51905
52192
  spinner.fail("Failed to install skills");
51906
52193
  logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -51942,7 +52229,7 @@ function registerSkillsCommand(program2) {
51942
52229
  const mode = skill.mode === "symlink" ? " (canonical)" : "";
51943
52230
  const scope = skill.scope === "global" ? " [global]" : "";
51944
52231
  logger.info(`\n ${green(skill.name)} - ${skill.description}${scope}${mode}`);
51945
- logger.info(` Path: ${relative6(process.cwd(), skill.path) || skill.path}`);
52232
+ logger.info(` Path: ${relative7(process.cwd(), skill.path) || skill.path}`);
51946
52233
  logger.info(` Agents: ${[...skill.agents].join(", ")}`);
51947
52234
  }
51948
52235
  });
@@ -52135,7 +52422,7 @@ var formatSkillsDir = function(projectPath, dir) {
52135
52422
  const normalizedProjectPath = projectPath.replace(/\\/g, "/");
52136
52423
  const normalizedHome = homedir5().replace(/\\/g, "/");
52137
52424
  if (normalizedDir.startsWith(`${normalizedProjectPath}/`)) {
52138
- return `${relative6(projectPath, dir).replace(/\\/g, "/").replace(/\/?$/, "/")}`;
52425
+ return `${relative7(projectPath, dir).replace(/\\/g, "/").replace(/\/?$/, "/")}`;
52139
52426
  }
52140
52427
  if (normalizedDir.startsWith(`${normalizedHome}/`)) {
52141
52428
  return normalizedDir.replace(normalizedHome, "~");
@@ -52223,6 +52510,86 @@ var buildSkillsAddCommand = function(source, from, extraArgs) {
52223
52510
  args.push(...extraArgs);
52224
52511
  return args.join(" ");
52225
52512
  };
52513
+ var displayDiscoveredSkills = function(skills, warnings) {
52514
+ if (skills.length === 0) {
52515
+ logger.info("No skills found in the source.");
52516
+ for (const warning of warnings) {
52517
+ logger.warn(warning);
52518
+ }
52519
+ return;
52520
+ }
52521
+ logger.info(`Found ${green(String(skills.length))} skill(s):\n`);
52522
+ logger.info(" Name Description");
52523
+ 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");
52524
+ for (const skill of skills) {
52525
+ const name = skill.name.padEnd(18);
52526
+ logger.info(` ${green(name)} ${skill.description}`);
52527
+ }
52528
+ if (warnings.length > 0) {
52529
+ logger.info("");
52530
+ for (const warning of warnings) {
52531
+ logger.warn(warning);
52532
+ }
52533
+ }
52534
+ };
52535
+ var displayInstallResult = function(result, spinner, agentManager9, skillsManager5, source, options2) {
52536
+ if (result.installed.length === 0 && result.skipped.length === 0) {
52537
+ spinner.warn("No skills found in the source.");
52538
+ for (const warning of result.warnings) {
52539
+ logger.warn(warning);
52540
+ }
52541
+ return;
52542
+ }
52543
+ if (result.installed.length === 0 && result.skipped.length > 0 && result.skipped.every((skip) => skip.reason === "No target agents found")) {
52544
+ spinner.warn("No target agents found.");
52545
+ logNoTargetAgentsGuidance(skillsManager5, agentManager9, source, {
52546
+ ...options2.from !== undefined ? { from: options2.from } : {}
52547
+ });
52548
+ if (result.warnings.length > 0) {
52549
+ logger.info("");
52550
+ for (const warning of result.warnings) {
52551
+ logger.warn(warning);
52552
+ }
52553
+ }
52554
+ return;
52555
+ }
52556
+ const uniqueInstallCount = new Set(result.installed.map((item) => `${item.path}:${item.skill.name}`)).size;
52557
+ spinner.succeed(`Installed ${green(String(uniqueInstallCount))} skill(s)`);
52558
+ const byPath = new Map;
52559
+ for (const item of result.installed) {
52560
+ const path = item.path;
52561
+ const existing = byPath.get(path) || {
52562
+ agents: new Set,
52563
+ skills: new Set
52564
+ };
52565
+ existing.agents.add(agentManager9.getAgentById(item.agent)?.name || item.agent);
52566
+ existing.skills.add(item.skill.name);
52567
+ byPath.set(path, existing);
52568
+ }
52569
+ for (const [path, details] of byPath) {
52570
+ logger.info(` ${relative7(process.cwd(), path) || path}`);
52571
+ logger.info(` Agents: ${[...details.agents].join(", ")}`);
52572
+ logger.info(` Skills: ${green(String(details.skills.size))} installed (${[...details.skills].join(", ")})`);
52573
+ }
52574
+ const copiedFallbacks = result.installed.filter((item) => item.symlinkFailed);
52575
+ if (copiedFallbacks.length > 0) {
52576
+ logger.warn(`Symlink creation failed for ${copiedFallbacks.length} install(s); copied the skill files instead.`);
52577
+ }
52578
+ if (result.skipped.length > 0) {
52579
+ logger.info("");
52580
+ logger.warn(`Skipped ${result.skipped.length} skill(s):`);
52581
+ for (const skip of result.skipped) {
52582
+ logger.info(` ${skip.skill.name}: ${skip.reason}`);
52583
+ }
52584
+ }
52585
+ if (result.warnings.length > 0) {
52586
+ logger.info("");
52587
+ for (const warning of result.warnings) {
52588
+ logger.warn(warning);
52589
+ }
52590
+ }
52591
+ logger.success("Skills installation complete.");
52592
+ };
52226
52593
 
52227
52594
  // dist/commands/mcp.js
52228
52595
  init_mcpFilter();
@@ -53088,7 +53455,8 @@ function registerPluginsCommand(program2) {
53088
53455
  const p = result.plugin;
53089
53456
  const totalSkills = result.skills.installed.length;
53090
53457
  const totalMcp = result.mcpServers.applied.length;
53091
- if (totalSkills === 0 && totalMcp === 0) {
53458
+ const totalNative = result.nativePlugins.installed.length;
53459
+ if (totalSkills === 0 && totalMcp === 0 && totalNative === 0) {
53092
53460
  spinner.warn(`Plugin "${p.name}" has no portable components to install.`);
53093
53461
  if (result.warnings.length > 0) {
53094
53462
  for (const w of result.warnings) {
@@ -53122,7 +53490,12 @@ function registerPluginsCommand(program2) {
53122
53490
  logger.info(` ${agent}: ${cyan(String(servers.length))} MCP server(s) [${servers.join(", ")}]`);
53123
53491
  }
53124
53492
  }
53125
- if (result.skills.skipped.length > 0 || result.mcpServers.skipped.length > 0) {
53493
+ if (totalNative > 0) {
53494
+ for (const nativePlugin of result.nativePlugins.installed) {
53495
+ logger.info(` ${nativePlugin.agent}: native plugin payload installed at ${nativePlugin.installPath}`);
53496
+ }
53497
+ }
53498
+ if (result.skills.skipped.length > 0 || result.mcpServers.skipped.length > 0 || result.nativePlugins.skipped.length > 0) {
53126
53499
  console.log("");
53127
53500
  for (const s of result.skills.skipped) {
53128
53501
  logger.debug(`Skipped skill ${s.name}: ${s.reason}`);
@@ -53130,6 +53503,9 @@ function registerPluginsCommand(program2) {
53130
53503
  for (const s of result.mcpServers.skipped) {
53131
53504
  logger.debug(`Skipped MCP ${s.name}: ${s.reason}`);
53132
53505
  }
53506
+ for (const s of result.nativePlugins.skipped) {
53507
+ logger.warn(`Skipped native plugin payload for ${s.agent}: ${s.reason}`);
53508
+ }
53133
53509
  }
53134
53510
  if (result.warnings.length > 0) {
53135
53511
  console.log("");
@@ -53209,6 +53585,10 @@ function registerPluginsCommand(program2) {
53209
53585
  const agents = [...new Set(p.components.mcpServers.map((m) => m.agent))];
53210
53586
  logger.info(` MCP: ${p.components.mcpServers.length} \u2192 ${agents.join(", ")}`);
53211
53587
  }
53588
+ if ((p.components.nativePlugins || []).length > 0) {
53589
+ const agents = [...new Set((p.components.nativePlugins || []).map((nativePlugin) => nativePlugin.agent))];
53590
+ logger.info(` Native Plugins: ${(p.components.nativePlugins || []).length} \u2192 ${agents.join(", ")}`);
53591
+ }
53212
53592
  if (p.warnings.length > 0) {
53213
53593
  for (const w of p.warnings) {
53214
53594
  logger.warn(` ${w}`);