agentinit 1.14.0 → 1.15.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
@@ -16717,15 +16717,207 @@ var init_agentManager = __esm(() => {
16717
16717
  init_ZedAgent();
16718
16718
  });
16719
16719
 
16720
+ // dist/core/userConfig.js
16721
+ import {existsSync, readFileSync} from "fs";
16722
+ import {promises as fs20} from "fs";
16723
+ import {homedir as homedir3} from "os";
16724
+ import {join as join3} from "path";
16725
+ function getUserConfigPath() {
16726
+ return join3(homedir3(), ".agentinit", "config.json");
16727
+ }
16728
+ function createDefaultUserConfig() {
16729
+ return {
16730
+ customMarketplaces: [],
16731
+ verifiedGithubRepos: []
16732
+ };
16733
+ }
16734
+ function normalizeMarketplaceIdentifier(identifier) {
16735
+ const normalized = identifier.trim().toLowerCase();
16736
+ if (!MARKETPLACE_IDENTIFIER_PATTERN.test(normalized)) {
16737
+ throw new Error('Invalid marketplace identifier. Use lowercase letters, numbers, ".", "_" or "-".');
16738
+ }
16739
+ return normalized;
16740
+ }
16741
+ function normalizeMarketplaceName(name, identifier) {
16742
+ const normalized = name?.trim();
16743
+ return normalized ? normalized : identifier;
16744
+ }
16745
+ function normalizeMarketplaceRepoUrl(repoUrl) {
16746
+ const normalized = repoUrl.trim().replace(/\/+$/, "");
16747
+ if (!normalized || !GIT_REPO_URL_PATTERN.test(normalized)) {
16748
+ throw new Error("Invalid marketplace repo URL. Use https://..., ssh://..., or git@...");
16749
+ }
16750
+ return normalized;
16751
+ }
16752
+ function normalizeGitHubRepoRef(repo) {
16753
+ const normalized = repo.trim();
16754
+ const match = normalized.match(GITHUB_REPO_PATTERN);
16755
+ if (!match) {
16756
+ throw new Error("Invalid GitHub repo. Use exact owner/repo.");
16757
+ }
16758
+ return `${match[1].toLowerCase()}/${match[2].toLowerCase()}`;
16759
+ }
16760
+ function sanitizeUserConfig(raw) {
16761
+ const defaults = createDefaultUserConfig();
16762
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
16763
+ return defaults;
16764
+ }
16765
+ const parsed = raw;
16766
+ const seenMarketplaces = new Set;
16767
+ const customMarketplaces = [];
16768
+ if (Array.isArray(parsed.customMarketplaces)) {
16769
+ for (const entry of parsed.customMarketplaces) {
16770
+ const sanitized = sanitizeCustomMarketplaceConfig(entry);
16771
+ if (!sanitized || seenMarketplaces.has(sanitized.identifier)) {
16772
+ continue;
16773
+ }
16774
+ seenMarketplaces.add(sanitized.identifier);
16775
+ customMarketplaces.push(sanitized);
16776
+ }
16777
+ }
16778
+ const seenRepos = new Set;
16779
+ const verifiedGithubRepos = [];
16780
+ if (Array.isArray(parsed.verifiedGithubRepos)) {
16781
+ for (const entry of parsed.verifiedGithubRepos) {
16782
+ if (typeof entry !== "string") {
16783
+ continue;
16784
+ }
16785
+ try {
16786
+ const normalized = normalizeGitHubRepoRef(entry);
16787
+ if (seenRepos.has(normalized)) {
16788
+ continue;
16789
+ }
16790
+ seenRepos.add(normalized);
16791
+ verifiedGithubRepos.push(normalized);
16792
+ } catch {
16793
+ continue;
16794
+ }
16795
+ }
16796
+ }
16797
+ let defaultMarketplace;
16798
+ if (typeof parsed.defaultMarketplace === "string") {
16799
+ try {
16800
+ defaultMarketplace = normalizeMarketplaceIdentifier(parsed.defaultMarketplace);
16801
+ } catch {
16802
+ defaultMarketplace = undefined;
16803
+ }
16804
+ }
16805
+ return {
16806
+ ...defaultMarketplace ? { defaultMarketplace } : {},
16807
+ customMarketplaces,
16808
+ verifiedGithubRepos
16809
+ };
16810
+ }
16811
+ function readUserConfigSync() {
16812
+ const configPath = getUserConfigPath();
16813
+ if (!existsSync(configPath)) {
16814
+ return createDefaultUserConfig();
16815
+ }
16816
+ try {
16817
+ const content = readFileSync(configPath, "utf8");
16818
+ return sanitizeUserConfig(JSON.parse(content));
16819
+ } catch {
16820
+ return createDefaultUserConfig();
16821
+ }
16822
+ }
16823
+ async function readUserConfig() {
16824
+ const configPath = getUserConfigPath();
16825
+ try {
16826
+ const content = await fs20.readFile(configPath, "utf8");
16827
+ return sanitizeUserConfig(JSON.parse(content));
16828
+ } catch {
16829
+ return createDefaultUserConfig();
16830
+ }
16831
+ }
16832
+ async function writeUserConfig(config) {
16833
+ const sanitized = sanitizeUserConfig(config);
16834
+ await writeFile(getUserConfigPath(), `${JSON.stringify(sanitized, null, 2)}\n`);
16835
+ }
16836
+ function getBuiltInVerifiedGithubRepos() {
16837
+ return [...BUILTIN_VERIFIED_GITHUB_REPOS];
16838
+ }
16839
+ function getEffectiveVerifiedGithubReposSync() {
16840
+ const repos = new Set(BUILTIN_VERIFIED_GITHUB_REPOS);
16841
+ for (const repo of readUserConfigSync().verifiedGithubRepos) {
16842
+ repos.add(repo);
16843
+ }
16844
+ return [...repos];
16845
+ }
16846
+ function isVerifiedGitHubRepoSync(owner, repo) {
16847
+ const normalized = normalizeGitHubRepoRef(`${owner}/${repo}`);
16848
+ return getEffectiveVerifiedGithubReposSync().includes(normalized);
16849
+ }
16850
+ var sanitizeCustomMarketplaceConfig, MARKETPLACE_IDENTIFIER_PATTERN, GITHUB_REPO_PATTERN, GIT_REPO_URL_PATTERN, BUILTIN_VERIFIED_GITHUB_REPOS;
16851
+ var init_userConfig = __esm(() => {
16852
+ init_fs();
16853
+ sanitizeCustomMarketplaceConfig = function(entry) {
16854
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
16855
+ return null;
16856
+ }
16857
+ const candidate = entry;
16858
+ try {
16859
+ const identifier = normalizeMarketplaceIdentifier(String(candidate.identifier || ""));
16860
+ return {
16861
+ identifier,
16862
+ name: normalizeMarketplaceName(typeof candidate.name === "string" ? candidate.name : undefined, identifier),
16863
+ repoUrl: normalizeMarketplaceRepoUrl(String(candidate.repoUrl || ""))
16864
+ };
16865
+ } catch {
16866
+ return null;
16867
+ }
16868
+ };
16869
+ MARKETPLACE_IDENTIFIER_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
16870
+ GITHUB_REPO_PATTERN = /^([A-Za-z0-9._-]+)\/([A-Za-z0-9._-]+)$/;
16871
+ GIT_REPO_URL_PATTERN = /^(https?:\/\/|ssh:\/\/|git@).+/;
16872
+ BUILTIN_VERIFIED_GITHUB_REPOS = ["openai/codex-plugin-cc"];
16873
+ });
16874
+
16720
16875
  // dist/core/marketplaceRegistry.js
16876
+ function getMarketplaceCategoryForDir(dir) {
16877
+ if (dir === "plugins") {
16878
+ return "official";
16879
+ }
16880
+ if (dir === "external_plugins") {
16881
+ return "community";
16882
+ }
16883
+ if (dir.startsWith("skills/.")) {
16884
+ return dir.slice("skills/.".length);
16885
+ }
16886
+ return dir;
16887
+ }
16721
16888
  function getMarketplace(id) {
16722
- return MARKETPLACES.find((marketplace) => marketplace.id === id);
16889
+ return getAllMarketplaces().find((marketplace) => marketplace.id === id);
16723
16890
  }
16724
16891
  function getMarketplaceIds() {
16725
- return MARKETPLACES.map((marketplace) => marketplace.id);
16892
+ return getAllMarketplaces().map((marketplace) => marketplace.id);
16893
+ }
16894
+ function getMarketplaceCategories(id) {
16895
+ const marketplaces = id ? [getMarketplace(id)].filter((marketplace) => !!marketplace) : getAllMarketplaces();
16896
+ return [...new Set(marketplaces.flatMap((marketplace) => marketplace.pluginDirs.map(getMarketplaceCategoryForDir)))];
16897
+ }
16898
+ function getConfiguredDefaultMarketplaceId() {
16899
+ const defaultMarketplace = readUserConfigSync().defaultMarketplace;
16900
+ if (!defaultMarketplace) {
16901
+ return;
16902
+ }
16903
+ return getMarketplace(defaultMarketplace)?.id;
16726
16904
  }
16727
- var MARKETPLACES;
16905
+ var getCustomMarketplaces, getAllMarketplaces, MARKETPLACES, CUSTOM_MARKETPLACE_PLUGIN_DIRS, CUSTOM_MARKETPLACE_CACHE_TTL_MS;
16728
16906
  var init_marketplaceRegistry = __esm(() => {
16907
+ init_userConfig();
16908
+ getCustomMarketplaces = function() {
16909
+ const builtInIds = new Set(MARKETPLACES.map((marketplace) => marketplace.id));
16910
+ return readUserConfigSync().customMarketplaces.filter((marketplace) => !builtInIds.has(marketplace.identifier)).map((marketplace) => ({
16911
+ id: marketplace.identifier,
16912
+ name: marketplace.name,
16913
+ repoUrl: marketplace.repoUrl,
16914
+ pluginDirs: [...CUSTOM_MARKETPLACE_PLUGIN_DIRS],
16915
+ cacheTtlMs: CUSTOM_MARKETPLACE_CACHE_TTL_MS
16916
+ }));
16917
+ };
16918
+ getAllMarketplaces = function() {
16919
+ return [...MARKETPLACES, ...getCustomMarketplaces()];
16920
+ };
16729
16921
  MARKETPLACES = [
16730
16922
  {
16731
16923
  id: "agentinit",
@@ -16749,6 +16941,8 @@ var init_marketplaceRegistry = __esm(() => {
16749
16941
  cacheTtlMs: 3600000
16750
16942
  }
16751
16943
  ];
16944
+ CUSTOM_MARKETPLACE_PLUGIN_DIRS = ["skills", "mcps", "rules"];
16945
+ CUSTOM_MARKETPLACE_CACHE_TTL_MS = 3600000;
16752
16946
  });
16753
16947
 
16754
16948
  // dist/core/mcpFilter.js
@@ -16860,9 +17054,9 @@ __export(exports_pluginManager, {
16860
17054
  }
16861
17055
  }
16862
17056
  });
16863
- import {resolve as resolve7, join as join3, basename as basename2, relative as relative2, dirname as dirname2} from "path";
16864
- import {promises as fs20} from "fs";
16865
- import {homedir as homedir3} from "os";
17057
+ import {resolve as resolve7, join as join4, basename as basename2, relative as relative2, dirname as dirname2} from "path";
17058
+ import {promises as fs22} from "fs";
17059
+ import {homedir as homedir4} from "os";
16866
17060
 
16867
17061
  class MarketplacePluginNotFoundError extends Error {
16868
17062
  pluginName;
@@ -16896,7 +17090,7 @@ class PluginManager {
16896
17090
  }
16897
17091
  async cleanupLoadedPluginContext(context) {
16898
17092
  if (context?.tempDir) {
16899
- await fs20.rm(context.tempDir, { recursive: true, force: true }).catch(() => {
17093
+ await fs22.rm(context.tempDir, { recursive: true, force: true }).catch(() => {
16900
17094
  });
16901
17095
  }
16902
17096
  }
@@ -16968,13 +17162,13 @@ class PluginManager {
16968
17162
  return `https://github.com/${source.owner}/${source.repo}`;
16969
17163
  }
16970
17164
  getGitHubFallbackTrust(source) {
16971
- if (source.owner === "openai" && source.repo === "codex-plugin-cc") {
17165
+ if (source.owner && source.repo && isVerifiedGitHubRepoSync(source.owner, source.repo)) {
16972
17166
  return "verified";
16973
17167
  }
16974
17168
  return "unverified";
16975
17169
  }
16976
17170
  async resolvePreparedPluginDir(pluginDir, source) {
16977
- const claudeMarketplaceManifestPath = join3(pluginDir, ".claude-plugin", "marketplace.json");
17171
+ const claudeMarketplaceManifestPath = join4(pluginDir, ".claude-plugin", "marketplace.json");
16978
17172
  if (!await fileExists(claudeMarketplaceManifestPath)) {
16979
17173
  return { pluginDir, warnings: [] };
16980
17174
  }
@@ -17115,13 +17309,13 @@ class PluginManager {
17115
17309
  }
17116
17310
  async getClaudeNativeFeatureKinds(pluginDir, manifest) {
17117
17311
  const featureChecks = await Promise.all([
17118
- (async () => !!manifest.commands || await isDirectory(join3(pluginDir, "commands")))(),
17119
- (async () => !!manifest.hooks || await isDirectory(join3(pluginDir, "hooks")))(),
17120
- (async () => !!manifest.agents || await isDirectory(join3(pluginDir, "agents")))(),
17121
- isDirectory(join3(pluginDir, "prompts")),
17122
- isDirectory(join3(pluginDir, "schemas")),
17123
- isDirectory(join3(pluginDir, "scripts")),
17124
- isDirectory(join3(pluginDir, "templates"))
17312
+ (async () => !!manifest.commands || await isDirectory(join4(pluginDir, "commands")))(),
17313
+ (async () => !!manifest.hooks || await isDirectory(join4(pluginDir, "hooks")))(),
17314
+ (async () => !!manifest.agents || await isDirectory(join4(pluginDir, "agents")))(),
17315
+ isDirectory(join4(pluginDir, "prompts")),
17316
+ isDirectory(join4(pluginDir, "schemas")),
17317
+ isDirectory(join4(pluginDir, "scripts")),
17318
+ isDirectory(join4(pluginDir, "templates"))
17125
17319
  ]);
17126
17320
  return [
17127
17321
  ...featureChecks[0] ? ["commands"] : [],
@@ -17137,7 +17331,7 @@ class PluginManager {
17137
17331
  if (plugin.format !== "claude") {
17138
17332
  return null;
17139
17333
  }
17140
- const manifestContent = await readFileIfExists(join3(pluginDir, ".claude-plugin", "plugin.json"));
17334
+ const manifestContent = await readFileIfExists(join4(pluginDir, ".claude-plugin", "plugin.json"));
17141
17335
  if (!manifestContent) {
17142
17336
  return null;
17143
17337
  }
@@ -17157,7 +17351,7 @@ class PluginManager {
17157
17351
  return {
17158
17352
  namespace,
17159
17353
  pluginKey: `${plugin.name}@${namespace}`,
17160
- installPath: join3(homedir3(), ".claude", "plugins", "cache", namespace, plugin.name, versionDir),
17354
+ installPath: join4(homedir4(), ".claude", "plugins", "cache", namespace, plugin.name, versionDir),
17161
17355
  features
17162
17356
  };
17163
17357
  }
@@ -17230,10 +17424,10 @@ class PluginManager {
17230
17424
  warnings.push(`Skipped native Claude plugin install because Claude already has "${plugin.name}" installed as ${conflictingKey}.`);
17231
17425
  return { installed, skipped, warnings };
17232
17426
  }
17233
- await fs20.rm(nativeTarget.installPath, { recursive: true, force: true }).catch(() => {
17427
+ await fs22.rm(nativeTarget.installPath, { recursive: true, force: true }).catch(() => {
17234
17428
  });
17235
- await fs20.mkdir(dirname2(nativeTarget.installPath), { recursive: true });
17236
- await fs20.cp(pluginDir, nativeTarget.installPath, { recursive: true, dereference: true });
17429
+ await fs22.mkdir(dirname2(nativeTarget.installPath), { recursive: true });
17430
+ await fs22.cp(pluginDir, nativeTarget.installPath, { recursive: true, dereference: true });
17237
17431
  const now = new Date().toISOString();
17238
17432
  claudeInstalled.plugins[nativeTarget.pluginKey] = [{
17239
17433
  scope: "user",
@@ -17281,7 +17475,7 @@ class PluginManager {
17281
17475
  claudeSettings.enabledPlugins = remainingEnabledPlugins;
17282
17476
  await this.saveClaudeSettings(claudeSettings);
17283
17477
  }
17284
- await fs20.rm(component.installPath, { recursive: true, force: true }).catch(() => {
17478
+ await fs22.rm(component.installPath, { recursive: true, force: true }).catch(() => {
17285
17479
  });
17286
17480
  return true;
17287
17481
  }
@@ -17332,7 +17526,7 @@ class PluginManager {
17332
17526
  repo
17333
17527
  };
17334
17528
  }
17335
- const defaultMarketplace = this.getMarketplaceIds()[0];
17529
+ const defaultMarketplace = getConfiguredDefaultMarketplaceId() || this.getMarketplaceIds()[0];
17336
17530
  if (defaultMarketplace) {
17337
17531
  return {
17338
17532
  type: "marketplace",
@@ -17351,43 +17545,81 @@ class PluginManager {
17351
17545
  async ensureMarketplaceCache(registryId) {
17352
17546
  const registry = this.getMarketplace(registryId);
17353
17547
  if (!registry) {
17354
- throw new Error(`Unknown marketplace: ${registryId}. Available: ${MARKETPLACES.map((m) => m.id).join(", ")}`);
17548
+ throw new Error(`Unknown marketplace: ${registryId}. Available: ${this.getMarketplaceIds().join(", ")}`);
17355
17549
  }
17356
17550
  const cacheDir = getMarketplaceCacheDir(registryId);
17357
- const cacheMetaPath = join3(cacheDir, ".agentinit-cache-meta.json");
17358
- if (await fileExists(cacheMetaPath)) {
17359
- try {
17360
- const meta = JSON.parse(await fs20.readFile(cacheMetaPath, "utf8"));
17361
- const age = Date.now() - (meta.fetchedAt || 0);
17362
- if (age < registry.cacheTtlMs) {
17363
- return cacheDir;
17364
- }
17365
- } catch {
17366
- }
17367
- }
17368
- if (await fileExists(join3(cacheDir, ".git"))) {
17369
- const { execFile } = await import("child_process");
17370
- const { promisify } = await import("util");
17371
- const exec = promisify(execFile);
17372
- try {
17373
- await exec("git", ["pull", "--ff-only"], { cwd: cacheDir, timeout: 30000 });
17374
- } catch {
17375
- await fs20.rm(cacheDir, { recursive: true, force: true });
17551
+ const cacheMetaPath = join4(cacheDir, ".agentinit-cache-meta.json");
17552
+ const cacheMeta = await this.readMarketplaceCacheMeta(cacheMetaPath);
17553
+ if (cacheMeta?.repoUrl === registry.repoUrl) {
17554
+ const age = Date.now() - cacheMeta.fetchedAt;
17555
+ if (age < registry.cacheTtlMs) {
17556
+ return cacheDir;
17557
+ }
17558
+ }
17559
+ if (await fileExists(join4(cacheDir, ".git"))) {
17560
+ const originUrl = await this.getMarketplaceCacheOriginUrl(cacheDir);
17561
+ if (originUrl !== registry.repoUrl) {
17562
+ await fs22.rm(cacheDir, { recursive: true, force: true });
17376
17563
  await this.cloneMarketplace(registry.repoUrl, cacheDir);
17564
+ } else {
17565
+ const { execFile } = await import("child_process");
17566
+ const { promisify } = await import("util");
17567
+ const exec = promisify(execFile);
17568
+ try {
17569
+ await exec("git", ["pull", "--ff-only"], { cwd: cacheDir, timeout: 30000 });
17570
+ } catch {
17571
+ await fs22.rm(cacheDir, { recursive: true, force: true });
17572
+ await this.cloneMarketplace(registry.repoUrl, cacheDir);
17573
+ }
17377
17574
  }
17378
17575
  } else {
17379
17576
  await this.cloneMarketplace(registry.repoUrl, cacheDir);
17380
17577
  }
17381
- await fs20.mkdir(cacheDir, { recursive: true });
17382
- await fs20.writeFile(cacheMetaPath, JSON.stringify({ fetchedAt: Date.now() }));
17578
+ await fs22.mkdir(cacheDir, { recursive: true });
17579
+ await fs22.writeFile(cacheMetaPath, JSON.stringify({
17580
+ fetchedAt: Date.now(),
17581
+ repoUrl: registry.repoUrl
17582
+ }));
17383
17583
  return cacheDir;
17384
17584
  }
17585
+ async readMarketplaceCacheMeta(cacheMetaPath) {
17586
+ if (!await fileExists(cacheMetaPath)) {
17587
+ return null;
17588
+ }
17589
+ try {
17590
+ const meta = JSON.parse(await fs22.readFile(cacheMetaPath, "utf8"));
17591
+ if (typeof meta.fetchedAt !== "number") {
17592
+ return null;
17593
+ }
17594
+ return {
17595
+ fetchedAt: meta.fetchedAt,
17596
+ ...typeof meta.repoUrl === "string" ? { repoUrl: meta.repoUrl } : {}
17597
+ };
17598
+ } catch {
17599
+ return null;
17600
+ }
17601
+ }
17602
+ async getMarketplaceCacheOriginUrl(cacheDir) {
17603
+ const { execFile } = await import("child_process");
17604
+ const { promisify } = await import("util");
17605
+ const exec = promisify(execFile);
17606
+ try {
17607
+ const { stdout } = await exec("git", ["config", "--get", "remote.origin.url"], {
17608
+ cwd: cacheDir,
17609
+ timeout: 30000
17610
+ });
17611
+ const originUrl = stdout.trim();
17612
+ return originUrl || null;
17613
+ } catch {
17614
+ return null;
17615
+ }
17616
+ }
17385
17617
  async cloneMarketplace(repoUrl, dest) {
17386
- await fs20.mkdir(dest, { recursive: true });
17618
+ await fs22.mkdir(dest, { recursive: true });
17387
17619
  const { execFile } = await import("child_process");
17388
17620
  const { promisify } = await import("util");
17389
17621
  const exec = promisify(execFile);
17390
- await fs20.rm(dest, { recursive: true, force: true }).catch(() => {
17622
+ await fs22.rm(dest, { recursive: true, force: true }).catch(() => {
17391
17623
  });
17392
17624
  await exec("git", ["clone", "--depth", "1", repoUrl, dest], { timeout: 60000 });
17393
17625
  }
@@ -17397,7 +17629,7 @@ class PluginManager {
17397
17629
  throw new Error(`Unknown marketplace: ${registryId}`);
17398
17630
  const cacheDir = await this.ensureMarketplaceCache(registryId);
17399
17631
  for (const dir of registry.pluginDirs) {
17400
- const pluginPath = join3(cacheDir, dir, name);
17632
+ const pluginPath = join4(cacheDir, dir, name);
17401
17633
  if (await isDirectory(pluginPath)) {
17402
17634
  return pluginPath;
17403
17635
  }
@@ -17413,36 +17645,36 @@ class PluginManager {
17413
17645
  const cacheDir = await this.ensureMarketplaceCache(registryId);
17414
17646
  const results = [];
17415
17647
  for (const dir of registry.pluginDirs) {
17416
- const fullDir = join3(cacheDir, dir);
17648
+ const fullDir = join4(cacheDir, dir);
17417
17649
  if (!await isDirectory(fullDir))
17418
17650
  continue;
17419
- const cat = dir === "plugins" ? "official" : dir === "external_plugins" ? "community" : dir.startsWith("skills/.") ? dir.slice("skills/.".length) : dir;
17651
+ const cat = getMarketplaceCategoryForDir(dir);
17420
17652
  if (category && cat !== category)
17421
17653
  continue;
17422
17654
  const entries = await listFiles(fullDir);
17423
17655
  for (const entry of entries) {
17424
17656
  if (entry.startsWith("."))
17425
17657
  continue;
17426
- const entryPath = join3(fullDir, entry);
17658
+ const entryPath = join4(fullDir, entry);
17427
17659
  if (!await isDirectory(entryPath))
17428
17660
  continue;
17429
- const manifestPath = join3(entryPath, ".claude-plugin", "plugin.json");
17661
+ const manifestPath = join4(entryPath, ".claude-plugin", "plugin.json");
17430
17662
  let name = entry;
17431
17663
  let description = "";
17432
17664
  let version = "0.0.0";
17433
17665
  if (await fileExists(manifestPath)) {
17434
17666
  try {
17435
- const manifest = JSON.parse(await fs20.readFile(manifestPath, "utf8"));
17667
+ const manifest = JSON.parse(await fs22.readFile(manifestPath, "utf8"));
17436
17668
  name = manifest.name || entry;
17437
17669
  description = manifest.description || "";
17438
17670
  version = manifest.version || "0.0.0";
17439
17671
  } catch {
17440
17672
  }
17441
17673
  } else {
17442
- const skillMdPath = join3(entryPath, "SKILL.md");
17674
+ const skillMdPath = join4(entryPath, "SKILL.md");
17443
17675
  if (await fileExists(skillMdPath)) {
17444
17676
  try {
17445
- const parsed = import_gray_matter.default(await fs20.readFile(skillMdPath, "utf8"));
17677
+ const parsed = import_gray_matter.default(await fs22.readFile(skillMdPath, "utf8"));
17446
17678
  if (parsed.data.name)
17447
17679
  name = parsed.data.name;
17448
17680
  if (parsed.data.description)
@@ -17450,10 +17682,10 @@ class PluginManager {
17450
17682
  } catch {
17451
17683
  }
17452
17684
  } else {
17453
- const mcpPath = join3(entryPath, ".mcp.json");
17685
+ const mcpPath = join4(entryPath, ".mcp.json");
17454
17686
  if (await fileExists(mcpPath)) {
17455
17687
  try {
17456
- const mcpConfig = JSON.parse(await fs20.readFile(mcpPath, "utf8"));
17688
+ const mcpConfig = JSON.parse(await fs22.readFile(mcpPath, "utf8"));
17457
17689
  const serverNames = Object.keys(mcpConfig.mcpServers || mcpConfig);
17458
17690
  if (serverNames.length > 0) {
17459
17691
  description = `MCP server(s): ${serverNames.join(", ")}`;
@@ -17475,10 +17707,10 @@ class PluginManager {
17475
17707
  return results.sort((a, b) => a.name.localeCompare(b.name));
17476
17708
  }
17477
17709
  async detectFormat(pluginDir) {
17478
- if (await fileExists(join3(pluginDir, ".claude-plugin", "plugin.json"))) {
17710
+ if (await fileExists(join4(pluginDir, ".claude-plugin", "plugin.json"))) {
17479
17711
  return "claude";
17480
17712
  }
17481
- if (await fileExists(join3(pluginDir, ".cursor-plugin", "plugin.json"))) {
17713
+ if (await fileExists(join4(pluginDir, ".cursor-plugin", "plugin.json"))) {
17482
17714
  return "cursor";
17483
17715
  }
17484
17716
  return "generic";
@@ -17495,7 +17727,7 @@ class PluginManager {
17495
17727
  }
17496
17728
  }
17497
17729
  async parseClaudePlugin(pluginDir, source) {
17498
- const manifestPath = join3(pluginDir, ".claude-plugin", "plugin.json");
17730
+ const manifestPath = join4(pluginDir, ".claude-plugin", "plugin.json");
17499
17731
  const manifestContent = await readFileIfExists(manifestPath);
17500
17732
  if (!manifestContent) {
17501
17733
  throw new Error(`Missing .claude-plugin/plugin.json in ${pluginDir}`);
@@ -17506,10 +17738,10 @@ class PluginManager {
17506
17738
  const convertedSkills = await this.convertCommandsToSkills(pluginDir, manifest);
17507
17739
  skills.push(...convertedSkills);
17508
17740
  const mcpServers = await this.parseMcpJson(pluginDir);
17509
- if (await isDirectory(join3(pluginDir, "hooks")) || manifest.hooks) {
17741
+ if (await isDirectory(join4(pluginDir, "hooks")) || manifest.hooks) {
17510
17742
  warnings.push("Hooks (hooks/) are Claude Code-specific");
17511
17743
  }
17512
- if (await isDirectory(join3(pluginDir, "agents")) || manifest.agents) {
17744
+ if (await isDirectory(join4(pluginDir, "agents")) || manifest.agents) {
17513
17745
  warnings.push("Agent definitions (agents/) are Claude Code-specific");
17514
17746
  }
17515
17747
  return {
@@ -17524,7 +17756,7 @@ class PluginManager {
17524
17756
  };
17525
17757
  }
17526
17758
  async parseCursorPlugin(pluginDir, source) {
17527
- const manifestPath = join3(pluginDir, ".cursor-plugin", "plugin.json");
17759
+ const manifestPath = join4(pluginDir, ".cursor-plugin", "plugin.json");
17528
17760
  const manifestContent = await readFileIfExists(manifestPath);
17529
17761
  if (!manifestContent) {
17530
17762
  throw new Error(`Missing .cursor-plugin/plugin.json in ${pluginDir}`);
@@ -17563,7 +17795,7 @@ class PluginManager {
17563
17795
  };
17564
17796
  }
17565
17797
  async parseMcpJson(pluginDir) {
17566
- const mcpPath = join3(pluginDir, ".mcp.json");
17798
+ const mcpPath = join4(pluginDir, ".mcp.json");
17567
17799
  const content = await readFileIfExists(mcpPath);
17568
17800
  if (!content)
17569
17801
  return [];
@@ -17610,7 +17842,7 @@ class PluginManager {
17610
17842
  commandsDirs.push(resolve7(pluginDir, cmd));
17611
17843
  }
17612
17844
  } else {
17613
- commandsDirs.push(join3(pluginDir, "commands"));
17845
+ commandsDirs.push(join4(pluginDir, "commands"));
17614
17846
  }
17615
17847
  for (const commandsDir of commandsDirs) {
17616
17848
  if (!await isDirectory(commandsDir))
@@ -17619,7 +17851,7 @@ class PluginManager {
17619
17851
  for (const entry of entries) {
17620
17852
  if (!entry.endsWith(".md"))
17621
17853
  continue;
17622
- const cmdPath = join3(commandsDir, entry);
17854
+ const cmdPath = join4(commandsDir, entry);
17623
17855
  const skill = await this.convertSingleCommandToSkill(cmdPath, manifest.name);
17624
17856
  if (skill)
17625
17857
  skills.push(skill);
@@ -17908,7 +18140,7 @@ ${body.trim()}
17908
18140
  }
17909
18141
  if (!removedSkillPaths.has(skill.path)) {
17910
18142
  try {
17911
- await fs20.rm(skill.path, { recursive: true, force: true });
18143
+ await fs22.rm(skill.path, { recursive: true, force: true });
17912
18144
  removedSkillPaths.add(skill.path);
17913
18145
  } catch {
17914
18146
  details.push(`Could not remove skill path: ${skill.path}`);
@@ -17917,7 +18149,7 @@ ${body.trim()}
17917
18149
  }
17918
18150
  if (skill.canonicalPath && skill.canonicalPath !== skill.path && !removedCanonicalPaths.has(skill.canonicalPath) && !sharedCanonicalPath) {
17919
18151
  try {
17920
- await fs20.rm(skill.canonicalPath, { recursive: true, force: true });
18152
+ await fs22.rm(skill.canonicalPath, { recursive: true, force: true });
17921
18153
  removedCanonicalPaths.add(skill.canonicalPath);
17922
18154
  } catch {
17923
18155
  details.push(`Could not remove canonical skill path: ${skill.canonicalPath}`);
@@ -18021,27 +18253,28 @@ var init_pluginManager = __esm(() => {
18021
18253
  init_mcpFilter();
18022
18254
  init_marketplaceRegistry();
18023
18255
  init_skillsManager();
18256
+ init_userConfig();
18024
18257
  getMarketplaceCacheDir = function(registryId) {
18025
- return join3(homedir3(), ".agentinit", "marketplace-cache", registryId);
18258
+ return join4(homedir4(), ".agentinit", "marketplace-cache", registryId);
18026
18259
  };
18027
18260
  getRegistryPath = function(projectPath, global3) {
18028
18261
  if (global3) {
18029
- return join3(homedir3(), ".agentinit", "plugins.json");
18262
+ return join4(homedir4(), ".agentinit", "plugins.json");
18030
18263
  }
18031
- return join3(projectPath, ".agentinit", "plugins.json");
18264
+ return join4(projectPath, ".agentinit", "plugins.json");
18032
18265
  };
18033
18266
  getClaudeInstalledPluginsPath = function() {
18034
- return join3(homedir3(), ".claude", "plugins", "installed_plugins.json");
18267
+ return join4(homedir4(), ".claude", "plugins", "installed_plugins.json");
18035
18268
  };
18036
18269
  getClaudeSettingsPath = function() {
18037
- return join3(homedir3(), ".claude", "settings.json");
18270
+ return join4(homedir4(), ".claude", "settings.json");
18038
18271
  };
18039
18272
  });
18040
18273
 
18041
18274
  // dist/core/skillsManager.js
18042
- import {resolve as resolve8, join as join4, relative as relative3} from "path";
18043
- import {promises as fs22} from "fs";
18044
- import {homedir as homedir4, tmpdir} from "os";
18275
+ import {resolve as resolve8, join as join5, relative as relative3} from "path";
18276
+ import {promises as fs24} from "fs";
18277
+ import {homedir as homedir5, tmpdir} from "os";
18045
18278
  import {execFile} from "child_process";
18046
18279
  import {promisify} from "util";
18047
18280
 
@@ -18108,6 +18341,17 @@ class SkillsManager {
18108
18341
  }
18109
18342
  resolveSourceRequest(source, options2) {
18110
18343
  if (this.isImplicitCatalogSkillSource(source, options2)) {
18344
+ const configuredDefaultMarketplace = getConfiguredDefaultMarketplaceId();
18345
+ if (configuredDefaultMarketplace) {
18346
+ return {
18347
+ source: {
18348
+ type: "marketplace",
18349
+ marketplace: configuredDefaultMarketplace,
18350
+ pluginName: source.trim()
18351
+ },
18352
+ implicitSkills: []
18353
+ };
18354
+ }
18111
18355
  return {
18112
18356
  source: {
18113
18357
  type: "github",
@@ -18144,7 +18388,7 @@ class SkillsManager {
18144
18388
  const fullDir = resolve8(repoPath, searchDir);
18145
18389
  if (!await fileExists(fullDir))
18146
18390
  continue;
18147
- const directSkillMd = join4(fullDir, "SKILL.md");
18391
+ const directSkillMd = join5(fullDir, "SKILL.md");
18148
18392
  if (await fileExists(directSkillMd)) {
18149
18393
  const parsed = await this.parseSkillMd(directSkillMd);
18150
18394
  if (parsed && !seen.has(parsed.name)) {
@@ -18152,7 +18396,7 @@ class SkillsManager {
18152
18396
  skills.push({ ...parsed, path: resolve8(fullDir) });
18153
18397
  }
18154
18398
  }
18155
- const directSkillMdLower = join4(fullDir, "skill.md");
18399
+ const directSkillMdLower = join5(fullDir, "skill.md");
18156
18400
  if (await fileExists(directSkillMdLower)) {
18157
18401
  const parsed = await this.parseSkillMd(directSkillMdLower);
18158
18402
  if (parsed && !seen.has(parsed.name)) {
@@ -18164,11 +18408,11 @@ class SkillsManager {
18164
18408
  continue;
18165
18409
  const entries = await listFiles(fullDir);
18166
18410
  for (const entry of entries) {
18167
- const entryPath = join4(fullDir, entry);
18411
+ const entryPath = join5(fullDir, entry);
18168
18412
  if (!await isDirectory(entryPath))
18169
18413
  continue;
18170
- const skillMdPath = join4(entryPath, "SKILL.md");
18171
- const skillMdPathLower = join4(entryPath, "skill.md");
18414
+ const skillMdPath = join5(entryPath, "SKILL.md");
18415
+ const skillMdPathLower = join5(entryPath, "skill.md");
18172
18416
  const skillFile = await fileExists(skillMdPath) ? skillMdPath : await fileExists(skillMdPathLower) ? skillMdPathLower : null;
18173
18417
  if (!skillFile)
18174
18418
  continue;
@@ -18182,14 +18426,14 @@ class SkillsManager {
18182
18426
  return skills;
18183
18427
  }
18184
18428
  async cloneRepo(url) {
18185
- const tempDir = await fs22.mkdtemp(join4(tmpdir(), "agentinit-skills-"));
18186
- await fs22.rm(tempDir, { recursive: true, force: true });
18429
+ const tempDir = await fs24.mkdtemp(join5(tmpdir(), "agentinit-skills-"));
18430
+ await fs24.rm(tempDir, { recursive: true, force: true });
18187
18431
  try {
18188
18432
  await execFileAsync("git", ["clone", "--depth", "1", url, tempDir], {
18189
18433
  timeout: 60000
18190
18434
  });
18191
18435
  } catch (error) {
18192
- await fs22.rm(tempDir, { recursive: true, force: true }).catch(() => {
18436
+ await fs24.rm(tempDir, { recursive: true, force: true }).catch(() => {
18193
18437
  });
18194
18438
  throw new Error(`Failed to clone ${url}: ${error.message}`);
18195
18439
  }
@@ -18283,7 +18527,7 @@ class SkillsManager {
18283
18527
  return { skills, warnings };
18284
18528
  } finally {
18285
18529
  if (tempDir) {
18286
- await fs22.rm(tempDir, { recursive: true, force: true }).catch(() => {
18530
+ await fs24.rm(tempDir, { recursive: true, force: true }).catch(() => {
18287
18531
  });
18288
18532
  }
18289
18533
  }
@@ -18304,30 +18548,30 @@ class SkillsManager {
18304
18548
  async installSkill(skillPath, skillName, targetDir, copy = false) {
18305
18549
  const normalizedSkillName = this.normalizeSkillName(skillName);
18306
18550
  const destPath = this.resolveInstallPath(targetDir, normalizedSkillName);
18307
- await fs22.mkdir(resolve8(targetDir), { recursive: true });
18551
+ await fs24.mkdir(resolve8(targetDir), { recursive: true });
18308
18552
  if (await fileExists(destPath)) {
18309
- await fs22.rm(destPath, { recursive: true, force: true });
18553
+ await fs24.rm(destPath, { recursive: true, force: true });
18310
18554
  }
18311
18555
  if (copy) {
18312
18556
  await this.copyDir(skillPath, destPath);
18313
18557
  } else {
18314
- await fs22.symlink(skillPath, destPath, "dir");
18558
+ await fs24.symlink(skillPath, destPath, "dir");
18315
18559
  }
18316
18560
  return destPath;
18317
18561
  }
18318
18562
  async installSkillFromContent(skillName, skillContent, targetDir) {
18319
18563
  const normalizedSkillName = this.normalizeSkillName(skillName);
18320
18564
  const destPath = this.resolveInstallPath(targetDir, normalizedSkillName);
18321
- await fs22.mkdir(resolve8(targetDir), { recursive: true });
18565
+ await fs24.mkdir(resolve8(targetDir), { recursive: true });
18322
18566
  if (await fileExists(destPath)) {
18323
- await fs22.rm(destPath, { recursive: true, force: true });
18567
+ await fs24.rm(destPath, { recursive: true, force: true });
18324
18568
  }
18325
- await fs22.mkdir(destPath, { recursive: true });
18326
- await fs22.writeFile(join4(destPath, "SKILL.md"), skillContent, "utf8");
18569
+ await fs24.mkdir(destPath, { recursive: true });
18570
+ await fs24.writeFile(join5(destPath, "SKILL.md"), skillContent, "utf8");
18327
18571
  return destPath;
18328
18572
  }
18329
18573
  getCanonicalSkillsDir(projectPath, global3 = false) {
18330
- return global3 ? resolve8(homedir4(), ".agents/skills") : resolve8(projectPath, ".agents/skills");
18574
+ return global3 ? resolve8(homedir5(), ".agents/skills") : resolve8(projectPath, ".agents/skills");
18331
18575
  }
18332
18576
  async getInstallPlan(skillName, agent, projectPath, options2 = {}) {
18333
18577
  const normalizedSkillName = this.normalizeSkillName(skillName);
@@ -18401,7 +18645,7 @@ class SkillsManager {
18401
18645
  throw new Error(`Missing canonical path for ${skillName}`);
18402
18646
  }
18403
18647
  await this.cleanAndCreateDirectory(canonicalPath);
18404
- await fs22.writeFile(join4(canonicalPath, "SKILL.md"), skillContent, "utf8");
18648
+ await fs24.writeFile(join5(canonicalPath, "SKILL.md"), skillContent, "utf8");
18405
18649
  if (plan.path === canonicalPath) {
18406
18650
  return plan;
18407
18651
  }
@@ -18438,16 +18682,16 @@ class SkillsManager {
18438
18682
  return this.resolveInstallPath(targetDir, this.normalizeSkillName(skillName));
18439
18683
  }
18440
18684
  async cleanAndCreateDirectory(path) {
18441
- await fs22.rm(path, { recursive: true, force: true }).catch(() => {
18685
+ await fs24.rm(path, { recursive: true, force: true }).catch(() => {
18442
18686
  });
18443
- await fs22.mkdir(path, { recursive: true });
18687
+ await fs24.mkdir(path, { recursive: true });
18444
18688
  }
18445
18689
  isWithinPath(basePath, targetPath) {
18446
18690
  const relativePath = relative3(resolve8(basePath), resolve8(targetPath));
18447
18691
  return relativePath === "" || !relativePath.startsWith("..") && !relativePath.includes("/../") && !relativePath.includes("\\..\\");
18448
18692
  }
18449
18693
  async copyDir(src, dest) {
18450
- await fs22.cp(src, dest, { recursive: true, dereference: true });
18694
+ await fs24.cp(src, dest, { recursive: true, dereference: true });
18451
18695
  }
18452
18696
  async addFromSource(source, projectPath, options2 = {}) {
18453
18697
  const discovered = await this.discoverFromSource(source, projectPath, {
@@ -18522,11 +18766,11 @@ class SkillsManager {
18522
18766
  continue;
18523
18767
  const entries = await listFiles(dir);
18524
18768
  for (const entry of entries) {
18525
- const entryPath = join4(dir, entry);
18769
+ const entryPath = join5(dir, entry);
18526
18770
  if (!await isDirectory(entryPath))
18527
18771
  continue;
18528
- const skillMdPath = join4(entryPath, "SKILL.md");
18529
- const skillMdPathLower = join4(entryPath, "skill.md");
18772
+ const skillMdPath = join5(entryPath, "SKILL.md");
18773
+ const skillMdPathLower = join5(entryPath, "skill.md");
18530
18774
  const skillFile = await fileExists(skillMdPath) ? skillMdPath : await fileExists(skillMdPathLower) ? skillMdPathLower : null;
18531
18775
  if (!skillFile)
18532
18776
  continue;
@@ -18536,7 +18780,7 @@ class SkillsManager {
18536
18780
  let isSymlink = false;
18537
18781
  let canonicalPath;
18538
18782
  try {
18539
- const stat = await fs22.lstat(entryPath);
18783
+ const stat = await fs24.lstat(entryPath);
18540
18784
  isSymlink = stat.isSymbolicLink();
18541
18785
  const canonicalBase = this.getCanonicalSkillsDir(projectPath, scope === "global");
18542
18786
  const [resolvedEntryPath, resolvedCanonicalBase] = await Promise.all([
@@ -18602,7 +18846,7 @@ class SkillsManager {
18602
18846
  }
18603
18847
  if (!removedPaths.has(entry.path)) {
18604
18848
  try {
18605
- await fs22.rm(entry.path, { recursive: true, force: true });
18849
+ await fs24.rm(entry.path, { recursive: true, force: true });
18606
18850
  removedPaths.add(entry.path);
18607
18851
  } catch {
18608
18852
  skipped.push({
@@ -18615,7 +18859,7 @@ class SkillsManager {
18615
18859
  if (entry.canonicalPath && entry.canonicalPath !== entry.path && !removedCanonicalPaths.has(entry.canonicalPath)) {
18616
18860
  const stillReferenced = remainingEntries.some((other) => other.name.toLowerCase() === entry.name.toLowerCase() && other.canonicalPath === entry.canonicalPath);
18617
18861
  if (!stillReferenced) {
18618
- await fs22.rm(entry.canonicalPath, { recursive: true, force: true }).catch(() => {
18862
+ await fs24.rm(entry.canonicalPath, { recursive: true, force: true }).catch(() => {
18619
18863
  });
18620
18864
  removedCanonicalPaths.add(entry.canonicalPath);
18621
18865
  }
@@ -24851,27 +25095,27 @@ var require_windows = __commonJS((exports, module) => {
24851
25095
  return checkPathExt(path, options2);
24852
25096
  };
24853
25097
  var isexe = function(path, options2, cb) {
24854
- fs29.stat(path, function(er, stat) {
25098
+ fs31.stat(path, function(er, stat) {
24855
25099
  cb(er, er ? false : checkStat(stat, path, options2));
24856
25100
  });
24857
25101
  };
24858
25102
  var sync = function(path, options2) {
24859
- return checkStat(fs29.statSync(path), path, options2);
25103
+ return checkStat(fs31.statSync(path), path, options2);
24860
25104
  };
24861
25105
  module.exports = isexe;
24862
25106
  isexe.sync = sync;
24863
- var fs29 = __require("fs");
25107
+ var fs31 = __require("fs");
24864
25108
  });
24865
25109
 
24866
25110
  // node_modules/isexe/mode.js
24867
25111
  var require_mode = __commonJS((exports, module) => {
24868
25112
  var isexe = function(path, options2, cb) {
24869
- fs29.stat(path, function(er, stat) {
25113
+ fs31.stat(path, function(er, stat) {
24870
25114
  cb(er, er ? false : checkStat(stat, options2));
24871
25115
  });
24872
25116
  };
24873
25117
  var sync = function(path, options2) {
24874
- return checkStat(fs29.statSync(path), options2);
25118
+ return checkStat(fs31.statSync(path), options2);
24875
25119
  };
24876
25120
  var checkStat = function(stat, options2) {
24877
25121
  return stat.isFile() && checkMode(stat, options2);
@@ -24891,7 +25135,7 @@ var require_mode = __commonJS((exports, module) => {
24891
25135
  };
24892
25136
  module.exports = isexe;
24893
25137
  isexe.sync = sync;
24894
- var fs29 = __require("fs");
25138
+ var fs31 = __require("fs");
24895
25139
  });
24896
25140
 
24897
25141
  // node_modules/isexe/index.js
@@ -24936,7 +25180,7 @@ var require_isexe = __commonJS((exports, module) => {
24936
25180
  }
24937
25181
  }
24938
25182
  };
24939
- var fs29 = __require("fs");
25183
+ var fs31 = __require("fs");
24940
25184
  var core2;
24941
25185
  if (process.platform === "win32" || global.TESTING_WINDOWS) {
24942
25186
  core2 = require_windows();
@@ -25143,14 +25387,14 @@ var require_readShebang = __commonJS((exports, module) => {
25143
25387
  const buffer = Buffer.alloc(size);
25144
25388
  let fd;
25145
25389
  try {
25146
- fd = fs29.openSync(command, "r");
25147
- fs29.readSync(fd, buffer, 0, size, 0);
25148
- fs29.closeSync(fd);
25390
+ fd = fs31.openSync(command, "r");
25391
+ fs31.readSync(fd, buffer, 0, size, 0);
25392
+ fs31.closeSync(fd);
25149
25393
  } catch (e) {
25150
25394
  }
25151
25395
  return shebangCommand(buffer.toString());
25152
25396
  };
25153
- var fs29 = __require("fs");
25397
+ var fs31 = __require("fs");
25154
25398
  var shebangCommand = require_shebang_command();
25155
25399
  module.exports = readShebang;
25156
25400
  });
@@ -27484,7 +27728,7 @@ import {relative as relative5} from "path";
27484
27728
 
27485
27729
  // dist/core/propagator.js
27486
27730
  var import_gray_matter3 = __toESM(require_gray_matter(), 1);
27487
- import {promises as fs24} from "fs";
27731
+ import {promises as fs26} from "fs";
27488
27732
  import {resolve as resolve9} from "path";
27489
27733
 
27490
27734
  // node_modules/js-yaml/dist/js-yaml.mjs
@@ -30252,7 +30496,7 @@ class Propagator {
30252
30496
  resolvedTargets: []
30253
30497
  };
30254
30498
  const exists = await fileExists(generatedFile.path);
30255
- const existingStats = exists ? await fs24.lstat(generatedFile.path).catch(() => null) : null;
30499
+ const existingStats = exists ? await fs26.lstat(generatedFile.path).catch(() => null) : null;
30256
30500
  const existingContent = exists && !existingStats?.isSymbolicLink() ? await readFileIfExists(generatedFile.path) : null;
30257
30501
  const existingTarget = existingStats?.isSymbolicLink() ? await readSymlinkTarget(generatedFile.path) : null;
30258
30502
  if (options2.managedState && !options2.dryRun) {
@@ -30283,7 +30527,7 @@ class Propagator {
30283
30527
  if (!options2.dryRun) {
30284
30528
  if (generatedFile.kind === "file") {
30285
30529
  if (existingStats?.isSymbolicLink()) {
30286
- await fs24.rm(generatedFile.path, { force: true }).catch(() => {
30530
+ await fs26.rm(generatedFile.path, { force: true }).catch(() => {
30287
30531
  });
30288
30532
  }
30289
30533
  await writeFile(generatedFile.path, generatedFile.content || "");
@@ -30460,14 +30704,14 @@ ${content}
30460
30704
 
30461
30705
  // dist/core/managedState.js
30462
30706
  init_fs();
30463
- import {promises as fs26} from "fs";
30464
- import {dirname as dirname3, join as join5, relative as relative4, resolve as resolve10} from "path";
30707
+ import {promises as fs28} from "fs";
30708
+ import {dirname as dirname3, join as join6, relative as relative4, resolve as resolve10} from "path";
30465
30709
  var toPosixPath = function(value) {
30466
30710
  return value.replace(/\\/g, "/");
30467
30711
  };
30468
30712
  async function pathType(targetPath) {
30469
30713
  try {
30470
- const stat = await fs26.lstat(targetPath);
30714
+ const stat = await fs28.lstat(targetPath);
30471
30715
  if (stat.isSymbolicLink()) {
30472
30716
  return "symlink";
30473
30717
  }
@@ -30477,20 +30721,20 @@ async function pathType(targetPath) {
30477
30721
  }
30478
30722
  }
30479
30723
  async function copyDirectory(src, dest) {
30480
- await fs26.mkdir(dest, { recursive: true });
30481
- const entries = await fs26.readdir(src, { withFileTypes: true });
30724
+ await fs28.mkdir(dest, { recursive: true });
30725
+ const entries = await fs28.readdir(src, { withFileTypes: true });
30482
30726
  for (const entry of entries) {
30483
- const srcPath = join5(src, entry.name);
30484
- const destPath = join5(dest, entry.name);
30727
+ const srcPath = join6(src, entry.name);
30728
+ const destPath = join6(dest, entry.name);
30485
30729
  if (entry.isDirectory()) {
30486
30730
  await copyDirectory(srcPath, destPath);
30487
30731
  } else if (entry.isSymbolicLink()) {
30488
- const target = await fs26.readlink(srcPath);
30489
- await fs26.mkdir(dirname3(destPath), { recursive: true });
30490
- await fs26.symlink(target, destPath);
30732
+ const target = await fs28.readlink(srcPath);
30733
+ await fs28.mkdir(dirname3(destPath), { recursive: true });
30734
+ await fs28.symlink(target, destPath);
30491
30735
  } else {
30492
- await fs26.mkdir(dirname3(destPath), { recursive: true });
30493
- await fs26.copyFile(srcPath, destPath);
30736
+ await fs28.mkdir(dirname3(destPath), { recursive: true });
30737
+ await fs28.copyFile(srcPath, destPath);
30494
30738
  }
30495
30739
  }
30496
30740
  }
@@ -30499,14 +30743,14 @@ async function copyPath(src, dest) {
30499
30743
  if (!type2) {
30500
30744
  return;
30501
30745
  }
30502
- await fs26.mkdir(dirname3(dest), { recursive: true });
30746
+ await fs28.mkdir(dirname3(dest), { recursive: true });
30503
30747
  if (type2 === "symlink") {
30504
- const target = await fs26.readlink(src);
30505
- await fs26.symlink(target, dest);
30748
+ const target = await fs28.readlink(src);
30749
+ await fs28.symlink(target, dest);
30506
30750
  } else if (type2 === "directory") {
30507
30751
  await copyDirectory(src, dest);
30508
30752
  } else {
30509
- await fs26.copyFile(src, dest);
30753
+ await fs28.copyFile(src, dest);
30510
30754
  }
30511
30755
  }
30512
30756
  var MANAGED_STATE_FILE = "managed-state.json";
@@ -30520,11 +30764,11 @@ class ManagedStateStore {
30520
30764
  this.state = state;
30521
30765
  }
30522
30766
  static async open(projectPath) {
30523
- const agentInitDir = join5(projectPath, ".agentinit");
30524
- const statePath = join5(agentInitDir, MANAGED_STATE_FILE);
30767
+ const agentInitDir = join6(projectPath, ".agentinit");
30768
+ const statePath = join6(agentInitDir, MANAGED_STATE_FILE);
30525
30769
  const emptyState = { version: 1, entries: [] };
30526
30770
  try {
30527
- const raw = await fs26.readFile(statePath, "utf8");
30771
+ const raw = await fs28.readFile(statePath, "utf8");
30528
30772
  const parsed = JSON.parse(raw);
30529
30773
  if (!parsed || parsed.version !== 1 || !Array.isArray(parsed.entries)) {
30530
30774
  return new ManagedStateStore(projectPath, emptyState);
@@ -30535,13 +30779,13 @@ class ManagedStateStore {
30535
30779
  }
30536
30780
  }
30537
30781
  get agentInitDir() {
30538
- return join5(this.projectPath, ".agentinit");
30782
+ return join6(this.projectPath, ".agentinit");
30539
30783
  }
30540
30784
  get stateFilePath() {
30541
- return join5(this.agentInitDir, MANAGED_STATE_FILE);
30785
+ return join6(this.agentInitDir, MANAGED_STATE_FILE);
30542
30786
  }
30543
30787
  get backupsDir() {
30544
- return join5(this.agentInitDir, BACKUPS_DIR);
30788
+ return join6(this.agentInitDir, BACKUPS_DIR);
30545
30789
  }
30546
30790
  normalizeRelativePath(targetPath, preserveTrailingSlash = false) {
30547
30791
  const hasTrailingSlash = preserveTrailingSlash && /[\\/]$/.test(targetPath);
@@ -30563,14 +30807,14 @@ class ManagedStateStore {
30563
30807
  }
30564
30808
  if (type2 === "symlink") {
30565
30809
  try {
30566
- const backupLinkTarget = await fs26.readlink(targetPath);
30810
+ const backupLinkTarget = await fs28.readlink(targetPath);
30567
30811
  return { backupLinkTarget };
30568
30812
  } catch {
30569
30813
  return {};
30570
30814
  }
30571
30815
  }
30572
30816
  const relativeTargetPath = this.normalizeRelativePath(targetPath);
30573
- const backupPath = join5(this.backupsDir, relativeTargetPath);
30817
+ const backupPath = join6(this.backupsDir, relativeTargetPath);
30574
30818
  if (!await fileExists(backupPath)) {
30575
30819
  await copyPath(targetPath, backupPath);
30576
30820
  }
@@ -30617,8 +30861,8 @@ class ManagedStateStore {
30617
30861
  return [...paths5];
30618
30862
  }
30619
30863
  async save() {
30620
- await fs26.mkdir(this.agentInitDir, { recursive: true });
30621
- await fs26.writeFile(this.stateFilePath, JSON.stringify(this.state, null, 2), "utf8");
30864
+ await fs28.mkdir(this.agentInitDir, { recursive: true });
30865
+ await fs28.writeFile(this.stateFilePath, JSON.stringify(this.state, null, 2), "utf8");
30622
30866
  }
30623
30867
  async revertAll(options2 = {}) {
30624
30868
  const summary = {
@@ -30633,29 +30877,29 @@ class ManagedStateStore {
30633
30877
  const backupLinkTarget = entry.backupLinkTarget;
30634
30878
  if (entry.existedBefore && backupLinkTarget !== undefined) {
30635
30879
  if (!options2.dryRun) {
30636
- await fs26.rm(absolutePath, { recursive: true, force: true }).catch(() => {
30880
+ await fs28.rm(absolutePath, { recursive: true, force: true }).catch(() => {
30637
30881
  });
30638
- await fs26.mkdir(dirname3(absolutePath), { recursive: true });
30639
- await fs26.symlink(backupLinkTarget, absolutePath);
30882
+ await fs28.mkdir(dirname3(absolutePath), { recursive: true });
30883
+ await fs28.symlink(backupLinkTarget, absolutePath);
30640
30884
  }
30641
30885
  summary.restored++;
30642
30886
  } else if (entry.existedBefore && backupPath && await fileExists(backupPath)) {
30643
30887
  if (!options2.dryRun) {
30644
- await fs26.rm(absolutePath, { recursive: true, force: true }).catch(() => {
30888
+ await fs28.rm(absolutePath, { recursive: true, force: true }).catch(() => {
30645
30889
  });
30646
30890
  await copyPath(backupPath, absolutePath);
30647
30891
  }
30648
30892
  summary.restored++;
30649
30893
  } else {
30650
30894
  if (!options2.dryRun) {
30651
- await fs26.rm(absolutePath, { recursive: true, force: true }).catch(() => {
30895
+ await fs28.rm(absolutePath, { recursive: true, force: true }).catch(() => {
30652
30896
  });
30653
30897
  }
30654
30898
  summary.removed++;
30655
30899
  }
30656
30900
  if (!options2.keepBackups && backupPath && await fileExists(backupPath)) {
30657
30901
  if (!options2.dryRun) {
30658
- await fs26.rm(backupPath, { recursive: true, force: true }).catch(() => {
30902
+ await fs28.rm(backupPath, { recursive: true, force: true }).catch(() => {
30659
30903
  });
30660
30904
  }
30661
30905
  summary.backupsRemoved++;
@@ -30663,16 +30907,16 @@ class ManagedStateStore {
30663
30907
  }
30664
30908
  if (!options2.dryRun) {
30665
30909
  this.state.entries.length = 0;
30666
- await fs26.rm(this.stateFilePath, { force: true }).catch(() => {
30910
+ await fs28.rm(this.stateFilePath, { force: true }).catch(() => {
30667
30911
  });
30668
30912
  if (!options2.keepBackups) {
30669
- await fs26.rm(this.backupsDir, { recursive: true, force: true }).catch(() => {
30913
+ await fs28.rm(this.backupsDir, { recursive: true, force: true }).catch(() => {
30670
30914
  });
30671
30915
  }
30672
30916
  try {
30673
- const remainingEntries = await fs26.readdir(this.agentInitDir);
30917
+ const remainingEntries = await fs28.readdir(this.agentInitDir);
30674
30918
  if (remainingEntries.length === 0) {
30675
- await fs26.rm(this.agentInitDir, { recursive: true, force: true });
30919
+ await fs28.rm(this.agentInitDir, { recursive: true, force: true });
30676
30920
  }
30677
30921
  } catch {
30678
30922
  }
@@ -31015,15 +31259,15 @@ class MCPParser {
31015
31259
  }
31016
31260
 
31017
31261
  // dist/constants/mcp.js
31018
- import {readFileSync} from "fs";
31262
+ import {readFileSync as readFileSync2} from "fs";
31019
31263
  import {fileURLToPath} from "url";
31020
- import {dirname as dirname4, join as join6} from "path";
31264
+ import {dirname as dirname4, join as join7} from "path";
31021
31265
  var getPackageVersion = function() {
31022
31266
  try {
31023
31267
  const __filename2 = fileURLToPath(import.meta.url);
31024
31268
  const __dirname2 = dirname4(__filename2);
31025
- const packageJsonPath = join6(__dirname2, "../../package.json");
31026
- const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
31269
+ const packageJsonPath = join7(__dirname2, "../../package.json");
31270
+ const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
31027
31271
  return packageJson.version || "1.0.0";
31028
31272
  } catch {
31029
31273
  return "1.0.0";
@@ -31049,13 +31293,13 @@ var TOKEN_COUNT_THRESHOLDS = {
31049
31293
  };
31050
31294
  // dist/core/rulesParser.js
31051
31295
  init_fs();
31052
- import {readFileSync as readFileSync3} from "fs";
31296
+ import {readFileSync as readFileSync4} from "fs";
31053
31297
 
31054
31298
  // dist/core/rulesTemplateLoader.js
31055
31299
  var toml = __toESM(require_toml(), 1);
31056
31300
  import {resolve as resolve11, dirname as dirname5} from "path";
31057
31301
  import {fileURLToPath as fileURLToPath2} from "url";
31058
- import {readFileSync as readFileSync2, readdirSync, existsSync} from "fs";
31302
+ import {readFileSync as readFileSync3, readdirSync, existsSync as existsSync2} from "fs";
31059
31303
  var __filename2 = fileURLToPath2(import.meta.url);
31060
31304
  var __dirname2 = dirname5(__filename2);
31061
31305
 
@@ -31067,14 +31311,14 @@ class RulesTemplateLoader {
31067
31311
  this.loadTemplates();
31068
31312
  }
31069
31313
  loadTemplates() {
31070
- if (!existsSync(this.templatesPath)) {
31314
+ if (!existsSync2(this.templatesPath)) {
31071
31315
  throw new Error(`Rules templates directory not found: ${this.templatesPath}`);
31072
31316
  }
31073
31317
  const files = readdirSync(this.templatesPath).filter((file) => file.endsWith(".toml"));
31074
31318
  for (const file of files) {
31075
31319
  try {
31076
31320
  const filePath = resolve11(this.templatesPath, file);
31077
- const content = readFileSync2(filePath, "utf-8");
31321
+ const content = readFileSync3(filePath, "utf-8");
31078
31322
  const parsed = toml.default.parse(content);
31079
31323
  const template = {
31080
31324
  id: parsed.template.id,
@@ -31222,7 +31466,7 @@ class RulesParser {
31222
31466
  throw new RulesParseError(`Rules file not found: ${filePath}`);
31223
31467
  }
31224
31468
  try {
31225
- const content = readFileSync3(filePath, "utf-8");
31469
+ const content = readFileSync4(filePath, "utf-8");
31226
31470
  if (filePath.endsWith(".json")) {
31227
31471
  const parsed = JSON.parse(content);
31228
31472
  return this.extractRulesFromObject(parsed);
@@ -39292,8 +39536,8 @@ class MCPVerifier {
39292
39536
  }
39293
39537
 
39294
39538
  // dist/core/gitignoreManager.js
39295
- import {promises as fs29} from "fs";
39296
- import {dirname as dirname6, join as join7} from "path";
39539
+ import {promises as fs31} from "fs";
39540
+ import {dirname as dirname6, join as join8} from "path";
39297
39541
  var normalizeIgnorePath = function(projectPath, value) {
39298
39542
  const relative6 = value.startsWith(projectPath) ? value.slice(projectPath.length + 1) : value;
39299
39543
  const normalized = relative6.replace(/\\/g, "/").replace(/^\/+/, "");
@@ -39340,12 +39584,12 @@ var updateManagedBlock = function(existingContent, entries) {
39340
39584
  return content;
39341
39585
  };
39342
39586
  async function updateManagedIgnoreFile(projectPath, paths5, options2 = {}) {
39343
- const ignoreFile = options2.local ? join7(".git", "info", "exclude") : ".gitignore";
39344
- const ignoreFilePath = join7(projectPath, ignoreFile);
39587
+ const ignoreFile = options2.local ? join8(".git", "info", "exclude") : ".gitignore";
39588
+ const ignoreFilePath = join8(projectPath, ignoreFile);
39345
39589
  if (options2.local) {
39346
- const gitDir = join7(projectPath, ".git");
39590
+ const gitDir = join8(projectPath, ".git");
39347
39591
  try {
39348
- const stat = await fs29.stat(gitDir);
39592
+ const stat = await fs31.stat(gitDir);
39349
39593
  if (!stat.isDirectory()) {
39350
39594
  throw new Error;
39351
39595
  }
@@ -39356,21 +39600,21 @@ async function updateManagedIgnoreFile(projectPath, paths5, options2 = {}) {
39356
39600
  const normalizedPaths = [...new Set(paths5.map((path) => normalizeIgnorePath(projectPath, path)).filter(Boolean))].sort();
39357
39601
  let existingContent = "";
39358
39602
  try {
39359
- existingContent = await fs29.readFile(ignoreFilePath, "utf8");
39603
+ existingContent = await fs31.readFile(ignoreFilePath, "utf8");
39360
39604
  } catch {
39361
39605
  existingContent = "";
39362
39606
  }
39363
39607
  const updatedContent = updateManagedBlock(existingContent, normalizedPaths);
39364
- await fs29.mkdir(dirname6(ignoreFilePath), { recursive: true });
39365
- await fs29.writeFile(ignoreFilePath, updatedContent, "utf8");
39608
+ await fs31.mkdir(dirname6(ignoreFilePath), { recursive: true });
39609
+ await fs31.writeFile(ignoreFilePath, updatedContent, "utf8");
39366
39610
  return ignoreFilePath;
39367
39611
  }
39368
39612
  async function removeManagedIgnoreBlock(projectPath, options2 = {}) {
39369
- const ignoreFile = options2.local ? join7(".git", "info", "exclude") : ".gitignore";
39370
- const ignoreFilePath = join7(projectPath, ignoreFile);
39613
+ const ignoreFile = options2.local ? join8(".git", "info", "exclude") : ".gitignore";
39614
+ const ignoreFilePath = join8(projectPath, ignoreFile);
39371
39615
  let content;
39372
39616
  try {
39373
- content = await fs29.readFile(ignoreFilePath, "utf8");
39617
+ content = await fs31.readFile(ignoreFilePath, "utf8");
39374
39618
  } catch {
39375
39619
  return false;
39376
39620
  }
@@ -39386,13 +39630,13 @@ async function removeManagedIgnoreBlock(projectPath, options2 = {}) {
39386
39630
  const afterBlock = content.slice(endIndex + END_MARKER.length).replace(/^\n+/, "");
39387
39631
  let nextContent = `${beforeBlock}${afterBlock}`.replace(/\n{3,}/g, "\n\n").replace(/^\n+/, "");
39388
39632
  if (nextContent.trim() === "") {
39389
- await fs29.rm(ignoreFilePath, { force: true }).catch(() => {
39633
+ await fs31.rm(ignoreFilePath, { force: true }).catch(() => {
39390
39634
  });
39391
39635
  } else {
39392
39636
  if (!nextContent.endsWith("\n")) {
39393
39637
  nextContent += "\n";
39394
39638
  }
39395
- await fs29.writeFile(ignoreFilePath, nextContent, "utf8");
39639
+ await fs31.writeFile(ignoreFilePath, nextContent, "utf8");
39396
39640
  }
39397
39641
  return true;
39398
39642
  }
@@ -39403,12 +39647,12 @@ var END_MARKER = "# END AgentInit Generated Files";
39403
39647
  init_agentManager();
39404
39648
  init_skillsManager();
39405
39649
  init_fs();
39406
- import {dirname as dirname7, join as join8} from "path";
39650
+ import {dirname as dirname7, join as join9} from "path";
39407
39651
  async function discoverProjectSkills(projectPath, skillsManager4) {
39408
39652
  const sources = [];
39409
39653
  const skills = new Map;
39410
39654
  for (const sourceDir of PROJECT_SKILL_SOURCE_DIRS) {
39411
- const absoluteSourceDir = join8(projectPath, sourceDir);
39655
+ const absoluteSourceDir = join9(projectPath, sourceDir);
39412
39656
  if (!await fileExists(absoluteSourceDir)) {
39413
39657
  continue;
39414
39658
  }
@@ -40300,9 +40544,197 @@ async function revertCommand(options2) {
40300
40544
  }
40301
40545
  }
40302
40546
 
40547
+ // dist/utils/colors.js
40548
+ var colorsEnabled = function() {
40549
+ const env2 = process.env || {};
40550
+ const isTTY2 = !!process.stdout?.isTTY;
40551
+ return !env2.NODE_DISABLE_COLORS && env2.NO_COLOR == null && env2.TERM !== "dumb" && (env2.FORCE_COLOR != null && env2.FORCE_COLOR !== "0" || isTTY2);
40552
+ };
40553
+ function orange(text) {
40554
+ if (!colorsEnabled()) {
40555
+ return text;
40556
+ }
40557
+ return `\x1B[38;5;208m${text}\x1B[39m`;
40558
+ }
40559
+
40560
+ // dist/commands/config.js
40561
+ init_marketplaceRegistry();
40562
+ init_userConfig();
40563
+ var sortConfig = function(config) {
40564
+ config.customMarketplaces.sort((left, right) => left.identifier.localeCompare(right.identifier));
40565
+ config.verifiedGithubRepos.sort((left, right) => left.localeCompare(right));
40566
+ return config;
40567
+ };
40568
+ var failConfigCommand = function(error) {
40569
+ logger.error(error instanceof Error ? error.message : "Configuration update failed.");
40570
+ process.exitCode = 1;
40571
+ };
40572
+ function registerConfigCommand(program2) {
40573
+ const config = program2.command("config").description("Manage AgentInit user configuration");
40574
+ const marketplaces = config.command("marketplaces").description("Manage configured marketplaces");
40575
+ marketplaces.command("list").description("List built-in and custom marketplaces").action(async () => {
40576
+ logger.titleBox("AgentInit Configuration");
40577
+ logger.section("Marketplaces");
40578
+ const defaultMarketplace = getConfiguredDefaultMarketplaceId();
40579
+ const marketplaceIds = getMarketplaceIds();
40580
+ for (let i = 0;i < marketplaceIds.length; i++) {
40581
+ const identifier = marketplaceIds[i];
40582
+ const marketplace = getMarketplace(identifier);
40583
+ if (!marketplace) {
40584
+ continue;
40585
+ }
40586
+ const flags = [
40587
+ BUILT_IN_MARKETPLACE_IDS.has(identifier) ? "built-in" : "custom",
40588
+ defaultMarketplace === identifier ? "default" : null
40589
+ ].filter(Boolean).join(", ");
40590
+ logger.tree(`${cyan(identifier)} ${dim(`[${flags}]`)} ${marketplace.name} ${dim(`-> ${marketplace.repoUrl}`)}`, i === marketplaceIds.length - 1);
40591
+ }
40592
+ if (!defaultMarketplace) {
40593
+ logger.info("No default marketplace configured.");
40594
+ }
40595
+ });
40596
+ marketplaces.command("add <identifier> <repoUrl>").description("Add a custom marketplace").option("--name <displayName>", "Display name for this marketplace").option("--default", "Set this marketplace as the default").action(async (identifierArg, repoUrlArg, options2) => {
40597
+ logger.titleBox("AgentInit Configuration");
40598
+ try {
40599
+ const identifier = normalizeMarketplaceIdentifier(identifierArg);
40600
+ const repoUrl = normalizeMarketplaceRepoUrl(repoUrlArg);
40601
+ const configState = await readUserConfig();
40602
+ if (BUILT_IN_MARKETPLACE_IDS.has(identifier)) {
40603
+ throw new Error(`Marketplace "${identifier}" is built in and cannot be redefined.`);
40604
+ }
40605
+ if (configState.customMarketplaces.some((marketplace) => marketplace.identifier === identifier)) {
40606
+ throw new Error(`Marketplace "${identifier}" already exists.`);
40607
+ }
40608
+ configState.customMarketplaces.push({
40609
+ identifier,
40610
+ name: normalizeMarketplaceName(options2.name, identifier),
40611
+ repoUrl
40612
+ });
40613
+ if (options2.default) {
40614
+ configState.defaultMarketplace = identifier;
40615
+ }
40616
+ await writeUserConfig(sortConfig(configState));
40617
+ logger.success(`Added marketplace ${green(identifier)}.`);
40618
+ logger.info(` ${repoUrl}`);
40619
+ if (options2.default) {
40620
+ logger.info(" Set as the configured default marketplace.");
40621
+ }
40622
+ } catch (error) {
40623
+ failConfigCommand(error);
40624
+ }
40625
+ });
40626
+ marketplaces.command("remove <identifier>").description("Remove a custom marketplace").action(async (identifierArg) => {
40627
+ logger.titleBox("AgentInit Configuration");
40628
+ try {
40629
+ const identifier = normalizeMarketplaceIdentifier(identifierArg);
40630
+ if (BUILT_IN_MARKETPLACE_IDS.has(identifier)) {
40631
+ throw new Error(`Marketplace "${identifier}" is built in and cannot be removed.`);
40632
+ }
40633
+ const configState = await readUserConfig();
40634
+ const nextMarketplaces = configState.customMarketplaces.filter((marketplace) => marketplace.identifier !== identifier);
40635
+ if (nextMarketplaces.length === configState.customMarketplaces.length) {
40636
+ throw new Error(`Marketplace "${identifier}" is not configured.`);
40637
+ }
40638
+ configState.customMarketplaces = nextMarketplaces;
40639
+ const clearedDefault = configState.defaultMarketplace === identifier;
40640
+ if (clearedDefault) {
40641
+ delete configState.defaultMarketplace;
40642
+ }
40643
+ await writeUserConfig(sortConfig(configState));
40644
+ logger.success(`Removed marketplace ${green(identifier)}.`);
40645
+ if (clearedDefault) {
40646
+ logger.info(" Cleared the configured default marketplace.");
40647
+ }
40648
+ } catch (error) {
40649
+ failConfigCommand(error);
40650
+ }
40651
+ });
40652
+ marketplaces.command("default <identifier>").description("Set the configured default marketplace").action(async (identifierArg) => {
40653
+ logger.titleBox("AgentInit Configuration");
40654
+ try {
40655
+ const identifier = normalizeMarketplaceIdentifier(identifierArg);
40656
+ if (!getMarketplace(identifier)) {
40657
+ throw new Error(`Unknown marketplace: ${identifier}. Available: ${getMarketplaceIds().join(", ")}`);
40658
+ }
40659
+ const configState = await readUserConfig();
40660
+ configState.defaultMarketplace = identifier;
40661
+ await writeUserConfig(sortConfig(configState));
40662
+ logger.success(`Set ${green(identifier)} as the configured default marketplace.`);
40663
+ } catch (error) {
40664
+ failConfigCommand(error);
40665
+ }
40666
+ });
40667
+ marketplaces.command("clear-default").description("Clear the configured default marketplace").action(async () => {
40668
+ logger.titleBox("AgentInit Configuration");
40669
+ const configState = await readUserConfig();
40670
+ if (!configState.defaultMarketplace) {
40671
+ logger.info("No configured default marketplace to clear.");
40672
+ return;
40673
+ }
40674
+ delete configState.defaultMarketplace;
40675
+ await writeUserConfig(sortConfig(configState));
40676
+ logger.success("Cleared the configured default marketplace.");
40677
+ });
40678
+ const verifiedRepos = config.command("verified-repos").description("Manage exact verified GitHub repositories");
40679
+ verifiedRepos.command("list").description("List verified GitHub repositories").action(async () => {
40680
+ logger.titleBox("AgentInit Configuration");
40681
+ logger.section("Verified GitHub Repos");
40682
+ const configState = await readUserConfig();
40683
+ const entries = [
40684
+ ...getBuiltInVerifiedGithubRepos().map((repo) => ({ repo, builtIn: true })),
40685
+ ...configState.verifiedGithubRepos.filter((repo) => !BUILT_IN_VERIFIED_REPOS.has(repo)).map((repo) => ({ repo, builtIn: false }))
40686
+ ];
40687
+ for (let i = 0;i < entries.length; i++) {
40688
+ const entry = entries[i];
40689
+ logger.tree(`${cyan(entry.repo)} ${dim(entry.builtIn ? "[built-in]" : "[custom]")}`, i === entries.length - 1);
40690
+ }
40691
+ });
40692
+ verifiedRepos.command("add <repo>").description("Add an exact verified GitHub repo in owner/repo form").action(async (repoArg) => {
40693
+ logger.titleBox("AgentInit Configuration");
40694
+ try {
40695
+ const repo = normalizeGitHubRepoRef(repoArg);
40696
+ if (BUILT_IN_VERIFIED_REPOS.has(repo)) {
40697
+ logger.info(`${repo} is already verified by AgentInit.`);
40698
+ return;
40699
+ }
40700
+ const configState = await readUserConfig();
40701
+ if (configState.verifiedGithubRepos.includes(repo)) {
40702
+ logger.info(`${repo} is already configured as verified.`);
40703
+ return;
40704
+ }
40705
+ configState.verifiedGithubRepos.push(repo);
40706
+ await writeUserConfig(sortConfig(configState));
40707
+ logger.success(`Added verified GitHub repo ${green(repo)}.`);
40708
+ } catch (error) {
40709
+ failConfigCommand(error);
40710
+ }
40711
+ });
40712
+ verifiedRepos.command("remove <repo>").description("Remove a custom verified GitHub repo").action(async (repoArg) => {
40713
+ logger.titleBox("AgentInit Configuration");
40714
+ try {
40715
+ const repo = normalizeGitHubRepoRef(repoArg);
40716
+ if (BUILT_IN_VERIFIED_REPOS.has(repo)) {
40717
+ throw new Error(`${repo} is built in and cannot be removed.`);
40718
+ }
40719
+ const configState = await readUserConfig();
40720
+ const nextRepos = configState.verifiedGithubRepos.filter((entry) => entry !== repo);
40721
+ if (nextRepos.length === configState.verifiedGithubRepos.length) {
40722
+ throw new Error(`${repo} is not configured as verified.`);
40723
+ }
40724
+ configState.verifiedGithubRepos = nextRepos;
40725
+ await writeUserConfig(sortConfig(configState));
40726
+ logger.success(`Removed verified GitHub repo ${green(repo)}.`);
40727
+ } catch (error) {
40728
+ failConfigCommand(error);
40729
+ }
40730
+ });
40731
+ }
40732
+ var BUILT_IN_MARKETPLACE_IDS = new Set(MARKETPLACES.map((marketplace) => marketplace.id));
40733
+ var BUILT_IN_VERIFIED_REPOS = new Set(getBuiltInVerifiedGithubRepos());
40734
+
40303
40735
  // dist/commands/skills.js
40304
40736
  var import_prompts2 = __toESM(require_prompts3(), 1);
40305
- import {homedir as homedir5} from "os";
40737
+ import {homedir as homedir6} from "os";
40306
40738
  import {relative as relative7, resolve as resolve12} from "path";
40307
40739
  init_skillsManager();
40308
40740
  init_marketplaceRegistry();
@@ -40587,7 +41019,7 @@ var prependCanonicalGlobalGroup = function(agentManager9, projectPath, groups) {
40587
41019
  var formatSkillsDir = function(projectPath, dir) {
40588
41020
  const normalizedDir = dir.replace(/\\/g, "/").replace(/\/?$/, "/");
40589
41021
  const normalizedProjectPath = projectPath.replace(/\\/g, "/");
40590
- const normalizedHome = homedir5().replace(/\\/g, "/");
41022
+ const normalizedHome = homedir6().replace(/\\/g, "/");
40591
41023
  if (normalizedDir.startsWith(`${normalizedProjectPath}/`)) {
40592
41024
  return `${relative7(projectPath, dir).replace(/\\/g, "/").replace(/\/?$/, "/")}`;
40593
41025
  }
@@ -40598,7 +41030,7 @@ var formatSkillsDir = function(projectPath, dir) {
40598
41030
  };
40599
41031
  var formatPromptPath = function(path) {
40600
41032
  const normalizedPath = path.replace(/\\/g, "/").replace(/\/?$/, "/");
40601
- const normalizedHome = homedir5().replace(/\\/g, "/");
41033
+ const normalizedHome = homedir6().replace(/\\/g, "/");
40602
41034
  if (normalizedPath === `${normalizedHome}/`) {
40603
41035
  return "~/";
40604
41036
  }
@@ -40608,7 +41040,7 @@ var formatPromptPath = function(path) {
40608
41040
  return normalizedPath;
40609
41041
  };
40610
41042
  var getCanonicalGlobalSkillsDir = function() {
40611
- return resolve12(homedir5(), ".agents/skills");
41043
+ return resolve12(homedir6(), ".agents/skills");
40612
41044
  };
40613
41045
  var getCanonicalGlobalSkillsDisplayPath = function() {
40614
41046
  return formatPromptPath(getCanonicalGlobalSkillsDir());
@@ -41550,25 +41982,12 @@ function registerRulesCommand(program2) {
41550
41982
  // dist/commands/plugins.js
41551
41983
  var import_prompts3 = __toESM(require_prompts3(), 1);
41552
41984
  import {dirname as dirname8, relative as relative8} from "path";
41553
-
41554
- // dist/utils/colors.js
41555
- var colorsEnabled = function() {
41556
- const env2 = process.env || {};
41557
- const isTTY2 = !!process.stdout?.isTTY;
41558
- return !env2.NODE_DISABLE_COLORS && env2.NO_COLOR == null && env2.TERM !== "dumb" && (env2.FORCE_COLOR != null && env2.FORCE_COLOR !== "0" || isTTY2);
41559
- };
41560
- function orange(text) {
41561
- if (!colorsEnabled()) {
41562
- return text;
41563
- }
41564
- return `\x1B[38;5;208m${text}\x1B[39m`;
41565
- }
41566
-
41567
- // dist/commands/plugins.js
41568
41985
  init_pluginManager();
41569
41986
  init_agentManager();
41987
+ init_marketplaceRegistry();
41570
41988
  function registerPluginsCommand(program2) {
41571
41989
  const marketplaceHelp = new PluginManager().getMarketplaceIds().join(", ");
41990
+ const marketplaceCategoryHelp = getMarketplaceCategories().join(", ");
41572
41991
  const plugins = program2.command("plugins").description("Install agent-agnostic plugins from any marketplace or source");
41573
41992
  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) => {
41574
41993
  logger.titleBox("AgentInit Plugins");
@@ -41686,17 +42105,17 @@ function registerPluginsCommand(program2) {
41686
42105
  logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
41687
42106
  }
41688
42107
  });
41689
- plugins.command("search [query]").description("Search marketplace plugins").option("--from <marketplace>", `Which marketplace to search (available: ${marketplaceHelp})`).option("--category <category>", "Filter: official, community").action(async (query, options2) => {
42108
+ 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) => {
41690
42109
  logger.titleBox("AgentInit Plugin Search");
41691
42110
  const pluginManager2 = new PluginManager;
41692
- if (!options2.from) {
42111
+ const registryId = options2.from || getConfiguredDefaultMarketplaceId();
42112
+ if (!registryId) {
41693
42113
  logger.info(`Please specify a marketplace with --from <marketplace>. Available: ${marketplaceHelp}`);
41694
42114
  logger.info("Examples:");
41695
42115
  logger.info(" agentinit plugins search --from claude");
41696
42116
  logger.info(" agentinit plugins search code-review --from claude");
41697
42117
  return;
41698
42118
  }
41699
- const registryId = options2.from;
41700
42119
  const spinner = ora(`Fetching ${registryId} marketplace...`).start();
41701
42120
  try {
41702
42121
  const results = await pluginManager2.listMarketplacePlugins(registryId, query, options2.category);
@@ -42111,6 +42530,7 @@ registerSkillsCommand(program2);
42111
42530
  registerMcpCommand(program2);
42112
42531
  registerRulesCommand(program2);
42113
42532
  registerPluginsCommand(program2);
42533
+ registerConfigCommand(program2);
42114
42534
  program2.command("init").description("Initialize agents.md configuration for the current project").option("-f, --force", "Overwrite existing configuration").option("-t, --template <template>", "Use specific template (web, cli, library)").action(initCommand);
42115
42535
  program2.command("detect").description("Detect current project stack and existing agent configurations").option("-v, --verbose", "Show detailed detection results").action(detectCommand);
42116
42536
  program2.command("sync").description("Sync agents.md with agent-specific configuration files").option("-a, --agent <agents...>", "Target specific agent(s)").option("-d, --dry-run", "Show what would be changed without making changes").option("-b, --backup", "Create backup before syncing").action(syncCommand);