agentinit 1.13.4 → 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.
Files changed (82) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/README.md +60 -7
  3. package/dist/agents/Agent.d.ts +5 -1
  4. package/dist/agents/Agent.d.ts.map +1 -1
  5. package/dist/agents/Agent.js +6 -0
  6. package/dist/agents/Agent.js.map +1 -1
  7. package/dist/agents/HermesAgent.d.ts +14 -0
  8. package/dist/agents/HermesAgent.d.ts.map +1 -0
  9. package/dist/agents/HermesAgent.js +64 -0
  10. package/dist/agents/HermesAgent.js.map +1 -0
  11. package/dist/agents/OpenClawAgent.d.ts +14 -0
  12. package/dist/agents/OpenClawAgent.d.ts.map +1 -0
  13. package/dist/agents/OpenClawAgent.js +64 -0
  14. package/dist/agents/OpenClawAgent.js.map +1 -0
  15. package/dist/cli.js +1023 -330
  16. package/dist/cli.js.map +1 -1
  17. package/dist/commands/apply.js +2 -2
  18. package/dist/commands/apply.js.map +1 -1
  19. package/dist/commands/config.d.ts +2 -7
  20. package/dist/commands/config.d.ts.map +1 -1
  21. package/dist/commands/config.js +208 -3
  22. package/dist/commands/config.js.map +1 -1
  23. package/dist/commands/detect.js +1 -1
  24. package/dist/commands/detect.js.map +1 -1
  25. package/dist/commands/init.js +1 -1
  26. package/dist/commands/init.js.map +1 -1
  27. package/dist/commands/plugins.d.ts.map +1 -1
  28. package/dist/commands/plugins.js +119 -44
  29. package/dist/commands/plugins.js.map +1 -1
  30. package/dist/commands/revert.js +1 -1
  31. package/dist/commands/revert.js.map +1 -1
  32. package/dist/commands/rules.js +3 -3
  33. package/dist/commands/rules.js.map +1 -1
  34. package/dist/commands/skills.js +4 -4
  35. package/dist/commands/skills.js.map +1 -1
  36. package/dist/commands/subagents.js +1 -1
  37. package/dist/commands/subagents.js.map +1 -1
  38. package/dist/commands/sync.js +1 -1
  39. package/dist/commands/sync.js.map +1 -1
  40. package/dist/commands/verifyMcp.js +1 -1
  41. package/dist/commands/verifyMcp.js.map +1 -1
  42. package/dist/core/agentDetector.d.ts +8 -2
  43. package/dist/core/agentDetector.d.ts.map +1 -1
  44. package/dist/core/agentDetector.js +32 -4
  45. package/dist/core/agentDetector.js.map +1 -1
  46. package/dist/core/agentManager.d.ts +10 -5
  47. package/dist/core/agentManager.d.ts.map +1 -1
  48. package/dist/core/agentManager.js +25 -9
  49. package/dist/core/agentManager.js.map +1 -1
  50. package/dist/core/marketplaceRegistry.d.ts +1 -0
  51. package/dist/core/marketplaceRegistry.d.ts.map +1 -1
  52. package/dist/core/marketplaceRegistry.js +27 -2
  53. package/dist/core/marketplaceRegistry.js.map +1 -1
  54. package/dist/core/mcpClient.js +3 -3
  55. package/dist/core/mcpClient.js.map +1 -1
  56. package/dist/core/pluginManager.d.ts +1 -0
  57. package/dist/core/pluginManager.d.ts.map +1 -1
  58. package/dist/core/pluginManager.js +14 -6
  59. package/dist/core/pluginManager.js.map +1 -1
  60. package/dist/core/skillsManager.d.ts.map +1 -1
  61. package/dist/core/skillsManager.js +12 -1
  62. package/dist/core/skillsManager.js.map +1 -1
  63. package/dist/core/userConfig.d.ts +25 -0
  64. package/dist/core/userConfig.d.ts.map +1 -0
  65. package/dist/core/userConfig.js +156 -0
  66. package/dist/core/userConfig.js.map +1 -0
  67. package/dist/types/index.d.ts +2 -0
  68. package/dist/types/index.d.ts.map +1 -1
  69. package/dist/types/index.js.map +1 -1
  70. package/dist/utils/colors.d.ts +10 -0
  71. package/dist/utils/colors.d.ts.map +1 -0
  72. package/dist/utils/colors.js +27 -0
  73. package/dist/utils/colors.js.map +1 -0
  74. package/dist/utils/logger.d.ts +16 -0
  75. package/dist/utils/logger.d.ts.map +1 -1
  76. package/dist/utils/logger.js +59 -5
  77. package/dist/utils/logger.js.map +1 -1
  78. package/dist/utils/symbols.d.ts +27 -0
  79. package/dist/utils/symbols.d.ts.map +1 -0
  80. package/dist/utils/symbols.js +27 -0
  81. package/dist/utils/symbols.js.map +1 -0
  82. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -8510,6 +8510,74 @@ async function createRelativeSymlink(target, linkPath) {
8510
8510
  var init_fs = __esm(() => {
8511
8511
  });
8512
8512
 
8513
+ // dist/utils/paths.js
8514
+ import {resolve as resolve2, join as join2} from "path";
8515
+ import {homedir} from "os";
8516
+ function getHomeDirectory() {
8517
+ return homedir();
8518
+ }
8519
+ function getPlatform() {
8520
+ switch (process.platform) {
8521
+ case "win32":
8522
+ return "windows";
8523
+ case "darwin":
8524
+ return "darwin";
8525
+ case "linux":
8526
+ return "linux";
8527
+ default:
8528
+ return "linux";
8529
+ }
8530
+ }
8531
+ function expandTilde(path) {
8532
+ if (path.startsWith("~/")) {
8533
+ return join2(getHomeDirectory(), path.slice(2));
8534
+ }
8535
+ if (path === "~") {
8536
+ return getHomeDirectory();
8537
+ }
8538
+ return path;
8539
+ }
8540
+ function getEnvironmentPath(key) {
8541
+ return process.env[key];
8542
+ }
8543
+ function resolveGlobalConfigPath(globalConfigPath, globalConfigPaths) {
8544
+ if (globalConfigPath) {
8545
+ return expandTilde(globalConfigPath);
8546
+ }
8547
+ if (globalConfigPaths) {
8548
+ const platform2 = getPlatform();
8549
+ const platformPath = globalConfigPaths[platform2];
8550
+ if (platformPath) {
8551
+ return expandTilde(platformPath);
8552
+ }
8553
+ }
8554
+ return null;
8555
+ }
8556
+ function getWindowsAppDataPaths() {
8557
+ return {
8558
+ roaming: getEnvironmentPath("APPDATA"),
8559
+ local: getEnvironmentPath("LOCALAPPDATA"),
8560
+ userProfile: getEnvironmentPath("USERPROFILE")
8561
+ };
8562
+ }
8563
+ function resolveEnvironmentVariables(path) {
8564
+ if (getPlatform() === "windows") {
8565
+ const appDataPaths = getWindowsAppDataPaths();
8566
+ return path.replace(/%APPDATA%/g, appDataPaths.roaming || "").replace(/%LOCALAPPDATA%/g, appDataPaths.local || "").replace(/%USERPROFILE%/g, appDataPaths.userProfile || "");
8567
+ }
8568
+ return path;
8569
+ }
8570
+ function getFullGlobalConfigPath(globalConfigPath, globalConfigPaths) {
8571
+ const path = resolveGlobalConfigPath(globalConfigPath, globalConfigPaths);
8572
+ if (!path) {
8573
+ return null;
8574
+ }
8575
+ const resolvedPath = resolveEnvironmentVariables(path);
8576
+ return resolve2(resolvedPath);
8577
+ }
8578
+ var init_paths = __esm(() => {
8579
+ });
8580
+
8513
8581
  // node_modules/kind-of/index.js
8514
8582
  var require_kind_of = __commonJS((exports, module) => {
8515
8583
  var ctorName = function(val) {
@@ -11935,74 +12003,6 @@ var require_gray_matter = __commonJS((exports, module) => {
11935
12003
  module.exports = matter;
11936
12004
  });
11937
12005
 
11938
- // dist/utils/paths.js
11939
- import {resolve as resolve5, join as join2} from "path";
11940
- import {homedir} from "os";
11941
- function getHomeDirectory() {
11942
- return homedir();
11943
- }
11944
- function getPlatform() {
11945
- switch (process.platform) {
11946
- case "win32":
11947
- return "windows";
11948
- case "darwin":
11949
- return "darwin";
11950
- case "linux":
11951
- return "linux";
11952
- default:
11953
- return "linux";
11954
- }
11955
- }
11956
- function expandTilde(path) {
11957
- if (path.startsWith("~/")) {
11958
- return join2(getHomeDirectory(), path.slice(2));
11959
- }
11960
- if (path === "~") {
11961
- return getHomeDirectory();
11962
- }
11963
- return path;
11964
- }
11965
- function getEnvironmentPath(key) {
11966
- return process.env[key];
11967
- }
11968
- function resolveGlobalConfigPath(globalConfigPath, globalConfigPaths) {
11969
- if (globalConfigPath) {
11970
- return expandTilde(globalConfigPath);
11971
- }
11972
- if (globalConfigPaths) {
11973
- const platform2 = getPlatform();
11974
- const platformPath = globalConfigPaths[platform2];
11975
- if (platformPath) {
11976
- return expandTilde(platformPath);
11977
- }
11978
- }
11979
- return null;
11980
- }
11981
- function getWindowsAppDataPaths() {
11982
- return {
11983
- roaming: getEnvironmentPath("APPDATA"),
11984
- local: getEnvironmentPath("LOCALAPPDATA"),
11985
- userProfile: getEnvironmentPath("USERPROFILE")
11986
- };
11987
- }
11988
- function resolveEnvironmentVariables(path) {
11989
- if (getPlatform() === "windows") {
11990
- const appDataPaths = getWindowsAppDataPaths();
11991
- return path.replace(/%APPDATA%/g, appDataPaths.roaming || "").replace(/%LOCALAPPDATA%/g, appDataPaths.local || "").replace(/%USERPROFILE%/g, appDataPaths.userProfile || "");
11992
- }
11993
- return path;
11994
- }
11995
- function getFullGlobalConfigPath(globalConfigPath, globalConfigPaths) {
11996
- const path = resolveGlobalConfigPath(globalConfigPath, globalConfigPaths);
11997
- if (!path) {
11998
- return null;
11999
- }
12000
- const resolvedPath = resolveEnvironmentVariables(path);
12001
- return resolve5(resolvedPath);
12002
- }
12003
- var init_paths = __esm(() => {
12004
- });
12005
-
12006
12006
  // node_modules/contextcalc/dist/lib/index.js
12007
12007
  import {get_encoding} from "tiktoken";
12008
12008
  async function isBinaryFile(filePath) {
@@ -12389,6 +12389,9 @@ class Agent {
12389
12389
  get name() {
12390
12390
  return this.definition.name;
12391
12391
  }
12392
+ getDetectionScope() {
12393
+ return this.definition.detectionScope || "project";
12394
+ }
12392
12395
  get capabilities() {
12393
12396
  return this.definition.capabilities;
12394
12397
  }
@@ -15899,6 +15902,140 @@ var init_CopilotAgent = __esm(() => {
15899
15902
  init_fs();
15900
15903
  });
15901
15904
 
15905
+ // dist/agents/OpenClawAgent.js
15906
+ class OpenClawAgent extends Agent {
15907
+ constructor() {
15908
+ const definition = {
15909
+ id: "openclaw",
15910
+ name: "OpenClaw",
15911
+ capabilities: {
15912
+ mcp: {
15913
+ stdio: false,
15914
+ http: false,
15915
+ sse: false
15916
+ },
15917
+ rules: false,
15918
+ hooks: false,
15919
+ commands: false,
15920
+ subagents: false,
15921
+ statusline: false,
15922
+ skills: true
15923
+ },
15924
+ configFiles: [],
15925
+ nativeConfigPath: ".openclaw/config.json",
15926
+ detectionScope: "environment",
15927
+ skillPaths: {
15928
+ project: ".agents/skills/",
15929
+ global: "~/.openclaw/skills/"
15930
+ },
15931
+ projectStandards: {
15932
+ skills: "agents"
15933
+ }
15934
+ };
15935
+ super(definition);
15936
+ }
15937
+ async detectPresence(_projectPath) {
15938
+ const openClawHome = expandTilde("~/.openclaw");
15939
+ if (!await fileExists(openClawHome)) {
15940
+ return null;
15941
+ }
15942
+ return {
15943
+ agent: this,
15944
+ configPath: openClawHome
15945
+ };
15946
+ }
15947
+ async applyMCPConfig(_projectPath, _servers) {
15948
+ throw new Error("OpenClaw does not support MCP configuration.");
15949
+ }
15950
+ async removeMCPServer(_projectPath, _serverName) {
15951
+ throw new Error("OpenClaw does not support MCP configuration.");
15952
+ }
15953
+ async applyRulesConfig(_configPath, _rules, _existingContent) {
15954
+ throw new Error("OpenClaw does not support rules configuration.");
15955
+ }
15956
+ extractExistingRules(_content) {
15957
+ return [];
15958
+ }
15959
+ extractExistingSections(_content) {
15960
+ return [];
15961
+ }
15962
+ generateRulesContent(_sections) {
15963
+ return "";
15964
+ }
15965
+ }
15966
+ var init_OpenClawAgent = __esm(() => {
15967
+ init_Agent();
15968
+ init_fs();
15969
+ init_paths();
15970
+ });
15971
+
15972
+ // dist/agents/HermesAgent.js
15973
+ class HermesAgent extends Agent {
15974
+ constructor() {
15975
+ const definition = {
15976
+ id: "hermes",
15977
+ name: "Hermes",
15978
+ capabilities: {
15979
+ mcp: {
15980
+ stdio: false,
15981
+ http: false,
15982
+ sse: false
15983
+ },
15984
+ rules: false,
15985
+ hooks: false,
15986
+ commands: false,
15987
+ subagents: false,
15988
+ statusline: false,
15989
+ skills: true
15990
+ },
15991
+ configFiles: [],
15992
+ nativeConfigPath: ".hermes/config.json",
15993
+ detectionScope: "environment",
15994
+ skillPaths: {
15995
+ project: ".agents/skills/",
15996
+ global: "~/.hermes/skills/"
15997
+ },
15998
+ projectStandards: {
15999
+ skills: "agents"
16000
+ }
16001
+ };
16002
+ super(definition);
16003
+ }
16004
+ async detectPresence(_projectPath) {
16005
+ const hermesHome = expandTilde("~/.hermes");
16006
+ if (!await fileExists(hermesHome)) {
16007
+ return null;
16008
+ }
16009
+ return {
16010
+ agent: this,
16011
+ configPath: hermesHome
16012
+ };
16013
+ }
16014
+ async applyMCPConfig(_projectPath, _servers) {
16015
+ throw new Error("Hermes does not support MCP configuration.");
16016
+ }
16017
+ async removeMCPServer(_projectPath, _serverName) {
16018
+ throw new Error("Hermes does not support MCP configuration.");
16019
+ }
16020
+ async applyRulesConfig(_configPath, _rules, _existingContent) {
16021
+ throw new Error("Hermes does not support rules configuration.");
16022
+ }
16023
+ extractExistingRules(_content) {
16024
+ return [];
16025
+ }
16026
+ extractExistingSections(_content) {
16027
+ return [];
16028
+ }
16029
+ generateRulesContent(_sections) {
16030
+ return "";
16031
+ }
16032
+ }
16033
+ var init_HermesAgent = __esm(() => {
16034
+ init_Agent();
16035
+ init_fs();
16036
+ init_paths();
16037
+ });
16038
+
15902
16039
  // dist/agents/AiderAgent.js
15903
16040
  class AiderAgent extends MarkdownRulesAgent {
15904
16041
  constructor() {
@@ -16493,7 +16630,9 @@ class AgentManager {
16493
16630
  new WindsurfAgent,
16494
16631
  new RooCodeAgent,
16495
16632
  new ZedAgent,
16496
- new DroidAgent
16633
+ new DroidAgent,
16634
+ new OpenClawAgent,
16635
+ new HermesAgent
16497
16636
  ];
16498
16637
  }
16499
16638
  getAllAgents() {
@@ -16505,9 +16644,18 @@ class AgentManager {
16505
16644
  getSupportedAgentIds() {
16506
16645
  return this.agents.map((agent) => agent.id);
16507
16646
  }
16508
- async detectAgents(projectPath) {
16647
+ shouldIncludeForDetection(agent, options2) {
16648
+ if (options2.includeEnvironment) {
16649
+ return true;
16650
+ }
16651
+ return agent.getDetectionScope() !== "environment";
16652
+ }
16653
+ async detectAgents(projectPath, options2 = {}) {
16509
16654
  const results = [];
16510
16655
  for (const agent of this.agents) {
16656
+ if (!this.shouldIncludeForDetection(agent, options2)) {
16657
+ continue;
16658
+ }
16511
16659
  const detection = await agent.detectPresence(projectPath);
16512
16660
  if (detection) {
16513
16661
  results.push(detection);
@@ -16515,27 +16663,30 @@ class AgentManager {
16515
16663
  }
16516
16664
  return results;
16517
16665
  }
16518
- async detectAgentById(projectPath, agentId) {
16666
+ async detectAgentById(projectPath, agentId, options2 = {}) {
16519
16667
  const agent = this.getAgentById(agentId);
16520
16668
  if (!agent) {
16521
16669
  return null;
16522
16670
  }
16671
+ if (!this.shouldIncludeForDetection(agent, options2)) {
16672
+ return null;
16673
+ }
16523
16674
  return await agent.detectPresence(projectPath);
16524
16675
  }
16525
- async getPrimaryAgent(projectPath) {
16526
- const detectedAgents = await this.detectAgents(projectPath);
16676
+ async getPrimaryAgent(projectPath, options2 = {}) {
16677
+ const detectedAgents = await this.detectAgents(projectPath, options2);
16527
16678
  return detectedAgents.length > 0 ? detectedAgents[0] : null;
16528
16679
  }
16529
16680
  registerAgent(agent) {
16530
16681
  this.agents = this.agents.filter((existing) => existing.id !== agent.id);
16531
16682
  this.agents.push(agent);
16532
16683
  }
16533
- async hasAnyAgents(projectPath) {
16534
- const detected = await this.detectAgents(projectPath);
16684
+ async hasAnyAgents(projectPath, options2 = {}) {
16685
+ const detected = await this.detectAgents(projectPath, options2);
16535
16686
  return detected.length > 0;
16536
16687
  }
16537
- async getDetectionSummary(projectPath) {
16538
- const detected = await this.detectAgents(projectPath);
16688
+ async getDetectionSummary(projectPath, options2 = {}) {
16689
+ const detected = await this.detectAgents(projectPath, options2);
16539
16690
  if (detected.length === 0) {
16540
16691
  return "No AI coding agents detected in this project.";
16541
16692
  }
@@ -16557,6 +16708,8 @@ var init_agentManager = __esm(() => {
16557
16708
  init_CursorAgent();
16558
16709
  init_DroidAgent();
16559
16710
  init_CopilotAgent();
16711
+ init_OpenClawAgent();
16712
+ init_HermesAgent();
16560
16713
  init_AiderAgent();
16561
16714
  init_ClineAgent();
16562
16715
  init_WindsurfAgent();
@@ -16564,15 +16717,191 @@ var init_agentManager = __esm(() => {
16564
16717
  init_ZedAgent();
16565
16718
  });
16566
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
+
16567
16875
  // dist/core/marketplaceRegistry.js
16568
16876
  function getMarketplace(id) {
16569
- return MARKETPLACES.find((marketplace) => marketplace.id === id);
16877
+ return getAllMarketplaces().find((marketplace) => marketplace.id === id);
16570
16878
  }
16571
16879
  function getMarketplaceIds() {
16572
- return MARKETPLACES.map((marketplace) => marketplace.id);
16880
+ return getAllMarketplaces().map((marketplace) => marketplace.id);
16573
16881
  }
16574
- 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;
16575
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
+ };
16576
16905
  MARKETPLACES = [
16577
16906
  {
16578
16907
  id: "agentinit",
@@ -16596,6 +16925,8 @@ var init_marketplaceRegistry = __esm(() => {
16596
16925
  cacheTtlMs: 3600000
16597
16926
  }
16598
16927
  ];
16928
+ CUSTOM_MARKETPLACE_PLUGIN_DIRS = ["skills", "mcps", "rules"];
16929
+ CUSTOM_MARKETPLACE_CACHE_TTL_MS = 3600000;
16599
16930
  });
16600
16931
 
16601
16932
  // dist/core/mcpFilter.js
@@ -16707,9 +17038,9 @@ __export(exports_pluginManager, {
16707
17038
  }
16708
17039
  }
16709
17040
  });
16710
- import {resolve as resolve7, join as join3, basename as basename2, relative as relative2, dirname as dirname2} from "path";
16711
- import {promises as fs18} from "fs";
16712
- 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";
16713
17044
 
16714
17045
  class MarketplacePluginNotFoundError extends Error {
16715
17046
  pluginName;
@@ -16743,7 +17074,7 @@ class PluginManager {
16743
17074
  }
16744
17075
  async cleanupLoadedPluginContext(context) {
16745
17076
  if (context?.tempDir) {
16746
- await fs18.rm(context.tempDir, { recursive: true, force: true }).catch(() => {
17077
+ await fs22.rm(context.tempDir, { recursive: true, force: true }).catch(() => {
16747
17078
  });
16748
17079
  }
16749
17080
  }
@@ -16814,8 +17145,14 @@ class PluginManager {
16814
17145
  }
16815
17146
  return `https://github.com/${source.owner}/${source.repo}`;
16816
17147
  }
17148
+ getGitHubFallbackTrust(source) {
17149
+ if (source.owner && source.repo && isVerifiedGitHubRepoSync(source.owner, source.repo)) {
17150
+ return "verified";
17151
+ }
17152
+ return "unverified";
17153
+ }
16817
17154
  async resolvePreparedPluginDir(pluginDir, source) {
16818
- const claudeMarketplaceManifestPath = join3(pluginDir, ".claude-plugin", "marketplace.json");
17155
+ const claudeMarketplaceManifestPath = join4(pluginDir, ".claude-plugin", "marketplace.json");
16819
17156
  if (!await fileExists(claudeMarketplaceManifestPath)) {
16820
17157
  return { pluginDir, warnings: [] };
16821
17158
  }
@@ -16894,12 +17231,13 @@ class PluginManager {
16894
17231
  throw error;
16895
17232
  }
16896
17233
  const fallbackUrl = this.formatGitHubRepoUrl(fallbackSource) || fallbackSource.url.replace(/\.git$/, "");
17234
+ const fallbackTrust = this.getGitHubFallbackTrust(fallbackSource);
16897
17235
  resolutionWarnings.push(error.message);
16898
- resolutionWarnings.push(`Marketplace lookup failed; trying unverified GitHub repository ${fallbackUrl} instead.`);
17236
+ resolutionWarnings.push(`Marketplace lookup failed; trying ${fallbackTrust} GitHub repository ${fallbackUrl} instead.`);
16899
17237
  try {
16900
17238
  tempDir = await this.skillsManager.cloneRepo(fallbackSource.url);
16901
17239
  } catch (fallbackError) {
16902
- throw new Error(`${error.message} Tried unverified GitHub repository ${fallbackUrl} but failed: ${fallbackError instanceof Error ? fallbackError.message : "Unknown error"}`);
17240
+ throw new Error(`${error.message} Tried ${fallbackTrust} GitHub repository ${fallbackUrl} but failed: ${fallbackError instanceof Error ? fallbackError.message : "Unknown error"}`);
16903
17241
  }
16904
17242
  effectiveSource = {
16905
17243
  ...fallbackSource,
@@ -16955,13 +17293,13 @@ class PluginManager {
16955
17293
  }
16956
17294
  async getClaudeNativeFeatureKinds(pluginDir, manifest) {
16957
17295
  const featureChecks = await Promise.all([
16958
- (async () => !!manifest.commands || await isDirectory(join3(pluginDir, "commands")))(),
16959
- (async () => !!manifest.hooks || await isDirectory(join3(pluginDir, "hooks")))(),
16960
- (async () => !!manifest.agents || await isDirectory(join3(pluginDir, "agents")))(),
16961
- isDirectory(join3(pluginDir, "prompts")),
16962
- isDirectory(join3(pluginDir, "schemas")),
16963
- isDirectory(join3(pluginDir, "scripts")),
16964
- 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"))
16965
17303
  ]);
16966
17304
  return [
16967
17305
  ...featureChecks[0] ? ["commands"] : [],
@@ -16977,7 +17315,7 @@ class PluginManager {
16977
17315
  if (plugin.format !== "claude") {
16978
17316
  return null;
16979
17317
  }
16980
- const manifestContent = await readFileIfExists(join3(pluginDir, ".claude-plugin", "plugin.json"));
17318
+ const manifestContent = await readFileIfExists(join4(pluginDir, ".claude-plugin", "plugin.json"));
16981
17319
  if (!manifestContent) {
16982
17320
  return null;
16983
17321
  }
@@ -16997,7 +17335,7 @@ class PluginManager {
16997
17335
  return {
16998
17336
  namespace,
16999
17337
  pluginKey: `${plugin.name}@${namespace}`,
17000
- installPath: join3(homedir3(), ".claude", "plugins", "cache", namespace, plugin.name, versionDir),
17338
+ installPath: join4(homedir4(), ".claude", "plugins", "cache", namespace, plugin.name, versionDir),
17001
17339
  features
17002
17340
  };
17003
17341
  }
@@ -17070,10 +17408,10 @@ class PluginManager {
17070
17408
  warnings.push(`Skipped native Claude plugin install because Claude already has "${plugin.name}" installed as ${conflictingKey}.`);
17071
17409
  return { installed, skipped, warnings };
17072
17410
  }
17073
- await fs18.rm(nativeTarget.installPath, { recursive: true, force: true }).catch(() => {
17411
+ await fs22.rm(nativeTarget.installPath, { recursive: true, force: true }).catch(() => {
17074
17412
  });
17075
- await fs18.mkdir(dirname2(nativeTarget.installPath), { recursive: true });
17076
- await fs18.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 });
17077
17415
  const now = new Date().toISOString();
17078
17416
  claudeInstalled.plugins[nativeTarget.pluginKey] = [{
17079
17417
  scope: "user",
@@ -17121,7 +17459,7 @@ class PluginManager {
17121
17459
  claudeSettings.enabledPlugins = remainingEnabledPlugins;
17122
17460
  await this.saveClaudeSettings(claudeSettings);
17123
17461
  }
17124
- await fs18.rm(component.installPath, { recursive: true, force: true }).catch(() => {
17462
+ await fs22.rm(component.installPath, { recursive: true, force: true }).catch(() => {
17125
17463
  });
17126
17464
  return true;
17127
17465
  }
@@ -17172,7 +17510,7 @@ class PluginManager {
17172
17510
  repo
17173
17511
  };
17174
17512
  }
17175
- const defaultMarketplace = this.getMarketplaceIds()[0];
17513
+ const defaultMarketplace = getConfiguredDefaultMarketplaceId() || this.getMarketplaceIds()[0];
17176
17514
  if (defaultMarketplace) {
17177
17515
  return {
17178
17516
  type: "marketplace",
@@ -17191,13 +17529,13 @@ class PluginManager {
17191
17529
  async ensureMarketplaceCache(registryId) {
17192
17530
  const registry = this.getMarketplace(registryId);
17193
17531
  if (!registry) {
17194
- throw new Error(`Unknown marketplace: ${registryId}. Available: ${MARKETPLACES.map((m) => m.id).join(", ")}`);
17532
+ throw new Error(`Unknown marketplace: ${registryId}. Available: ${this.getMarketplaceIds().join(", ")}`);
17195
17533
  }
17196
17534
  const cacheDir = getMarketplaceCacheDir(registryId);
17197
- const cacheMetaPath = join3(cacheDir, ".agentinit-cache-meta.json");
17535
+ const cacheMetaPath = join4(cacheDir, ".agentinit-cache-meta.json");
17198
17536
  if (await fileExists(cacheMetaPath)) {
17199
17537
  try {
17200
- const meta = JSON.parse(await fs18.readFile(cacheMetaPath, "utf8"));
17538
+ const meta = JSON.parse(await fs22.readFile(cacheMetaPath, "utf8"));
17201
17539
  const age = Date.now() - (meta.fetchedAt || 0);
17202
17540
  if (age < registry.cacheTtlMs) {
17203
17541
  return cacheDir;
@@ -17205,29 +17543,29 @@ class PluginManager {
17205
17543
  } catch {
17206
17544
  }
17207
17545
  }
17208
- if (await fileExists(join3(cacheDir, ".git"))) {
17546
+ if (await fileExists(join4(cacheDir, ".git"))) {
17209
17547
  const { execFile } = await import("child_process");
17210
17548
  const { promisify } = await import("util");
17211
17549
  const exec = promisify(execFile);
17212
17550
  try {
17213
17551
  await exec("git", ["pull", "--ff-only"], { cwd: cacheDir, timeout: 30000 });
17214
17552
  } catch {
17215
- await fs18.rm(cacheDir, { recursive: true, force: true });
17553
+ await fs22.rm(cacheDir, { recursive: true, force: true });
17216
17554
  await this.cloneMarketplace(registry.repoUrl, cacheDir);
17217
17555
  }
17218
17556
  } else {
17219
17557
  await this.cloneMarketplace(registry.repoUrl, cacheDir);
17220
17558
  }
17221
- await fs18.mkdir(cacheDir, { recursive: true });
17222
- await fs18.writeFile(cacheMetaPath, JSON.stringify({ fetchedAt: Date.now() }));
17559
+ await fs22.mkdir(cacheDir, { recursive: true });
17560
+ await fs22.writeFile(cacheMetaPath, JSON.stringify({ fetchedAt: Date.now() }));
17223
17561
  return cacheDir;
17224
17562
  }
17225
17563
  async cloneMarketplace(repoUrl, dest) {
17226
- await fs18.mkdir(dest, { recursive: true });
17564
+ await fs22.mkdir(dest, { recursive: true });
17227
17565
  const { execFile } = await import("child_process");
17228
17566
  const { promisify } = await import("util");
17229
17567
  const exec = promisify(execFile);
17230
- await fs18.rm(dest, { recursive: true, force: true }).catch(() => {
17568
+ await fs22.rm(dest, { recursive: true, force: true }).catch(() => {
17231
17569
  });
17232
17570
  await exec("git", ["clone", "--depth", "1", repoUrl, dest], { timeout: 60000 });
17233
17571
  }
@@ -17237,7 +17575,7 @@ class PluginManager {
17237
17575
  throw new Error(`Unknown marketplace: ${registryId}`);
17238
17576
  const cacheDir = await this.ensureMarketplaceCache(registryId);
17239
17577
  for (const dir of registry.pluginDirs) {
17240
- const pluginPath = join3(cacheDir, dir, name);
17578
+ const pluginPath = join4(cacheDir, dir, name);
17241
17579
  if (await isDirectory(pluginPath)) {
17242
17580
  return pluginPath;
17243
17581
  }
@@ -17253,7 +17591,7 @@ class PluginManager {
17253
17591
  const cacheDir = await this.ensureMarketplaceCache(registryId);
17254
17592
  const results = [];
17255
17593
  for (const dir of registry.pluginDirs) {
17256
- const fullDir = join3(cacheDir, dir);
17594
+ const fullDir = join4(cacheDir, dir);
17257
17595
  if (!await isDirectory(fullDir))
17258
17596
  continue;
17259
17597
  const cat = dir === "plugins" ? "official" : dir === "external_plugins" ? "community" : dir.startsWith("skills/.") ? dir.slice("skills/.".length) : dir;
@@ -17263,26 +17601,26 @@ class PluginManager {
17263
17601
  for (const entry of entries) {
17264
17602
  if (entry.startsWith("."))
17265
17603
  continue;
17266
- const entryPath = join3(fullDir, entry);
17604
+ const entryPath = join4(fullDir, entry);
17267
17605
  if (!await isDirectory(entryPath))
17268
17606
  continue;
17269
- const manifestPath = join3(entryPath, ".claude-plugin", "plugin.json");
17607
+ const manifestPath = join4(entryPath, ".claude-plugin", "plugin.json");
17270
17608
  let name = entry;
17271
17609
  let description = "";
17272
17610
  let version = "0.0.0";
17273
17611
  if (await fileExists(manifestPath)) {
17274
17612
  try {
17275
- const manifest = JSON.parse(await fs18.readFile(manifestPath, "utf8"));
17613
+ const manifest = JSON.parse(await fs22.readFile(manifestPath, "utf8"));
17276
17614
  name = manifest.name || entry;
17277
17615
  description = manifest.description || "";
17278
17616
  version = manifest.version || "0.0.0";
17279
17617
  } catch {
17280
17618
  }
17281
17619
  } else {
17282
- const skillMdPath = join3(entryPath, "SKILL.md");
17620
+ const skillMdPath = join4(entryPath, "SKILL.md");
17283
17621
  if (await fileExists(skillMdPath)) {
17284
17622
  try {
17285
- const parsed = import_gray_matter.default(await fs18.readFile(skillMdPath, "utf8"));
17623
+ const parsed = import_gray_matter.default(await fs22.readFile(skillMdPath, "utf8"));
17286
17624
  if (parsed.data.name)
17287
17625
  name = parsed.data.name;
17288
17626
  if (parsed.data.description)
@@ -17290,10 +17628,10 @@ class PluginManager {
17290
17628
  } catch {
17291
17629
  }
17292
17630
  } else {
17293
- const mcpPath = join3(entryPath, ".mcp.json");
17631
+ const mcpPath = join4(entryPath, ".mcp.json");
17294
17632
  if (await fileExists(mcpPath)) {
17295
17633
  try {
17296
- const mcpConfig = JSON.parse(await fs18.readFile(mcpPath, "utf8"));
17634
+ const mcpConfig = JSON.parse(await fs22.readFile(mcpPath, "utf8"));
17297
17635
  const serverNames = Object.keys(mcpConfig.mcpServers || mcpConfig);
17298
17636
  if (serverNames.length > 0) {
17299
17637
  description = `MCP server(s): ${serverNames.join(", ")}`;
@@ -17315,10 +17653,10 @@ class PluginManager {
17315
17653
  return results.sort((a, b) => a.name.localeCompare(b.name));
17316
17654
  }
17317
17655
  async detectFormat(pluginDir) {
17318
- if (await fileExists(join3(pluginDir, ".claude-plugin", "plugin.json"))) {
17656
+ if (await fileExists(join4(pluginDir, ".claude-plugin", "plugin.json"))) {
17319
17657
  return "claude";
17320
17658
  }
17321
- if (await fileExists(join3(pluginDir, ".cursor-plugin", "plugin.json"))) {
17659
+ if (await fileExists(join4(pluginDir, ".cursor-plugin", "plugin.json"))) {
17322
17660
  return "cursor";
17323
17661
  }
17324
17662
  return "generic";
@@ -17335,7 +17673,7 @@ class PluginManager {
17335
17673
  }
17336
17674
  }
17337
17675
  async parseClaudePlugin(pluginDir, source) {
17338
- const manifestPath = join3(pluginDir, ".claude-plugin", "plugin.json");
17676
+ const manifestPath = join4(pluginDir, ".claude-plugin", "plugin.json");
17339
17677
  const manifestContent = await readFileIfExists(manifestPath);
17340
17678
  if (!manifestContent) {
17341
17679
  throw new Error(`Missing .claude-plugin/plugin.json in ${pluginDir}`);
@@ -17346,10 +17684,10 @@ class PluginManager {
17346
17684
  const convertedSkills = await this.convertCommandsToSkills(pluginDir, manifest);
17347
17685
  skills.push(...convertedSkills);
17348
17686
  const mcpServers = await this.parseMcpJson(pluginDir);
17349
- if (await isDirectory(join3(pluginDir, "hooks")) || manifest.hooks) {
17687
+ if (await isDirectory(join4(pluginDir, "hooks")) || manifest.hooks) {
17350
17688
  warnings.push("Hooks (hooks/) are Claude Code-specific");
17351
17689
  }
17352
- if (await isDirectory(join3(pluginDir, "agents")) || manifest.agents) {
17690
+ if (await isDirectory(join4(pluginDir, "agents")) || manifest.agents) {
17353
17691
  warnings.push("Agent definitions (agents/) are Claude Code-specific");
17354
17692
  }
17355
17693
  return {
@@ -17364,7 +17702,7 @@ class PluginManager {
17364
17702
  };
17365
17703
  }
17366
17704
  async parseCursorPlugin(pluginDir, source) {
17367
- const manifestPath = join3(pluginDir, ".cursor-plugin", "plugin.json");
17705
+ const manifestPath = join4(pluginDir, ".cursor-plugin", "plugin.json");
17368
17706
  const manifestContent = await readFileIfExists(manifestPath);
17369
17707
  if (!manifestContent) {
17370
17708
  throw new Error(`Missing .cursor-plugin/plugin.json in ${pluginDir}`);
@@ -17403,7 +17741,7 @@ class PluginManager {
17403
17741
  };
17404
17742
  }
17405
17743
  async parseMcpJson(pluginDir) {
17406
- const mcpPath = join3(pluginDir, ".mcp.json");
17744
+ const mcpPath = join4(pluginDir, ".mcp.json");
17407
17745
  const content = await readFileIfExists(mcpPath);
17408
17746
  if (!content)
17409
17747
  return [];
@@ -17450,7 +17788,7 @@ class PluginManager {
17450
17788
  commandsDirs.push(resolve7(pluginDir, cmd));
17451
17789
  }
17452
17790
  } else {
17453
- commandsDirs.push(join3(pluginDir, "commands"));
17791
+ commandsDirs.push(join4(pluginDir, "commands"));
17454
17792
  }
17455
17793
  for (const commandsDir of commandsDirs) {
17456
17794
  if (!await isDirectory(commandsDir))
@@ -17459,7 +17797,7 @@ class PluginManager {
17459
17797
  for (const entry of entries) {
17460
17798
  if (!entry.endsWith(".md"))
17461
17799
  continue;
17462
- const cmdPath = join3(commandsDir, entry);
17800
+ const cmdPath = join4(commandsDir, entry);
17463
17801
  const skill = await this.convertSingleCommandToSkill(cmdPath, manifest.name);
17464
17802
  if (skill)
17465
17803
  skills.push(skill);
@@ -17748,7 +18086,7 @@ ${body.trim()}
17748
18086
  }
17749
18087
  if (!removedSkillPaths.has(skill.path)) {
17750
18088
  try {
17751
- await fs18.rm(skill.path, { recursive: true, force: true });
18089
+ await fs22.rm(skill.path, { recursive: true, force: true });
17752
18090
  removedSkillPaths.add(skill.path);
17753
18091
  } catch {
17754
18092
  details.push(`Could not remove skill path: ${skill.path}`);
@@ -17757,7 +18095,7 @@ ${body.trim()}
17757
18095
  }
17758
18096
  if (skill.canonicalPath && skill.canonicalPath !== skill.path && !removedCanonicalPaths.has(skill.canonicalPath) && !sharedCanonicalPath) {
17759
18097
  try {
17760
- await fs18.rm(skill.canonicalPath, { recursive: true, force: true });
18098
+ await fs22.rm(skill.canonicalPath, { recursive: true, force: true });
17761
18099
  removedCanonicalPaths.add(skill.canonicalPath);
17762
18100
  } catch {
17763
18101
  details.push(`Could not remove canonical skill path: ${skill.canonicalPath}`);
@@ -17861,27 +18199,28 @@ var init_pluginManager = __esm(() => {
17861
18199
  init_mcpFilter();
17862
18200
  init_marketplaceRegistry();
17863
18201
  init_skillsManager();
18202
+ init_userConfig();
17864
18203
  getMarketplaceCacheDir = function(registryId) {
17865
- return join3(homedir3(), ".agentinit", "marketplace-cache", registryId);
18204
+ return join4(homedir4(), ".agentinit", "marketplace-cache", registryId);
17866
18205
  };
17867
18206
  getRegistryPath = function(projectPath, global3) {
17868
18207
  if (global3) {
17869
- return join3(homedir3(), ".agentinit", "plugins.json");
18208
+ return join4(homedir4(), ".agentinit", "plugins.json");
17870
18209
  }
17871
- return join3(projectPath, ".agentinit", "plugins.json");
18210
+ return join4(projectPath, ".agentinit", "plugins.json");
17872
18211
  };
17873
18212
  getClaudeInstalledPluginsPath = function() {
17874
- return join3(homedir3(), ".claude", "plugins", "installed_plugins.json");
18213
+ return join4(homedir4(), ".claude", "plugins", "installed_plugins.json");
17875
18214
  };
17876
18215
  getClaudeSettingsPath = function() {
17877
- return join3(homedir3(), ".claude", "settings.json");
18216
+ return join4(homedir4(), ".claude", "settings.json");
17878
18217
  };
17879
18218
  });
17880
18219
 
17881
18220
  // dist/core/skillsManager.js
17882
- import {resolve as resolve8, join as join4, relative as relative3} from "path";
17883
- import {promises as fs20} from "fs";
17884
- 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";
17885
18224
  import {execFile} from "child_process";
17886
18225
  import {promisify} from "util";
17887
18226
 
@@ -17948,6 +18287,17 @@ class SkillsManager {
17948
18287
  }
17949
18288
  resolveSourceRequest(source, options2) {
17950
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
+ }
17951
18301
  return {
17952
18302
  source: {
17953
18303
  type: "github",
@@ -17984,7 +18334,7 @@ class SkillsManager {
17984
18334
  const fullDir = resolve8(repoPath, searchDir);
17985
18335
  if (!await fileExists(fullDir))
17986
18336
  continue;
17987
- const directSkillMd = join4(fullDir, "SKILL.md");
18337
+ const directSkillMd = join5(fullDir, "SKILL.md");
17988
18338
  if (await fileExists(directSkillMd)) {
17989
18339
  const parsed = await this.parseSkillMd(directSkillMd);
17990
18340
  if (parsed && !seen.has(parsed.name)) {
@@ -17992,7 +18342,7 @@ class SkillsManager {
17992
18342
  skills.push({ ...parsed, path: resolve8(fullDir) });
17993
18343
  }
17994
18344
  }
17995
- const directSkillMdLower = join4(fullDir, "skill.md");
18345
+ const directSkillMdLower = join5(fullDir, "skill.md");
17996
18346
  if (await fileExists(directSkillMdLower)) {
17997
18347
  const parsed = await this.parseSkillMd(directSkillMdLower);
17998
18348
  if (parsed && !seen.has(parsed.name)) {
@@ -18004,11 +18354,11 @@ class SkillsManager {
18004
18354
  continue;
18005
18355
  const entries = await listFiles(fullDir);
18006
18356
  for (const entry of entries) {
18007
- const entryPath = join4(fullDir, entry);
18357
+ const entryPath = join5(fullDir, entry);
18008
18358
  if (!await isDirectory(entryPath))
18009
18359
  continue;
18010
- const skillMdPath = join4(entryPath, "SKILL.md");
18011
- const skillMdPathLower = join4(entryPath, "skill.md");
18360
+ const skillMdPath = join5(entryPath, "SKILL.md");
18361
+ const skillMdPathLower = join5(entryPath, "skill.md");
18012
18362
  const skillFile = await fileExists(skillMdPath) ? skillMdPath : await fileExists(skillMdPathLower) ? skillMdPathLower : null;
18013
18363
  if (!skillFile)
18014
18364
  continue;
@@ -18022,14 +18372,14 @@ class SkillsManager {
18022
18372
  return skills;
18023
18373
  }
18024
18374
  async cloneRepo(url) {
18025
- const tempDir = await fs20.mkdtemp(join4(tmpdir(), "agentinit-skills-"));
18026
- await fs20.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 });
18027
18377
  try {
18028
18378
  await execFileAsync("git", ["clone", "--depth", "1", url, tempDir], {
18029
18379
  timeout: 60000
18030
18380
  });
18031
18381
  } catch (error) {
18032
- await fs20.rm(tempDir, { recursive: true, force: true }).catch(() => {
18382
+ await fs24.rm(tempDir, { recursive: true, force: true }).catch(() => {
18033
18383
  });
18034
18384
  throw new Error(`Failed to clone ${url}: ${error.message}`);
18035
18385
  }
@@ -18123,7 +18473,7 @@ class SkillsManager {
18123
18473
  return { skills, warnings };
18124
18474
  } finally {
18125
18475
  if (tempDir) {
18126
- await fs20.rm(tempDir, { recursive: true, force: true }).catch(() => {
18476
+ await fs24.rm(tempDir, { recursive: true, force: true }).catch(() => {
18127
18477
  });
18128
18478
  }
18129
18479
  }
@@ -18144,30 +18494,30 @@ class SkillsManager {
18144
18494
  async installSkill(skillPath, skillName, targetDir, copy = false) {
18145
18495
  const normalizedSkillName = this.normalizeSkillName(skillName);
18146
18496
  const destPath = this.resolveInstallPath(targetDir, normalizedSkillName);
18147
- await fs20.mkdir(resolve8(targetDir), { recursive: true });
18497
+ await fs24.mkdir(resolve8(targetDir), { recursive: true });
18148
18498
  if (await fileExists(destPath)) {
18149
- await fs20.rm(destPath, { recursive: true, force: true });
18499
+ await fs24.rm(destPath, { recursive: true, force: true });
18150
18500
  }
18151
18501
  if (copy) {
18152
18502
  await this.copyDir(skillPath, destPath);
18153
18503
  } else {
18154
- await fs20.symlink(skillPath, destPath, "dir");
18504
+ await fs24.symlink(skillPath, destPath, "dir");
18155
18505
  }
18156
18506
  return destPath;
18157
18507
  }
18158
18508
  async installSkillFromContent(skillName, skillContent, targetDir) {
18159
18509
  const normalizedSkillName = this.normalizeSkillName(skillName);
18160
18510
  const destPath = this.resolveInstallPath(targetDir, normalizedSkillName);
18161
- await fs20.mkdir(resolve8(targetDir), { recursive: true });
18511
+ await fs24.mkdir(resolve8(targetDir), { recursive: true });
18162
18512
  if (await fileExists(destPath)) {
18163
- await fs20.rm(destPath, { recursive: true, force: true });
18513
+ await fs24.rm(destPath, { recursive: true, force: true });
18164
18514
  }
18165
- await fs20.mkdir(destPath, { recursive: true });
18166
- await fs20.writeFile(join4(destPath, "SKILL.md"), skillContent, "utf8");
18515
+ await fs24.mkdir(destPath, { recursive: true });
18516
+ await fs24.writeFile(join5(destPath, "SKILL.md"), skillContent, "utf8");
18167
18517
  return destPath;
18168
18518
  }
18169
18519
  getCanonicalSkillsDir(projectPath, global3 = false) {
18170
- return global3 ? resolve8(homedir4(), ".agents/skills") : resolve8(projectPath, ".agents/skills");
18520
+ return global3 ? resolve8(homedir5(), ".agents/skills") : resolve8(projectPath, ".agents/skills");
18171
18521
  }
18172
18522
  async getInstallPlan(skillName, agent, projectPath, options2 = {}) {
18173
18523
  const normalizedSkillName = this.normalizeSkillName(skillName);
@@ -18241,7 +18591,7 @@ class SkillsManager {
18241
18591
  throw new Error(`Missing canonical path for ${skillName}`);
18242
18592
  }
18243
18593
  await this.cleanAndCreateDirectory(canonicalPath);
18244
- await fs20.writeFile(join4(canonicalPath, "SKILL.md"), skillContent, "utf8");
18594
+ await fs24.writeFile(join5(canonicalPath, "SKILL.md"), skillContent, "utf8");
18245
18595
  if (plan.path === canonicalPath) {
18246
18596
  return plan;
18247
18597
  }
@@ -18278,16 +18628,16 @@ class SkillsManager {
18278
18628
  return this.resolveInstallPath(targetDir, this.normalizeSkillName(skillName));
18279
18629
  }
18280
18630
  async cleanAndCreateDirectory(path) {
18281
- await fs20.rm(path, { recursive: true, force: true }).catch(() => {
18631
+ await fs24.rm(path, { recursive: true, force: true }).catch(() => {
18282
18632
  });
18283
- await fs20.mkdir(path, { recursive: true });
18633
+ await fs24.mkdir(path, { recursive: true });
18284
18634
  }
18285
18635
  isWithinPath(basePath, targetPath) {
18286
18636
  const relativePath = relative3(resolve8(basePath), resolve8(targetPath));
18287
18637
  return relativePath === "" || !relativePath.startsWith("..") && !relativePath.includes("/../") && !relativePath.includes("\\..\\");
18288
18638
  }
18289
18639
  async copyDir(src, dest) {
18290
- await fs20.cp(src, dest, { recursive: true, dereference: true });
18640
+ await fs24.cp(src, dest, { recursive: true, dereference: true });
18291
18641
  }
18292
18642
  async addFromSource(source, projectPath, options2 = {}) {
18293
18643
  const discovered = await this.discoverFromSource(source, projectPath, {
@@ -18362,11 +18712,11 @@ class SkillsManager {
18362
18712
  continue;
18363
18713
  const entries = await listFiles(dir);
18364
18714
  for (const entry of entries) {
18365
- const entryPath = join4(dir, entry);
18715
+ const entryPath = join5(dir, entry);
18366
18716
  if (!await isDirectory(entryPath))
18367
18717
  continue;
18368
- const skillMdPath = join4(entryPath, "SKILL.md");
18369
- const skillMdPathLower = join4(entryPath, "skill.md");
18718
+ const skillMdPath = join5(entryPath, "SKILL.md");
18719
+ const skillMdPathLower = join5(entryPath, "skill.md");
18370
18720
  const skillFile = await fileExists(skillMdPath) ? skillMdPath : await fileExists(skillMdPathLower) ? skillMdPathLower : null;
18371
18721
  if (!skillFile)
18372
18722
  continue;
@@ -18376,7 +18726,7 @@ class SkillsManager {
18376
18726
  let isSymlink = false;
18377
18727
  let canonicalPath;
18378
18728
  try {
18379
- const stat = await fs20.lstat(entryPath);
18729
+ const stat = await fs24.lstat(entryPath);
18380
18730
  isSymlink = stat.isSymbolicLink();
18381
18731
  const canonicalBase = this.getCanonicalSkillsDir(projectPath, scope === "global");
18382
18732
  const [resolvedEntryPath, resolvedCanonicalBase] = await Promise.all([
@@ -18442,7 +18792,7 @@ class SkillsManager {
18442
18792
  }
18443
18793
  if (!removedPaths.has(entry.path)) {
18444
18794
  try {
18445
- await fs20.rm(entry.path, { recursive: true, force: true });
18795
+ await fs24.rm(entry.path, { recursive: true, force: true });
18446
18796
  removedPaths.add(entry.path);
18447
18797
  } catch {
18448
18798
  skipped.push({
@@ -18455,7 +18805,7 @@ class SkillsManager {
18455
18805
  if (entry.canonicalPath && entry.canonicalPath !== entry.path && !removedCanonicalPaths.has(entry.canonicalPath)) {
18456
18806
  const stillReferenced = remainingEntries.some((other) => other.name.toLowerCase() === entry.name.toLowerCase() && other.canonicalPath === entry.canonicalPath);
18457
18807
  if (!stillReferenced) {
18458
- await fs20.rm(entry.canonicalPath, { recursive: true, force: true }).catch(() => {
18808
+ await fs24.rm(entry.canonicalPath, { recursive: true, force: true }).catch(() => {
18459
18809
  });
18460
18810
  removedCanonicalPaths.add(entry.canonicalPath);
18461
18811
  }
@@ -19869,7 +20219,7 @@ var require_util3 = __commonJS((exports, module) => {
19869
20219
  var path = jsonPointers ? toQuotedString("/" + escapeJsonPointer(prop)) : toQuotedString(getProperty(prop));
19870
20220
  return joinPaths(currentPath, path);
19871
20221
  };
19872
- var getData = function($data, lvl, paths2) {
20222
+ var getData = function($data, lvl, paths5) {
19873
20223
  var up, jsonPointer, data, matches;
19874
20224
  if ($data === "")
19875
20225
  return "rootData";
@@ -19887,7 +20237,7 @@ var require_util3 = __commonJS((exports, module) => {
19887
20237
  if (jsonPointer == "#") {
19888
20238
  if (up >= lvl)
19889
20239
  throw new Error("Cannot access property/index " + up + " levels up, current level is " + lvl);
19890
- return paths2[lvl - up];
20240
+ return paths5[lvl - up];
19891
20241
  }
19892
20242
  if (up > lvl)
19893
20243
  throw new Error("Cannot access data " + up + " levels up, current level is " + lvl);
@@ -24691,27 +25041,27 @@ var require_windows = __commonJS((exports, module) => {
24691
25041
  return checkPathExt(path, options2);
24692
25042
  };
24693
25043
  var isexe = function(path, options2, cb) {
24694
- fs27.stat(path, function(er, stat) {
25044
+ fs31.stat(path, function(er, stat) {
24695
25045
  cb(er, er ? false : checkStat(stat, path, options2));
24696
25046
  });
24697
25047
  };
24698
25048
  var sync = function(path, options2) {
24699
- return checkStat(fs27.statSync(path), path, options2);
25049
+ return checkStat(fs31.statSync(path), path, options2);
24700
25050
  };
24701
25051
  module.exports = isexe;
24702
25052
  isexe.sync = sync;
24703
- var fs27 = __require("fs");
25053
+ var fs31 = __require("fs");
24704
25054
  });
24705
25055
 
24706
25056
  // node_modules/isexe/mode.js
24707
25057
  var require_mode = __commonJS((exports, module) => {
24708
25058
  var isexe = function(path, options2, cb) {
24709
- fs27.stat(path, function(er, stat) {
25059
+ fs31.stat(path, function(er, stat) {
24710
25060
  cb(er, er ? false : checkStat(stat, options2));
24711
25061
  });
24712
25062
  };
24713
25063
  var sync = function(path, options2) {
24714
- return checkStat(fs27.statSync(path), options2);
25064
+ return checkStat(fs31.statSync(path), options2);
24715
25065
  };
24716
25066
  var checkStat = function(stat, options2) {
24717
25067
  return stat.isFile() && checkMode(stat, options2);
@@ -24731,7 +25081,7 @@ var require_mode = __commonJS((exports, module) => {
24731
25081
  };
24732
25082
  module.exports = isexe;
24733
25083
  isexe.sync = sync;
24734
- var fs27 = __require("fs");
25084
+ var fs31 = __require("fs");
24735
25085
  });
24736
25086
 
24737
25087
  // node_modules/isexe/index.js
@@ -24776,7 +25126,7 @@ var require_isexe = __commonJS((exports, module) => {
24776
25126
  }
24777
25127
  }
24778
25128
  };
24779
- var fs27 = __require("fs");
25129
+ var fs31 = __require("fs");
24780
25130
  var core2;
24781
25131
  if (process.platform === "win32" || global.TESTING_WINDOWS) {
24782
25132
  core2 = require_windows();
@@ -24983,14 +25333,14 @@ var require_readShebang = __commonJS((exports, module) => {
24983
25333
  const buffer = Buffer.alloc(size);
24984
25334
  let fd;
24985
25335
  try {
24986
- fd = fs27.openSync(command, "r");
24987
- fs27.readSync(fd, buffer, 0, size, 0);
24988
- fs27.closeSync(fd);
25336
+ fd = fs31.openSync(command, "r");
25337
+ fs31.readSync(fd, buffer, 0, size, 0);
25338
+ fs31.closeSync(fd);
24989
25339
  } catch (e) {
24990
25340
  }
24991
25341
  return shebangCommand(buffer.toString());
24992
25342
  };
24993
- var fs27 = __require("fs");
25343
+ var fs31 = __require("fs");
24994
25344
  var shebangCommand = require_shebang_command();
24995
25345
  module.exports = readShebang;
24996
25346
  });
@@ -25142,7 +25492,7 @@ var {
25142
25492
  } = import_.default;
25143
25493
 
25144
25494
  // dist/commands/init.js
25145
- import {resolve as resolve4} from "path";
25495
+ import {resolve as resolve5} from "path";
25146
25496
 
25147
25497
  // node_modules/ora/index.js
25148
25498
  import process9 from "node:process";
@@ -26493,7 +26843,45 @@ var bgMagenta = init(45, 49);
26493
26843
  var bgCyan = init(46, 49);
26494
26844
  var bgWhite = init(47, 49);
26495
26845
 
26846
+ // dist/utils/symbols.js
26847
+ var STATUS = {
26848
+ success: "\u2713",
26849
+ error: "\u2717",
26850
+ warning: "\u26A0",
26851
+ info: "\u2139",
26852
+ debug: "\u2022"
26853
+ };
26854
+ var TREE = {
26855
+ branch: "\u251C\u2500",
26856
+ last: "\u2514\u2500"
26857
+ };
26858
+ var BOX = {
26859
+ topLeft: "\u250C",
26860
+ topRight: "\u2510",
26861
+ bottomLeft: "\u2514",
26862
+ bottomRight: "\u2518",
26863
+ horizontal: "\u2500",
26864
+ vertical: "\u2502"
26865
+ };
26866
+
26496
26867
  // dist/utils/logger.js
26868
+ var getTerminalWidth = function() {
26869
+ const columns = process.stdout.columns;
26870
+ return typeof columns === "number" && columns > 0 ? columns : 80;
26871
+ };
26872
+ var truncateText = function(text, maxLength) {
26873
+ if (maxLength <= 0) {
26874
+ return "";
26875
+ }
26876
+ if (text.length <= maxLength) {
26877
+ return text;
26878
+ }
26879
+ if (maxLength <= 3) {
26880
+ return ".".repeat(maxLength);
26881
+ }
26882
+ return `${text.slice(0, maxLength - 3)}...`;
26883
+ };
26884
+
26497
26885
  class Logger {
26498
26886
  static instance;
26499
26887
  static getInstance() {
@@ -26503,22 +26891,22 @@ class Logger {
26503
26891
  return Logger.instance;
26504
26892
  }
26505
26893
  info(message) {
26506
- console.log(cyan("\u2139"), message);
26894
+ console.log(cyan(STATUS.info), message);
26507
26895
  }
26508
26896
  success(message) {
26509
- console.log(green("\u2713"), message);
26897
+ console.log(green(STATUS.success), message);
26510
26898
  }
26511
26899
  warning(message) {
26512
- console.log(yellow("\u26A0"), message);
26900
+ console.log(yellow(STATUS.warning), message);
26513
26901
  }
26514
26902
  warn(message) {
26515
26903
  this.warning(message);
26516
26904
  }
26517
26905
  error(message) {
26518
- console.log(red("\u2717"), message);
26906
+ console.log(red(STATUS.error), message);
26519
26907
  }
26520
26908
  debug(message) {
26521
- console.log(dim("\u2022"), dim(message));
26909
+ console.log(dim(STATUS.debug), dim(message));
26522
26910
  }
26523
26911
  title(message) {
26524
26912
  console.log(bold(cyan(message)));
@@ -26526,6 +26914,30 @@ class Logger {
26526
26914
  subtitle(message) {
26527
26915
  console.log(bold(message));
26528
26916
  }
26917
+ titleBox(message) {
26918
+ const w = getTerminalWidth();
26919
+ if (w < 8) {
26920
+ console.log(bold(cyan(truncateText(message, w))));
26921
+ return;
26922
+ }
26923
+ const maxInner = Math.max(4, w - 2);
26924
+ const inner = Math.min(Math.max(message.length + 4, 40), maxInner);
26925
+ const visibleMessage = truncateText(message, inner - 2);
26926
+ const padR = Math.max(0, inner - visibleMessage.length - 2);
26927
+ console.log(dim(BOX.topLeft + BOX.horizontal.repeat(inner) + BOX.topRight));
26928
+ console.log(dim(BOX.vertical) + " " + bold(cyan(visibleMessage)) + " ".repeat(padR) + " " + dim(BOX.vertical));
26929
+ console.log(dim(BOX.bottomLeft + BOX.horizontal.repeat(inner) + BOX.bottomRight));
26930
+ }
26931
+ section(title) {
26932
+ const w = getTerminalWidth();
26933
+ const lineLen = Math.max(0, w - title.length - 5);
26934
+ console.log("");
26935
+ console.log(bold(`${BOX.horizontal}${BOX.horizontal} ${title} ${BOX.horizontal.repeat(lineLen)}`));
26936
+ }
26937
+ tree(message, isLast) {
26938
+ const connector = isLast ? TREE.last : TREE.branch;
26939
+ console.log(`${connector} ${message}`);
26940
+ }
26529
26941
  }
26530
26942
  var logger = Logger.getInstance();
26531
26943
 
@@ -26534,7 +26946,8 @@ init_fs();
26534
26946
 
26535
26947
  // dist/core/agentDetector.js
26536
26948
  init_fs();
26537
- import {resolve as resolve2} from "path";
26949
+ init_paths();
26950
+ import {isAbsolute, resolve as resolve3} from "path";
26538
26951
 
26539
26952
  class AgentDetector {
26540
26953
  agentConfigs = [
@@ -26545,14 +26958,19 @@ class AgentDetector {
26545
26958
  { name: "codeium", files: [".codeium/config.json"] },
26546
26959
  { name: "codex", files: [".codex/config.toml"] },
26547
26960
  { name: "gemini", files: [".gemini/settings.json"] },
26961
+ { name: "openclaw", files: ["~/.openclaw"], scope: "environment" },
26962
+ { name: "hermes", files: ["~/.hermes"], scope: "environment" },
26548
26963
  { name: "aider", files: [".aider.conf.yml"] },
26549
26964
  { name: "cline", files: [".clinerules"] },
26550
26965
  { name: "roo", files: [".roo/mcp.json"] },
26551
26966
  { name: "zed", files: [".zed/settings.json"] }
26552
26967
  ];
26553
- async detectAgents(projectPath) {
26968
+ async detectAgents(projectPath, options2 = {}) {
26554
26969
  const results = [];
26555
26970
  for (const config of this.agentConfigs) {
26971
+ if (!this.shouldCheckScope(config.scope, options2)) {
26972
+ continue;
26973
+ }
26556
26974
  const detected = await this.checkAgentFiles(projectPath, config.files);
26557
26975
  results.push({
26558
26976
  name: config.name,
@@ -26563,19 +26981,41 @@ class AgentDetector {
26563
26981
  }
26564
26982
  return results;
26565
26983
  }
26984
+ shouldCheckScope(scope, options2) {
26985
+ if (options2.includeEnvironment) {
26986
+ return true;
26987
+ }
26988
+ return scope !== "environment";
26989
+ }
26566
26990
  async checkAgentFiles(projectPath, files) {
26567
26991
  for (const file of files) {
26568
- const fullPath = resolve2(projectPath, file);
26992
+ const fullPath = this.resolveDetectionPath(projectPath, file);
26569
26993
  if (await fileExists(fullPath)) {
26570
26994
  return { found: true, path: fullPath };
26571
26995
  }
26572
26996
  }
26573
26997
  return { found: false };
26574
26998
  }
26575
- async detectAgentByName(projectPath, agentName) {
26999
+ resolveDetectionPath(projectPath, file) {
27000
+ if (file.startsWith("~")) {
27001
+ return expandTilde(file);
27002
+ }
27003
+ if (isAbsolute(file)) {
27004
+ return file;
27005
+ }
27006
+ return resolve3(projectPath, file);
27007
+ }
27008
+ async detectAgentByName(projectPath, agentName, options2 = {}) {
26576
27009
  const config = this.agentConfigs.find((c) => c.name === agentName);
26577
27010
  if (!config)
26578
27011
  return null;
27012
+ if (!this.shouldCheckScope(config.scope, options2)) {
27013
+ return {
27014
+ name: config.name,
27015
+ files: config.files,
27016
+ detected: false
27017
+ };
27018
+ }
26579
27019
  const detected = await this.checkAgentFiles(projectPath, config.files);
26580
27020
  return {
26581
27021
  name: config.name,
@@ -26591,7 +27031,7 @@ class AgentDetector {
26591
27031
 
26592
27032
  // dist/core/stackDetector.js
26593
27033
  init_fs();
26594
- import {resolve as resolve3} from "path";
27034
+ import {resolve as resolve4} from "path";
26595
27035
 
26596
27036
  class StackDetector {
26597
27037
  lockFiles = [
@@ -26637,7 +27077,7 @@ class StackDetector {
26637
27077
  }
26638
27078
  async detectFromLockFiles(projectPath) {
26639
27079
  for (const lockFile of this.lockFiles) {
26640
- const lockPath = resolve3(projectPath, lockFile);
27080
+ const lockPath = resolve4(projectPath, lockFile);
26641
27081
  if (await fileExists(lockPath)) {
26642
27082
  return this.inferStackFromLockFile(projectPath, lockFile);
26643
27083
  }
@@ -26669,7 +27109,7 @@ class StackDetector {
26669
27109
  }
26670
27110
  async detectFromManifests(projectPath) {
26671
27111
  for (const manifest of this.manifestFiles) {
26672
- const manifestPath = resolve3(projectPath, manifest);
27112
+ const manifestPath = resolve4(projectPath, manifest);
26673
27113
  if (await fileExists(manifestPath)) {
26674
27114
  return this.inferStackFromManifest(projectPath, manifest);
26675
27115
  }
@@ -26701,7 +27141,7 @@ class StackDetector {
26701
27141
  }
26702
27142
  async detectFromConfigs(projectPath) {
26703
27143
  for (const config of this.configFiles) {
26704
- const configPath = resolve3(projectPath, config);
27144
+ const configPath = resolve4(projectPath, config);
26705
27145
  if (await fileExists(configPath)) {
26706
27146
  return this.inferStackFromConfig(projectPath, config);
26707
27147
  }
@@ -26760,7 +27200,7 @@ class StackDetector {
26760
27200
  };
26761
27201
  }
26762
27202
  async analyzeJavaScriptProject(projectPath) {
26763
- const packageJsonPath = resolve3(projectPath, "package.json");
27203
+ const packageJsonPath = resolve4(projectPath, "package.json");
26764
27204
  const packageJsonContent = await readFileIfExists(packageJsonPath);
26765
27205
  const info = {
26766
27206
  language: "javascript",
@@ -26775,7 +27215,7 @@ class StackDetector {
26775
27215
  ...packageJson.devDependencies
26776
27216
  };
26777
27217
  info.dependencies = Object.keys(allDeps);
26778
- if (allDeps.typescript || await fileExists(resolve3(projectPath, "tsconfig.json"))) {
27218
+ if (allDeps.typescript || await fileExists(resolve4(projectPath, "tsconfig.json"))) {
26779
27219
  info.language = "typescript";
26780
27220
  }
26781
27221
  if (allDeps.next)
@@ -26792,11 +27232,11 @@ class StackDetector {
26792
27232
  info.framework = "express";
26793
27233
  else if (allDeps.fastify)
26794
27234
  info.framework = "fastify";
26795
- if (await fileExists(resolve3(projectPath, "yarn.lock")))
27235
+ if (await fileExists(resolve4(projectPath, "yarn.lock")))
26796
27236
  info.packageManager = "yarn";
26797
- else if (await fileExists(resolve3(projectPath, "pnpm-lock.yaml")))
27237
+ else if (await fileExists(resolve4(projectPath, "pnpm-lock.yaml")))
26798
27238
  info.packageManager = "pnpm";
26799
- else if (await fileExists(resolve3(projectPath, "bun.lockb")))
27239
+ else if (await fileExists(resolve4(projectPath, "bun.lockb")))
26800
27240
  info.packageManager = "bun";
26801
27241
  else
26802
27242
  info.packageManager = "npm";
@@ -27075,8 +27515,8 @@ This is a {{STACK}} project{{FRAMEWORK_CONTEXT}}. The codebase follows modern de
27075
27515
  // dist/commands/init.js
27076
27516
  async function initCommand(options2) {
27077
27517
  const cwd = process.cwd();
27078
- const agentsPath = resolve4(cwd, "agents.md");
27079
- logger.title("\uD83D\uDE80 AgentInit - Initialize Project");
27518
+ const agentsPath = resolve5(cwd, "agents.md");
27519
+ logger.titleBox("AgentInit Initialize Project");
27080
27520
  if (!options2.force && await fileExists(agentsPath)) {
27081
27521
  const response = await import_prompts.default({
27082
27522
  type: "confirm",
@@ -27153,7 +27593,7 @@ async function initCommand(options2) {
27153
27593
  }
27154
27594
  var getProjectName = function(cwd) {
27155
27595
  try {
27156
- const packageJsonPath = resolve4(cwd, "package.json");
27596
+ const packageJsonPath = resolve5(cwd, "package.json");
27157
27597
  const packageJson = __require(packageJsonPath);
27158
27598
  return packageJson.name || cwd.split("/").pop() || "project";
27159
27599
  } catch {
@@ -27166,7 +27606,7 @@ init_skillsManager();
27166
27606
  init_agentManager();
27167
27607
  async function detectCommand(options2) {
27168
27608
  const cwd = process.cwd();
27169
- logger.title("\uD83D\uDD0D AgentInit - Project Detection");
27609
+ logger.titleBox("AgentInit Project Detection");
27170
27610
  const spinner = ora("Detecting project configuration...").start();
27171
27611
  try {
27172
27612
  const agentDetector3 = new AgentDetector;
@@ -27234,7 +27674,7 @@ import {relative as relative5} from "path";
27234
27674
 
27235
27675
  // dist/core/propagator.js
27236
27676
  var import_gray_matter3 = __toESM(require_gray_matter(), 1);
27237
- import {promises as fs22} from "fs";
27677
+ import {promises as fs26} from "fs";
27238
27678
  import {resolve as resolve9} from "path";
27239
27679
 
27240
27680
  // node_modules/js-yaml/dist/js-yaml.mjs
@@ -30002,7 +30442,7 @@ class Propagator {
30002
30442
  resolvedTargets: []
30003
30443
  };
30004
30444
  const exists = await fileExists(generatedFile.path);
30005
- const existingStats = exists ? await fs22.lstat(generatedFile.path).catch(() => null) : null;
30445
+ const existingStats = exists ? await fs26.lstat(generatedFile.path).catch(() => null) : null;
30006
30446
  const existingContent = exists && !existingStats?.isSymbolicLink() ? await readFileIfExists(generatedFile.path) : null;
30007
30447
  const existingTarget = existingStats?.isSymbolicLink() ? await readSymlinkTarget(generatedFile.path) : null;
30008
30448
  if (options2.managedState && !options2.dryRun) {
@@ -30033,7 +30473,7 @@ class Propagator {
30033
30473
  if (!options2.dryRun) {
30034
30474
  if (generatedFile.kind === "file") {
30035
30475
  if (existingStats?.isSymbolicLink()) {
30036
- await fs22.rm(generatedFile.path, { force: true }).catch(() => {
30476
+ await fs26.rm(generatedFile.path, { force: true }).catch(() => {
30037
30477
  });
30038
30478
  }
30039
30479
  await writeFile(generatedFile.path, generatedFile.content || "");
@@ -30210,14 +30650,14 @@ ${content}
30210
30650
 
30211
30651
  // dist/core/managedState.js
30212
30652
  init_fs();
30213
- import {promises as fs24} from "fs";
30214
- 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";
30215
30655
  var toPosixPath = function(value) {
30216
30656
  return value.replace(/\\/g, "/");
30217
30657
  };
30218
30658
  async function pathType(targetPath) {
30219
30659
  try {
30220
- const stat = await fs24.lstat(targetPath);
30660
+ const stat = await fs28.lstat(targetPath);
30221
30661
  if (stat.isSymbolicLink()) {
30222
30662
  return "symlink";
30223
30663
  }
@@ -30227,20 +30667,20 @@ async function pathType(targetPath) {
30227
30667
  }
30228
30668
  }
30229
30669
  async function copyDirectory(src, dest) {
30230
- await fs24.mkdir(dest, { recursive: true });
30231
- const entries = await fs24.readdir(src, { withFileTypes: true });
30670
+ await fs28.mkdir(dest, { recursive: true });
30671
+ const entries = await fs28.readdir(src, { withFileTypes: true });
30232
30672
  for (const entry of entries) {
30233
- const srcPath = join5(src, entry.name);
30234
- const destPath = join5(dest, entry.name);
30673
+ const srcPath = join6(src, entry.name);
30674
+ const destPath = join6(dest, entry.name);
30235
30675
  if (entry.isDirectory()) {
30236
30676
  await copyDirectory(srcPath, destPath);
30237
30677
  } else if (entry.isSymbolicLink()) {
30238
- const target = await fs24.readlink(srcPath);
30239
- await fs24.mkdir(dirname3(destPath), { recursive: true });
30240
- await fs24.symlink(target, destPath);
30678
+ const target = await fs28.readlink(srcPath);
30679
+ await fs28.mkdir(dirname3(destPath), { recursive: true });
30680
+ await fs28.symlink(target, destPath);
30241
30681
  } else {
30242
- await fs24.mkdir(dirname3(destPath), { recursive: true });
30243
- await fs24.copyFile(srcPath, destPath);
30682
+ await fs28.mkdir(dirname3(destPath), { recursive: true });
30683
+ await fs28.copyFile(srcPath, destPath);
30244
30684
  }
30245
30685
  }
30246
30686
  }
@@ -30249,14 +30689,14 @@ async function copyPath(src, dest) {
30249
30689
  if (!type2) {
30250
30690
  return;
30251
30691
  }
30252
- await fs24.mkdir(dirname3(dest), { recursive: true });
30692
+ await fs28.mkdir(dirname3(dest), { recursive: true });
30253
30693
  if (type2 === "symlink") {
30254
- const target = await fs24.readlink(src);
30255
- await fs24.symlink(target, dest);
30694
+ const target = await fs28.readlink(src);
30695
+ await fs28.symlink(target, dest);
30256
30696
  } else if (type2 === "directory") {
30257
30697
  await copyDirectory(src, dest);
30258
30698
  } else {
30259
- await fs24.copyFile(src, dest);
30699
+ await fs28.copyFile(src, dest);
30260
30700
  }
30261
30701
  }
30262
30702
  var MANAGED_STATE_FILE = "managed-state.json";
@@ -30270,11 +30710,11 @@ class ManagedStateStore {
30270
30710
  this.state = state;
30271
30711
  }
30272
30712
  static async open(projectPath) {
30273
- const agentInitDir = join5(projectPath, ".agentinit");
30274
- const statePath = join5(agentInitDir, MANAGED_STATE_FILE);
30713
+ const agentInitDir = join6(projectPath, ".agentinit");
30714
+ const statePath = join6(agentInitDir, MANAGED_STATE_FILE);
30275
30715
  const emptyState = { version: 1, entries: [] };
30276
30716
  try {
30277
- const raw = await fs24.readFile(statePath, "utf8");
30717
+ const raw = await fs28.readFile(statePath, "utf8");
30278
30718
  const parsed = JSON.parse(raw);
30279
30719
  if (!parsed || parsed.version !== 1 || !Array.isArray(parsed.entries)) {
30280
30720
  return new ManagedStateStore(projectPath, emptyState);
@@ -30285,13 +30725,13 @@ class ManagedStateStore {
30285
30725
  }
30286
30726
  }
30287
30727
  get agentInitDir() {
30288
- return join5(this.projectPath, ".agentinit");
30728
+ return join6(this.projectPath, ".agentinit");
30289
30729
  }
30290
30730
  get stateFilePath() {
30291
- return join5(this.agentInitDir, MANAGED_STATE_FILE);
30731
+ return join6(this.agentInitDir, MANAGED_STATE_FILE);
30292
30732
  }
30293
30733
  get backupsDir() {
30294
- return join5(this.agentInitDir, BACKUPS_DIR);
30734
+ return join6(this.agentInitDir, BACKUPS_DIR);
30295
30735
  }
30296
30736
  normalizeRelativePath(targetPath, preserveTrailingSlash = false) {
30297
30737
  const hasTrailingSlash = preserveTrailingSlash && /[\\/]$/.test(targetPath);
@@ -30313,14 +30753,14 @@ class ManagedStateStore {
30313
30753
  }
30314
30754
  if (type2 === "symlink") {
30315
30755
  try {
30316
- const backupLinkTarget = await fs24.readlink(targetPath);
30756
+ const backupLinkTarget = await fs28.readlink(targetPath);
30317
30757
  return { backupLinkTarget };
30318
30758
  } catch {
30319
30759
  return {};
30320
30760
  }
30321
30761
  }
30322
30762
  const relativeTargetPath = this.normalizeRelativePath(targetPath);
30323
- const backupPath = join5(this.backupsDir, relativeTargetPath);
30763
+ const backupPath = join6(this.backupsDir, relativeTargetPath);
30324
30764
  if (!await fileExists(backupPath)) {
30325
30765
  await copyPath(targetPath, backupPath);
30326
30766
  }
@@ -30355,20 +30795,20 @@ class ManagedStateStore {
30355
30795
  if (this.state.entries.length === 0) {
30356
30796
  return [];
30357
30797
  }
30358
- const paths2 = new Set([
30798
+ const paths5 = new Set([
30359
30799
  ".agentinit/managed-state.json",
30360
30800
  ".agentinit/backups/"
30361
30801
  ]);
30362
30802
  for (const entry of this.state.entries) {
30363
30803
  if (entry.ignorePath) {
30364
- paths2.add(entry.ignorePath);
30804
+ paths5.add(entry.ignorePath);
30365
30805
  }
30366
30806
  }
30367
- return [...paths2];
30807
+ return [...paths5];
30368
30808
  }
30369
30809
  async save() {
30370
- await fs24.mkdir(this.agentInitDir, { recursive: true });
30371
- await fs24.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");
30372
30812
  }
30373
30813
  async revertAll(options2 = {}) {
30374
30814
  const summary = {
@@ -30383,29 +30823,29 @@ class ManagedStateStore {
30383
30823
  const backupLinkTarget = entry.backupLinkTarget;
30384
30824
  if (entry.existedBefore && backupLinkTarget !== undefined) {
30385
30825
  if (!options2.dryRun) {
30386
- await fs24.rm(absolutePath, { recursive: true, force: true }).catch(() => {
30826
+ await fs28.rm(absolutePath, { recursive: true, force: true }).catch(() => {
30387
30827
  });
30388
- await fs24.mkdir(dirname3(absolutePath), { recursive: true });
30389
- await fs24.symlink(backupLinkTarget, absolutePath);
30828
+ await fs28.mkdir(dirname3(absolutePath), { recursive: true });
30829
+ await fs28.symlink(backupLinkTarget, absolutePath);
30390
30830
  }
30391
30831
  summary.restored++;
30392
30832
  } else if (entry.existedBefore && backupPath && await fileExists(backupPath)) {
30393
30833
  if (!options2.dryRun) {
30394
- await fs24.rm(absolutePath, { recursive: true, force: true }).catch(() => {
30834
+ await fs28.rm(absolutePath, { recursive: true, force: true }).catch(() => {
30395
30835
  });
30396
30836
  await copyPath(backupPath, absolutePath);
30397
30837
  }
30398
30838
  summary.restored++;
30399
30839
  } else {
30400
30840
  if (!options2.dryRun) {
30401
- await fs24.rm(absolutePath, { recursive: true, force: true }).catch(() => {
30841
+ await fs28.rm(absolutePath, { recursive: true, force: true }).catch(() => {
30402
30842
  });
30403
30843
  }
30404
30844
  summary.removed++;
30405
30845
  }
30406
30846
  if (!options2.keepBackups && backupPath && await fileExists(backupPath)) {
30407
30847
  if (!options2.dryRun) {
30408
- await fs24.rm(backupPath, { recursive: true, force: true }).catch(() => {
30848
+ await fs28.rm(backupPath, { recursive: true, force: true }).catch(() => {
30409
30849
  });
30410
30850
  }
30411
30851
  summary.backupsRemoved++;
@@ -30413,16 +30853,16 @@ class ManagedStateStore {
30413
30853
  }
30414
30854
  if (!options2.dryRun) {
30415
30855
  this.state.entries.length = 0;
30416
- await fs24.rm(this.stateFilePath, { force: true }).catch(() => {
30856
+ await fs28.rm(this.stateFilePath, { force: true }).catch(() => {
30417
30857
  });
30418
30858
  if (!options2.keepBackups) {
30419
- await fs24.rm(this.backupsDir, { recursive: true, force: true }).catch(() => {
30859
+ await fs28.rm(this.backupsDir, { recursive: true, force: true }).catch(() => {
30420
30860
  });
30421
30861
  }
30422
30862
  try {
30423
- const remainingEntries = await fs24.readdir(this.agentInitDir);
30863
+ const remainingEntries = await fs28.readdir(this.agentInitDir);
30424
30864
  if (remainingEntries.length === 0) {
30425
- await fs24.rm(this.agentInitDir, { recursive: true, force: true });
30865
+ await fs28.rm(this.agentInitDir, { recursive: true, force: true });
30426
30866
  }
30427
30867
  } catch {
30428
30868
  }
@@ -30436,7 +30876,7 @@ init_agentManager();
30436
30876
  async function syncCommand(options2) {
30437
30877
  const cwd = process.cwd();
30438
30878
  const agentManager5 = new AgentManager;
30439
- logger.title("\uD83D\uDD04 AgentInit - Sync Configuration");
30879
+ logger.titleBox("AgentInit Sync");
30440
30880
  if (options2.dryRun) {
30441
30881
  logger.info("Running in dry-run mode - no files will be modified");
30442
30882
  }
@@ -30765,15 +31205,15 @@ class MCPParser {
30765
31205
  }
30766
31206
 
30767
31207
  // dist/constants/mcp.js
30768
- import {readFileSync} from "fs";
31208
+ import {readFileSync as readFileSync2} from "fs";
30769
31209
  import {fileURLToPath} from "url";
30770
- import {dirname as dirname4, join as join6} from "path";
31210
+ import {dirname as dirname4, join as join7} from "path";
30771
31211
  var getPackageVersion = function() {
30772
31212
  try {
30773
31213
  const __filename2 = fileURLToPath(import.meta.url);
30774
31214
  const __dirname2 = dirname4(__filename2);
30775
- const packageJsonPath = join6(__dirname2, "../../package.json");
30776
- const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
31215
+ const packageJsonPath = join7(__dirname2, "../../package.json");
31216
+ const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
30777
31217
  return packageJson.version || "1.0.0";
30778
31218
  } catch {
30779
31219
  return "1.0.0";
@@ -30799,13 +31239,13 @@ var TOKEN_COUNT_THRESHOLDS = {
30799
31239
  };
30800
31240
  // dist/core/rulesParser.js
30801
31241
  init_fs();
30802
- import {readFileSync as readFileSync3} from "fs";
31242
+ import {readFileSync as readFileSync4} from "fs";
30803
31243
 
30804
31244
  // dist/core/rulesTemplateLoader.js
30805
31245
  var toml = __toESM(require_toml(), 1);
30806
31246
  import {resolve as resolve11, dirname as dirname5} from "path";
30807
31247
  import {fileURLToPath as fileURLToPath2} from "url";
30808
- import {readFileSync as readFileSync2, readdirSync, existsSync} from "fs";
31248
+ import {readFileSync as readFileSync3, readdirSync, existsSync as existsSync2} from "fs";
30809
31249
  var __filename2 = fileURLToPath2(import.meta.url);
30810
31250
  var __dirname2 = dirname5(__filename2);
30811
31251
 
@@ -30817,14 +31257,14 @@ class RulesTemplateLoader {
30817
31257
  this.loadTemplates();
30818
31258
  }
30819
31259
  loadTemplates() {
30820
- if (!existsSync(this.templatesPath)) {
31260
+ if (!existsSync2(this.templatesPath)) {
30821
31261
  throw new Error(`Rules templates directory not found: ${this.templatesPath}`);
30822
31262
  }
30823
31263
  const files = readdirSync(this.templatesPath).filter((file) => file.endsWith(".toml"));
30824
31264
  for (const file of files) {
30825
31265
  try {
30826
31266
  const filePath = resolve11(this.templatesPath, file);
30827
- const content = readFileSync2(filePath, "utf-8");
31267
+ const content = readFileSync3(filePath, "utf-8");
30828
31268
  const parsed = toml.default.parse(content);
30829
31269
  const template = {
30830
31270
  id: parsed.template.id,
@@ -30972,7 +31412,7 @@ class RulesParser {
30972
31412
  throw new RulesParseError(`Rules file not found: ${filePath}`);
30973
31413
  }
30974
31414
  try {
30975
- const content = readFileSync3(filePath, "utf-8");
31415
+ const content = readFileSync4(filePath, "utf-8");
30976
31416
  if (filePath.endsWith(".json")) {
30977
31417
  const parsed = JSON.parse(content);
30978
31418
  return this.extractRulesFromObject(parsed);
@@ -38960,7 +39400,7 @@ class MCPVerifier {
38960
39400
  for (const result of results) {
38961
39401
  const { server, status, capabilities, error, connectionTime } = result;
38962
39402
  if (status === "success" && capabilities) {
38963
- output.push(`\u2705 MCP Server: ${server.name} (${server.type.toUpperCase()})`);
39403
+ output.push(`\u2713 MCP Server: ${server.name} (${server.type.toUpperCase()})`);
38964
39404
  output.push(` Status: Connected successfully (${connectionTime}ms)`);
38965
39405
  if (capabilities.serverInfo) {
38966
39406
  output.push(` Version: ${capabilities.serverInfo.version}`);
@@ -39010,10 +39450,10 @@ class MCPVerifier {
39010
39450
  }
39011
39451
  }
39012
39452
  if (capabilities.tools.length === 0 && capabilities.resources.length === 0 && capabilities.prompts.length === 0) {
39013
- output.push(` \u26A0\uFE0F No tools, resources, or prompts available`);
39453
+ output.push(` \u26A0 No tools, resources, or prompts available`);
39014
39454
  }
39015
39455
  } else {
39016
- const statusIcon = status === "timeout" ? "\u23F1\uFE0F" : "\u274C";
39456
+ const statusIcon = status === "timeout" ? "\u29D7" : "\u2717";
39017
39457
  output.push(`${statusIcon} MCP Server: ${server.name} (${server.type.toUpperCase()})`);
39018
39458
  output.push(` Status: ${status === "timeout" ? "Connection timeout" : "Failed"} (${connectionTime || 0}ms)`);
39019
39459
  if (error) {
@@ -39042,8 +39482,8 @@ class MCPVerifier {
39042
39482
  }
39043
39483
 
39044
39484
  // dist/core/gitignoreManager.js
39045
- import {promises as fs27} from "fs";
39046
- 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";
39047
39487
  var normalizeIgnorePath = function(projectPath, value) {
39048
39488
  const relative6 = value.startsWith(projectPath) ? value.slice(projectPath.length + 1) : value;
39049
39489
  const normalized = relative6.replace(/\\/g, "/").replace(/^\/+/, "");
@@ -39089,13 +39529,13 @@ var updateManagedBlock = function(existingContent, entries) {
39089
39529
  }
39090
39530
  return content;
39091
39531
  };
39092
- async function updateManagedIgnoreFile(projectPath, paths2, options2 = {}) {
39093
- const ignoreFile = options2.local ? join7(".git", "info", "exclude") : ".gitignore";
39094
- const ignoreFilePath = join7(projectPath, ignoreFile);
39532
+ async function updateManagedIgnoreFile(projectPath, paths5, options2 = {}) {
39533
+ const ignoreFile = options2.local ? join8(".git", "info", "exclude") : ".gitignore";
39534
+ const ignoreFilePath = join8(projectPath, ignoreFile);
39095
39535
  if (options2.local) {
39096
- const gitDir = join7(projectPath, ".git");
39536
+ const gitDir = join8(projectPath, ".git");
39097
39537
  try {
39098
- const stat = await fs27.stat(gitDir);
39538
+ const stat = await fs31.stat(gitDir);
39099
39539
  if (!stat.isDirectory()) {
39100
39540
  throw new Error;
39101
39541
  }
@@ -39103,24 +39543,24 @@ async function updateManagedIgnoreFile(projectPath, paths2, options2 = {}) {
39103
39543
  throw new Error("Cannot update .git/info/exclude because this project is not a Git repository");
39104
39544
  }
39105
39545
  }
39106
- const normalizedPaths = [...new Set(paths2.map((path) => normalizeIgnorePath(projectPath, path)).filter(Boolean))].sort();
39546
+ const normalizedPaths = [...new Set(paths5.map((path) => normalizeIgnorePath(projectPath, path)).filter(Boolean))].sort();
39107
39547
  let existingContent = "";
39108
39548
  try {
39109
- existingContent = await fs27.readFile(ignoreFilePath, "utf8");
39549
+ existingContent = await fs31.readFile(ignoreFilePath, "utf8");
39110
39550
  } catch {
39111
39551
  existingContent = "";
39112
39552
  }
39113
39553
  const updatedContent = updateManagedBlock(existingContent, normalizedPaths);
39114
- await fs27.mkdir(dirname6(ignoreFilePath), { recursive: true });
39115
- await fs27.writeFile(ignoreFilePath, updatedContent, "utf8");
39554
+ await fs31.mkdir(dirname6(ignoreFilePath), { recursive: true });
39555
+ await fs31.writeFile(ignoreFilePath, updatedContent, "utf8");
39116
39556
  return ignoreFilePath;
39117
39557
  }
39118
39558
  async function removeManagedIgnoreBlock(projectPath, options2 = {}) {
39119
- const ignoreFile = options2.local ? join7(".git", "info", "exclude") : ".gitignore";
39120
- const ignoreFilePath = join7(projectPath, ignoreFile);
39559
+ const ignoreFile = options2.local ? join8(".git", "info", "exclude") : ".gitignore";
39560
+ const ignoreFilePath = join8(projectPath, ignoreFile);
39121
39561
  let content;
39122
39562
  try {
39123
- content = await fs27.readFile(ignoreFilePath, "utf8");
39563
+ content = await fs31.readFile(ignoreFilePath, "utf8");
39124
39564
  } catch {
39125
39565
  return false;
39126
39566
  }
@@ -39136,13 +39576,13 @@ async function removeManagedIgnoreBlock(projectPath, options2 = {}) {
39136
39576
  const afterBlock = content.slice(endIndex + END_MARKER.length).replace(/^\n+/, "");
39137
39577
  let nextContent = `${beforeBlock}${afterBlock}`.replace(/\n{3,}/g, "\n\n").replace(/^\n+/, "");
39138
39578
  if (nextContent.trim() === "") {
39139
- await fs27.rm(ignoreFilePath, { force: true }).catch(() => {
39579
+ await fs31.rm(ignoreFilePath, { force: true }).catch(() => {
39140
39580
  });
39141
39581
  } else {
39142
39582
  if (!nextContent.endsWith("\n")) {
39143
39583
  nextContent += "\n";
39144
39584
  }
39145
- await fs27.writeFile(ignoreFilePath, nextContent, "utf8");
39585
+ await fs31.writeFile(ignoreFilePath, nextContent, "utf8");
39146
39586
  }
39147
39587
  return true;
39148
39588
  }
@@ -39153,12 +39593,12 @@ var END_MARKER = "# END AgentInit Generated Files";
39153
39593
  init_agentManager();
39154
39594
  init_skillsManager();
39155
39595
  init_fs();
39156
- import {dirname as dirname7, join as join8} from "path";
39596
+ import {dirname as dirname7, join as join9} from "path";
39157
39597
  async function discoverProjectSkills(projectPath, skillsManager4) {
39158
39598
  const sources = [];
39159
39599
  const skills = new Map;
39160
39600
  for (const sourceDir of PROJECT_SKILL_SOURCE_DIRS) {
39161
- const absoluteSourceDir = join8(projectPath, sourceDir);
39601
+ const absoluteSourceDir = join9(projectPath, sourceDir);
39162
39602
  if (!await fileExists(absoluteSourceDir)) {
39163
39603
  continue;
39164
39604
  }
@@ -39276,7 +39716,7 @@ async function applyProjectCommand(options2) {
39276
39716
  const cwd = process.cwd();
39277
39717
  const agentManager7 = new AgentManager;
39278
39718
  let managedState3 = null;
39279
- logger.title("\uD83D\uDD27 AgentInit - Apply");
39719
+ logger.titleBox("AgentInit Apply");
39280
39720
  if (options2.dryRun) {
39281
39721
  logger.info("Running in dry-run mode - no files will be modified");
39282
39722
  }
@@ -39400,7 +39840,7 @@ async function applyProjectCommand(options2) {
39400
39840
  }
39401
39841
  async function applyCommand(args) {
39402
39842
  const cwd = process.cwd();
39403
- logger.title("\uD83D\uDD27 AgentInit - Apply Configuration");
39843
+ logger.titleBox("AgentInit Apply Configuration");
39404
39844
  const hasMcpArgs = args.some((arg) => arg.startsWith("--mcp-"));
39405
39845
  const hasRulesArgs = args.some((arg) => arg === "--rules" || arg === "--rule-raw" || arg === "--rules-file" || arg === "--rules-remote");
39406
39846
  const clientArgIndex = args.findIndex((arg) => arg === "--client" || arg === "--agent");
@@ -39805,7 +40245,7 @@ var LEGACY_APPLY_FLAGS = new Set([
39805
40245
  init_agentManager();
39806
40246
  async function verifyMcpCommand(args) {
39807
40247
  const cwd = process.cwd();
39808
- logger.title("\uD83D\uDD0D AgentInit - MCP Verification");
40248
+ logger.titleBox("AgentInit MCP Verification");
39809
40249
  const hasAll = args.includes("--all");
39810
40250
  const mcpNameIndex = args.findIndex((arg) => arg === "--mcp-name");
39811
40251
  const mcpName = mcpNameIndex >= 0 && mcpNameIndex + 1 < args.length ? args[mcpNameIndex + 1] : null;
@@ -40009,7 +40449,7 @@ async function verifyMcpCommand(args) {
40009
40449
  // dist/commands/revert.js
40010
40450
  async function revertCommand(options2) {
40011
40451
  const cwd = process.cwd();
40012
- logger.title("\u21A9\uFE0F AgentInit - Revert");
40452
+ logger.titleBox("AgentInit Revert");
40013
40453
  if (options2.dryRun) {
40014
40454
  logger.info("Running in dry-run mode - no files will be modified");
40015
40455
  }
@@ -40050,9 +40490,193 @@ async function revertCommand(options2) {
40050
40490
  }
40051
40491
  }
40052
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
+
40053
40677
  // dist/commands/skills.js
40054
40678
  var import_prompts2 = __toESM(require_prompts3(), 1);
40055
- import {homedir as homedir5} from "os";
40679
+ import {homedir as homedir6} from "os";
40056
40680
  import {relative as relative7, resolve as resolve12} from "path";
40057
40681
  init_skillsManager();
40058
40682
  init_marketplaceRegistry();
@@ -40060,8 +40684,8 @@ init_agentManager();
40060
40684
  function registerSkillsCommand(program2) {
40061
40685
  const marketplaceHelp = getMarketplaceIds().join(", ");
40062
40686
  const skills = program2.command("skills").description("Manage agent skills");
40063
- skills.command("add <source>").description("Add skills from a marketplace, GitHub repo, or local path").option("--from <marketplace>", `Marketplace source override (available: ${marketplaceHelp})`).option("-g, --global", "Install skills globally").option("-a, --agent <agents...>", "Target specific agent(s)").option("-s, --skill <names...>", "Install only specific skills by name").option("-l, --list", "List available skills from the source without installing").option("--copy", "Copy skill files instead of symlinking").option("-y, --yes", "Skip prompts and auto-detect project agents only").action(async (source, options2) => {
40064
- logger.title("\uD83D\uDCE6 AgentInit - Skills");
40687
+ skills.command("add <source>").description("Add skills from a marketplace, GitHub repo, or local path").option("--from <marketplace>", `Marketplace source override (available: ${marketplaceHelp})`).option("-g, --global", "Install skills globally").option("-a, --agent <agents...>", "Target specific agent(s)").option("-s, --skill <names...>", "Install only specific skills by name").option("-l, --list", "List available skills from the source without installing").option("--copy", "Copy skill files instead of symlinking").option("-y, --yes", "Skip prompts and auto-detect project-configured agents only").action(async (source, options2) => {
40688
+ logger.titleBox("AgentInit Skills");
40065
40689
  const agentManager9 = new AgentManager;
40066
40690
  const skillsManager5 = new SkillsManager(agentManager9);
40067
40691
  if (options2.list) {
@@ -40111,7 +40735,7 @@ function registerSkillsCommand(program2) {
40111
40735
  }
40112
40736
  });
40113
40737
  skills.command("list").alias("ls").description("List installed skills").option("-g, --global", "List only global skills").option("-a, --agent <agents...>", "Filter by specific agent(s)").action(async (options2) => {
40114
- logger.title("\uD83D\uDCE6 AgentInit - Skills");
40738
+ logger.titleBox("AgentInit Skills");
40115
40739
  const agentManager9 = new AgentManager;
40116
40740
  const skillsManager5 = new SkillsManager(agentManager9);
40117
40741
  const installed = await skillsManager5.listInstalled(process.cwd(), {
@@ -40151,7 +40775,7 @@ function registerSkillsCommand(program2) {
40151
40775
  }
40152
40776
  });
40153
40777
  skills.command("remove [names...]").alias("rm").description("Remove installed skills by name").option("-g, --global", "Remove from global scope").option("-a, --agent <agents...>", "Target specific agent(s)").option("-y, --yes", "Skip confirmation prompts").action(async (names, options2) => {
40154
- logger.title("\uD83D\uDCE6 AgentInit - Skills");
40778
+ logger.titleBox("AgentInit Skills");
40155
40779
  if (!names || names.length === 0) {
40156
40780
  if (!options2.yes) {
40157
40781
  logger.error("Please specify skill name(s) to remove.");
@@ -40337,7 +40961,7 @@ var prependCanonicalGlobalGroup = function(agentManager9, projectPath, groups) {
40337
40961
  var formatSkillsDir = function(projectPath, dir) {
40338
40962
  const normalizedDir = dir.replace(/\\/g, "/").replace(/\/?$/, "/");
40339
40963
  const normalizedProjectPath = projectPath.replace(/\\/g, "/");
40340
- const normalizedHome = homedir5().replace(/\\/g, "/");
40964
+ const normalizedHome = homedir6().replace(/\\/g, "/");
40341
40965
  if (normalizedDir.startsWith(`${normalizedProjectPath}/`)) {
40342
40966
  return `${relative7(projectPath, dir).replace(/\\/g, "/").replace(/\/?$/, "/")}`;
40343
40967
  }
@@ -40348,7 +40972,7 @@ var formatSkillsDir = function(projectPath, dir) {
40348
40972
  };
40349
40973
  var formatPromptPath = function(path) {
40350
40974
  const normalizedPath = path.replace(/\\/g, "/").replace(/\/?$/, "/");
40351
- const normalizedHome = homedir5().replace(/\\/g, "/");
40975
+ const normalizedHome = homedir6().replace(/\\/g, "/");
40352
40976
  if (normalizedPath === `${normalizedHome}/`) {
40353
40977
  return "~/";
40354
40978
  }
@@ -40358,7 +40982,7 @@ var formatPromptPath = function(path) {
40358
40982
  return normalizedPath;
40359
40983
  };
40360
40984
  var getCanonicalGlobalSkillsDir = function() {
40361
- return resolve12(homedir5(), ".agents/skills");
40985
+ return resolve12(homedir6(), ".agents/skills");
40362
40986
  };
40363
40987
  var getCanonicalGlobalSkillsDisplayPath = function() {
40364
40988
  return formatPromptPath(getCanonicalGlobalSkillsDir());
@@ -41073,7 +41697,7 @@ var buildAppliedRules = function(sections) {
41073
41697
  function registerRulesCommand(program2) {
41074
41698
  const rules = program2.command("rules").description("Manage agent rules");
41075
41699
  rules.command("add").description("Add rules to agent configuration").option("-t, --template <templates...>", "Rule templates to apply (comma-separated values accepted)").option("-r, --raw <rules...>", "Raw rule strings").option("-f, --file <path>", "Load rules from a file").option("--remote <url>", "Load rules from a remote URL").option("--auth <token>", "Authentication token for remote rules (Bearer token)").option("-a, --agent <agents...>", "Target specific agent(s)").option("-g, --global", "Apply rules globally").action(async (options2) => {
41076
- logger.title("\uD83D\uDCCF AgentInit - Rules");
41700
+ logger.titleBox("AgentInit Rules");
41077
41701
  const cwd = process.cwd();
41078
41702
  const isGlobal = !!options2.global;
41079
41703
  const templates = [];
@@ -41201,7 +41825,7 @@ function registerRulesCommand(program2) {
41201
41825
  }
41202
41826
  });
41203
41827
  rules.command("list").alias("ls").description("List rules configured for each agent").option("-a, --agent <agents...>", "Filter by specific agent(s)").option("-g, --global", "List global rules").action(async (options2) => {
41204
- logger.title("\uD83D\uDCCF AgentInit - Rules");
41828
+ logger.titleBox("AgentInit Rules");
41205
41829
  const cwd = process.cwd();
41206
41830
  const isGlobal = !!options2.global;
41207
41831
  const agentManager11 = new AgentManager;
@@ -41241,7 +41865,7 @@ function registerRulesCommand(program2) {
41241
41865
  }
41242
41866
  });
41243
41867
  rules.command("remove [names...]").alias("rm").description("Remove rule sections by template ID (e.g. git, write_docs)").option("-a, --agent <agents...>", "Target specific agent(s)").option("-g, --global", "Remove from global rules").action(async (names, options2) => {
41244
- logger.title("\uD83D\uDCCF AgentInit - Rules");
41868
+ logger.titleBox("AgentInit Rules");
41245
41869
  if (!names || names.length === 0) {
41246
41870
  logger.error("Please specify rule section name(s) to remove.");
41247
41871
  logger.info("Usage: agentinit rules remove <name...>");
@@ -41302,11 +41926,12 @@ var import_prompts3 = __toESM(require_prompts3(), 1);
41302
41926
  import {dirname as dirname8, relative as relative8} from "path";
41303
41927
  init_pluginManager();
41304
41928
  init_agentManager();
41929
+ init_marketplaceRegistry();
41305
41930
  function registerPluginsCommand(program2) {
41306
41931
  const marketplaceHelp = new PluginManager().getMarketplaceIds().join(", ");
41307
41932
  const plugins = program2.command("plugins").description("Install agent-agnostic plugins from any marketplace or source");
41308
- 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 all agents").action(async (source, options2) => {
41309
- logger.title("\uD83D\uDD0C AgentInit - Plugins");
41933
+ 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) => {
41934
+ logger.titleBox("AgentInit Plugins");
41310
41935
  const agentManager12 = new AgentManager;
41311
41936
  const pluginManager2 = new PluginManager(agentManager12);
41312
41937
  if (options2.list) {
@@ -41422,16 +42047,16 @@ function registerPluginsCommand(program2) {
41422
42047
  }
41423
42048
  });
41424
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) => {
41425
- logger.title("\uD83D\uDD0C AgentInit - Plugin Search");
42050
+ logger.titleBox("AgentInit Plugin Search");
41426
42051
  const pluginManager2 = new PluginManager;
41427
- if (!options2.from) {
42052
+ const registryId = options2.from || getConfiguredDefaultMarketplaceId();
42053
+ if (!registryId) {
41428
42054
  logger.info(`Please specify a marketplace with --from <marketplace>. Available: ${marketplaceHelp}`);
41429
42055
  logger.info("Examples:");
41430
42056
  logger.info(" agentinit plugins search --from claude");
41431
42057
  logger.info(" agentinit plugins search code-review --from claude");
41432
42058
  return;
41433
42059
  }
41434
- const registryId = options2.from;
41435
42060
  const spinner = ora(`Fetching ${registryId} marketplace...`).start();
41436
42061
  try {
41437
42062
  const results = await pluginManager2.listMarketplacePlugins(registryId, query, options2.category);
@@ -41463,7 +42088,7 @@ function registerPluginsCommand(program2) {
41463
42088
  }
41464
42089
  });
41465
42090
  plugins.command("list").alias("ls").description("List installed plugins").option("-a, --agent <agents...>", "Filter by specific agent(s)").option("-g, --global", "List global plugins").action(async (options2) => {
41466
- logger.title("\uD83D\uDD0C AgentInit - Installed Plugins");
42091
+ logger.titleBox("AgentInit Installed Plugins");
41467
42092
  const pluginManager2 = new PluginManager;
41468
42093
  const installed = await pluginManager2.listPlugins(process.cwd(), {
41469
42094
  global: options2.global,
@@ -41499,7 +42124,7 @@ function registerPluginsCommand(program2) {
41499
42124
  }
41500
42125
  });
41501
42126
  plugins.command("remove <name>").alias("rm").description("Remove an installed plugin").option("-a, --agent <agents...>", "Target specific agent(s)").option("-g, --global", "Remove from global scope").option("-y, --yes", "Skip confirmation prompts").action(async (name, options2) => {
41502
- logger.title("\uD83D\uDD0C AgentInit - Remove Plugin");
42127
+ logger.titleBox("AgentInit Remove Plugin");
41503
42128
  const pluginManager2 = new PluginManager;
41504
42129
  const spinner = ora(`Removing plugin "${name}"...`).start();
41505
42130
  try {
@@ -41549,28 +42174,40 @@ var getPortableComponentSummary = function(preview) {
41549
42174
  return parts.length > 0 ? parts.join(", ") : "No portable components";
41550
42175
  };
41551
42176
  var getSourceWarnings = function(warnings) {
41552
- const lines = [];
42177
+ const items = [];
41553
42178
  for (const warning of warnings) {
41554
42179
  const missingMatch = warning.match(/^Plugin "(.+)" not found in (.+) marketplace\.$/);
41555
42180
  if (missingMatch) {
41556
- lines.push(`${missingMatch[2]} marketplace does not contain "${missingMatch[1]}".`);
42181
+ items.push({
42182
+ type: "marketplace-miss",
42183
+ text: `${missingMatch[2]} marketplace does not contain "${missingMatch[1]}".`
42184
+ });
41557
42185
  continue;
41558
42186
  }
41559
- const fallbackMatch = warning.match(/^Marketplace lookup failed; trying unverified GitHub repository (.+) instead\.$/);
42187
+ const fallbackMatch = warning.match(/^Marketplace lookup failed; trying (verified|unverified) GitHub repository (.+) instead\.$/);
41560
42188
  if (fallbackMatch) {
41561
- lines.push(`Falling back to unverified GitHub repository: ${fallbackMatch[1]}`);
42189
+ items.push({
42190
+ type: fallbackMatch[1] === "verified" ? "fallback-verified" : "fallback-unverified",
42191
+ text: `${fallbackMatch[1] === "verified" ? "Verified" : "Unverified"} GitHub repository: ${fallbackMatch[2]}`
42192
+ });
41562
42193
  continue;
41563
42194
  }
41564
42195
  const bundleMatch = warning.match(/^Source "(.+)" is a Claude Code marketplace bundle; using bundled plugin "(.+)"\.$/);
41565
42196
  if (bundleMatch) {
41566
- lines.push(`Claude Code marketplace bundle detected: ${bundleMatch[1]}`);
41567
- lines.push(`Using bundled plugin "${bundleMatch[2]}".`);
42197
+ items.push({
42198
+ type: "bundle-detected",
42199
+ text: `Claude Code marketplace bundle detected: ${bundleMatch[1]}`
42200
+ });
42201
+ items.push({
42202
+ type: "bundle-using",
42203
+ text: `Using bundled plugin "${bundleMatch[2]}".`
42204
+ });
41568
42205
  }
41569
42206
  }
41570
- return lines;
42207
+ return items;
41571
42208
  };
41572
42209
  var getRemainingWarnings = function(warnings) {
41573
- return warnings.filter((warning) => !/^Plugin "(.+)" not found in (.+) marketplace\.$/.test(warning) && !/^Marketplace lookup failed; trying unverified GitHub repository (.+) instead\.$/.test(warning) && !/^Source "(.+)" is a Claude Code marketplace bundle; using bundled plugin "(.+)"\.$/.test(warning) && !/^Hooks \(hooks\/\) are Claude Code-specific$/.test(warning) && !/^Agent definitions \(agents\/\) are Claude Code-specific$/.test(warning) && !/^Claude Code-native plugin components detected \((.+)\);/.test(warning) && !/^Claude Code-native plugin components detected \((.+)\), but no Claude Code target was selected; skipped native install\.$/.test(warning) && warning !== "Reload plugins in Claude Code with /reload-plugins to activate native plugin components.");
42210
+ return warnings.filter((warning) => !/^Plugin "(.+)" not found in (.+) marketplace\.$/.test(warning) && !/^Marketplace lookup failed; trying (verified|unverified) GitHub repository (.+) instead\.$/.test(warning) && !/^Source "(.+)" is a Claude Code marketplace bundle; using bundled plugin "(.+)"\.$/.test(warning) && !/^Hooks \(hooks\/\) are Claude Code-specific$/.test(warning) && !/^Agent definitions \(agents\/\) are Claude Code-specific$/.test(warning) && !/^Claude Code-native plugin components detected \((.+)\);/.test(warning) && !/^Claude Code-native plugin components detected \((.+)\), but no Claude Code target was selected; skipped native install\.$/.test(warning) && warning !== "Reload plugins in Claude Code with /reload-plugins to activate native plugin components.");
41574
42211
  };
41575
42212
  var getNativeCompatibilityWarning = function(previewOrResult) {
41576
42213
  if ("nativePreview" in previewOrResult) {
@@ -41606,33 +42243,67 @@ var renderPluginWarnings = function(previewOrResult, projectPath) {
41606
42243
  const allWarnings = "nativePreview" in previewOrResult ? previewOrResult.plugin.warnings : previewOrResult.warnings;
41607
42244
  const sourceWarnings = getSourceWarnings(previewOrResult.plugin.warnings);
41608
42245
  if (sourceWarnings.length > 0) {
41609
- console.log("");
41610
- logger.subtitle("Source");
41611
- for (const warning of sourceWarnings) {
41612
- logger.warn(` ${warning}`);
42246
+ logger.section("Source");
42247
+ const lastIdx = sourceWarnings.length - 1;
42248
+ for (let i = 0;i < sourceWarnings.length; i++) {
42249
+ const item = sourceWarnings[i];
42250
+ const isLast = i === lastIdx;
42251
+ if (item.type === "marketplace-miss") {
42252
+ logger.tree(yellow("\u26A0") + ` ${item.text}`, isLast);
42253
+ } else if (item.type === "fallback-verified") {
42254
+ logger.tree(green("\u2713") + ` ${item.text}`, isLast);
42255
+ } else if (item.type === "fallback-unverified") {
42256
+ logger.tree(yellow("\u26A0") + ` ${item.text}`, isLast);
42257
+ } else if (item.type === "bundle-detected") {
42258
+ logger.tree(orange("\u2713") + ` ${orange(item.text)}`, isLast);
42259
+ } else if (item.type === "bundle-using") {
42260
+ logger.tree(green("\u2713") + ` ${item.text}`, isLast);
42261
+ }
41613
42262
  }
41614
42263
  }
41615
42264
  const nativeWarning = getNativeCompatibilityWarning(previewOrResult);
41616
42265
  if (nativeWarning) {
41617
- console.log("");
41618
- logger.subtitle("Compatibility");
41619
- logger.warn(` Claude Code-only components detected: ${nativeWarning.features.join(", ")}`);
42266
+ logger.section("Compatibility");
42267
+ const lines = [];
42268
+ lines.push({
42269
+ text: orange("\u26A0") + ` ${orange("Claude Code")}-only components detected: ${dim(nativeWarning.features.join(", "))}`,
42270
+ isLast: false
42271
+ });
41620
42272
  if (nativeWarning.installPath) {
41621
- logger.info(` Claude native install path: ${formatPathForDisplay(nativeWarning.installPath, projectPath)}`);
42273
+ lines.push({
42274
+ text: orange("\u2139") + ` ${orange("Claude")} native install path: ${dim(formatPathForDisplay(nativeWarning.installPath, projectPath))}`,
42275
+ isLast: false
42276
+ });
41622
42277
  }
41623
42278
  if (nativeWarning.skipped) {
41624
- logger.warn(" No Claude Code target selected. Native Claude installation was skipped.");
42279
+ lines.push({
42280
+ text: orange("\u26A0") + ` No ${orange("Claude Code")} target selected. Native installation was skipped.`,
42281
+ isLast: true
42282
+ });
41625
42283
  } else {
41626
- logger.info(" Non-Claude targets install only the portable skills and MCP servers.");
41627
- logger.info("nativePreview" in previewOrResult ? " If you install to Claude Code, reload plugins with /reload-plugins afterward." : " Reload plugins in Claude Code with /reload-plugins after install.");
42284
+ lines.push({
42285
+ text: cyan("\u2139") + " Non-Claude targets install only the portable skills and MCP servers.",
42286
+ isLast: false
42287
+ });
42288
+ const reloadMsg = "nativePreview" in previewOrResult ? ` If you install to ${orange("Claude Code")}, reload plugins with ${bold("/reload-plugins")} afterward.` : ` Reload plugins in ${orange("Claude Code")} with ${bold("/reload-plugins")} after install.`;
42289
+ lines.push({
42290
+ text: orange("\u2139") + reloadMsg,
42291
+ isLast: true
42292
+ });
42293
+ }
42294
+ if (lines.length > 0) {
42295
+ lines[lines.length - 1].isLast = true;
42296
+ }
42297
+ for (const line of lines) {
42298
+ logger.tree(line.text, line.isLast);
41628
42299
  }
41629
42300
  }
41630
42301
  const otherWarnings = getRemainingWarnings(allWarnings);
41631
42302
  if (otherWarnings.length > 0) {
41632
- console.log("");
41633
- logger.subtitle("Warnings");
41634
- for (const warning of otherWarnings) {
41635
- logger.warn(` ${warning}`);
42303
+ logger.section("Warnings");
42304
+ const lastIdx = otherWarnings.length - 1;
42305
+ for (let i = 0;i < otherWarnings.length; i++) {
42306
+ logger.tree(yellow("\u26A0") + ` ${otherWarnings[i]}`, i === lastIdx);
41636
42307
  }
41637
42308
  }
41638
42309
  };
@@ -41646,34 +42317,55 @@ var renderInstalledComponents = function(result, agentManager12, projectPath) {
41646
42317
  skillGroups.set(targetDir, existing);
41647
42318
  }
41648
42319
  if (skillGroups.size > 0) {
41649
- logger.subtitle("Skills");
41650
- for (const [targetDir, data] of skillGroups) {
41651
- logger.info(` ${getAgentLabel([...data.agents], agentManager12)}: ${green(String(data.skillNames.size))} skill(s) -> ${formatPathForDisplay(targetDir, projectPath)}`);
41652
- }
42320
+ logger.section("Skills");
42321
+ const entries = [...skillGroups.entries()];
41653
42322
  const copiedFallbacks = result.skills.installed.filter((item) => item.symlinkFailed);
42323
+ const totalItems = entries.length + (copiedFallbacks.length > 0 ? 1 : 0);
42324
+ let idx = 0;
42325
+ for (const [targetDir, data] of entries) {
42326
+ idx++;
42327
+ const agentLabel = colorAgentLabel([...data.agents], agentManager12);
42328
+ logger.tree(`${agentLabel}: ${green(String(data.skillNames.size))} skill(s) -> ${dim(formatPathForDisplay(targetDir, projectPath))}`, idx === totalItems);
42329
+ }
41654
42330
  if (copiedFallbacks.length > 0) {
41655
- logger.warn(` Symlink creation failed for ${copiedFallbacks.length} skill install(s); copied the files instead.`);
42331
+ logger.tree(yellow("\u26A0") + ` Symlink creation failed for ${copiedFallbacks.length} skill install(s); copied the files instead.`, true);
41656
42332
  }
41657
42333
  }
41658
42334
  if (result.mcpServers.applied.length > 0) {
41659
- logger.subtitle("MCP");
42335
+ logger.section("MCP Servers");
41660
42336
  const byAgent = new Map;
41661
42337
  for (const item of result.mcpServers.applied) {
41662
42338
  const list = byAgent.get(item.agent) || [];
41663
42339
  list.push(item.name);
41664
42340
  byAgent.set(item.agent, list);
41665
42341
  }
41666
- for (const [agent, servers] of byAgent) {
41667
- logger.info(` ${agentManager12.getAgentById(agent)?.name || agent}: ${cyan(String(servers.length))} server(s) [${servers.join(", ")}]`);
42342
+ const entries = [...byAgent.entries()];
42343
+ for (let i = 0;i < entries.length; i++) {
42344
+ const [agent, servers] = entries[i];
42345
+ const agentName = agentManager12.getAgentById(agent)?.name || agent;
42346
+ const coloredName = isClaudeAgent(agent) ? orange(agentName) : agentName;
42347
+ logger.tree(`${coloredName}: ${cyan(String(servers.length))} server(s) [${servers.join(", ")}]`, i === entries.length - 1);
41668
42348
  }
41669
42349
  }
41670
42350
  if (result.nativePlugins.installed.length > 0) {
41671
- logger.subtitle("Native");
41672
- for (const nativePlugin of result.nativePlugins.installed) {
41673
- logger.info(` ${agentManager12.getAgentById(nativePlugin.agent)?.name || nativePlugin.agent}: ${formatPathForDisplay(nativePlugin.installPath, projectPath)}`);
42351
+ logger.section("Native Install");
42352
+ for (let i = 0;i < result.nativePlugins.installed.length; i++) {
42353
+ const nativePlugin = result.nativePlugins.installed[i];
42354
+ const agentName = agentManager12.getAgentById(nativePlugin.agent)?.name || nativePlugin.agent;
42355
+ const coloredName = isClaudeAgent(nativePlugin.agent) ? orange(agentName) : agentName;
42356
+ logger.tree(`${coloredName}: ${dim(formatPathForDisplay(nativePlugin.installPath, projectPath))}`, i === result.nativePlugins.installed.length - 1);
41674
42357
  }
41675
42358
  }
41676
42359
  };
42360
+ var isClaudeAgent = function(agentId) {
42361
+ return agentId === "claude" || agentId.startsWith("claude-");
42362
+ };
42363
+ var colorAgentLabel = function(agentIds, agentManager12) {
42364
+ return agentIds.map((agentId) => {
42365
+ const name = agentManager12.getAgentById(agentId)?.name || agentId;
42366
+ return isClaudeAgent(agentId) ? orange(name) : name;
42367
+ }).join(", ");
42368
+ };
41677
42369
  var buildGlobalPluginGroups = function(agentManager12, projectPath) {
41678
42370
  const dirToAgents = new Map;
41679
42371
  for (const agent of agentManager12.getAllAgents()) {
@@ -41779,6 +42471,7 @@ registerSkillsCommand(program2);
41779
42471
  registerMcpCommand(program2);
41780
42472
  registerRulesCommand(program2);
41781
42473
  registerPluginsCommand(program2);
42474
+ registerConfigCommand(program2);
41782
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);
41783
42476
  program2.command("detect").description("Detect current project stack and existing agent configurations").option("-v, --verbose", "Show detailed detection results").action(detectCommand);
41784
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);