agentinit 1.14.0 → 1.15.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
@@ -16717,15 +16717,191 @@ 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
16721
16876
  function getMarketplace(id) {
16722
- return MARKETPLACES.find((marketplace) => marketplace.id === id);
16877
+ return getAllMarketplaces().find((marketplace) => marketplace.id === id);
16723
16878
  }
16724
16879
  function getMarketplaceIds() {
16725
- return MARKETPLACES.map((marketplace) => marketplace.id);
16880
+ return getAllMarketplaces().map((marketplace) => marketplace.id);
16726
16881
  }
16727
- var MARKETPLACES;
16882
+ function getConfiguredDefaultMarketplaceId() {
16883
+ const defaultMarketplace = readUserConfigSync().defaultMarketplace;
16884
+ if (!defaultMarketplace) {
16885
+ return;
16886
+ }
16887
+ return getMarketplace(defaultMarketplace)?.id;
16888
+ }
16889
+ var getCustomMarketplaces, getAllMarketplaces, MARKETPLACES, CUSTOM_MARKETPLACE_PLUGIN_DIRS, CUSTOM_MARKETPLACE_CACHE_TTL_MS;
16728
16890
  var init_marketplaceRegistry = __esm(() => {
16891
+ init_userConfig();
16892
+ getCustomMarketplaces = function() {
16893
+ const builtInIds = new Set(MARKETPLACES.map((marketplace) => marketplace.id));
16894
+ return readUserConfigSync().customMarketplaces.filter((marketplace) => !builtInIds.has(marketplace.identifier)).map((marketplace) => ({
16895
+ id: marketplace.identifier,
16896
+ name: marketplace.name,
16897
+ repoUrl: marketplace.repoUrl,
16898
+ pluginDirs: [...CUSTOM_MARKETPLACE_PLUGIN_DIRS],
16899
+ cacheTtlMs: CUSTOM_MARKETPLACE_CACHE_TTL_MS
16900
+ }));
16901
+ };
16902
+ getAllMarketplaces = function() {
16903
+ return [...MARKETPLACES, ...getCustomMarketplaces()];
16904
+ };
16729
16905
  MARKETPLACES = [
16730
16906
  {
16731
16907
  id: "agentinit",
@@ -16749,6 +16925,8 @@ var init_marketplaceRegistry = __esm(() => {
16749
16925
  cacheTtlMs: 3600000
16750
16926
  }
16751
16927
  ];
16928
+ CUSTOM_MARKETPLACE_PLUGIN_DIRS = ["skills", "mcps", "rules"];
16929
+ CUSTOM_MARKETPLACE_CACHE_TTL_MS = 3600000;
16752
16930
  });
16753
16931
 
16754
16932
  // dist/core/mcpFilter.js
@@ -16860,9 +17038,9 @@ __export(exports_pluginManager, {
16860
17038
  }
16861
17039
  }
16862
17040
  });
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";
17041
+ import {resolve as resolve7, join as join4, basename as basename2, relative as relative2, dirname as dirname2} from "path";
17042
+ import {promises as fs22} from "fs";
17043
+ import {homedir as homedir4} from "os";
16866
17044
 
16867
17045
  class MarketplacePluginNotFoundError extends Error {
16868
17046
  pluginName;
@@ -16896,7 +17074,7 @@ class PluginManager {
16896
17074
  }
16897
17075
  async cleanupLoadedPluginContext(context) {
16898
17076
  if (context?.tempDir) {
16899
- await fs20.rm(context.tempDir, { recursive: true, force: true }).catch(() => {
17077
+ await fs22.rm(context.tempDir, { recursive: true, force: true }).catch(() => {
16900
17078
  });
16901
17079
  }
16902
17080
  }
@@ -16968,13 +17146,13 @@ class PluginManager {
16968
17146
  return `https://github.com/${source.owner}/${source.repo}`;
16969
17147
  }
16970
17148
  getGitHubFallbackTrust(source) {
16971
- if (source.owner === "openai" && source.repo === "codex-plugin-cc") {
17149
+ if (source.owner && source.repo && isVerifiedGitHubRepoSync(source.owner, source.repo)) {
16972
17150
  return "verified";
16973
17151
  }
16974
17152
  return "unverified";
16975
17153
  }
16976
17154
  async resolvePreparedPluginDir(pluginDir, source) {
16977
- const claudeMarketplaceManifestPath = join3(pluginDir, ".claude-plugin", "marketplace.json");
17155
+ const claudeMarketplaceManifestPath = join4(pluginDir, ".claude-plugin", "marketplace.json");
16978
17156
  if (!await fileExists(claudeMarketplaceManifestPath)) {
16979
17157
  return { pluginDir, warnings: [] };
16980
17158
  }
@@ -17115,13 +17293,13 @@ class PluginManager {
17115
17293
  }
17116
17294
  async getClaudeNativeFeatureKinds(pluginDir, manifest) {
17117
17295
  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"))
17296
+ (async () => !!manifest.commands || await isDirectory(join4(pluginDir, "commands")))(),
17297
+ (async () => !!manifest.hooks || await isDirectory(join4(pluginDir, "hooks")))(),
17298
+ (async () => !!manifest.agents || await isDirectory(join4(pluginDir, "agents")))(),
17299
+ isDirectory(join4(pluginDir, "prompts")),
17300
+ isDirectory(join4(pluginDir, "schemas")),
17301
+ isDirectory(join4(pluginDir, "scripts")),
17302
+ isDirectory(join4(pluginDir, "templates"))
17125
17303
  ]);
17126
17304
  return [
17127
17305
  ...featureChecks[0] ? ["commands"] : [],
@@ -17137,7 +17315,7 @@ class PluginManager {
17137
17315
  if (plugin.format !== "claude") {
17138
17316
  return null;
17139
17317
  }
17140
- const manifestContent = await readFileIfExists(join3(pluginDir, ".claude-plugin", "plugin.json"));
17318
+ const manifestContent = await readFileIfExists(join4(pluginDir, ".claude-plugin", "plugin.json"));
17141
17319
  if (!manifestContent) {
17142
17320
  return null;
17143
17321
  }
@@ -17157,7 +17335,7 @@ class PluginManager {
17157
17335
  return {
17158
17336
  namespace,
17159
17337
  pluginKey: `${plugin.name}@${namespace}`,
17160
- installPath: join3(homedir3(), ".claude", "plugins", "cache", namespace, plugin.name, versionDir),
17338
+ installPath: join4(homedir4(), ".claude", "plugins", "cache", namespace, plugin.name, versionDir),
17161
17339
  features
17162
17340
  };
17163
17341
  }
@@ -17230,10 +17408,10 @@ class PluginManager {
17230
17408
  warnings.push(`Skipped native Claude plugin install because Claude already has "${plugin.name}" installed as ${conflictingKey}.`);
17231
17409
  return { installed, skipped, warnings };
17232
17410
  }
17233
- await fs20.rm(nativeTarget.installPath, { recursive: true, force: true }).catch(() => {
17411
+ await fs22.rm(nativeTarget.installPath, { recursive: true, force: true }).catch(() => {
17234
17412
  });
17235
- await fs20.mkdir(dirname2(nativeTarget.installPath), { recursive: true });
17236
- await fs20.cp(pluginDir, nativeTarget.installPath, { recursive: true, dereference: true });
17413
+ await fs22.mkdir(dirname2(nativeTarget.installPath), { recursive: true });
17414
+ await fs22.cp(pluginDir, nativeTarget.installPath, { recursive: true, dereference: true });
17237
17415
  const now = new Date().toISOString();
17238
17416
  claudeInstalled.plugins[nativeTarget.pluginKey] = [{
17239
17417
  scope: "user",
@@ -17281,7 +17459,7 @@ class PluginManager {
17281
17459
  claudeSettings.enabledPlugins = remainingEnabledPlugins;
17282
17460
  await this.saveClaudeSettings(claudeSettings);
17283
17461
  }
17284
- await fs20.rm(component.installPath, { recursive: true, force: true }).catch(() => {
17462
+ await fs22.rm(component.installPath, { recursive: true, force: true }).catch(() => {
17285
17463
  });
17286
17464
  return true;
17287
17465
  }
@@ -17332,7 +17510,7 @@ class PluginManager {
17332
17510
  repo
17333
17511
  };
17334
17512
  }
17335
- const defaultMarketplace = this.getMarketplaceIds()[0];
17513
+ const defaultMarketplace = getConfiguredDefaultMarketplaceId() || this.getMarketplaceIds()[0];
17336
17514
  if (defaultMarketplace) {
17337
17515
  return {
17338
17516
  type: "marketplace",
@@ -17351,13 +17529,13 @@ class PluginManager {
17351
17529
  async ensureMarketplaceCache(registryId) {
17352
17530
  const registry = this.getMarketplace(registryId);
17353
17531
  if (!registry) {
17354
- throw new Error(`Unknown marketplace: ${registryId}. Available: ${MARKETPLACES.map((m) => m.id).join(", ")}`);
17532
+ throw new Error(`Unknown marketplace: ${registryId}. Available: ${this.getMarketplaceIds().join(", ")}`);
17355
17533
  }
17356
17534
  const cacheDir = getMarketplaceCacheDir(registryId);
17357
- const cacheMetaPath = join3(cacheDir, ".agentinit-cache-meta.json");
17535
+ const cacheMetaPath = join4(cacheDir, ".agentinit-cache-meta.json");
17358
17536
  if (await fileExists(cacheMetaPath)) {
17359
17537
  try {
17360
- const meta = JSON.parse(await fs20.readFile(cacheMetaPath, "utf8"));
17538
+ const meta = JSON.parse(await fs22.readFile(cacheMetaPath, "utf8"));
17361
17539
  const age = Date.now() - (meta.fetchedAt || 0);
17362
17540
  if (age < registry.cacheTtlMs) {
17363
17541
  return cacheDir;
@@ -17365,29 +17543,29 @@ class PluginManager {
17365
17543
  } catch {
17366
17544
  }
17367
17545
  }
17368
- if (await fileExists(join3(cacheDir, ".git"))) {
17546
+ if (await fileExists(join4(cacheDir, ".git"))) {
17369
17547
  const { execFile } = await import("child_process");
17370
17548
  const { promisify } = await import("util");
17371
17549
  const exec = promisify(execFile);
17372
17550
  try {
17373
17551
  await exec("git", ["pull", "--ff-only"], { cwd: cacheDir, timeout: 30000 });
17374
17552
  } catch {
17375
- await fs20.rm(cacheDir, { recursive: true, force: true });
17553
+ await fs22.rm(cacheDir, { recursive: true, force: true });
17376
17554
  await this.cloneMarketplace(registry.repoUrl, cacheDir);
17377
17555
  }
17378
17556
  } else {
17379
17557
  await this.cloneMarketplace(registry.repoUrl, cacheDir);
17380
17558
  }
17381
- await fs20.mkdir(cacheDir, { recursive: true });
17382
- await fs20.writeFile(cacheMetaPath, JSON.stringify({ fetchedAt: Date.now() }));
17559
+ await fs22.mkdir(cacheDir, { recursive: true });
17560
+ await fs22.writeFile(cacheMetaPath, JSON.stringify({ fetchedAt: Date.now() }));
17383
17561
  return cacheDir;
17384
17562
  }
17385
17563
  async cloneMarketplace(repoUrl, dest) {
17386
- await fs20.mkdir(dest, { recursive: true });
17564
+ await fs22.mkdir(dest, { recursive: true });
17387
17565
  const { execFile } = await import("child_process");
17388
17566
  const { promisify } = await import("util");
17389
17567
  const exec = promisify(execFile);
17390
- await fs20.rm(dest, { recursive: true, force: true }).catch(() => {
17568
+ await fs22.rm(dest, { recursive: true, force: true }).catch(() => {
17391
17569
  });
17392
17570
  await exec("git", ["clone", "--depth", "1", repoUrl, dest], { timeout: 60000 });
17393
17571
  }
@@ -17397,7 +17575,7 @@ class PluginManager {
17397
17575
  throw new Error(`Unknown marketplace: ${registryId}`);
17398
17576
  const cacheDir = await this.ensureMarketplaceCache(registryId);
17399
17577
  for (const dir of registry.pluginDirs) {
17400
- const pluginPath = join3(cacheDir, dir, name);
17578
+ const pluginPath = join4(cacheDir, dir, name);
17401
17579
  if (await isDirectory(pluginPath)) {
17402
17580
  return pluginPath;
17403
17581
  }
@@ -17413,7 +17591,7 @@ class PluginManager {
17413
17591
  const cacheDir = await this.ensureMarketplaceCache(registryId);
17414
17592
  const results = [];
17415
17593
  for (const dir of registry.pluginDirs) {
17416
- const fullDir = join3(cacheDir, dir);
17594
+ const fullDir = join4(cacheDir, dir);
17417
17595
  if (!await isDirectory(fullDir))
17418
17596
  continue;
17419
17597
  const cat = dir === "plugins" ? "official" : dir === "external_plugins" ? "community" : dir.startsWith("skills/.") ? dir.slice("skills/.".length) : dir;
@@ -17423,26 +17601,26 @@ class PluginManager {
17423
17601
  for (const entry of entries) {
17424
17602
  if (entry.startsWith("."))
17425
17603
  continue;
17426
- const entryPath = join3(fullDir, entry);
17604
+ const entryPath = join4(fullDir, entry);
17427
17605
  if (!await isDirectory(entryPath))
17428
17606
  continue;
17429
- const manifestPath = join3(entryPath, ".claude-plugin", "plugin.json");
17607
+ const manifestPath = join4(entryPath, ".claude-plugin", "plugin.json");
17430
17608
  let name = entry;
17431
17609
  let description = "";
17432
17610
  let version = "0.0.0";
17433
17611
  if (await fileExists(manifestPath)) {
17434
17612
  try {
17435
- const manifest = JSON.parse(await fs20.readFile(manifestPath, "utf8"));
17613
+ const manifest = JSON.parse(await fs22.readFile(manifestPath, "utf8"));
17436
17614
  name = manifest.name || entry;
17437
17615
  description = manifest.description || "";
17438
17616
  version = manifest.version || "0.0.0";
17439
17617
  } catch {
17440
17618
  }
17441
17619
  } else {
17442
- const skillMdPath = join3(entryPath, "SKILL.md");
17620
+ const skillMdPath = join4(entryPath, "SKILL.md");
17443
17621
  if (await fileExists(skillMdPath)) {
17444
17622
  try {
17445
- const parsed = import_gray_matter.default(await fs20.readFile(skillMdPath, "utf8"));
17623
+ const parsed = import_gray_matter.default(await fs22.readFile(skillMdPath, "utf8"));
17446
17624
  if (parsed.data.name)
17447
17625
  name = parsed.data.name;
17448
17626
  if (parsed.data.description)
@@ -17450,10 +17628,10 @@ class PluginManager {
17450
17628
  } catch {
17451
17629
  }
17452
17630
  } else {
17453
- const mcpPath = join3(entryPath, ".mcp.json");
17631
+ const mcpPath = join4(entryPath, ".mcp.json");
17454
17632
  if (await fileExists(mcpPath)) {
17455
17633
  try {
17456
- const mcpConfig = JSON.parse(await fs20.readFile(mcpPath, "utf8"));
17634
+ const mcpConfig = JSON.parse(await fs22.readFile(mcpPath, "utf8"));
17457
17635
  const serverNames = Object.keys(mcpConfig.mcpServers || mcpConfig);
17458
17636
  if (serverNames.length > 0) {
17459
17637
  description = `MCP server(s): ${serverNames.join(", ")}`;
@@ -17475,10 +17653,10 @@ class PluginManager {
17475
17653
  return results.sort((a, b) => a.name.localeCompare(b.name));
17476
17654
  }
17477
17655
  async detectFormat(pluginDir) {
17478
- if (await fileExists(join3(pluginDir, ".claude-plugin", "plugin.json"))) {
17656
+ if (await fileExists(join4(pluginDir, ".claude-plugin", "plugin.json"))) {
17479
17657
  return "claude";
17480
17658
  }
17481
- if (await fileExists(join3(pluginDir, ".cursor-plugin", "plugin.json"))) {
17659
+ if (await fileExists(join4(pluginDir, ".cursor-plugin", "plugin.json"))) {
17482
17660
  return "cursor";
17483
17661
  }
17484
17662
  return "generic";
@@ -17495,7 +17673,7 @@ class PluginManager {
17495
17673
  }
17496
17674
  }
17497
17675
  async parseClaudePlugin(pluginDir, source) {
17498
- const manifestPath = join3(pluginDir, ".claude-plugin", "plugin.json");
17676
+ const manifestPath = join4(pluginDir, ".claude-plugin", "plugin.json");
17499
17677
  const manifestContent = await readFileIfExists(manifestPath);
17500
17678
  if (!manifestContent) {
17501
17679
  throw new Error(`Missing .claude-plugin/plugin.json in ${pluginDir}`);
@@ -17506,10 +17684,10 @@ class PluginManager {
17506
17684
  const convertedSkills = await this.convertCommandsToSkills(pluginDir, manifest);
17507
17685
  skills.push(...convertedSkills);
17508
17686
  const mcpServers = await this.parseMcpJson(pluginDir);
17509
- if (await isDirectory(join3(pluginDir, "hooks")) || manifest.hooks) {
17687
+ if (await isDirectory(join4(pluginDir, "hooks")) || manifest.hooks) {
17510
17688
  warnings.push("Hooks (hooks/) are Claude Code-specific");
17511
17689
  }
17512
- if (await isDirectory(join3(pluginDir, "agents")) || manifest.agents) {
17690
+ if (await isDirectory(join4(pluginDir, "agents")) || manifest.agents) {
17513
17691
  warnings.push("Agent definitions (agents/) are Claude Code-specific");
17514
17692
  }
17515
17693
  return {
@@ -17524,7 +17702,7 @@ class PluginManager {
17524
17702
  };
17525
17703
  }
17526
17704
  async parseCursorPlugin(pluginDir, source) {
17527
- const manifestPath = join3(pluginDir, ".cursor-plugin", "plugin.json");
17705
+ const manifestPath = join4(pluginDir, ".cursor-plugin", "plugin.json");
17528
17706
  const manifestContent = await readFileIfExists(manifestPath);
17529
17707
  if (!manifestContent) {
17530
17708
  throw new Error(`Missing .cursor-plugin/plugin.json in ${pluginDir}`);
@@ -17563,7 +17741,7 @@ class PluginManager {
17563
17741
  };
17564
17742
  }
17565
17743
  async parseMcpJson(pluginDir) {
17566
- const mcpPath = join3(pluginDir, ".mcp.json");
17744
+ const mcpPath = join4(pluginDir, ".mcp.json");
17567
17745
  const content = await readFileIfExists(mcpPath);
17568
17746
  if (!content)
17569
17747
  return [];
@@ -17610,7 +17788,7 @@ class PluginManager {
17610
17788
  commandsDirs.push(resolve7(pluginDir, cmd));
17611
17789
  }
17612
17790
  } else {
17613
- commandsDirs.push(join3(pluginDir, "commands"));
17791
+ commandsDirs.push(join4(pluginDir, "commands"));
17614
17792
  }
17615
17793
  for (const commandsDir of commandsDirs) {
17616
17794
  if (!await isDirectory(commandsDir))
@@ -17619,7 +17797,7 @@ class PluginManager {
17619
17797
  for (const entry of entries) {
17620
17798
  if (!entry.endsWith(".md"))
17621
17799
  continue;
17622
- const cmdPath = join3(commandsDir, entry);
17800
+ const cmdPath = join4(commandsDir, entry);
17623
17801
  const skill = await this.convertSingleCommandToSkill(cmdPath, manifest.name);
17624
17802
  if (skill)
17625
17803
  skills.push(skill);
@@ -17908,7 +18086,7 @@ ${body.trim()}
17908
18086
  }
17909
18087
  if (!removedSkillPaths.has(skill.path)) {
17910
18088
  try {
17911
- await fs20.rm(skill.path, { recursive: true, force: true });
18089
+ await fs22.rm(skill.path, { recursive: true, force: true });
17912
18090
  removedSkillPaths.add(skill.path);
17913
18091
  } catch {
17914
18092
  details.push(`Could not remove skill path: ${skill.path}`);
@@ -17917,7 +18095,7 @@ ${body.trim()}
17917
18095
  }
17918
18096
  if (skill.canonicalPath && skill.canonicalPath !== skill.path && !removedCanonicalPaths.has(skill.canonicalPath) && !sharedCanonicalPath) {
17919
18097
  try {
17920
- await fs20.rm(skill.canonicalPath, { recursive: true, force: true });
18098
+ await fs22.rm(skill.canonicalPath, { recursive: true, force: true });
17921
18099
  removedCanonicalPaths.add(skill.canonicalPath);
17922
18100
  } catch {
17923
18101
  details.push(`Could not remove canonical skill path: ${skill.canonicalPath}`);
@@ -18021,27 +18199,28 @@ var init_pluginManager = __esm(() => {
18021
18199
  init_mcpFilter();
18022
18200
  init_marketplaceRegistry();
18023
18201
  init_skillsManager();
18202
+ init_userConfig();
18024
18203
  getMarketplaceCacheDir = function(registryId) {
18025
- return join3(homedir3(), ".agentinit", "marketplace-cache", registryId);
18204
+ return join4(homedir4(), ".agentinit", "marketplace-cache", registryId);
18026
18205
  };
18027
18206
  getRegistryPath = function(projectPath, global3) {
18028
18207
  if (global3) {
18029
- return join3(homedir3(), ".agentinit", "plugins.json");
18208
+ return join4(homedir4(), ".agentinit", "plugins.json");
18030
18209
  }
18031
- return join3(projectPath, ".agentinit", "plugins.json");
18210
+ return join4(projectPath, ".agentinit", "plugins.json");
18032
18211
  };
18033
18212
  getClaudeInstalledPluginsPath = function() {
18034
- return join3(homedir3(), ".claude", "plugins", "installed_plugins.json");
18213
+ return join4(homedir4(), ".claude", "plugins", "installed_plugins.json");
18035
18214
  };
18036
18215
  getClaudeSettingsPath = function() {
18037
- return join3(homedir3(), ".claude", "settings.json");
18216
+ return join4(homedir4(), ".claude", "settings.json");
18038
18217
  };
18039
18218
  });
18040
18219
 
18041
18220
  // 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";
18221
+ import {resolve as resolve8, join as join5, relative as relative3} from "path";
18222
+ import {promises as fs24} from "fs";
18223
+ import {homedir as homedir5, tmpdir} from "os";
18045
18224
  import {execFile} from "child_process";
18046
18225
  import {promisify} from "util";
18047
18226
 
@@ -18108,6 +18287,17 @@ class SkillsManager {
18108
18287
  }
18109
18288
  resolveSourceRequest(source, options2) {
18110
18289
  if (this.isImplicitCatalogSkillSource(source, options2)) {
18290
+ const configuredDefaultMarketplace = getConfiguredDefaultMarketplaceId();
18291
+ if (configuredDefaultMarketplace) {
18292
+ return {
18293
+ source: {
18294
+ type: "marketplace",
18295
+ marketplace: configuredDefaultMarketplace,
18296
+ pluginName: source.trim()
18297
+ },
18298
+ implicitSkills: []
18299
+ };
18300
+ }
18111
18301
  return {
18112
18302
  source: {
18113
18303
  type: "github",
@@ -18144,7 +18334,7 @@ class SkillsManager {
18144
18334
  const fullDir = resolve8(repoPath, searchDir);
18145
18335
  if (!await fileExists(fullDir))
18146
18336
  continue;
18147
- const directSkillMd = join4(fullDir, "SKILL.md");
18337
+ const directSkillMd = join5(fullDir, "SKILL.md");
18148
18338
  if (await fileExists(directSkillMd)) {
18149
18339
  const parsed = await this.parseSkillMd(directSkillMd);
18150
18340
  if (parsed && !seen.has(parsed.name)) {
@@ -18152,7 +18342,7 @@ class SkillsManager {
18152
18342
  skills.push({ ...parsed, path: resolve8(fullDir) });
18153
18343
  }
18154
18344
  }
18155
- const directSkillMdLower = join4(fullDir, "skill.md");
18345
+ const directSkillMdLower = join5(fullDir, "skill.md");
18156
18346
  if (await fileExists(directSkillMdLower)) {
18157
18347
  const parsed = await this.parseSkillMd(directSkillMdLower);
18158
18348
  if (parsed && !seen.has(parsed.name)) {
@@ -18164,11 +18354,11 @@ class SkillsManager {
18164
18354
  continue;
18165
18355
  const entries = await listFiles(fullDir);
18166
18356
  for (const entry of entries) {
18167
- const entryPath = join4(fullDir, entry);
18357
+ const entryPath = join5(fullDir, entry);
18168
18358
  if (!await isDirectory(entryPath))
18169
18359
  continue;
18170
- const skillMdPath = join4(entryPath, "SKILL.md");
18171
- const skillMdPathLower = join4(entryPath, "skill.md");
18360
+ const skillMdPath = join5(entryPath, "SKILL.md");
18361
+ const skillMdPathLower = join5(entryPath, "skill.md");
18172
18362
  const skillFile = await fileExists(skillMdPath) ? skillMdPath : await fileExists(skillMdPathLower) ? skillMdPathLower : null;
18173
18363
  if (!skillFile)
18174
18364
  continue;
@@ -18182,14 +18372,14 @@ class SkillsManager {
18182
18372
  return skills;
18183
18373
  }
18184
18374
  async cloneRepo(url) {
18185
- const tempDir = await fs22.mkdtemp(join4(tmpdir(), "agentinit-skills-"));
18186
- await fs22.rm(tempDir, { recursive: true, force: true });
18375
+ const tempDir = await fs24.mkdtemp(join5(tmpdir(), "agentinit-skills-"));
18376
+ await fs24.rm(tempDir, { recursive: true, force: true });
18187
18377
  try {
18188
18378
  await execFileAsync("git", ["clone", "--depth", "1", url, tempDir], {
18189
18379
  timeout: 60000
18190
18380
  });
18191
18381
  } catch (error) {
18192
- await fs22.rm(tempDir, { recursive: true, force: true }).catch(() => {
18382
+ await fs24.rm(tempDir, { recursive: true, force: true }).catch(() => {
18193
18383
  });
18194
18384
  throw new Error(`Failed to clone ${url}: ${error.message}`);
18195
18385
  }
@@ -18283,7 +18473,7 @@ class SkillsManager {
18283
18473
  return { skills, warnings };
18284
18474
  } finally {
18285
18475
  if (tempDir) {
18286
- await fs22.rm(tempDir, { recursive: true, force: true }).catch(() => {
18476
+ await fs24.rm(tempDir, { recursive: true, force: true }).catch(() => {
18287
18477
  });
18288
18478
  }
18289
18479
  }
@@ -18304,30 +18494,30 @@ class SkillsManager {
18304
18494
  async installSkill(skillPath, skillName, targetDir, copy = false) {
18305
18495
  const normalizedSkillName = this.normalizeSkillName(skillName);
18306
18496
  const destPath = this.resolveInstallPath(targetDir, normalizedSkillName);
18307
- await fs22.mkdir(resolve8(targetDir), { recursive: true });
18497
+ await fs24.mkdir(resolve8(targetDir), { recursive: true });
18308
18498
  if (await fileExists(destPath)) {
18309
- await fs22.rm(destPath, { recursive: true, force: true });
18499
+ await fs24.rm(destPath, { recursive: true, force: true });
18310
18500
  }
18311
18501
  if (copy) {
18312
18502
  await this.copyDir(skillPath, destPath);
18313
18503
  } else {
18314
- await fs22.symlink(skillPath, destPath, "dir");
18504
+ await fs24.symlink(skillPath, destPath, "dir");
18315
18505
  }
18316
18506
  return destPath;
18317
18507
  }
18318
18508
  async installSkillFromContent(skillName, skillContent, targetDir) {
18319
18509
  const normalizedSkillName = this.normalizeSkillName(skillName);
18320
18510
  const destPath = this.resolveInstallPath(targetDir, normalizedSkillName);
18321
- await fs22.mkdir(resolve8(targetDir), { recursive: true });
18511
+ await fs24.mkdir(resolve8(targetDir), { recursive: true });
18322
18512
  if (await fileExists(destPath)) {
18323
- await fs22.rm(destPath, { recursive: true, force: true });
18513
+ await fs24.rm(destPath, { recursive: true, force: true });
18324
18514
  }
18325
- await fs22.mkdir(destPath, { recursive: true });
18326
- await fs22.writeFile(join4(destPath, "SKILL.md"), skillContent, "utf8");
18515
+ await fs24.mkdir(destPath, { recursive: true });
18516
+ await fs24.writeFile(join5(destPath, "SKILL.md"), skillContent, "utf8");
18327
18517
  return destPath;
18328
18518
  }
18329
18519
  getCanonicalSkillsDir(projectPath, global3 = false) {
18330
- return global3 ? resolve8(homedir4(), ".agents/skills") : resolve8(projectPath, ".agents/skills");
18520
+ return global3 ? resolve8(homedir5(), ".agents/skills") : resolve8(projectPath, ".agents/skills");
18331
18521
  }
18332
18522
  async getInstallPlan(skillName, agent, projectPath, options2 = {}) {
18333
18523
  const normalizedSkillName = this.normalizeSkillName(skillName);
@@ -18401,7 +18591,7 @@ class SkillsManager {
18401
18591
  throw new Error(`Missing canonical path for ${skillName}`);
18402
18592
  }
18403
18593
  await this.cleanAndCreateDirectory(canonicalPath);
18404
- await fs22.writeFile(join4(canonicalPath, "SKILL.md"), skillContent, "utf8");
18594
+ await fs24.writeFile(join5(canonicalPath, "SKILL.md"), skillContent, "utf8");
18405
18595
  if (plan.path === canonicalPath) {
18406
18596
  return plan;
18407
18597
  }
@@ -18438,16 +18628,16 @@ class SkillsManager {
18438
18628
  return this.resolveInstallPath(targetDir, this.normalizeSkillName(skillName));
18439
18629
  }
18440
18630
  async cleanAndCreateDirectory(path) {
18441
- await fs22.rm(path, { recursive: true, force: true }).catch(() => {
18631
+ await fs24.rm(path, { recursive: true, force: true }).catch(() => {
18442
18632
  });
18443
- await fs22.mkdir(path, { recursive: true });
18633
+ await fs24.mkdir(path, { recursive: true });
18444
18634
  }
18445
18635
  isWithinPath(basePath, targetPath) {
18446
18636
  const relativePath = relative3(resolve8(basePath), resolve8(targetPath));
18447
18637
  return relativePath === "" || !relativePath.startsWith("..") && !relativePath.includes("/../") && !relativePath.includes("\\..\\");
18448
18638
  }
18449
18639
  async copyDir(src, dest) {
18450
- await fs22.cp(src, dest, { recursive: true, dereference: true });
18640
+ await fs24.cp(src, dest, { recursive: true, dereference: true });
18451
18641
  }
18452
18642
  async addFromSource(source, projectPath, options2 = {}) {
18453
18643
  const discovered = await this.discoverFromSource(source, projectPath, {
@@ -18522,11 +18712,11 @@ class SkillsManager {
18522
18712
  continue;
18523
18713
  const entries = await listFiles(dir);
18524
18714
  for (const entry of entries) {
18525
- const entryPath = join4(dir, entry);
18715
+ const entryPath = join5(dir, entry);
18526
18716
  if (!await isDirectory(entryPath))
18527
18717
  continue;
18528
- const skillMdPath = join4(entryPath, "SKILL.md");
18529
- const skillMdPathLower = join4(entryPath, "skill.md");
18718
+ const skillMdPath = join5(entryPath, "SKILL.md");
18719
+ const skillMdPathLower = join5(entryPath, "skill.md");
18530
18720
  const skillFile = await fileExists(skillMdPath) ? skillMdPath : await fileExists(skillMdPathLower) ? skillMdPathLower : null;
18531
18721
  if (!skillFile)
18532
18722
  continue;
@@ -18536,7 +18726,7 @@ class SkillsManager {
18536
18726
  let isSymlink = false;
18537
18727
  let canonicalPath;
18538
18728
  try {
18539
- const stat = await fs22.lstat(entryPath);
18729
+ const stat = await fs24.lstat(entryPath);
18540
18730
  isSymlink = stat.isSymbolicLink();
18541
18731
  const canonicalBase = this.getCanonicalSkillsDir(projectPath, scope === "global");
18542
18732
  const [resolvedEntryPath, resolvedCanonicalBase] = await Promise.all([
@@ -18602,7 +18792,7 @@ class SkillsManager {
18602
18792
  }
18603
18793
  if (!removedPaths.has(entry.path)) {
18604
18794
  try {
18605
- await fs22.rm(entry.path, { recursive: true, force: true });
18795
+ await fs24.rm(entry.path, { recursive: true, force: true });
18606
18796
  removedPaths.add(entry.path);
18607
18797
  } catch {
18608
18798
  skipped.push({
@@ -18615,7 +18805,7 @@ class SkillsManager {
18615
18805
  if (entry.canonicalPath && entry.canonicalPath !== entry.path && !removedCanonicalPaths.has(entry.canonicalPath)) {
18616
18806
  const stillReferenced = remainingEntries.some((other) => other.name.toLowerCase() === entry.name.toLowerCase() && other.canonicalPath === entry.canonicalPath);
18617
18807
  if (!stillReferenced) {
18618
- await fs22.rm(entry.canonicalPath, { recursive: true, force: true }).catch(() => {
18808
+ await fs24.rm(entry.canonicalPath, { recursive: true, force: true }).catch(() => {
18619
18809
  });
18620
18810
  removedCanonicalPaths.add(entry.canonicalPath);
18621
18811
  }
@@ -24851,27 +25041,27 @@ var require_windows = __commonJS((exports, module) => {
24851
25041
  return checkPathExt(path, options2);
24852
25042
  };
24853
25043
  var isexe = function(path, options2, cb) {
24854
- fs29.stat(path, function(er, stat) {
25044
+ fs31.stat(path, function(er, stat) {
24855
25045
  cb(er, er ? false : checkStat(stat, path, options2));
24856
25046
  });
24857
25047
  };
24858
25048
  var sync = function(path, options2) {
24859
- return checkStat(fs29.statSync(path), path, options2);
25049
+ return checkStat(fs31.statSync(path), path, options2);
24860
25050
  };
24861
25051
  module.exports = isexe;
24862
25052
  isexe.sync = sync;
24863
- var fs29 = __require("fs");
25053
+ var fs31 = __require("fs");
24864
25054
  });
24865
25055
 
24866
25056
  // node_modules/isexe/mode.js
24867
25057
  var require_mode = __commonJS((exports, module) => {
24868
25058
  var isexe = function(path, options2, cb) {
24869
- fs29.stat(path, function(er, stat) {
25059
+ fs31.stat(path, function(er, stat) {
24870
25060
  cb(er, er ? false : checkStat(stat, options2));
24871
25061
  });
24872
25062
  };
24873
25063
  var sync = function(path, options2) {
24874
- return checkStat(fs29.statSync(path), options2);
25064
+ return checkStat(fs31.statSync(path), options2);
24875
25065
  };
24876
25066
  var checkStat = function(stat, options2) {
24877
25067
  return stat.isFile() && checkMode(stat, options2);
@@ -24891,7 +25081,7 @@ var require_mode = __commonJS((exports, module) => {
24891
25081
  };
24892
25082
  module.exports = isexe;
24893
25083
  isexe.sync = sync;
24894
- var fs29 = __require("fs");
25084
+ var fs31 = __require("fs");
24895
25085
  });
24896
25086
 
24897
25087
  // node_modules/isexe/index.js
@@ -24936,7 +25126,7 @@ var require_isexe = __commonJS((exports, module) => {
24936
25126
  }
24937
25127
  }
24938
25128
  };
24939
- var fs29 = __require("fs");
25129
+ var fs31 = __require("fs");
24940
25130
  var core2;
24941
25131
  if (process.platform === "win32" || global.TESTING_WINDOWS) {
24942
25132
  core2 = require_windows();
@@ -25143,14 +25333,14 @@ var require_readShebang = __commonJS((exports, module) => {
25143
25333
  const buffer = Buffer.alloc(size);
25144
25334
  let fd;
25145
25335
  try {
25146
- fd = fs29.openSync(command, "r");
25147
- fs29.readSync(fd, buffer, 0, size, 0);
25148
- fs29.closeSync(fd);
25336
+ fd = fs31.openSync(command, "r");
25337
+ fs31.readSync(fd, buffer, 0, size, 0);
25338
+ fs31.closeSync(fd);
25149
25339
  } catch (e) {
25150
25340
  }
25151
25341
  return shebangCommand(buffer.toString());
25152
25342
  };
25153
- var fs29 = __require("fs");
25343
+ var fs31 = __require("fs");
25154
25344
  var shebangCommand = require_shebang_command();
25155
25345
  module.exports = readShebang;
25156
25346
  });
@@ -27484,7 +27674,7 @@ import {relative as relative5} from "path";
27484
27674
 
27485
27675
  // dist/core/propagator.js
27486
27676
  var import_gray_matter3 = __toESM(require_gray_matter(), 1);
27487
- import {promises as fs24} from "fs";
27677
+ import {promises as fs26} from "fs";
27488
27678
  import {resolve as resolve9} from "path";
27489
27679
 
27490
27680
  // node_modules/js-yaml/dist/js-yaml.mjs
@@ -30252,7 +30442,7 @@ class Propagator {
30252
30442
  resolvedTargets: []
30253
30443
  };
30254
30444
  const exists = await fileExists(generatedFile.path);
30255
- const existingStats = exists ? await fs24.lstat(generatedFile.path).catch(() => null) : null;
30445
+ const existingStats = exists ? await fs26.lstat(generatedFile.path).catch(() => null) : null;
30256
30446
  const existingContent = exists && !existingStats?.isSymbolicLink() ? await readFileIfExists(generatedFile.path) : null;
30257
30447
  const existingTarget = existingStats?.isSymbolicLink() ? await readSymlinkTarget(generatedFile.path) : null;
30258
30448
  if (options2.managedState && !options2.dryRun) {
@@ -30283,7 +30473,7 @@ class Propagator {
30283
30473
  if (!options2.dryRun) {
30284
30474
  if (generatedFile.kind === "file") {
30285
30475
  if (existingStats?.isSymbolicLink()) {
30286
- await fs24.rm(generatedFile.path, { force: true }).catch(() => {
30476
+ await fs26.rm(generatedFile.path, { force: true }).catch(() => {
30287
30477
  });
30288
30478
  }
30289
30479
  await writeFile(generatedFile.path, generatedFile.content || "");
@@ -30460,14 +30650,14 @@ ${content}
30460
30650
 
30461
30651
  // dist/core/managedState.js
30462
30652
  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";
30653
+ import {promises as fs28} from "fs";
30654
+ import {dirname as dirname3, join as join6, relative as relative4, resolve as resolve10} from "path";
30465
30655
  var toPosixPath = function(value) {
30466
30656
  return value.replace(/\\/g, "/");
30467
30657
  };
30468
30658
  async function pathType(targetPath) {
30469
30659
  try {
30470
- const stat = await fs26.lstat(targetPath);
30660
+ const stat = await fs28.lstat(targetPath);
30471
30661
  if (stat.isSymbolicLink()) {
30472
30662
  return "symlink";
30473
30663
  }
@@ -30477,20 +30667,20 @@ async function pathType(targetPath) {
30477
30667
  }
30478
30668
  }
30479
30669
  async function copyDirectory(src, dest) {
30480
- await fs26.mkdir(dest, { recursive: true });
30481
- const entries = await fs26.readdir(src, { withFileTypes: true });
30670
+ await fs28.mkdir(dest, { recursive: true });
30671
+ const entries = await fs28.readdir(src, { withFileTypes: true });
30482
30672
  for (const entry of entries) {
30483
- const srcPath = join5(src, entry.name);
30484
- const destPath = join5(dest, entry.name);
30673
+ const srcPath = join6(src, entry.name);
30674
+ const destPath = join6(dest, entry.name);
30485
30675
  if (entry.isDirectory()) {
30486
30676
  await copyDirectory(srcPath, destPath);
30487
30677
  } 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);
30678
+ const target = await fs28.readlink(srcPath);
30679
+ await fs28.mkdir(dirname3(destPath), { recursive: true });
30680
+ await fs28.symlink(target, destPath);
30491
30681
  } else {
30492
- await fs26.mkdir(dirname3(destPath), { recursive: true });
30493
- await fs26.copyFile(srcPath, destPath);
30682
+ await fs28.mkdir(dirname3(destPath), { recursive: true });
30683
+ await fs28.copyFile(srcPath, destPath);
30494
30684
  }
30495
30685
  }
30496
30686
  }
@@ -30499,14 +30689,14 @@ async function copyPath(src, dest) {
30499
30689
  if (!type2) {
30500
30690
  return;
30501
30691
  }
30502
- await fs26.mkdir(dirname3(dest), { recursive: true });
30692
+ await fs28.mkdir(dirname3(dest), { recursive: true });
30503
30693
  if (type2 === "symlink") {
30504
- const target = await fs26.readlink(src);
30505
- await fs26.symlink(target, dest);
30694
+ const target = await fs28.readlink(src);
30695
+ await fs28.symlink(target, dest);
30506
30696
  } else if (type2 === "directory") {
30507
30697
  await copyDirectory(src, dest);
30508
30698
  } else {
30509
- await fs26.copyFile(src, dest);
30699
+ await fs28.copyFile(src, dest);
30510
30700
  }
30511
30701
  }
30512
30702
  var MANAGED_STATE_FILE = "managed-state.json";
@@ -30520,11 +30710,11 @@ class ManagedStateStore {
30520
30710
  this.state = state;
30521
30711
  }
30522
30712
  static async open(projectPath) {
30523
- const agentInitDir = join5(projectPath, ".agentinit");
30524
- const statePath = join5(agentInitDir, MANAGED_STATE_FILE);
30713
+ const agentInitDir = join6(projectPath, ".agentinit");
30714
+ const statePath = join6(agentInitDir, MANAGED_STATE_FILE);
30525
30715
  const emptyState = { version: 1, entries: [] };
30526
30716
  try {
30527
- const raw = await fs26.readFile(statePath, "utf8");
30717
+ const raw = await fs28.readFile(statePath, "utf8");
30528
30718
  const parsed = JSON.parse(raw);
30529
30719
  if (!parsed || parsed.version !== 1 || !Array.isArray(parsed.entries)) {
30530
30720
  return new ManagedStateStore(projectPath, emptyState);
@@ -30535,13 +30725,13 @@ class ManagedStateStore {
30535
30725
  }
30536
30726
  }
30537
30727
  get agentInitDir() {
30538
- return join5(this.projectPath, ".agentinit");
30728
+ return join6(this.projectPath, ".agentinit");
30539
30729
  }
30540
30730
  get stateFilePath() {
30541
- return join5(this.agentInitDir, MANAGED_STATE_FILE);
30731
+ return join6(this.agentInitDir, MANAGED_STATE_FILE);
30542
30732
  }
30543
30733
  get backupsDir() {
30544
- return join5(this.agentInitDir, BACKUPS_DIR);
30734
+ return join6(this.agentInitDir, BACKUPS_DIR);
30545
30735
  }
30546
30736
  normalizeRelativePath(targetPath, preserveTrailingSlash = false) {
30547
30737
  const hasTrailingSlash = preserveTrailingSlash && /[\\/]$/.test(targetPath);
@@ -30563,14 +30753,14 @@ class ManagedStateStore {
30563
30753
  }
30564
30754
  if (type2 === "symlink") {
30565
30755
  try {
30566
- const backupLinkTarget = await fs26.readlink(targetPath);
30756
+ const backupLinkTarget = await fs28.readlink(targetPath);
30567
30757
  return { backupLinkTarget };
30568
30758
  } catch {
30569
30759
  return {};
30570
30760
  }
30571
30761
  }
30572
30762
  const relativeTargetPath = this.normalizeRelativePath(targetPath);
30573
- const backupPath = join5(this.backupsDir, relativeTargetPath);
30763
+ const backupPath = join6(this.backupsDir, relativeTargetPath);
30574
30764
  if (!await fileExists(backupPath)) {
30575
30765
  await copyPath(targetPath, backupPath);
30576
30766
  }
@@ -30617,8 +30807,8 @@ class ManagedStateStore {
30617
30807
  return [...paths5];
30618
30808
  }
30619
30809
  async save() {
30620
- await fs26.mkdir(this.agentInitDir, { recursive: true });
30621
- await fs26.writeFile(this.stateFilePath, JSON.stringify(this.state, null, 2), "utf8");
30810
+ await fs28.mkdir(this.agentInitDir, { recursive: true });
30811
+ await fs28.writeFile(this.stateFilePath, JSON.stringify(this.state, null, 2), "utf8");
30622
30812
  }
30623
30813
  async revertAll(options2 = {}) {
30624
30814
  const summary = {
@@ -30633,29 +30823,29 @@ class ManagedStateStore {
30633
30823
  const backupLinkTarget = entry.backupLinkTarget;
30634
30824
  if (entry.existedBefore && backupLinkTarget !== undefined) {
30635
30825
  if (!options2.dryRun) {
30636
- await fs26.rm(absolutePath, { recursive: true, force: true }).catch(() => {
30826
+ await fs28.rm(absolutePath, { recursive: true, force: true }).catch(() => {
30637
30827
  });
30638
- await fs26.mkdir(dirname3(absolutePath), { recursive: true });
30639
- await fs26.symlink(backupLinkTarget, absolutePath);
30828
+ await fs28.mkdir(dirname3(absolutePath), { recursive: true });
30829
+ await fs28.symlink(backupLinkTarget, absolutePath);
30640
30830
  }
30641
30831
  summary.restored++;
30642
30832
  } else if (entry.existedBefore && backupPath && await fileExists(backupPath)) {
30643
30833
  if (!options2.dryRun) {
30644
- await fs26.rm(absolutePath, { recursive: true, force: true }).catch(() => {
30834
+ await fs28.rm(absolutePath, { recursive: true, force: true }).catch(() => {
30645
30835
  });
30646
30836
  await copyPath(backupPath, absolutePath);
30647
30837
  }
30648
30838
  summary.restored++;
30649
30839
  } else {
30650
30840
  if (!options2.dryRun) {
30651
- await fs26.rm(absolutePath, { recursive: true, force: true }).catch(() => {
30841
+ await fs28.rm(absolutePath, { recursive: true, force: true }).catch(() => {
30652
30842
  });
30653
30843
  }
30654
30844
  summary.removed++;
30655
30845
  }
30656
30846
  if (!options2.keepBackups && backupPath && await fileExists(backupPath)) {
30657
30847
  if (!options2.dryRun) {
30658
- await fs26.rm(backupPath, { recursive: true, force: true }).catch(() => {
30848
+ await fs28.rm(backupPath, { recursive: true, force: true }).catch(() => {
30659
30849
  });
30660
30850
  }
30661
30851
  summary.backupsRemoved++;
@@ -30663,16 +30853,16 @@ class ManagedStateStore {
30663
30853
  }
30664
30854
  if (!options2.dryRun) {
30665
30855
  this.state.entries.length = 0;
30666
- await fs26.rm(this.stateFilePath, { force: true }).catch(() => {
30856
+ await fs28.rm(this.stateFilePath, { force: true }).catch(() => {
30667
30857
  });
30668
30858
  if (!options2.keepBackups) {
30669
- await fs26.rm(this.backupsDir, { recursive: true, force: true }).catch(() => {
30859
+ await fs28.rm(this.backupsDir, { recursive: true, force: true }).catch(() => {
30670
30860
  });
30671
30861
  }
30672
30862
  try {
30673
- const remainingEntries = await fs26.readdir(this.agentInitDir);
30863
+ const remainingEntries = await fs28.readdir(this.agentInitDir);
30674
30864
  if (remainingEntries.length === 0) {
30675
- await fs26.rm(this.agentInitDir, { recursive: true, force: true });
30865
+ await fs28.rm(this.agentInitDir, { recursive: true, force: true });
30676
30866
  }
30677
30867
  } catch {
30678
30868
  }
@@ -31015,15 +31205,15 @@ class MCPParser {
31015
31205
  }
31016
31206
 
31017
31207
  // dist/constants/mcp.js
31018
- import {readFileSync} from "fs";
31208
+ import {readFileSync as readFileSync2} from "fs";
31019
31209
  import {fileURLToPath} from "url";
31020
- import {dirname as dirname4, join as join6} from "path";
31210
+ import {dirname as dirname4, join as join7} from "path";
31021
31211
  var getPackageVersion = function() {
31022
31212
  try {
31023
31213
  const __filename2 = fileURLToPath(import.meta.url);
31024
31214
  const __dirname2 = dirname4(__filename2);
31025
- const packageJsonPath = join6(__dirname2, "../../package.json");
31026
- const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
31215
+ const packageJsonPath = join7(__dirname2, "../../package.json");
31216
+ const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
31027
31217
  return packageJson.version || "1.0.0";
31028
31218
  } catch {
31029
31219
  return "1.0.0";
@@ -31049,13 +31239,13 @@ var TOKEN_COUNT_THRESHOLDS = {
31049
31239
  };
31050
31240
  // dist/core/rulesParser.js
31051
31241
  init_fs();
31052
- import {readFileSync as readFileSync3} from "fs";
31242
+ import {readFileSync as readFileSync4} from "fs";
31053
31243
 
31054
31244
  // dist/core/rulesTemplateLoader.js
31055
31245
  var toml = __toESM(require_toml(), 1);
31056
31246
  import {resolve as resolve11, dirname as dirname5} from "path";
31057
31247
  import {fileURLToPath as fileURLToPath2} from "url";
31058
- import {readFileSync as readFileSync2, readdirSync, existsSync} from "fs";
31248
+ import {readFileSync as readFileSync3, readdirSync, existsSync as existsSync2} from "fs";
31059
31249
  var __filename2 = fileURLToPath2(import.meta.url);
31060
31250
  var __dirname2 = dirname5(__filename2);
31061
31251
 
@@ -31067,14 +31257,14 @@ class RulesTemplateLoader {
31067
31257
  this.loadTemplates();
31068
31258
  }
31069
31259
  loadTemplates() {
31070
- if (!existsSync(this.templatesPath)) {
31260
+ if (!existsSync2(this.templatesPath)) {
31071
31261
  throw new Error(`Rules templates directory not found: ${this.templatesPath}`);
31072
31262
  }
31073
31263
  const files = readdirSync(this.templatesPath).filter((file) => file.endsWith(".toml"));
31074
31264
  for (const file of files) {
31075
31265
  try {
31076
31266
  const filePath = resolve11(this.templatesPath, file);
31077
- const content = readFileSync2(filePath, "utf-8");
31267
+ const content = readFileSync3(filePath, "utf-8");
31078
31268
  const parsed = toml.default.parse(content);
31079
31269
  const template = {
31080
31270
  id: parsed.template.id,
@@ -31222,7 +31412,7 @@ class RulesParser {
31222
31412
  throw new RulesParseError(`Rules file not found: ${filePath}`);
31223
31413
  }
31224
31414
  try {
31225
- const content = readFileSync3(filePath, "utf-8");
31415
+ const content = readFileSync4(filePath, "utf-8");
31226
31416
  if (filePath.endsWith(".json")) {
31227
31417
  const parsed = JSON.parse(content);
31228
31418
  return this.extractRulesFromObject(parsed);
@@ -39292,8 +39482,8 @@ class MCPVerifier {
39292
39482
  }
39293
39483
 
39294
39484
  // dist/core/gitignoreManager.js
39295
- import {promises as fs29} from "fs";
39296
- import {dirname as dirname6, join as join7} from "path";
39485
+ import {promises as fs31} from "fs";
39486
+ import {dirname as dirname6, join as join8} from "path";
39297
39487
  var normalizeIgnorePath = function(projectPath, value) {
39298
39488
  const relative6 = value.startsWith(projectPath) ? value.slice(projectPath.length + 1) : value;
39299
39489
  const normalized = relative6.replace(/\\/g, "/").replace(/^\/+/, "");
@@ -39340,12 +39530,12 @@ var updateManagedBlock = function(existingContent, entries) {
39340
39530
  return content;
39341
39531
  };
39342
39532
  async function updateManagedIgnoreFile(projectPath, paths5, options2 = {}) {
39343
- const ignoreFile = options2.local ? join7(".git", "info", "exclude") : ".gitignore";
39344
- const ignoreFilePath = join7(projectPath, ignoreFile);
39533
+ const ignoreFile = options2.local ? join8(".git", "info", "exclude") : ".gitignore";
39534
+ const ignoreFilePath = join8(projectPath, ignoreFile);
39345
39535
  if (options2.local) {
39346
- const gitDir = join7(projectPath, ".git");
39536
+ const gitDir = join8(projectPath, ".git");
39347
39537
  try {
39348
- const stat = await fs29.stat(gitDir);
39538
+ const stat = await fs31.stat(gitDir);
39349
39539
  if (!stat.isDirectory()) {
39350
39540
  throw new Error;
39351
39541
  }
@@ -39356,21 +39546,21 @@ async function updateManagedIgnoreFile(projectPath, paths5, options2 = {}) {
39356
39546
  const normalizedPaths = [...new Set(paths5.map((path) => normalizeIgnorePath(projectPath, path)).filter(Boolean))].sort();
39357
39547
  let existingContent = "";
39358
39548
  try {
39359
- existingContent = await fs29.readFile(ignoreFilePath, "utf8");
39549
+ existingContent = await fs31.readFile(ignoreFilePath, "utf8");
39360
39550
  } catch {
39361
39551
  existingContent = "";
39362
39552
  }
39363
39553
  const updatedContent = updateManagedBlock(existingContent, normalizedPaths);
39364
- await fs29.mkdir(dirname6(ignoreFilePath), { recursive: true });
39365
- await fs29.writeFile(ignoreFilePath, updatedContent, "utf8");
39554
+ await fs31.mkdir(dirname6(ignoreFilePath), { recursive: true });
39555
+ await fs31.writeFile(ignoreFilePath, updatedContent, "utf8");
39366
39556
  return ignoreFilePath;
39367
39557
  }
39368
39558
  async function removeManagedIgnoreBlock(projectPath, options2 = {}) {
39369
- const ignoreFile = options2.local ? join7(".git", "info", "exclude") : ".gitignore";
39370
- const ignoreFilePath = join7(projectPath, ignoreFile);
39559
+ const ignoreFile = options2.local ? join8(".git", "info", "exclude") : ".gitignore";
39560
+ const ignoreFilePath = join8(projectPath, ignoreFile);
39371
39561
  let content;
39372
39562
  try {
39373
- content = await fs29.readFile(ignoreFilePath, "utf8");
39563
+ content = await fs31.readFile(ignoreFilePath, "utf8");
39374
39564
  } catch {
39375
39565
  return false;
39376
39566
  }
@@ -39386,13 +39576,13 @@ async function removeManagedIgnoreBlock(projectPath, options2 = {}) {
39386
39576
  const afterBlock = content.slice(endIndex + END_MARKER.length).replace(/^\n+/, "");
39387
39577
  let nextContent = `${beforeBlock}${afterBlock}`.replace(/\n{3,}/g, "\n\n").replace(/^\n+/, "");
39388
39578
  if (nextContent.trim() === "") {
39389
- await fs29.rm(ignoreFilePath, { force: true }).catch(() => {
39579
+ await fs31.rm(ignoreFilePath, { force: true }).catch(() => {
39390
39580
  });
39391
39581
  } else {
39392
39582
  if (!nextContent.endsWith("\n")) {
39393
39583
  nextContent += "\n";
39394
39584
  }
39395
- await fs29.writeFile(ignoreFilePath, nextContent, "utf8");
39585
+ await fs31.writeFile(ignoreFilePath, nextContent, "utf8");
39396
39586
  }
39397
39587
  return true;
39398
39588
  }
@@ -39403,12 +39593,12 @@ var END_MARKER = "# END AgentInit Generated Files";
39403
39593
  init_agentManager();
39404
39594
  init_skillsManager();
39405
39595
  init_fs();
39406
- import {dirname as dirname7, join as join8} from "path";
39596
+ import {dirname as dirname7, join as join9} from "path";
39407
39597
  async function discoverProjectSkills(projectPath, skillsManager4) {
39408
39598
  const sources = [];
39409
39599
  const skills = new Map;
39410
39600
  for (const sourceDir of PROJECT_SKILL_SOURCE_DIRS) {
39411
- const absoluteSourceDir = join8(projectPath, sourceDir);
39601
+ const absoluteSourceDir = join9(projectPath, sourceDir);
39412
39602
  if (!await fileExists(absoluteSourceDir)) {
39413
39603
  continue;
39414
39604
  }
@@ -40300,9 +40490,193 @@ async function revertCommand(options2) {
40300
40490
  }
40301
40491
  }
40302
40492
 
40493
+ // dist/utils/colors.js
40494
+ var colorsEnabled = function() {
40495
+ const env2 = process.env || {};
40496
+ const isTTY2 = !!process.stdout?.isTTY;
40497
+ return !env2.NODE_DISABLE_COLORS && env2.NO_COLOR == null && env2.TERM !== "dumb" && (env2.FORCE_COLOR != null && env2.FORCE_COLOR !== "0" || isTTY2);
40498
+ };
40499
+ function orange(text) {
40500
+ if (!colorsEnabled()) {
40501
+ return text;
40502
+ }
40503
+ return `\x1B[38;5;208m${text}\x1B[39m`;
40504
+ }
40505
+
40506
+ // dist/commands/config.js
40507
+ init_marketplaceRegistry();
40508
+ init_userConfig();
40509
+ var sortConfig = function(config) {
40510
+ config.customMarketplaces.sort((left, right) => left.identifier.localeCompare(right.identifier));
40511
+ config.verifiedGithubRepos.sort((left, right) => left.localeCompare(right));
40512
+ return config;
40513
+ };
40514
+ function registerConfigCommand(program2) {
40515
+ const config = program2.command("config").description("Manage AgentInit user configuration");
40516
+ const marketplaces = config.command("marketplaces").description("Manage configured marketplaces");
40517
+ marketplaces.command("list").description("List built-in and custom marketplaces").action(async () => {
40518
+ logger.titleBox("AgentInit Configuration");
40519
+ logger.section("Marketplaces");
40520
+ const defaultMarketplace = getConfiguredDefaultMarketplaceId();
40521
+ const marketplaceIds = getMarketplaceIds();
40522
+ for (let i = 0;i < marketplaceIds.length; i++) {
40523
+ const identifier = marketplaceIds[i];
40524
+ const marketplace = getMarketplace(identifier);
40525
+ if (!marketplace) {
40526
+ continue;
40527
+ }
40528
+ const flags = [
40529
+ BUILT_IN_MARKETPLACE_IDS.has(identifier) ? "built-in" : "custom",
40530
+ defaultMarketplace === identifier ? "default" : null
40531
+ ].filter(Boolean).join(", ");
40532
+ logger.tree(`${cyan(identifier)} ${dim(`[${flags}]`)} ${marketplace.name} ${dim(`-> ${marketplace.repoUrl}`)}`, i === marketplaceIds.length - 1);
40533
+ }
40534
+ if (!defaultMarketplace) {
40535
+ logger.info("No default marketplace configured.");
40536
+ }
40537
+ });
40538
+ 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) => {
40539
+ logger.titleBox("AgentInit Configuration");
40540
+ try {
40541
+ const identifier = normalizeMarketplaceIdentifier(identifierArg);
40542
+ const repoUrl = normalizeMarketplaceRepoUrl(repoUrlArg);
40543
+ const configState = await readUserConfig();
40544
+ if (BUILT_IN_MARKETPLACE_IDS.has(identifier)) {
40545
+ throw new Error(`Marketplace "${identifier}" is built in and cannot be redefined.`);
40546
+ }
40547
+ if (configState.customMarketplaces.some((marketplace) => marketplace.identifier === identifier)) {
40548
+ throw new Error(`Marketplace "${identifier}" already exists.`);
40549
+ }
40550
+ configState.customMarketplaces.push({
40551
+ identifier,
40552
+ name: normalizeMarketplaceName(options2.name, identifier),
40553
+ repoUrl
40554
+ });
40555
+ if (options2.default) {
40556
+ configState.defaultMarketplace = identifier;
40557
+ }
40558
+ await writeUserConfig(sortConfig(configState));
40559
+ logger.success(`Added marketplace ${green(identifier)}.`);
40560
+ logger.info(` ${repoUrl}`);
40561
+ if (options2.default) {
40562
+ logger.info(" Set as the configured default marketplace.");
40563
+ }
40564
+ } catch (error) {
40565
+ logger.error(error instanceof Error ? error.message : "Failed to add marketplace.");
40566
+ }
40567
+ });
40568
+ marketplaces.command("remove <identifier>").description("Remove a custom marketplace").action(async (identifierArg) => {
40569
+ logger.titleBox("AgentInit Configuration");
40570
+ try {
40571
+ const identifier = normalizeMarketplaceIdentifier(identifierArg);
40572
+ if (BUILT_IN_MARKETPLACE_IDS.has(identifier)) {
40573
+ throw new Error(`Marketplace "${identifier}" is built in and cannot be removed.`);
40574
+ }
40575
+ const configState = await readUserConfig();
40576
+ const nextMarketplaces = configState.customMarketplaces.filter((marketplace) => marketplace.identifier !== identifier);
40577
+ if (nextMarketplaces.length === configState.customMarketplaces.length) {
40578
+ throw new Error(`Marketplace "${identifier}" is not configured.`);
40579
+ }
40580
+ configState.customMarketplaces = nextMarketplaces;
40581
+ const clearedDefault = configState.defaultMarketplace === identifier;
40582
+ if (clearedDefault) {
40583
+ delete configState.defaultMarketplace;
40584
+ }
40585
+ await writeUserConfig(sortConfig(configState));
40586
+ logger.success(`Removed marketplace ${green(identifier)}.`);
40587
+ if (clearedDefault) {
40588
+ logger.info(" Cleared the configured default marketplace.");
40589
+ }
40590
+ } catch (error) {
40591
+ logger.error(error instanceof Error ? error.message : "Failed to remove marketplace.");
40592
+ }
40593
+ });
40594
+ marketplaces.command("default <identifier>").description("Set the configured default marketplace").action(async (identifierArg) => {
40595
+ logger.titleBox("AgentInit Configuration");
40596
+ try {
40597
+ const identifier = normalizeMarketplaceIdentifier(identifierArg);
40598
+ if (!getMarketplace(identifier)) {
40599
+ throw new Error(`Unknown marketplace: ${identifier}. Available: ${getMarketplaceIds().join(", ")}`);
40600
+ }
40601
+ const configState = await readUserConfig();
40602
+ configState.defaultMarketplace = identifier;
40603
+ await writeUserConfig(sortConfig(configState));
40604
+ logger.success(`Set ${green(identifier)} as the configured default marketplace.`);
40605
+ } catch (error) {
40606
+ logger.error(error instanceof Error ? error.message : "Failed to set default marketplace.");
40607
+ }
40608
+ });
40609
+ marketplaces.command("clear-default").description("Clear the configured default marketplace").action(async () => {
40610
+ logger.titleBox("AgentInit Configuration");
40611
+ const configState = await readUserConfig();
40612
+ if (!configState.defaultMarketplace) {
40613
+ logger.info("No configured default marketplace to clear.");
40614
+ return;
40615
+ }
40616
+ delete configState.defaultMarketplace;
40617
+ await writeUserConfig(sortConfig(configState));
40618
+ logger.success("Cleared the configured default marketplace.");
40619
+ });
40620
+ const verifiedRepos = config.command("verified-repos").description("Manage exact verified GitHub repositories");
40621
+ verifiedRepos.command("list").description("List verified GitHub repositories").action(async () => {
40622
+ logger.titleBox("AgentInit Configuration");
40623
+ logger.section("Verified GitHub Repos");
40624
+ const configState = await readUserConfig();
40625
+ const entries = [
40626
+ ...getBuiltInVerifiedGithubRepos().map((repo) => ({ repo, builtIn: true })),
40627
+ ...configState.verifiedGithubRepos.filter((repo) => !BUILT_IN_VERIFIED_REPOS.has(repo)).map((repo) => ({ repo, builtIn: false }))
40628
+ ];
40629
+ for (let i = 0;i < entries.length; i++) {
40630
+ const entry = entries[i];
40631
+ logger.tree(`${cyan(entry.repo)} ${dim(entry.builtIn ? "[built-in]" : "[custom]")}`, i === entries.length - 1);
40632
+ }
40633
+ });
40634
+ verifiedRepos.command("add <repo>").description("Add an exact verified GitHub repo in owner/repo form").action(async (repoArg) => {
40635
+ logger.titleBox("AgentInit Configuration");
40636
+ try {
40637
+ const repo = normalizeGitHubRepoRef(repoArg);
40638
+ if (BUILT_IN_VERIFIED_REPOS.has(repo)) {
40639
+ logger.info(`${repo} is already verified by AgentInit.`);
40640
+ return;
40641
+ }
40642
+ const configState = await readUserConfig();
40643
+ if (configState.verifiedGithubRepos.includes(repo)) {
40644
+ logger.info(`${repo} is already configured as verified.`);
40645
+ return;
40646
+ }
40647
+ configState.verifiedGithubRepos.push(repo);
40648
+ await writeUserConfig(sortConfig(configState));
40649
+ logger.success(`Added verified GitHub repo ${green(repo)}.`);
40650
+ } catch (error) {
40651
+ logger.error(error instanceof Error ? error.message : "Failed to add verified repo.");
40652
+ }
40653
+ });
40654
+ verifiedRepos.command("remove <repo>").description("Remove a custom verified GitHub repo").action(async (repoArg) => {
40655
+ logger.titleBox("AgentInit Configuration");
40656
+ try {
40657
+ const repo = normalizeGitHubRepoRef(repoArg);
40658
+ if (BUILT_IN_VERIFIED_REPOS.has(repo)) {
40659
+ throw new Error(`${repo} is built in and cannot be removed.`);
40660
+ }
40661
+ const configState = await readUserConfig();
40662
+ const nextRepos = configState.verifiedGithubRepos.filter((entry) => entry !== repo);
40663
+ if (nextRepos.length === configState.verifiedGithubRepos.length) {
40664
+ throw new Error(`${repo} is not configured as verified.`);
40665
+ }
40666
+ configState.verifiedGithubRepos = nextRepos;
40667
+ await writeUserConfig(sortConfig(configState));
40668
+ logger.success(`Removed verified GitHub repo ${green(repo)}.`);
40669
+ } catch (error) {
40670
+ logger.error(error instanceof Error ? error.message : "Failed to remove verified repo.");
40671
+ }
40672
+ });
40673
+ }
40674
+ var BUILT_IN_MARKETPLACE_IDS = new Set(MARKETPLACES.map((marketplace) => marketplace.id));
40675
+ var BUILT_IN_VERIFIED_REPOS = new Set(getBuiltInVerifiedGithubRepos());
40676
+
40303
40677
  // dist/commands/skills.js
40304
40678
  var import_prompts2 = __toESM(require_prompts3(), 1);
40305
- import {homedir as homedir5} from "os";
40679
+ import {homedir as homedir6} from "os";
40306
40680
  import {relative as relative7, resolve as resolve12} from "path";
40307
40681
  init_skillsManager();
40308
40682
  init_marketplaceRegistry();
@@ -40587,7 +40961,7 @@ var prependCanonicalGlobalGroup = function(agentManager9, projectPath, groups) {
40587
40961
  var formatSkillsDir = function(projectPath, dir) {
40588
40962
  const normalizedDir = dir.replace(/\\/g, "/").replace(/\/?$/, "/");
40589
40963
  const normalizedProjectPath = projectPath.replace(/\\/g, "/");
40590
- const normalizedHome = homedir5().replace(/\\/g, "/");
40964
+ const normalizedHome = homedir6().replace(/\\/g, "/");
40591
40965
  if (normalizedDir.startsWith(`${normalizedProjectPath}/`)) {
40592
40966
  return `${relative7(projectPath, dir).replace(/\\/g, "/").replace(/\/?$/, "/")}`;
40593
40967
  }
@@ -40598,7 +40972,7 @@ var formatSkillsDir = function(projectPath, dir) {
40598
40972
  };
40599
40973
  var formatPromptPath = function(path) {
40600
40974
  const normalizedPath = path.replace(/\\/g, "/").replace(/\/?$/, "/");
40601
- const normalizedHome = homedir5().replace(/\\/g, "/");
40975
+ const normalizedHome = homedir6().replace(/\\/g, "/");
40602
40976
  if (normalizedPath === `${normalizedHome}/`) {
40603
40977
  return "~/";
40604
40978
  }
@@ -40608,7 +40982,7 @@ var formatPromptPath = function(path) {
40608
40982
  return normalizedPath;
40609
40983
  };
40610
40984
  var getCanonicalGlobalSkillsDir = function() {
40611
- return resolve12(homedir5(), ".agents/skills");
40985
+ return resolve12(homedir6(), ".agents/skills");
40612
40986
  };
40613
40987
  var getCanonicalGlobalSkillsDisplayPath = function() {
40614
40988
  return formatPromptPath(getCanonicalGlobalSkillsDir());
@@ -41550,23 +41924,9 @@ function registerRulesCommand(program2) {
41550
41924
  // dist/commands/plugins.js
41551
41925
  var import_prompts3 = __toESM(require_prompts3(), 1);
41552
41926
  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
41927
  init_pluginManager();
41569
41928
  init_agentManager();
41929
+ init_marketplaceRegistry();
41570
41930
  function registerPluginsCommand(program2) {
41571
41931
  const marketplaceHelp = new PluginManager().getMarketplaceIds().join(", ");
41572
41932
  const plugins = program2.command("plugins").description("Install agent-agnostic plugins from any marketplace or source");
@@ -41689,14 +42049,14 @@ function registerPluginsCommand(program2) {
41689
42049
  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) => {
41690
42050
  logger.titleBox("AgentInit Plugin Search");
41691
42051
  const pluginManager2 = new PluginManager;
41692
- if (!options2.from) {
42052
+ const registryId = options2.from || getConfiguredDefaultMarketplaceId();
42053
+ if (!registryId) {
41693
42054
  logger.info(`Please specify a marketplace with --from <marketplace>. Available: ${marketplaceHelp}`);
41694
42055
  logger.info("Examples:");
41695
42056
  logger.info(" agentinit plugins search --from claude");
41696
42057
  logger.info(" agentinit plugins search code-review --from claude");
41697
42058
  return;
41698
42059
  }
41699
- const registryId = options2.from;
41700
42060
  const spinner = ora(`Fetching ${registryId} marketplace...`).start();
41701
42061
  try {
41702
42062
  const results = await pluginManager2.listMarketplacePlugins(registryId, query, options2.category);
@@ -42111,6 +42471,7 @@ registerSkillsCommand(program2);
42111
42471
  registerMcpCommand(program2);
42112
42472
  registerRulesCommand(program2);
42113
42473
  registerPluginsCommand(program2);
42474
+ registerConfigCommand(program2);
42114
42475
  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
42476
  program2.command("detect").description("Detect current project stack and existing agent configurations").option("-v, --verbose", "Show detailed detection results").action(detectCommand);
42116
42477
  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);