rulesync 0.69.0 → 0.70.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 (4) hide show
  1. package/README.md +116 -9
  2. package/dist/index.cjs +851 -1009
  3. package/dist/index.js +846 -1004
  4. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli/index.ts
4
- import { join as join11 } from "path";
4
+ import { join as join49 } from "path";
5
5
  import { fileURLToPath } from "url";
6
6
  import { Command } from "commander";
7
7
 
@@ -194,14 +194,6 @@ async function listDirectoryFiles(dir) {
194
194
  return [];
195
195
  }
196
196
  }
197
- async function findFiles(dir, extension = ".md") {
198
- try {
199
- const files = await readdir(dir);
200
- return files.filter((file) => file.endsWith(extension)).map((file) => join(dir, file));
201
- } catch {
202
- return [];
203
- }
204
- }
205
197
  async function findFilesByGlobs(globs) {
206
198
  return globSync(globs);
207
199
  }
@@ -251,7 +243,7 @@ async function initConfig() {
251
243
  import { intersection } from "es-toolkit";
252
244
 
253
245
  // src/commands/commands-processor.ts
254
- import { basename as basename6, join as join3 } from "path";
246
+ import { basename as basename6, join as join7 } from "path";
255
247
  import { z as z7 } from "zod/mini";
256
248
 
257
249
  // src/types/feature-processor.ts
@@ -284,15 +276,48 @@ var FeatureProcessor = class {
284
276
  };
285
277
 
286
278
  // src/commands/claudecode-command.ts
287
- import { basename as basename3, join as join2 } from "path";
279
+ import { basename as basename3, join as join4 } from "path";
288
280
  import { z as z4 } from "zod/mini";
289
281
 
290
282
  // src/utils/frontmatter.ts
291
283
  import matter from "gray-matter";
284
+ function isPlainObject(value) {
285
+ if (value === null || typeof value !== "object") return false;
286
+ const prototype = Object.getPrototypeOf(value);
287
+ return prototype === Object.prototype || prototype === null;
288
+ }
289
+ function deepRemoveNullishValue(value) {
290
+ if (value === null || value === void 0) {
291
+ return void 0;
292
+ }
293
+ if (Array.isArray(value)) {
294
+ const cleanedArray = value.map((item) => deepRemoveNullishValue(item)).filter((item) => item !== void 0);
295
+ return cleanedArray;
296
+ }
297
+ if (isPlainObject(value)) {
298
+ const result = {};
299
+ for (const [key, val] of Object.entries(value)) {
300
+ const cleaned = deepRemoveNullishValue(val);
301
+ if (cleaned !== void 0) {
302
+ result[key] = cleaned;
303
+ }
304
+ }
305
+ return result;
306
+ }
307
+ return value;
308
+ }
309
+ function deepRemoveNullishObject(obj) {
310
+ const result = {};
311
+ for (const [key, val] of Object.entries(obj)) {
312
+ const cleaned = deepRemoveNullishValue(val);
313
+ if (cleaned !== void 0) {
314
+ result[key] = cleaned;
315
+ }
316
+ }
317
+ return result;
318
+ }
292
319
  function stringifyFrontmatter(body, frontmatter) {
293
- const cleanFrontmatter = Object.fromEntries(
294
- Object.entries(frontmatter).filter(([, value]) => value !== null && value !== void 0)
295
- );
320
+ const cleanFrontmatter = deepRemoveNullishObject(frontmatter);
296
321
  return matter.stringify(body, cleanFrontmatter);
297
322
  }
298
323
  function parseFrontmatter(content) {
@@ -301,9 +326,18 @@ function parseFrontmatter(content) {
301
326
  }
302
327
 
303
328
  // src/commands/rulesync-command.ts
304
- import { basename as basename2 } from "path";
329
+ import { basename as basename2, join as join3 } from "path";
305
330
  import { z as z3 } from "zod/mini";
306
331
 
332
+ // src/constants/paths.ts
333
+ import { join as join2 } from "path";
334
+ var RULESYNC_DIR = ".rulesync";
335
+ var RULESYNC_RULES_DIR = join2(".rulesync", "rules");
336
+ var RULESYNC_RULES_DIR_LEGACY = ".rulesync";
337
+ var RULESYNC_MCP_FILE = join2(".rulesync", ".mcp.json");
338
+ var RULESYNC_COMMANDS_DIR = join2(".rulesync", "commands");
339
+ var RULESYNC_SUBAGENTS_DIR = join2(".rulesync", "subagents");
340
+
307
341
  // src/types/ai-file.ts
308
342
  import path from "path";
309
343
  var AiFile = class {
@@ -341,7 +375,7 @@ var AiFile = class {
341
375
  }
342
376
  }
343
377
  }
344
- static async fromFilePath(_params) {
378
+ static async fromFile(_params) {
345
379
  throw new Error("Please implement this method in the subclass.");
346
380
  }
347
381
  getBaseDir() {
@@ -369,13 +403,10 @@ var AiFile = class {
369
403
 
370
404
  // src/types/rulesync-file.ts
371
405
  var RulesyncFile = class extends AiFile {
372
- static async fromFilePath(_params) {
373
- throw new Error("Please implement this method in the subclass.");
374
- }
375
406
  static async fromFile(_params) {
376
407
  throw new Error("Please implement this method in the subclass.");
377
408
  }
378
- static async fromLegacyFile(_params) {
409
+ static async fromFileLegacy(_params) {
379
410
  throw new Error("Please implement this method in the subclass.");
380
411
  }
381
412
  };
@@ -419,14 +450,16 @@ var RulesyncCommand = class _RulesyncCommand extends RulesyncFile {
419
450
  return { success: false, error: result.error };
420
451
  }
421
452
  }
422
- static async fromFilePath({ filePath }) {
423
- const fileContent = await readFileContent(filePath);
453
+ static async fromFile({
454
+ relativeFilePath
455
+ }) {
456
+ const fileContent = await readFileContent(join3(RULESYNC_COMMANDS_DIR, relativeFilePath));
424
457
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
425
458
  const result = RulesyncCommandFrontmatterSchema.safeParse(frontmatter);
426
459
  if (!result.success) {
427
- throw new Error(`Invalid frontmatter in ${filePath}: ${result.error.message}`);
460
+ throw new Error(`Invalid frontmatter in ${relativeFilePath}: ${result.error.message}`);
428
461
  }
429
- const filename = basename2(filePath);
462
+ const filename = basename2(relativeFilePath);
430
463
  return new _RulesyncCommand({
431
464
  baseDir: ".",
432
465
  relativeDirPath: ".rulesync/commands",
@@ -452,7 +485,7 @@ var ToolCommand = class extends AiFile {
452
485
  * @param params - Parameters including the file path to load
453
486
  * @returns Promise resolving to a concrete ToolCommand instance
454
487
  */
455
- static async fromFilePath(_params) {
488
+ static async fromFile(_params) {
456
489
  throw new Error("Please implement this method in the subclass.");
457
490
  }
458
491
  /**
@@ -529,7 +562,7 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
529
562
  baseDir,
530
563
  frontmatter: claudecodeFrontmatter,
531
564
  body,
532
- relativeDirPath: join2(".claude", "commands"),
565
+ relativeDirPath: join4(".claude", "commands"),
533
566
  relativeFilePath: rulesyncCommand.getRelativeFilePath(),
534
567
  validate
535
568
  });
@@ -545,11 +578,12 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
545
578
  return { success: false, error: result.error };
546
579
  }
547
580
  }
548
- static async fromFilePath({
581
+ static async fromFile({
549
582
  baseDir = ".",
550
- filePath,
583
+ relativeFilePath,
551
584
  validate = true
552
585
  }) {
586
+ const filePath = join4(baseDir, ".claude", "commands", relativeFilePath);
553
587
  const fileContent = await readFileContent(filePath);
554
588
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
555
589
  const result = ClaudecodeCommandFrontmatterSchema.safeParse(frontmatter);
@@ -559,7 +593,7 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
559
593
  return new _ClaudecodeCommand({
560
594
  baseDir,
561
595
  relativeDirPath: ".claude/commands",
562
- relativeFilePath: basename3(filePath),
596
+ relativeFilePath: basename3(relativeFilePath),
563
597
  frontmatter: result.data,
564
598
  body: content.trim(),
565
599
  validate
@@ -568,7 +602,7 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
568
602
  };
569
603
 
570
604
  // src/commands/geminicli-command.ts
571
- import { basename as basename4 } from "path";
605
+ import { basename as basename4, join as join5 } from "path";
572
606
  import { parse as parseToml } from "smol-toml";
573
607
  import { z as z5 } from "zod/mini";
574
608
  var GeminiCliCommandFrontmatterSchema = z5.object({
@@ -654,16 +688,17 @@ ${geminiFrontmatter.prompt}
654
688
  validate
655
689
  });
656
690
  }
657
- static async fromFilePath({
691
+ static async fromFile({
658
692
  baseDir = ".",
659
- filePath,
693
+ relativeFilePath,
660
694
  validate = true
661
695
  }) {
696
+ const filePath = join5(baseDir, ".gemini", "commands", relativeFilePath);
662
697
  const fileContent = await readFileContent(filePath);
663
698
  return new _GeminiCliCommand({
664
699
  baseDir,
665
700
  relativeDirPath: ".gemini/commands",
666
- relativeFilePath: basename4(filePath),
701
+ relativeFilePath: basename4(relativeFilePath),
667
702
  fileContent,
668
703
  validate
669
704
  });
@@ -676,26 +711,10 @@ ${geminiFrontmatter.prompt}
676
711
  return { success: false, error: error instanceof Error ? error : new Error(String(error)) };
677
712
  }
678
713
  }
679
- async processContent(content, args) {
680
- let processedContent = content;
681
- processedContent = this.processArgumentPlaceholder(processedContent, args);
682
- return processedContent;
683
- }
684
- processArgumentPlaceholder(content, args) {
685
- if (content.includes("{{args}}")) {
686
- return content.replace(/\{\{args\}\}/g, args || "");
687
- }
688
- if (args) {
689
- return `${content}
690
-
691
- ${args}`;
692
- }
693
- return content;
694
- }
695
714
  };
696
715
 
697
716
  // src/commands/roo-command.ts
698
- import { basename as basename5 } from "path";
717
+ import { basename as basename5, join as join6 } from "path";
699
718
  import { optional, z as z6 } from "zod/mini";
700
719
  var RooCommandFrontmatterSchema = z6.object({
701
720
  description: z6.string(),
@@ -772,11 +791,12 @@ var RooCommand = class _RooCommand extends ToolCommand {
772
791
  return { success: false, error: result.error };
773
792
  }
774
793
  }
775
- static async fromFilePath({
794
+ static async fromFile({
776
795
  baseDir = ".",
777
- filePath,
796
+ relativeFilePath,
778
797
  validate = true
779
798
  }) {
799
+ const filePath = join6(baseDir, ".roo", "commands", relativeFilePath);
780
800
  const fileContent = await readFileContent(filePath);
781
801
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
782
802
  const result = RooCommandFrontmatterSchema.safeParse(frontmatter);
@@ -786,7 +806,7 @@ var RooCommand = class _RooCommand extends ToolCommand {
786
806
  return new _RooCommand({
787
807
  baseDir,
788
808
  relativeDirPath: ".roo/commands",
789
- relativeFilePath: basename5(filePath),
809
+ relativeFilePath: basename5(relativeFilePath),
790
810
  frontmatter: result.data,
791
811
  body: content.trim(),
792
812
  fileContent,
@@ -848,37 +868,12 @@ var CommandsProcessor = class extends FeatureProcessor {
848
868
  * Load and parse rulesync command files from .rulesync/commands/ directory
849
869
  */
850
870
  async loadRulesyncFiles() {
851
- const commandsDir = join3(this.baseDir, ".rulesync", "commands");
852
- const dirExists = await directoryExists(commandsDir);
853
- if (!dirExists) {
854
- logger.debug(`Rulesync commands directory not found: ${commandsDir}`);
855
- return [];
856
- }
857
- const allMdFiles = await findFiles(commandsDir, ".md");
858
- const mdFiles = allMdFiles.map((f) => basename6(f));
859
- if (mdFiles.length === 0) {
860
- logger.debug(`No markdown files found in rulesync commands directory: ${commandsDir}`);
861
- return [];
862
- }
863
- logger.info(`Found ${mdFiles.length} command files in ${commandsDir}`);
864
- const rulesyncCommands = [];
865
- for (const mdFile of mdFiles) {
866
- const filepath = join3(commandsDir, mdFile);
867
- try {
868
- const rulesyncCommand = await RulesyncCommand.fromFilePath({
869
- filePath: filepath
870
- });
871
- rulesyncCommands.push(rulesyncCommand);
872
- logger.debug(`Successfully loaded command: ${mdFile}`);
873
- } catch (error) {
874
- logger.warn(`Failed to load command file ${filepath}:`, error);
875
- continue;
876
- }
877
- }
878
- if (rulesyncCommands.length === 0) {
879
- logger.debug(`No valid commands found in ${commandsDir}`);
880
- return [];
881
- }
871
+ const rulesyncCommandPaths = await findFilesByGlobs(join7(".rulesync", "commands", "*.md"));
872
+ const rulesyncCommands = (await Promise.allSettled(
873
+ rulesyncCommandPaths.map(
874
+ (path2) => RulesyncCommand.fromFile({ relativeFilePath: basename6(path2) })
875
+ )
876
+ )).filter((result) => result.status === "fulfilled").map((result) => result.value);
882
877
  logger.info(`Successfully loaded ${rulesyncCommands.length} rulesync commands`);
883
878
  return rulesyncCommands;
884
879
  }
@@ -891,122 +886,67 @@ var CommandsProcessor = class extends FeatureProcessor {
891
886
  case "claudecode":
892
887
  return await this.loadClaudecodeCommands();
893
888
  case "geminicli":
894
- return await this.loadGeminiCliCommands();
889
+ return await this.loadGeminicliCommands();
895
890
  case "roo":
896
891
  return await this.loadRooCommands();
897
892
  default:
898
893
  throw new Error(`Unsupported tool target: ${this.toolTarget}`);
899
894
  }
900
895
  }
896
+ async loadToolCommandDefault({
897
+ toolTarget,
898
+ relativeDirPath,
899
+ extension
900
+ }) {
901
+ const commandFilePaths = await findFilesByGlobs(
902
+ join7(this.baseDir, relativeDirPath, `*.${extension}`)
903
+ );
904
+ const toolCommands = (await Promise.allSettled(
905
+ commandFilePaths.map((path2) => {
906
+ switch (toolTarget) {
907
+ case "claudecode":
908
+ return ClaudecodeCommand.fromFile({ relativeFilePath: basename6(path2) });
909
+ case "geminicli":
910
+ return GeminiCliCommand.fromFile({ relativeFilePath: basename6(path2) });
911
+ case "roo":
912
+ return RooCommand.fromFile({ relativeFilePath: basename6(path2) });
913
+ default:
914
+ throw new Error(`Unsupported tool target: ${toolTarget}`);
915
+ }
916
+ })
917
+ )).filter((result) => result.status === "fulfilled").map((result) => result.value);
918
+ logger.info(`Successfully loaded ${toolCommands.length} ${relativeDirPath} commands`);
919
+ return toolCommands;
920
+ }
901
921
  /**
902
922
  * Load Claude Code command configurations from .claude/commands/ directory
903
923
  */
904
924
  async loadClaudecodeCommands() {
905
- const commandsDir = join3(this.baseDir, ".claude", "commands");
906
- if (!await directoryExists(commandsDir)) {
907
- logger.warn(`Claude Code commands directory not found: ${commandsDir}`);
908
- return [];
909
- }
910
- const allMdFiles = await findFiles(commandsDir, ".md");
911
- const mdFiles = allMdFiles.map((f) => basename6(f));
912
- if (mdFiles.length === 0) {
913
- logger.info(`No markdown command files found in ${commandsDir}`);
914
- return [];
915
- }
916
- logger.info(`Found ${mdFiles.length} Claude Code command files in ${commandsDir}`);
917
- const toolCommands = [];
918
- for (const mdFile of mdFiles) {
919
- const filepath = join3(commandsDir, mdFile);
920
- try {
921
- const claudecodeCommand = await ClaudecodeCommand.fromFilePath({
922
- baseDir: this.baseDir,
923
- filePath: filepath
924
- });
925
- toolCommands.push(claudecodeCommand);
926
- logger.debug(`Successfully loaded Claude Code command: ${mdFile}`);
927
- } catch (error) {
928
- logger.warn(`Failed to load Claude Code command file ${filepath}:`, error);
929
- continue;
930
- }
931
- }
932
- logger.info(`Successfully loaded ${toolCommands.length} Claude Code commands`);
933
- return toolCommands;
925
+ return await this.loadToolCommandDefault({
926
+ toolTarget: "claudecode",
927
+ relativeDirPath: ".claude/commands",
928
+ extension: "md"
929
+ });
934
930
  }
935
931
  /**
936
932
  * Load Gemini CLI command configurations from .gemini/commands/ directory
937
933
  */
938
- async loadGeminiCliCommands() {
939
- const commandsDir = join3(this.baseDir, ".gemini", "commands");
940
- if (!await directoryExists(commandsDir)) {
941
- logger.warn(`Gemini CLI commands directory not found: ${commandsDir}`);
942
- return [];
943
- }
944
- const allFiles = await listDirectoryFiles(commandsDir);
945
- const tomlFiles = allFiles.filter((file) => file.endsWith(".toml"));
946
- if (tomlFiles.length === 0) {
947
- logger.info(`No TOML command files found in ${commandsDir}`);
948
- return [];
949
- }
950
- logger.info(`Found ${tomlFiles.length} Gemini CLI command files in ${commandsDir}`);
951
- const toolCommands = [];
952
- for (const tomlFile of tomlFiles) {
953
- const filepath = join3(commandsDir, tomlFile);
954
- try {
955
- const geminiCliCommand = await GeminiCliCommand.fromFilePath({
956
- baseDir: this.baseDir,
957
- filePath: filepath
958
- });
959
- toolCommands.push(geminiCliCommand);
960
- logger.debug(`Successfully loaded Gemini CLI command: ${tomlFile}`);
961
- } catch (error) {
962
- logger.warn(`Failed to load Gemini CLI command file ${filepath}:`, error);
963
- continue;
964
- }
965
- }
966
- logger.info(`Successfully loaded ${toolCommands.length} Gemini CLI commands`);
967
- return toolCommands;
934
+ async loadGeminicliCommands() {
935
+ return await this.loadToolCommandDefault({
936
+ toolTarget: "geminicli",
937
+ relativeDirPath: ".gemini/commands",
938
+ extension: "md"
939
+ });
968
940
  }
969
941
  /**
970
942
  * Load Roo Code command configurations from .roo/commands/ directory
971
943
  */
972
944
  async loadRooCommands() {
973
- const commandsDir = join3(this.baseDir, ".roo", "commands");
974
- if (!await directoryExists(commandsDir)) {
975
- logger.warn(`Roo Code commands directory not found: ${commandsDir}`);
976
- return [];
977
- }
978
- const allMdFiles = await findFiles(commandsDir, ".md");
979
- const mdFiles = allMdFiles.map((f) => basename6(f));
980
- if (mdFiles.length === 0) {
981
- logger.info(`No markdown command files found in ${commandsDir}`);
982
- return [];
983
- }
984
- logger.info(`Found ${mdFiles.length} Roo Code command files in ${commandsDir}`);
985
- const toolCommands = [];
986
- for (const mdFile of mdFiles) {
987
- const filepath = join3(commandsDir, mdFile);
988
- try {
989
- const rooCommand = await RooCommand.fromFilePath({
990
- baseDir: this.baseDir,
991
- filePath: filepath
992
- });
993
- toolCommands.push(rooCommand);
994
- logger.debug(`Successfully loaded Roo Code command: ${mdFile}`);
995
- } catch (error) {
996
- logger.warn(`Failed to load Roo Code command file ${filepath}:`, error);
997
- continue;
998
- }
999
- }
1000
- logger.info(`Successfully loaded ${toolCommands.length} Roo Code commands`);
1001
- return toolCommands;
1002
- }
1003
- async writeToolCommandsFromRulesyncCommands(rulesyncCommands) {
1004
- const toolCommands = await this.convertRulesyncFilesToToolFiles(rulesyncCommands);
1005
- await this.writeAiFiles(toolCommands);
1006
- }
1007
- async writeRulesyncCommandsFromToolCommands(toolCommands) {
1008
- const rulesyncCommands = await this.convertToolFilesToRulesyncFiles(toolCommands);
1009
- await this.writeAiFiles(rulesyncCommands);
945
+ return await this.loadToolCommandDefault({
946
+ toolTarget: "roo",
947
+ relativeDirPath: ".roo/commands",
948
+ extension: "md"
949
+ });
1010
950
  }
1011
951
  /**
1012
952
  * Implementation of abstract method from FeatureProcessor
@@ -1118,6 +1058,9 @@ var ConfigResolver = class {
1118
1058
  // src/ignore/ignore-processor.ts
1119
1059
  import { z as z9 } from "zod/mini";
1120
1060
 
1061
+ // src/ignore/augmentcode-ignore.ts
1062
+ import { join as join8 } from "path";
1063
+
1121
1064
  // src/types/tool-file.ts
1122
1065
  var ToolFile = class extends AiFile {
1123
1066
  };
@@ -1136,9 +1079,6 @@ var RulesyncIgnore = class _RulesyncIgnore extends RulesyncFile {
1136
1079
  fileContent
1137
1080
  });
1138
1081
  }
1139
- static async fromFilePath(_params) {
1140
- throw new Error("Please use the fromFile method instead.");
1141
- }
1142
1082
  };
1143
1083
 
1144
1084
  // src/ignore/tool-ignore.ts
@@ -1175,12 +1115,9 @@ var ToolIgnore = class extends ToolFile {
1175
1115
  fileContent: this.fileContent
1176
1116
  });
1177
1117
  }
1178
- static async fromFile() {
1118
+ static async fromFile(_params) {
1179
1119
  throw new Error("Please implement this method in the subclass.");
1180
1120
  }
1181
- static async fromFilePath(_params) {
1182
- throw new Error("Please use the fromFile method instead.");
1183
- }
1184
1121
  };
1185
1122
 
1186
1123
  // src/ignore/augmentcode-ignore.ts
@@ -1210,18 +1147,23 @@ var AugmentcodeIgnore = class _AugmentcodeIgnore extends ToolIgnore {
1210
1147
  * Create AugmentcodeIgnore from file path
1211
1148
  * Reads and parses .augmentignore file
1212
1149
  */
1213
- static async fromFile() {
1214
- const fileContent = await readFileContent(".augmentignore");
1150
+ static async fromFile({
1151
+ baseDir = ".",
1152
+ validate = true
1153
+ }) {
1154
+ const fileContent = await readFileContent(join8(baseDir, ".augmentignore"));
1215
1155
  return new _AugmentcodeIgnore({
1216
- baseDir: ".",
1156
+ baseDir,
1217
1157
  relativeDirPath: ".",
1218
1158
  relativeFilePath: ".augmentignore",
1219
- fileContent
1159
+ fileContent,
1160
+ validate
1220
1161
  });
1221
1162
  }
1222
1163
  };
1223
1164
 
1224
1165
  // src/ignore/cline-ignore.ts
1166
+ import { join as join9 } from "path";
1225
1167
  var ClineIgnore = class _ClineIgnore extends ToolIgnore {
1226
1168
  /**
1227
1169
  * Convert ClineIgnore to RulesyncIgnore format
@@ -1247,18 +1189,23 @@ var ClineIgnore = class _ClineIgnore extends ToolIgnore {
1247
1189
  /**
1248
1190
  * Load ClineIgnore from .clineignore file
1249
1191
  */
1250
- static async fromFile() {
1251
- const fileContent = await readFileContent(".clineignore");
1192
+ static async fromFile({
1193
+ baseDir = ".",
1194
+ validate = true
1195
+ }) {
1196
+ const fileContent = await readFileContent(join9(baseDir, ".clineignore"));
1252
1197
  return new _ClineIgnore({
1253
- baseDir: ".",
1198
+ baseDir,
1254
1199
  relativeDirPath: ".",
1255
1200
  relativeFilePath: ".clineignore",
1256
- fileContent
1201
+ fileContent,
1202
+ validate
1257
1203
  });
1258
1204
  }
1259
1205
  };
1260
1206
 
1261
1207
  // src/ignore/codexcli-ignore.ts
1208
+ import { join as join10 } from "path";
1262
1209
  var CodexcliIgnore = class _CodexcliIgnore extends ToolIgnore {
1263
1210
  toRulesyncIgnore() {
1264
1211
  return this.toRulesyncIgnoreDefault();
@@ -1277,20 +1224,23 @@ var CodexcliIgnore = class _CodexcliIgnore extends ToolIgnore {
1277
1224
  // Skip validation to allow empty patterns
1278
1225
  });
1279
1226
  }
1280
- static async fromFile() {
1281
- const fileContent = await readFileContent(".codexignore");
1227
+ static async fromFile({
1228
+ baseDir = ".",
1229
+ validate = true
1230
+ }) {
1231
+ const fileContent = await readFileContent(join10(baseDir, ".codexignore"));
1282
1232
  return new _CodexcliIgnore({
1283
- baseDir: ".",
1233
+ baseDir,
1284
1234
  relativeDirPath: ".",
1285
1235
  relativeFilePath: ".codexignore",
1286
1236
  fileContent,
1287
- validate: true
1288
- // Skip validation to allow empty patterns
1237
+ validate
1289
1238
  });
1290
1239
  }
1291
1240
  };
1292
1241
 
1293
1242
  // src/ignore/cursor-ignore.ts
1243
+ import { join as join11 } from "path";
1294
1244
  var CursorIgnore = class _CursorIgnore extends ToolIgnore {
1295
1245
  toRulesyncIgnore() {
1296
1246
  return new RulesyncIgnore({
@@ -1312,18 +1262,23 @@ var CursorIgnore = class _CursorIgnore extends ToolIgnore {
1312
1262
  fileContent: body
1313
1263
  });
1314
1264
  }
1315
- static async fromFile() {
1316
- const fileContent = await readFileContent(".cursorignore");
1265
+ static async fromFile({
1266
+ baseDir = ".",
1267
+ validate = true
1268
+ }) {
1269
+ const fileContent = await readFileContent(join11(baseDir, ".cursorignore"));
1317
1270
  return new _CursorIgnore({
1318
- baseDir: ".",
1271
+ baseDir,
1319
1272
  relativeDirPath: ".",
1320
1273
  relativeFilePath: ".cursorignore",
1321
- fileContent
1274
+ fileContent,
1275
+ validate
1322
1276
  });
1323
1277
  }
1324
1278
  };
1325
1279
 
1326
1280
  // src/ignore/geminicli-ignore.ts
1281
+ import { join as join12 } from "path";
1327
1282
  var GeminiCliIgnore = class _GeminiCliIgnore extends ToolIgnore {
1328
1283
  toRulesyncIgnore() {
1329
1284
  return this.toRulesyncIgnoreDefault();
@@ -1339,18 +1294,23 @@ var GeminiCliIgnore = class _GeminiCliIgnore extends ToolIgnore {
1339
1294
  fileContent: rulesyncIgnore.getFileContent()
1340
1295
  });
1341
1296
  }
1342
- static async fromFile() {
1343
- const fileContent = await readFileContent(".aiexclude");
1297
+ static async fromFile({
1298
+ baseDir = ".",
1299
+ validate = true
1300
+ }) {
1301
+ const fileContent = await readFileContent(join12(baseDir, ".aiexclude"));
1344
1302
  return new _GeminiCliIgnore({
1345
- baseDir: ".",
1303
+ baseDir,
1346
1304
  relativeDirPath: ".",
1347
1305
  relativeFilePath: ".aiexclude",
1348
- fileContent
1306
+ fileContent,
1307
+ validate
1349
1308
  });
1350
1309
  }
1351
1310
  };
1352
1311
 
1353
1312
  // src/ignore/junie-ignore.ts
1313
+ import { join as join13 } from "path";
1354
1314
  var JunieIgnore = class _JunieIgnore extends ToolIgnore {
1355
1315
  toRulesyncIgnore() {
1356
1316
  return this.toRulesyncIgnoreDefault();
@@ -1366,18 +1326,23 @@ var JunieIgnore = class _JunieIgnore extends ToolIgnore {
1366
1326
  fileContent: rulesyncIgnore.getFileContent()
1367
1327
  });
1368
1328
  }
1369
- static async fromFile() {
1370
- const fileContent = await readFileContent(".junieignore");
1329
+ static async fromFile({
1330
+ baseDir = ".",
1331
+ validate = true
1332
+ }) {
1333
+ const fileContent = await readFileContent(join13(baseDir, ".junieignore"));
1371
1334
  return new _JunieIgnore({
1372
- baseDir: ".",
1335
+ baseDir,
1373
1336
  relativeDirPath: ".",
1374
1337
  relativeFilePath: ".junieignore",
1375
- fileContent
1338
+ fileContent,
1339
+ validate
1376
1340
  });
1377
1341
  }
1378
1342
  };
1379
1343
 
1380
1344
  // src/ignore/kiro-ignore.ts
1345
+ import { join as join14 } from "path";
1381
1346
  var KiroIgnore = class _KiroIgnore extends ToolIgnore {
1382
1347
  toRulesyncIgnore() {
1383
1348
  return this.toRulesyncIgnoreDefault();
@@ -1393,18 +1358,23 @@ var KiroIgnore = class _KiroIgnore extends ToolIgnore {
1393
1358
  fileContent: rulesyncIgnore.getFileContent()
1394
1359
  });
1395
1360
  }
1396
- static async fromFile() {
1397
- const fileContent = await readFileContent(".aiignore");
1361
+ static async fromFile({
1362
+ baseDir = ".",
1363
+ validate = true
1364
+ }) {
1365
+ const fileContent = await readFileContent(join14(baseDir, ".aiignore"));
1398
1366
  return new _KiroIgnore({
1399
- baseDir: ".",
1367
+ baseDir,
1400
1368
  relativeDirPath: ".",
1401
1369
  relativeFilePath: ".aiignore",
1402
- fileContent
1370
+ fileContent,
1371
+ validate
1403
1372
  });
1404
1373
  }
1405
1374
  };
1406
1375
 
1407
1376
  // src/ignore/qwencode-ignore.ts
1377
+ import { join as join15 } from "path";
1408
1378
  var QwencodeIgnore = class _QwencodeIgnore extends ToolIgnore {
1409
1379
  toRulesyncIgnore() {
1410
1380
  return this.toRulesyncIgnoreDefault();
@@ -1420,18 +1390,23 @@ var QwencodeIgnore = class _QwencodeIgnore extends ToolIgnore {
1420
1390
  fileContent: rulesyncIgnore.getFileContent()
1421
1391
  });
1422
1392
  }
1423
- static async fromFile() {
1424
- const fileContent = await readFileContent(".geminiignore");
1393
+ static async fromFile({
1394
+ baseDir = ".",
1395
+ validate = true
1396
+ }) {
1397
+ const fileContent = await readFileContent(join15(baseDir, ".geminiignore"));
1425
1398
  return new _QwencodeIgnore({
1426
- baseDir: ".",
1399
+ baseDir,
1427
1400
  relativeDirPath: ".",
1428
1401
  relativeFilePath: ".geminiignore",
1429
- fileContent
1402
+ fileContent,
1403
+ validate
1430
1404
  });
1431
1405
  }
1432
1406
  };
1433
1407
 
1434
1408
  // src/ignore/roo-ignore.ts
1409
+ import { join as join16 } from "path";
1435
1410
  var RooIgnore = class _RooIgnore extends ToolIgnore {
1436
1411
  toRulesyncIgnore() {
1437
1412
  return this.toRulesyncIgnoreDefault();
@@ -1447,18 +1422,23 @@ var RooIgnore = class _RooIgnore extends ToolIgnore {
1447
1422
  fileContent: rulesyncIgnore.getFileContent()
1448
1423
  });
1449
1424
  }
1450
- static async fromFile() {
1451
- const fileContent = await readFileContent(".rooignore");
1425
+ static async fromFile({
1426
+ baseDir = ".",
1427
+ validate = true
1428
+ }) {
1429
+ const fileContent = await readFileContent(join16(baseDir, ".rooignore"));
1452
1430
  return new _RooIgnore({
1453
- baseDir: ".",
1431
+ baseDir,
1454
1432
  relativeDirPath: ".",
1455
1433
  relativeFilePath: ".rooignore",
1456
- fileContent
1434
+ fileContent,
1435
+ validate
1457
1436
  });
1458
1437
  }
1459
1438
  };
1460
1439
 
1461
1440
  // src/ignore/windsurf-ignore.ts
1441
+ import { join as join17 } from "path";
1462
1442
  var WindsurfIgnore = class _WindsurfIgnore extends ToolIgnore {
1463
1443
  toRulesyncIgnore() {
1464
1444
  return this.toRulesyncIgnoreDefault();
@@ -1474,6 +1454,19 @@ var WindsurfIgnore = class _WindsurfIgnore extends ToolIgnore {
1474
1454
  fileContent: rulesyncIgnore.getFileContent()
1475
1455
  });
1476
1456
  }
1457
+ static async fromFile({
1458
+ baseDir = ".",
1459
+ validate = true
1460
+ }) {
1461
+ const fileContent = await readFileContent(join17(baseDir, ".codeiumignore"));
1462
+ return new _WindsurfIgnore({
1463
+ baseDir,
1464
+ relativeDirPath: ".",
1465
+ relativeFilePath: ".codeiumignore",
1466
+ fileContent,
1467
+ validate
1468
+ });
1469
+ }
1477
1470
  };
1478
1471
 
1479
1472
  // src/ignore/ignore-processor.ts
@@ -1531,25 +1524,25 @@ var IgnoreProcessor = class extends FeatureProcessor {
1531
1524
  async loadToolIgnores() {
1532
1525
  switch (this.toolTarget) {
1533
1526
  case "augmentcode":
1534
- return [await AugmentcodeIgnore.fromFile()];
1527
+ return [await AugmentcodeIgnore.fromFile({ baseDir: this.baseDir })];
1535
1528
  case "cline":
1536
- return [await ClineIgnore.fromFile()];
1529
+ return [await ClineIgnore.fromFile({ baseDir: this.baseDir })];
1537
1530
  case "codexcli":
1538
- return [await CodexcliIgnore.fromFile()];
1531
+ return [await CodexcliIgnore.fromFile({ baseDir: this.baseDir })];
1539
1532
  case "cursor":
1540
- return [await CursorIgnore.fromFile()];
1533
+ return [await CursorIgnore.fromFile({ baseDir: this.baseDir })];
1541
1534
  case "geminicli":
1542
- return [await GeminiCliIgnore.fromFile()];
1535
+ return [await GeminiCliIgnore.fromFile({ baseDir: this.baseDir })];
1543
1536
  case "junie":
1544
- return [await JunieIgnore.fromFile()];
1537
+ return [await JunieIgnore.fromFile({ baseDir: this.baseDir })];
1545
1538
  case "kiro":
1546
- return [await KiroIgnore.fromFile()];
1539
+ return [await KiroIgnore.fromFile({ baseDir: this.baseDir })];
1547
1540
  case "qwencode":
1548
- return [await QwencodeIgnore.fromFile()];
1541
+ return [await QwencodeIgnore.fromFile({ baseDir: this.baseDir })];
1549
1542
  case "roo":
1550
- return [await RooIgnore.fromFile()];
1543
+ return [await RooIgnore.fromFile({ baseDir: this.baseDir })];
1551
1544
  case "windsurf":
1552
- return [await WindsurfIgnore.fromFile()];
1545
+ return [await WindsurfIgnore.fromFile({ baseDir: this.baseDir })];
1553
1546
  default:
1554
1547
  throw new Error(`Unsupported tool target: ${this.toolTarget}`);
1555
1548
  }
@@ -1644,9 +1637,14 @@ var IgnoreProcessor = class extends FeatureProcessor {
1644
1637
  };
1645
1638
 
1646
1639
  // src/mcp/mcp-processor.ts
1647
- import { join as join4 } from "path";
1648
1640
  import { z as z11 } from "zod/mini";
1649
1641
 
1642
+ // src/mcp/amazonqcli-mcp.ts
1643
+ import { join as join19 } from "path";
1644
+
1645
+ // src/mcp/rulesync-mcp.ts
1646
+ import { join as join18 } from "path";
1647
+
1650
1648
  // src/types/mcp.ts
1651
1649
  import { z as z10 } from "zod/mini";
1652
1650
  var McpTransportTypeSchema = z10.enum(["stdio", "sse", "http"]);
@@ -1695,14 +1693,14 @@ var RulesyncMcp = class _RulesyncMcp extends RulesyncFile {
1695
1693
  validate() {
1696
1694
  return { success: true, error: null };
1697
1695
  }
1698
- static async fromFilePath({ filePath }) {
1699
- const fileContent = await readFileContent(filePath);
1696
+ static async fromFile({ validate = true }) {
1697
+ const fileContent = await readFileContent(join18(RULESYNC_DIR, ".mcp.json"));
1700
1698
  return new _RulesyncMcp({
1701
1699
  baseDir: ".",
1702
- relativeDirPath: ".rulesync",
1700
+ relativeDirPath: RULESYNC_DIR,
1703
1701
  relativeFilePath: ".mcp.json",
1704
1702
  fileContent,
1705
- validate: true
1703
+ validate
1706
1704
  });
1707
1705
  }
1708
1706
  getJson() {
@@ -1738,7 +1736,7 @@ var ToolMcp = class extends ToolFile {
1738
1736
  fileContent: this.fileContent
1739
1737
  });
1740
1738
  }
1741
- static async fromFilePath(_params) {
1739
+ static async fromFile(_params) {
1742
1740
  throw new Error("Please implement this method in the subclass.");
1743
1741
  }
1744
1742
  static fromRulesyncMcp(_params) {
@@ -1748,14 +1746,17 @@ var ToolMcp = class extends ToolFile {
1748
1746
 
1749
1747
  // src/mcp/amazonqcli-mcp.ts
1750
1748
  var AmazonqcliMcp = class _AmazonqcliMcp extends ToolMcp {
1751
- static async fromFilePath({ filePath }) {
1752
- const fileContent = await readFileContent(filePath);
1749
+ static async fromFile({
1750
+ baseDir = ".",
1751
+ validate = true
1752
+ }) {
1753
+ const fileContent = await readFileContent(join19(baseDir, ".amazonq/mcp.json"));
1753
1754
  return new _AmazonqcliMcp({
1754
- baseDir: ".",
1755
+ baseDir,
1755
1756
  relativeDirPath: ".amazonq",
1756
- relativeFilePath: ".mcp.json",
1757
+ relativeFilePath: "mcp.json",
1757
1758
  fileContent,
1758
- validate: true
1759
+ validate
1759
1760
  });
1760
1761
  }
1761
1762
  static fromRulesyncMcp({
@@ -1780,15 +1781,19 @@ var AmazonqcliMcp = class _AmazonqcliMcp extends ToolMcp {
1780
1781
  };
1781
1782
 
1782
1783
  // src/mcp/claudecode-mcp.ts
1784
+ import { join as join20 } from "path";
1783
1785
  var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
1784
- static async fromFilePath({ filePath }) {
1785
- const fileContent = await readFileContent(filePath);
1786
+ static async fromFile({
1787
+ baseDir = ".",
1788
+ validate = true
1789
+ }) {
1790
+ const fileContent = await readFileContent(join20(baseDir, ".mcp.json"));
1786
1791
  return new _ClaudecodeMcp({
1787
1792
  baseDir: ".",
1788
1793
  relativeDirPath: ".",
1789
1794
  relativeFilePath: ".mcp.json",
1790
1795
  fileContent,
1791
- validate: true
1796
+ validate
1792
1797
  });
1793
1798
  }
1794
1799
  static fromRulesyncMcp({
@@ -1813,15 +1818,19 @@ var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
1813
1818
  };
1814
1819
 
1815
1820
  // src/mcp/cline-mcp.ts
1821
+ import { join as join21 } from "path";
1816
1822
  var ClineMcp = class _ClineMcp extends ToolMcp {
1817
- static async fromFilePath({ filePath }) {
1818
- const fileContent = await readFileContent(filePath);
1823
+ static async fromFile({
1824
+ baseDir = ".",
1825
+ validate = true
1826
+ }) {
1827
+ const fileContent = await readFileContent(join21(baseDir, ".cline/mcp.json"));
1819
1828
  return new _ClineMcp({
1820
1829
  baseDir: ".",
1821
1830
  relativeDirPath: ".cline",
1822
1831
  relativeFilePath: "mcp.json",
1823
1832
  fileContent,
1824
- validate: true
1833
+ validate
1825
1834
  });
1826
1835
  }
1827
1836
  static fromRulesyncMcp({
@@ -1846,15 +1855,19 @@ var ClineMcp = class _ClineMcp extends ToolMcp {
1846
1855
  };
1847
1856
 
1848
1857
  // src/mcp/copilot-mcp.ts
1858
+ import { join as join22 } from "path";
1849
1859
  var CopilotMcp = class _CopilotMcp extends ToolMcp {
1850
- static async fromFilePath({ filePath }) {
1851
- const fileContent = await readFileContent(filePath);
1860
+ static async fromFilePath({
1861
+ baseDir = ".",
1862
+ validate = true
1863
+ }) {
1864
+ const fileContent = await readFileContent(join22(baseDir, ".vscode/mcp.json"));
1852
1865
  return new _CopilotMcp({
1853
1866
  baseDir: ".",
1854
1867
  relativeDirPath: ".vscode",
1855
1868
  relativeFilePath: "mcp.json",
1856
1869
  fileContent,
1857
- validate: true
1870
+ validate
1858
1871
  });
1859
1872
  }
1860
1873
  static fromRulesyncMcp({
@@ -1879,15 +1892,19 @@ var CopilotMcp = class _CopilotMcp extends ToolMcp {
1879
1892
  };
1880
1893
 
1881
1894
  // src/mcp/cursor-mcp.ts
1895
+ import { join as join23 } from "path";
1882
1896
  var CursorMcp = class _CursorMcp extends ToolMcp {
1883
- static async fromFilePath({ filePath }) {
1884
- const fileContent = await readFileContent(filePath);
1897
+ static async fromFile({
1898
+ baseDir = ".",
1899
+ validate = true
1900
+ }) {
1901
+ const fileContent = await readFileContent(join23(baseDir, ".cursor/mcp.json"));
1885
1902
  return new _CursorMcp({
1886
1903
  baseDir: ".",
1887
1904
  relativeDirPath: ".cursor",
1888
1905
  relativeFilePath: "mcp.json",
1889
1906
  fileContent,
1890
- validate: true
1907
+ validate
1891
1908
  });
1892
1909
  }
1893
1910
  static fromRulesyncMcp({
@@ -1923,15 +1940,19 @@ var CursorMcp = class _CursorMcp extends ToolMcp {
1923
1940
  };
1924
1941
 
1925
1942
  // src/mcp/roo-mcp.ts
1943
+ import { join as join24 } from "path";
1926
1944
  var RooMcp = class _RooMcp extends ToolMcp {
1927
- static async fromFilePath({ filePath }) {
1928
- const fileContent = await readFileContent(filePath);
1945
+ static async fromFile({
1946
+ baseDir = ".",
1947
+ validate = true
1948
+ }) {
1949
+ const fileContent = await readFileContent(join24(baseDir, ".roo/mcp.json"));
1929
1950
  return new _RooMcp({
1930
1951
  baseDir: ".",
1931
1952
  relativeDirPath: ".roo",
1932
1953
  relativeFilePath: "mcp.json",
1933
1954
  fileContent,
1934
- validate: true
1955
+ validate
1935
1956
  });
1936
1957
  }
1937
1958
  static fromRulesyncMcp({
@@ -1981,9 +2002,7 @@ var McpProcessor = class extends FeatureProcessor {
1981
2002
  */
1982
2003
  async loadRulesyncFiles() {
1983
2004
  try {
1984
- return [
1985
- await RulesyncMcp.fromFilePath({ filePath: join4(this.baseDir, ".rulesync", ".mcp.json") })
1986
- ];
2005
+ return [await RulesyncMcp.fromFile({})];
1987
2006
  } catch (error) {
1988
2007
  logger.debug(`No MCP files found for tool target: ${this.toolTarget}`, error);
1989
2008
  return [];
@@ -1995,42 +2014,62 @@ var McpProcessor = class extends FeatureProcessor {
1995
2014
  */
1996
2015
  async loadToolFiles() {
1997
2016
  try {
1998
- switch (this.toolTarget) {
1999
- case "amazonqcli": {
2000
- return [
2001
- await AmazonqcliMcp.fromFilePath({
2002
- filePath: join4(this.baseDir, ".amazonq", "mcp.json")
2003
- })
2004
- ];
2005
- }
2006
- case "claudecode": {
2007
- return [
2008
- await ClaudecodeMcp.fromFilePath({
2009
- filePath: join4(this.baseDir, ".mcp.json")
2010
- })
2011
- ];
2012
- }
2013
- case "cline": {
2014
- return [
2015
- await ClineMcp.fromFilePath({ filePath: join4(this.baseDir, ".cline", "mcp.json") })
2016
- ];
2017
- }
2018
- case "copilot": {
2019
- return [
2020
- await CopilotMcp.fromFilePath({ filePath: join4(this.baseDir, ".vscode", "mcp.json") })
2021
- ];
2022
- }
2023
- case "cursor": {
2024
- return [
2025
- await CursorMcp.fromFilePath({ filePath: join4(this.baseDir, ".cursor", "mcp.json") })
2026
- ];
2027
- }
2028
- case "roo": {
2029
- return [await RooMcp.fromFilePath({ filePath: join4(this.baseDir, ".roo", "mcp.json") })];
2017
+ const toolMcps = await (async () => {
2018
+ switch (this.toolTarget) {
2019
+ case "amazonqcli": {
2020
+ return [
2021
+ await AmazonqcliMcp.fromFile({
2022
+ baseDir: this.baseDir,
2023
+ validate: true
2024
+ })
2025
+ ];
2026
+ }
2027
+ case "claudecode": {
2028
+ return [
2029
+ await ClaudecodeMcp.fromFile({
2030
+ baseDir: this.baseDir,
2031
+ validate: true
2032
+ })
2033
+ ];
2034
+ }
2035
+ case "cline": {
2036
+ return [
2037
+ await ClineMcp.fromFile({
2038
+ baseDir: this.baseDir,
2039
+ validate: true
2040
+ })
2041
+ ];
2042
+ }
2043
+ case "copilot": {
2044
+ return [
2045
+ await CopilotMcp.fromFile({
2046
+ baseDir: this.baseDir,
2047
+ validate: true
2048
+ })
2049
+ ];
2050
+ }
2051
+ case "cursor": {
2052
+ return [
2053
+ await CursorMcp.fromFile({
2054
+ baseDir: this.baseDir,
2055
+ validate: true
2056
+ })
2057
+ ];
2058
+ }
2059
+ case "roo": {
2060
+ return [
2061
+ await RooMcp.fromFile({
2062
+ baseDir: this.baseDir,
2063
+ validate: true
2064
+ })
2065
+ ];
2066
+ }
2067
+ default:
2068
+ throw new Error(`Unsupported tool target: ${this.toolTarget}`);
2030
2069
  }
2031
- default:
2032
- throw new Error(`Unsupported tool target: ${this.toolTarget}`);
2033
- }
2070
+ })();
2071
+ logger.info(`Successfully loaded ${toolMcps.length} ${this.toolTarget} MCP files`);
2072
+ return toolMcps;
2034
2073
  } catch (error) {
2035
2074
  logger.debug(`No MCP files found for tool target: ${this.toolTarget}`, error);
2036
2075
  return [];
@@ -2106,21 +2145,15 @@ var McpProcessor = class extends FeatureProcessor {
2106
2145
  };
2107
2146
 
2108
2147
  // src/rules/rules-processor.ts
2109
- import { basename as basename9, join as join7 } from "path";
2148
+ import { basename as basename9, join as join43 } from "path";
2110
2149
  import { XMLBuilder } from "fast-xml-parser";
2111
2150
  import { z as z16 } from "zod/mini";
2112
2151
 
2113
- // src/constants/paths.ts
2114
- import { join as join5 } from "path";
2115
- var RULESYNC_DIR = ".rulesync";
2116
- var RULESYNC_RULES_DIR = join5(".rulesync", "rules");
2117
- var RULESYNC_RULES_DIR_LEGACY = ".rulesync";
2118
- var RULESYNC_MCP_FILE = join5(".rulesync", ".mcp.json");
2119
- var RULESYNC_COMMANDS_DIR = join5(".rulesync", "commands");
2120
- var RULESYNC_SUBAGENTS_DIR = join5(".rulesync", "subagents");
2152
+ // src/rules/agentsmd-rule.ts
2153
+ import { join as join26 } from "path";
2121
2154
 
2122
2155
  // src/rules/rulesync-rule.ts
2123
- import { basename as basename7, join as join6 } from "path";
2156
+ import { basename as basename7, join as join25 } from "path";
2124
2157
  import { z as z12 } from "zod/mini";
2125
2158
  var RulesyncRuleFrontmatterSchema = z12.object({
2126
2159
  root: z12.optional(z12.optional(z12.boolean())),
@@ -2166,10 +2199,11 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
2166
2199
  return { success: false, error: result.error };
2167
2200
  }
2168
2201
  }
2169
- static async fromLegacyFile({
2170
- relativeFilePath
2202
+ static async fromFileLegacy({
2203
+ relativeFilePath,
2204
+ validate = true
2171
2205
  }) {
2172
- const filePath = join6(RULESYNC_RULES_DIR_LEGACY, relativeFilePath);
2206
+ const filePath = join25(RULESYNC_RULES_DIR_LEGACY, relativeFilePath);
2173
2207
  const fileContent = await readFileContent(filePath);
2174
2208
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
2175
2209
  const result = RulesyncRuleFrontmatterSchema.safeParse(frontmatter);
@@ -2189,10 +2223,15 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
2189
2223
  relativeDirPath: RULESYNC_RULES_DIR,
2190
2224
  relativeFilePath: filename,
2191
2225
  frontmatter: validatedFrontmatter,
2192
- body: content.trim()
2226
+ body: content.trim(),
2227
+ validate
2193
2228
  });
2194
2229
  }
2195
- static async fromFilePath({ filePath }) {
2230
+ static async fromFile({
2231
+ relativeFilePath,
2232
+ validate = true
2233
+ }) {
2234
+ const filePath = join25(RULESYNC_RULES_DIR, relativeFilePath);
2196
2235
  const fileContent = await readFileContent(filePath);
2197
2236
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
2198
2237
  const result = RulesyncRuleFrontmatterSchema.safeParse(frontmatter);
@@ -2212,7 +2251,8 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
2212
2251
  relativeDirPath: RULESYNC_RULES_DIR,
2213
2252
  relativeFilePath: filename,
2214
2253
  frontmatter: validatedFrontmatter,
2215
- body: content.trim()
2254
+ body: content.trim(),
2255
+ validate
2216
2256
  });
2217
2257
  }
2218
2258
  getBody() {
@@ -2227,7 +2267,7 @@ var ToolRule = class extends ToolFile {
2227
2267
  super(rest);
2228
2268
  this.root = root;
2229
2269
  }
2230
- static async fromFilePath(_params) {
2270
+ static async fromFile(_params) {
2231
2271
  throw new Error("Please implement this method in the subclass.");
2232
2272
  }
2233
2273
  static fromRulesyncRule(_params) {
@@ -2278,19 +2318,18 @@ var AgentsMdRule = class _AgentsMdRule extends ToolRule {
2278
2318
  root: root ?? false
2279
2319
  });
2280
2320
  }
2281
- static async fromFilePath({
2321
+ static async fromFile({
2282
2322
  baseDir = ".",
2283
- relativeDirPath,
2284
2323
  relativeFilePath,
2285
- filePath,
2286
2324
  validate = true
2287
2325
  }) {
2288
- const fileContent = await readFileContent(filePath);
2289
2326
  const isRoot = relativeFilePath === "AGENTS.md";
2327
+ const relativePath = isRoot ? "AGENTS.md" : join26(".agents/memories", relativeFilePath);
2328
+ const fileContent = await readFileContent(join26(baseDir, relativePath));
2290
2329
  return new _AgentsMdRule({
2291
2330
  baseDir,
2292
- relativeDirPath,
2293
- relativeFilePath,
2331
+ relativeDirPath: isRoot ? "." : ".agents/memories",
2332
+ relativeFilePath: isRoot ? "AGENTS.md" : relativeFilePath,
2294
2333
  fileContent,
2295
2334
  validate,
2296
2335
  root: isRoot
@@ -2318,15 +2357,20 @@ var AgentsMdRule = class _AgentsMdRule extends ToolRule {
2318
2357
  };
2319
2358
 
2320
2359
  // src/rules/amazonqcli-rule.ts
2360
+ import { join as join27 } from "path";
2321
2361
  var AmazonQCliRule = class _AmazonQCliRule extends ToolRule {
2322
- static async fromFilePath(params) {
2323
- const fileContent = await readFileContent(params.filePath);
2362
+ static async fromFile({
2363
+ baseDir = ".",
2364
+ relativeFilePath,
2365
+ validate = true
2366
+ }) {
2367
+ const fileContent = await readFileContent(join27(baseDir, ".amazonq/rules", relativeFilePath));
2324
2368
  return new _AmazonQCliRule({
2325
- baseDir: params.baseDir || ".",
2326
- relativeDirPath: params.relativeDirPath,
2327
- relativeFilePath: params.relativeFilePath,
2369
+ baseDir,
2370
+ relativeDirPath: ".amazonq/rules",
2371
+ relativeFilePath,
2328
2372
  fileContent,
2329
- validate: params.validate ?? false,
2373
+ validate,
2330
2374
  root: false
2331
2375
  });
2332
2376
  }
@@ -2353,6 +2397,7 @@ var AmazonQCliRule = class _AmazonQCliRule extends ToolRule {
2353
2397
  };
2354
2398
 
2355
2399
  // src/rules/augmentcode-legacy-rule.ts
2400
+ import { join as join28 } from "path";
2356
2401
  var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
2357
2402
  toRulesyncRule() {
2358
2403
  const rulesyncFrontmatter = {
@@ -2388,19 +2433,18 @@ var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
2388
2433
  validate() {
2389
2434
  return { success: true, error: null };
2390
2435
  }
2391
- static async fromFilePath({
2436
+ static async fromFile({
2392
2437
  baseDir = ".",
2393
- relativeDirPath,
2394
2438
  relativeFilePath,
2395
- filePath,
2396
2439
  validate = true
2397
2440
  }) {
2398
- const fileContent = await readFileContent(filePath);
2399
2441
  const isRoot = relativeFilePath === ".augment-guidelines";
2442
+ const relativePath = isRoot ? ".augment-guidelines" : join28(".augment/rules", relativeFilePath);
2443
+ const fileContent = await readFileContent(join28(baseDir, relativePath));
2400
2444
  return new _AugmentcodeLegacyRule({
2401
2445
  baseDir,
2402
- relativeDirPath,
2403
- relativeFilePath,
2446
+ relativeDirPath: isRoot ? "." : ".augment/rules",
2447
+ relativeFilePath: isRoot ? ".augment-guidelines" : relativeFilePath,
2404
2448
  fileContent,
2405
2449
  validate,
2406
2450
  root: isRoot
@@ -2409,6 +2453,7 @@ var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
2409
2453
  };
2410
2454
 
2411
2455
  // src/rules/augmentcode-rule.ts
2456
+ import { join as join29 } from "path";
2412
2457
  var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
2413
2458
  toRulesyncRule() {
2414
2459
  return this.toRulesyncRuleDefault();
@@ -2427,18 +2472,16 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
2427
2472
  })
2428
2473
  );
2429
2474
  }
2430
- static async fromFilePath({
2475
+ static async fromFile({
2431
2476
  baseDir = ".",
2432
- relativeDirPath,
2433
2477
  relativeFilePath,
2434
- filePath,
2435
2478
  validate = true
2436
2479
  }) {
2437
- const fileContent = await readFileContent(filePath);
2480
+ const fileContent = await readFileContent(join29(baseDir, ".augment/rules", relativeFilePath));
2438
2481
  const { body: content } = parseFrontmatter(fileContent);
2439
2482
  return new _AugmentcodeRule({
2440
2483
  baseDir,
2441
- relativeDirPath,
2484
+ relativeDirPath: ".augment/rules",
2442
2485
  relativeFilePath,
2443
2486
  fileContent: content.trim(),
2444
2487
  validate
@@ -2450,16 +2493,23 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
2450
2493
  };
2451
2494
 
2452
2495
  // src/rules/claudecode-rule.ts
2496
+ import { join as join30 } from "path";
2453
2497
  var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
2454
- static async fromFilePath(params) {
2455
- const fileContent = await readFileContent(params.filePath);
2498
+ static async fromFile({
2499
+ baseDir = ".",
2500
+ relativeFilePath,
2501
+ validate = true
2502
+ }) {
2503
+ const isRoot = relativeFilePath === "CLAUDE.md";
2504
+ const relativePath = isRoot ? "CLAUDE.md" : join30(".claude/memories", relativeFilePath);
2505
+ const fileContent = await readFileContent(join30(baseDir, relativePath));
2456
2506
  return new _ClaudecodeRule({
2457
- baseDir: params.baseDir || process.cwd(),
2458
- relativeDirPath: params.relativeDirPath,
2459
- relativeFilePath: params.relativeFilePath,
2507
+ baseDir,
2508
+ relativeDirPath: isRoot ? "." : ".claude/memories",
2509
+ relativeFilePath: isRoot ? "CLAUDE.md" : relativeFilePath,
2460
2510
  fileContent,
2461
- validate: params.validate ?? true,
2462
- root: params.relativeFilePath === "CLAUDE.md"
2511
+ validate,
2512
+ root: isRoot
2463
2513
  });
2464
2514
  }
2465
2515
  static fromRulesyncRule({
@@ -2486,6 +2536,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
2486
2536
  };
2487
2537
 
2488
2538
  // src/rules/cline-rule.ts
2539
+ import { join as join31 } from "path";
2489
2540
  import { z as z13 } from "zod/mini";
2490
2541
  var ClineRuleFrontmatterSchema = z13.object({
2491
2542
  description: z13.string()
@@ -2511,17 +2562,15 @@ var ClineRule = class _ClineRule extends ToolRule {
2511
2562
  validate() {
2512
2563
  return { success: true, error: null };
2513
2564
  }
2514
- static async fromFilePath({
2565
+ static async fromFile({
2515
2566
  baseDir = ".",
2516
- relativeDirPath,
2517
2567
  relativeFilePath,
2518
- filePath,
2519
2568
  validate = true
2520
2569
  }) {
2521
- const fileContent = await readFileContent(filePath);
2570
+ const fileContent = await readFileContent(join31(baseDir, ".clinerules", relativeFilePath));
2522
2571
  return new _ClineRule({
2523
2572
  baseDir,
2524
- relativeDirPath,
2573
+ relativeDirPath: ".clinerules",
2525
2574
  relativeFilePath,
2526
2575
  fileContent,
2527
2576
  validate
@@ -2530,16 +2579,23 @@ var ClineRule = class _ClineRule extends ToolRule {
2530
2579
  };
2531
2580
 
2532
2581
  // src/rules/codexcli-rule.ts
2582
+ import { join as join32 } from "path";
2533
2583
  var CodexcliRule = class _CodexcliRule extends ToolRule {
2534
- static async fromFilePath(params) {
2535
- const fileContent = await readFileContent(params.filePath);
2584
+ static async fromFile({
2585
+ baseDir = ".",
2586
+ relativeFilePath,
2587
+ validate = true
2588
+ }) {
2589
+ const isRoot = relativeFilePath === "AGENTS.md";
2590
+ const relativePath = isRoot ? "AGENTS.md" : join32(".codex/memories", relativeFilePath);
2591
+ const fileContent = await readFileContent(join32(baseDir, relativePath));
2536
2592
  return new _CodexcliRule({
2537
- baseDir: params.baseDir || process.cwd(),
2538
- relativeDirPath: params.relativeDirPath,
2539
- relativeFilePath: params.relativeFilePath,
2593
+ baseDir,
2594
+ relativeDirPath: isRoot ? "." : ".codex/memories",
2595
+ relativeFilePath: isRoot ? "AGENTS.md" : relativeFilePath,
2540
2596
  fileContent,
2541
- validate: params.validate ?? true,
2542
- root: params.relativeFilePath === "AGENTS.md"
2597
+ validate,
2598
+ root: isRoot
2543
2599
  });
2544
2600
  }
2545
2601
  static fromRulesyncRule({
@@ -2566,6 +2622,7 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
2566
2622
  };
2567
2623
 
2568
2624
  // src/rules/copilot-rule.ts
2625
+ import { join as join33 } from "path";
2569
2626
  import { z as z14 } from "zod/mini";
2570
2627
  var CopilotRuleFrontmatterSchema = z14.object({
2571
2628
  description: z14.optional(z14.string()),
@@ -2640,45 +2697,43 @@ var CopilotRule = class _CopilotRule extends ToolRule {
2640
2697
  root
2641
2698
  });
2642
2699
  }
2643
- static async fromFilePath({
2700
+ static async fromFile({
2644
2701
  baseDir = ".",
2645
- relativeDirPath,
2646
2702
  relativeFilePath,
2647
- filePath,
2648
2703
  validate = true
2649
2704
  }) {
2650
- const fileContent = await readFileContent(filePath);
2651
- const root = relativeFilePath === "copilot-instructions.md";
2652
- if (root) {
2705
+ const isRoot = relativeFilePath === "copilot-instructions.md";
2706
+ const relativePath = isRoot ? "copilot-instructions.md" : join33(".github/instructions", relativeFilePath);
2707
+ const fileContent = await readFileContent(join33(baseDir, relativePath));
2708
+ if (isRoot) {
2653
2709
  return new _CopilotRule({
2654
2710
  baseDir,
2655
- relativeDirPath,
2656
- relativeFilePath,
2711
+ relativeDirPath: ".github",
2712
+ relativeFilePath: isRoot ? "copilot-instructions.md" : relativeFilePath,
2657
2713
  frontmatter: {
2658
2714
  description: "",
2659
2715
  applyTo: "**"
2660
2716
  },
2661
2717
  body: fileContent.trim(),
2662
2718
  validate,
2663
- root
2719
+ root: isRoot
2664
2720
  });
2665
2721
  }
2666
2722
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
2667
2723
  const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
2668
2724
  if (!result.success) {
2669
- throw new Error(`Invalid frontmatter in ${filePath}: ${result.error.message}`);
2725
+ throw new Error(
2726
+ `Invalid frontmatter in ${join33(baseDir, relativeFilePath)}: ${result.error.message}`
2727
+ );
2670
2728
  }
2671
2729
  return new _CopilotRule({
2672
2730
  baseDir,
2673
- relativeDirPath,
2674
- relativeFilePath,
2675
- frontmatter: {
2676
- ...result.data,
2677
- applyTo: result.data.applyTo || "**"
2678
- },
2731
+ relativeDirPath: ".github/instructions",
2732
+ relativeFilePath: relativeFilePath.replace(/\.md$/, ".instructions.md"),
2733
+ frontmatter: result.data,
2679
2734
  body: content.trim(),
2680
2735
  validate,
2681
- root
2736
+ root: isRoot
2682
2737
  });
2683
2738
  }
2684
2739
  validate() {
@@ -2701,7 +2756,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
2701
2756
  };
2702
2757
 
2703
2758
  // src/rules/cursor-rule.ts
2704
- import { basename as basename8 } from "path";
2759
+ import { basename as basename8, join as join34 } from "path";
2705
2760
  import { z as z15 } from "zod/mini";
2706
2761
  var CursorRuleFrontmatterSchema = z15.object({
2707
2762
  description: z15.optional(z15.string()),
@@ -2720,11 +2775,49 @@ var CursorRule = class _CursorRule extends ToolRule {
2720
2775
  }
2721
2776
  super({
2722
2777
  ...rest,
2723
- fileContent: stringifyFrontmatter(body, frontmatter)
2778
+ fileContent: _CursorRule.stringifyCursorFrontmatter(body, frontmatter)
2724
2779
  });
2725
2780
  this.frontmatter = frontmatter;
2726
2781
  this.body = body;
2727
2782
  }
2783
+ /**
2784
+ * Custom stringify function for Cursor MDC files
2785
+ * MDC files don't support quotes in YAML, so globs patterns must be output without quotes
2786
+ */
2787
+ static stringifyCursorFrontmatter(body, frontmatter) {
2788
+ if (!frontmatter.globs || typeof frontmatter.globs !== "string" || !frontmatter.globs.includes("*")) {
2789
+ return stringifyFrontmatter(body, frontmatter);
2790
+ }
2791
+ const lines = ["---"];
2792
+ if (frontmatter.alwaysApply !== void 0) {
2793
+ lines.push(`alwaysApply: ${frontmatter.alwaysApply}`);
2794
+ }
2795
+ if (frontmatter.description !== void 0) {
2796
+ lines.push(`description: ${frontmatter.description}`);
2797
+ }
2798
+ if (frontmatter.globs !== void 0) {
2799
+ lines.push(`globs: ${frontmatter.globs}`);
2800
+ }
2801
+ lines.push("---");
2802
+ lines.push("");
2803
+ if (body) {
2804
+ lines.push(body);
2805
+ }
2806
+ return lines.join("\n");
2807
+ }
2808
+ /**
2809
+ * Custom parse function for Cursor MDC files
2810
+ * MDC files don't support quotes in YAML, so we need to handle patterns like *.ts specially
2811
+ */
2812
+ static parseCursorFrontmatter(fileContent) {
2813
+ const preprocessedContent = fileContent.replace(
2814
+ /^globs:\s*(\*[^\n]*?)$/m,
2815
+ (_match, globPattern) => {
2816
+ return `globs: "${globPattern}"`;
2817
+ }
2818
+ );
2819
+ return parseFrontmatter(preprocessedContent);
2820
+ }
2728
2821
  toRulesyncRule() {
2729
2822
  const targets = ["*"];
2730
2823
  const isAlways = this.frontmatter.alwaysApply === true;
@@ -2741,13 +2834,18 @@ var CursorRule = class _CursorRule extends ToolRule {
2741
2834
  targets,
2742
2835
  root: false,
2743
2836
  description: this.frontmatter.description,
2744
- globs
2837
+ globs,
2838
+ cursor: {
2839
+ alwaysApply: this.frontmatter.alwaysApply,
2840
+ description: this.frontmatter.description,
2841
+ globs: globs.length > 0 ? globs : void 0
2842
+ }
2745
2843
  };
2746
2844
  return new RulesyncRule({
2747
2845
  frontmatter: rulesyncFrontmatter,
2748
2846
  body: this.body,
2749
2847
  relativeDirPath: ".rulesync/rules",
2750
- relativeFilePath: this.relativeFilePath,
2848
+ relativeFilePath: this.relativeFilePath.replace(/\.mdc$/, ".md"),
2751
2849
  validate: true
2752
2850
  });
2753
2851
  }
@@ -2775,20 +2873,23 @@ var CursorRule = class _CursorRule extends ToolRule {
2775
2873
  validate
2776
2874
  });
2777
2875
  }
2778
- static async fromFilePath({
2779
- filePath,
2876
+ static async fromFile({
2877
+ baseDir = ".",
2878
+ relativeFilePath,
2780
2879
  validate = true
2781
2880
  }) {
2782
- const fileContent = await readFileContent(filePath);
2783
- const { frontmatter, body: content } = parseFrontmatter(fileContent);
2881
+ const fileContent = await readFileContent(join34(baseDir, ".cursor/rules", relativeFilePath));
2882
+ const { frontmatter, body: content } = _CursorRule.parseCursorFrontmatter(fileContent);
2784
2883
  const result = CursorRuleFrontmatterSchema.safeParse(frontmatter);
2785
2884
  if (!result.success) {
2786
- throw new Error(`Invalid frontmatter in ${filePath}: ${result.error.message}`);
2885
+ throw new Error(
2886
+ `Invalid frontmatter in ${join34(baseDir, relativeFilePath)}: ${result.error.message}`
2887
+ );
2787
2888
  }
2788
2889
  return new _CursorRule({
2789
- baseDir: ".",
2890
+ baseDir,
2790
2891
  relativeDirPath: ".cursor/rules",
2791
- relativeFilePath: basename8(filePath),
2892
+ relativeFilePath: basename8(relativeFilePath),
2792
2893
  frontmatter: result.data,
2793
2894
  body: content.trim(),
2794
2895
  validate
@@ -2814,16 +2915,23 @@ var CursorRule = class _CursorRule extends ToolRule {
2814
2915
  };
2815
2916
 
2816
2917
  // src/rules/geminicli-rule.ts
2918
+ import { join as join35 } from "path";
2817
2919
  var GeminiCliRule = class _GeminiCliRule extends ToolRule {
2818
- static async fromFilePath(params) {
2819
- const fileContent = await readFileContent(params.filePath);
2920
+ static async fromFile({
2921
+ baseDir = ".",
2922
+ relativeFilePath,
2923
+ validate = true
2924
+ }) {
2925
+ const isRoot = relativeFilePath === "GEMINI.md";
2926
+ const relativePath = isRoot ? "GEMINI.md" : join35(".gemini/memories", relativeFilePath);
2927
+ const fileContent = await readFileContent(join35(baseDir, relativePath));
2820
2928
  return new _GeminiCliRule({
2821
- baseDir: params.baseDir || process.cwd(),
2822
- relativeDirPath: params.relativeDirPath,
2823
- relativeFilePath: params.relativeFilePath,
2929
+ baseDir,
2930
+ relativeDirPath: isRoot ? "." : ".gemini/memories",
2931
+ relativeFilePath: isRoot ? "GEMINI.md" : relativeFilePath,
2824
2932
  fileContent,
2825
- validate: params.validate ?? true,
2826
- root: params.relativeFilePath === "GEMINI.md"
2933
+ validate,
2934
+ root: isRoot
2827
2935
  });
2828
2936
  }
2829
2937
  static fromRulesyncRule({
@@ -2850,15 +2958,22 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
2850
2958
  };
2851
2959
 
2852
2960
  // src/rules/junie-rule.ts
2961
+ import { join as join36 } from "path";
2853
2962
  var JunieRule = class _JunieRule extends ToolRule {
2854
- static async fromFilePath(params) {
2855
- const fileContent = await readFileContent(params.filePath);
2963
+ static async fromFile({
2964
+ baseDir = ".",
2965
+ relativeFilePath,
2966
+ validate = true
2967
+ }) {
2968
+ const isRoot = relativeFilePath === "guidelines.md";
2969
+ const relativePath = isRoot ? "guidelines.md" : join36(".junie/memories", relativeFilePath);
2970
+ const fileContent = await readFileContent(join36(baseDir, relativePath));
2856
2971
  return new _JunieRule({
2857
- baseDir: params.baseDir || ".",
2858
- relativeDirPath: params.relativeDirPath,
2859
- relativeFilePath: params.relativeFilePath,
2972
+ baseDir,
2973
+ relativeDirPath: isRoot ? ".junie" : ".junie/memories",
2974
+ relativeFilePath: isRoot ? "guidelines.md" : relativeFilePath,
2860
2975
  fileContent,
2861
- validate: params.validate ?? true
2976
+ validate
2862
2977
  });
2863
2978
  }
2864
2979
  static fromRulesyncRule({
@@ -2871,8 +2986,8 @@ var JunieRule = class _JunieRule extends ToolRule {
2871
2986
  baseDir,
2872
2987
  rulesyncRule,
2873
2988
  validate,
2874
- rootPath: { relativeDirPath: ".", relativeFilePath: "guidelines.md" },
2875
- nonRootPath: { relativeDirPath: ".junie/guidelines" }
2989
+ rootPath: { relativeDirPath: ".junie", relativeFilePath: "guidelines.md" },
2990
+ nonRootPath: { relativeDirPath: ".junie/memories" }
2876
2991
  })
2877
2992
  );
2878
2993
  }
@@ -2885,15 +3000,20 @@ var JunieRule = class _JunieRule extends ToolRule {
2885
3000
  };
2886
3001
 
2887
3002
  // src/rules/kiro-rule.ts
3003
+ import { join as join37 } from "path";
2888
3004
  var KiroRule = class _KiroRule extends ToolRule {
2889
- static async fromFilePath(params) {
2890
- const fileContent = await readFileContent(params.filePath);
3005
+ static async fromFile({
3006
+ baseDir = ".",
3007
+ relativeFilePath,
3008
+ validate = true
3009
+ }) {
3010
+ const fileContent = await readFileContent(join37(baseDir, ".kiro/steering", relativeFilePath));
2891
3011
  return new _KiroRule({
2892
- baseDir: params.baseDir || ".",
2893
- relativeDirPath: params.relativeDirPath,
2894
- relativeFilePath: params.relativeFilePath,
3012
+ baseDir,
3013
+ relativeDirPath: ".kiro/steering",
3014
+ relativeFilePath,
2895
3015
  fileContent,
2896
- validate: params.validate ?? true,
3016
+ validate,
2897
3017
  root: false
2898
3018
  });
2899
3019
  }
@@ -2920,21 +3040,22 @@ var KiroRule = class _KiroRule extends ToolRule {
2920
3040
  };
2921
3041
 
2922
3042
  // src/rules/opencode-rule.ts
3043
+ import { join as join38 } from "path";
2923
3044
  var OpenCodeRule = class _OpenCodeRule extends ToolRule {
2924
- static async fromFilePath({
3045
+ static async fromFile({
2925
3046
  baseDir = ".",
2926
- relativeDirPath,
2927
3047
  relativeFilePath,
2928
- filePath,
2929
3048
  validate = true
2930
3049
  }) {
2931
- const fileContent = await readFileContent(filePath);
3050
+ const isRoot = relativeFilePath === "AGENTS.md";
3051
+ const relativePath = isRoot ? "AGENTS.md" : join38(".opencode/memories", relativeFilePath);
3052
+ const fileContent = await readFileContent(join38(baseDir, relativePath));
2932
3053
  return new _OpenCodeRule({
2933
3054
  baseDir,
2934
- relativeDirPath,
2935
- relativeFilePath,
3055
+ relativeDirPath: isRoot ? "." : ".opencode/memories",
3056
+ relativeFilePath: isRoot ? "AGENTS.md" : relativeFilePath,
2936
3057
  validate,
2937
- root: relativeFilePath === "AGENTS.md",
3058
+ root: isRoot,
2938
3059
  fileContent
2939
3060
  });
2940
3061
  }
@@ -2960,16 +3081,23 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
2960
3081
  };
2961
3082
 
2962
3083
  // src/rules/qwencode-rule.ts
3084
+ import { join as join39 } from "path";
2963
3085
  var QwencodeRule = class _QwencodeRule extends ToolRule {
2964
- static async fromFilePath(params) {
2965
- const fileContent = await readFileContent(params.filePath);
3086
+ static async fromFile({
3087
+ baseDir = ".",
3088
+ relativeFilePath,
3089
+ validate = true
3090
+ }) {
3091
+ const isRoot = relativeFilePath === "QWEN.md";
3092
+ const relativePath = isRoot ? "QWEN.md" : join39(".qwencode/memories", relativeFilePath);
3093
+ const fileContent = await readFileContent(join39(baseDir, relativePath));
2966
3094
  return new _QwencodeRule({
2967
- baseDir: params.baseDir || process.cwd(),
2968
- relativeDirPath: params.relativeDirPath,
2969
- relativeFilePath: params.relativeFilePath,
3095
+ baseDir,
3096
+ relativeDirPath: isRoot ? "." : ".qwencode/memories",
3097
+ relativeFilePath: isRoot ? "QWEN.md" : relativeFilePath,
2970
3098
  fileContent,
2971
- validate: params.validate ?? true,
2972
- root: params.relativeFilePath === "QWEN.md"
3099
+ validate,
3100
+ root: isRoot
2973
3101
  });
2974
3102
  }
2975
3103
  static fromRulesyncRule(params) {
@@ -2990,15 +3118,21 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
2990
3118
  };
2991
3119
 
2992
3120
  // src/rules/roo-rule.ts
3121
+ import { join as join40 } from "path";
2993
3122
  var RooRule = class _RooRule extends ToolRule {
2994
- static async fromFilePath(params) {
2995
- const fileContent = await readFileContent(params.filePath);
3123
+ static async fromFile({
3124
+ baseDir = ".",
3125
+ relativeFilePath,
3126
+ validate = true
3127
+ }) {
3128
+ const fileContent = await readFileContent(join40(baseDir, ".roo/rules", relativeFilePath));
2996
3129
  return new _RooRule({
2997
- baseDir: params.baseDir || ".",
2998
- relativeDirPath: params.relativeDirPath,
2999
- relativeFilePath: params.relativeFilePath,
3130
+ baseDir,
3131
+ relativeDirPath: ".roo/rules",
3132
+ relativeFilePath,
3000
3133
  fileContent,
3001
- validate: params.validate ?? true
3134
+ validate,
3135
+ root: false
3002
3136
  });
3003
3137
  }
3004
3138
  static fromRulesyncRule({
@@ -3039,6 +3173,7 @@ var RooRule = class _RooRule extends ToolRule {
3039
3173
  };
3040
3174
 
3041
3175
  // src/rules/warp-rule.ts
3176
+ import { join as join41 } from "path";
3042
3177
  var WarpRule = class _WarpRule extends ToolRule {
3043
3178
  constructor({ fileContent, root, ...rest }) {
3044
3179
  super({
@@ -3047,14 +3182,14 @@ var WarpRule = class _WarpRule extends ToolRule {
3047
3182
  root: root ?? false
3048
3183
  });
3049
3184
  }
3050
- static async fromFilePath({
3185
+ static async fromFile({
3051
3186
  baseDir = ".",
3052
3187
  relativeFilePath,
3053
- filePath,
3054
3188
  validate = true
3055
3189
  }) {
3056
- const fileContent = await readFileContent(filePath);
3057
3190
  const isRoot = relativeFilePath === "WARP.md";
3191
+ const relativePath = isRoot ? "WARP.md" : join41(".warp/memories", relativeFilePath);
3192
+ const fileContent = await readFileContent(join41(baseDir, relativePath));
3058
3193
  return new _WarpRule({
3059
3194
  baseDir,
3060
3195
  relativeDirPath: isRoot ? "." : ".warp",
@@ -3088,14 +3223,20 @@ var WarpRule = class _WarpRule extends ToolRule {
3088
3223
  };
3089
3224
 
3090
3225
  // src/rules/windsurf-rule.ts
3226
+ import { join as join42 } from "path";
3091
3227
  var WindsurfRule = class _WindsurfRule extends ToolRule {
3092
- static async fromFilePath(params) {
3093
- const fileContent = await readFileContent(params.filePath);
3228
+ static async fromFile({
3229
+ baseDir = ".",
3230
+ relativeFilePath,
3231
+ validate = true
3232
+ }) {
3233
+ const fileContent = await readFileContent(join42(baseDir, ".windsurf/rules", relativeFilePath));
3094
3234
  return new _WindsurfRule({
3095
- baseDir: params.baseDir || ".",
3096
- relativeDirPath: params.relativeDirPath,
3097
- relativeFilePath: params.relativeFilePath,
3098
- fileContent
3235
+ baseDir,
3236
+ relativeDirPath: ".windsurf/rules",
3237
+ relativeFilePath,
3238
+ fileContent,
3239
+ validate
3099
3240
  });
3100
3241
  }
3101
3242
  static fromRulesyncRule({
@@ -3353,57 +3494,18 @@ var RulesProcessor = class extends FeatureProcessor {
3353
3494
  * Load and parse rulesync rule files from .rulesync/rules/ directory
3354
3495
  */
3355
3496
  async loadRulesyncFiles() {
3356
- try {
3357
- const rulesDir = join7(this.baseDir, ".rulesync", "rules");
3358
- const dirExists = await directoryExists(rulesDir);
3359
- if (!dirExists) {
3360
- logger.debug(`Rulesync rules directory not found: ${rulesDir}`);
3361
- return [];
3362
- }
3363
- const entries = await listDirectoryFiles(rulesDir);
3364
- const mdFiles = entries.filter((file) => file.endsWith(".md"));
3365
- if (mdFiles.length === 0) {
3366
- logger.debug(`No markdown files found in rulesync rules directory: ${rulesDir}`);
3367
- return [];
3368
- }
3369
- logger.info(`Found ${mdFiles.length} rule files in ${rulesDir}`);
3370
- const rulesyncRules = [];
3371
- for (const mdFile of mdFiles) {
3372
- const filepath = join7(rulesDir, mdFile);
3373
- try {
3374
- const rulesyncRule = await RulesyncRule.fromFilePath({
3375
- filePath: filepath
3376
- });
3377
- rulesyncRules.push(rulesyncRule);
3378
- logger.debug(`Successfully loaded rule: ${mdFile}`);
3379
- } catch (error) {
3380
- logger.warn(`Failed to load rule file ${filepath}:`, error);
3381
- continue;
3382
- }
3383
- }
3384
- if (rulesyncRules.length === 0) {
3385
- logger.debug(`No valid rules found in ${rulesDir}`);
3386
- return [];
3387
- }
3388
- logger.info(`Successfully loaded ${rulesyncRules.length} rulesync rules`);
3389
- return rulesyncRules;
3390
- } catch (error) {
3391
- logger.debug(`No rulesync files found`, error);
3392
- return [];
3393
- }
3497
+ const files = await findFilesByGlobs(join43(RULESYNC_RULES_DIR, "*.md"));
3498
+ logger.debug(`Found ${files.length} rulesync files`);
3499
+ return Promise.all(
3500
+ files.map((file) => RulesyncRule.fromFile({ relativeFilePath: basename9(file) }))
3501
+ );
3394
3502
  }
3395
- async loadLegacyRulesyncFiles() {
3396
- try {
3397
- const legacyFiles = await findFilesByGlobs(join7(RULESYNC_RULES_DIR_LEGACY, "*.md"));
3398
- return Promise.all(
3399
- legacyFiles.map(
3400
- (file) => RulesyncRule.fromLegacyFile({ relativeFilePath: basename9(file) })
3401
- )
3402
- );
3403
- } catch (error) {
3404
- logger.debug(`No legacy rulesync files found`, error);
3405
- return [];
3406
- }
3503
+ async loadRulesyncFilesLegacy() {
3504
+ const legacyFiles = await findFilesByGlobs(join43(RULESYNC_RULES_DIR_LEGACY, "*.md"));
3505
+ logger.debug(`Found ${legacyFiles.length} legacy rulesync files`);
3506
+ return Promise.all(
3507
+ legacyFiles.map((file) => RulesyncRule.fromFileLegacy({ relativeFilePath: basename9(file) }))
3508
+ );
3407
3509
  }
3408
3510
  /**
3409
3511
  * Implementation of abstract method from FeatureProcessor
@@ -3454,527 +3556,296 @@ var RulesProcessor = class extends FeatureProcessor {
3454
3556
  return [];
3455
3557
  }
3456
3558
  }
3559
+ async loadToolRulesDefault({
3560
+ root,
3561
+ nonRoot
3562
+ }) {
3563
+ const rootToolRules = await (async () => {
3564
+ if (!root) {
3565
+ return [];
3566
+ }
3567
+ const rootFilePaths = await findFilesByGlobs(
3568
+ join43(this.baseDir, root.relativeDirPath ?? ".", root.relativeFilePath)
3569
+ );
3570
+ return await Promise.all(
3571
+ rootFilePaths.map(
3572
+ (filePath) => root.fromFile({
3573
+ baseDir: this.baseDir,
3574
+ relativeFilePath: basename9(filePath)
3575
+ })
3576
+ )
3577
+ );
3578
+ })();
3579
+ logger.debug(`Found ${rootToolRules.length} root tool rule files`);
3580
+ const nonRootToolRules = await (async () => {
3581
+ if (!nonRoot) {
3582
+ return [];
3583
+ }
3584
+ const nonRootFilePaths = await findFilesByGlobs(
3585
+ join43(this.baseDir, nonRoot.relativeFilePath, `*.${nonRoot.extension}`)
3586
+ );
3587
+ return await Promise.all(
3588
+ nonRootFilePaths.map(
3589
+ (filePath) => nonRoot.fromFile({
3590
+ baseDir: this.baseDir,
3591
+ relativeFilePath: basename9(filePath)
3592
+ })
3593
+ )
3594
+ );
3595
+ })();
3596
+ logger.debug(`Found ${nonRootToolRules.length} non-root tool rule files`);
3597
+ return [...rootToolRules, ...nonRootToolRules];
3598
+ }
3457
3599
  /**
3458
3600
  * Load AGENTS.md rule configuration
3459
3601
  */
3460
3602
  async loadAgentsmdRules() {
3461
- const agentsFile = join7(this.baseDir, "AGENTS.md");
3462
- if (!await fileExists(agentsFile)) {
3463
- logger.warn(`AGENTS.md file not found: ${agentsFile}`);
3464
- return [];
3465
- }
3466
- try {
3467
- const agentsmdRule = await AgentsMdRule.fromFilePath({
3468
- baseDir: this.baseDir,
3603
+ return await this.loadToolRulesDefault({
3604
+ root: {
3469
3605
  relativeDirPath: ".",
3470
3606
  relativeFilePath: "AGENTS.md",
3471
- filePath: agentsFile,
3472
- validate: true
3473
- });
3474
- logger.info(`Successfully loaded AGENTS.md rule`);
3475
- return [agentsmdRule];
3476
- } catch (error) {
3477
- logger.warn(`Failed to load AGENTS.md file ${agentsFile}:`, error);
3478
- return [];
3479
- }
3607
+ fromFile: (params) => AgentsMdRule.fromFile(params)
3608
+ },
3609
+ nonRoot: {
3610
+ relativeFilePath: ".agents/memories",
3611
+ fromFile: (params) => AgentsMdRule.fromFile(params),
3612
+ extension: "md"
3613
+ }
3614
+ });
3480
3615
  }
3481
3616
  async loadWarpRules() {
3482
- const rootFilePaths = await findFilesByGlobs(join7(this.baseDir, "WARP.md"));
3483
- const nonRootFilePaths = await findFilesByGlobs(join7(this.baseDir, ".warp/memories/*.md"));
3484
- const rootFiles = await Promise.all(
3485
- rootFilePaths.map(
3486
- (filePath) => WarpRule.fromFilePath({
3487
- filePath,
3488
- validate: true,
3489
- relativeDirPath: ".",
3490
- relativeFilePath: "WARP.md"
3491
- })
3492
- )
3493
- );
3494
- const nonRootFiles = await Promise.all(
3495
- nonRootFilePaths.map(
3496
- (filePath) => WarpRule.fromFilePath({
3497
- filePath,
3498
- validate: true,
3499
- relativeDirPath: ".warp/memories",
3500
- relativeFilePath: basename9(filePath)
3501
- })
3502
- )
3503
- );
3504
- return [...rootFiles, ...nonRootFiles];
3617
+ return await this.loadToolRulesDefault({
3618
+ root: {
3619
+ relativeDirPath: ".",
3620
+ relativeFilePath: "WARP.md",
3621
+ fromFile: (params) => WarpRule.fromFile(params)
3622
+ },
3623
+ nonRoot: {
3624
+ relativeFilePath: ".warp/memories",
3625
+ fromFile: (params) => WarpRule.fromFile(params),
3626
+ extension: "md"
3627
+ }
3628
+ });
3505
3629
  }
3506
3630
  /**
3507
3631
  * Load Amazon Q Developer CLI rule configurations from .amazonq/rules/ directory
3508
3632
  */
3509
3633
  async loadAmazonqcliRules() {
3510
- return this.loadToolRulesFromDirectory(
3511
- join7(this.baseDir, ".amazonq", "rules"),
3512
- (filePath, relativeFilePath) => AmazonQCliRule.fromFilePath({
3513
- baseDir: this.baseDir,
3514
- relativeDirPath: ".amazonq/rules",
3515
- relativeFilePath,
3516
- filePath,
3517
- validate: true
3518
- }),
3519
- "Amazon Q Developer CLI"
3520
- );
3634
+ return await this.loadToolRulesDefault({
3635
+ nonRoot: {
3636
+ relativeFilePath: ".amazonq/rules",
3637
+ fromFile: (params) => AmazonQCliRule.fromFile(params),
3638
+ extension: "md"
3639
+ }
3640
+ });
3521
3641
  }
3522
3642
  /**
3523
3643
  * Load AugmentCode rule configurations from .augment/rules/ directory
3524
3644
  */
3525
3645
  async loadAugmentcodeRules() {
3526
- return this.loadToolRulesFromDirectory(
3527
- join7(this.baseDir, ".augment", "rules"),
3528
- (filePath, relativeFilePath) => AugmentcodeRule.fromFilePath({
3529
- baseDir: this.baseDir,
3530
- relativeDirPath: ".augment/rules",
3531
- relativeFilePath,
3532
- filePath,
3533
- validate: true
3534
- }),
3535
- "AugmentCode"
3536
- );
3646
+ return await this.loadToolRulesDefault({
3647
+ nonRoot: {
3648
+ relativeFilePath: ".augment/rules",
3649
+ fromFile: (params) => AugmentcodeRule.fromFile(params),
3650
+ extension: "md"
3651
+ }
3652
+ });
3537
3653
  }
3538
3654
  /**
3539
3655
  * Load AugmentCode legacy rule configuration from .augment-guidelines file and .augment/rules/ directory
3540
3656
  */
3541
3657
  async loadAugmentcodeLegacyRules() {
3542
- const toolRules = [];
3543
- const guidelinesFile = join7(this.baseDir, ".augment-guidelines");
3544
- if (await fileExists(guidelinesFile)) {
3545
- try {
3546
- const augmentcodeLegacyRule = await AugmentcodeLegacyRule.fromFilePath({
3547
- baseDir: this.baseDir,
3548
- relativeDirPath: ".",
3549
- relativeFilePath: ".augment-guidelines",
3550
- filePath: guidelinesFile,
3551
- validate: true
3552
- });
3553
- toolRules.push(augmentcodeLegacyRule);
3554
- logger.info(`Successfully loaded AugmentCode legacy guidelines`);
3555
- } catch (error) {
3556
- logger.warn(`Failed to load AugmentCode legacy guidelines file ${guidelinesFile}:`, error);
3658
+ return await this.loadToolRulesDefault({
3659
+ root: {
3660
+ relativeDirPath: ".",
3661
+ relativeFilePath: ".augment-guidelines",
3662
+ fromFile: (params) => AugmentcodeLegacyRule.fromFile(params)
3663
+ },
3664
+ nonRoot: {
3665
+ relativeFilePath: ".augment/rules",
3666
+ fromFile: (params) => AugmentcodeLegacyRule.fromFile(params),
3667
+ extension: "md"
3557
3668
  }
3558
- }
3559
- const rulesDir = join7(this.baseDir, ".augment", "rules");
3560
- if (await directoryExists(rulesDir)) {
3561
- const dirRules = await this.loadToolRulesFromDirectory(
3562
- rulesDir,
3563
- (filePath, relativeFilePath) => AugmentcodeLegacyRule.fromFilePath({
3564
- baseDir: this.baseDir,
3565
- relativeDirPath: join7(".augment", "rules"),
3566
- relativeFilePath,
3567
- filePath,
3568
- validate: true
3569
- }),
3570
- "AugmentCode Legacy"
3571
- );
3572
- toolRules.push(...dirRules);
3573
- }
3574
- return toolRules;
3669
+ });
3575
3670
  }
3576
3671
  /**
3577
3672
  * Load Claude Code rule configuration from CLAUDE.md file
3578
3673
  */
3579
3674
  async loadClaudecodeRules() {
3580
- const claudeMemoriesDir = join7(this.baseDir, ".claude", "memories");
3581
- if (!await directoryExists(claudeMemoriesDir)) {
3582
- logger.debug(`Claude Code memories directory not found: ${claudeMemoriesDir}`);
3583
- const claudeFile = join7(this.baseDir, "CLAUDE.md");
3584
- if (!await fileExists(claudeFile)) {
3585
- logger.debug(`Claude Code memory file not found: ${claudeFile}`);
3586
- return [];
3587
- }
3588
- try {
3589
- const claudecodeRule = await ClaudecodeRule.fromFilePath({
3590
- baseDir: this.baseDir,
3591
- relativeDirPath: ".",
3592
- relativeFilePath: "CLAUDE.md",
3593
- filePath: claudeFile,
3594
- validate: true
3595
- });
3596
- logger.info(`Successfully loaded Claude Code memory file`);
3597
- return [claudecodeRule];
3598
- } catch (error) {
3599
- logger.warn(`Failed to load Claude Code memory file ${claudeFile}:`, error);
3600
- return [];
3601
- }
3602
- }
3603
- const entries = await listDirectoryFiles(claudeMemoriesDir);
3604
- const mdFiles = entries.filter((file) => file.endsWith(".md"));
3605
- if (mdFiles.length === 0) {
3606
- logger.debug(
3607
- `No markdown files found in Claude Code memories directory: ${claudeMemoriesDir}`
3608
- );
3609
- return [];
3610
- }
3611
- logger.info(`Found ${mdFiles.length} Claude Code memory files in ${claudeMemoriesDir}`);
3612
- const toolRules = [];
3613
- for (const mdFile of mdFiles) {
3614
- const filePath = join7(claudeMemoriesDir, mdFile);
3615
- try {
3616
- const claudecodeRule = await ClaudecodeRule.fromFilePath({
3617
- baseDir: this.baseDir,
3618
- relativeDirPath: join7(".claude", "memories"),
3619
- relativeFilePath: mdFile,
3620
- filePath,
3621
- validate: true
3622
- });
3623
- toolRules.push(claudecodeRule);
3624
- logger.debug(`Successfully loaded Claude Code memory file: ${mdFile}`);
3625
- } catch (error) {
3626
- logger.warn(`Failed to load Claude Code memory file ${filePath}:`, error);
3627
- continue;
3675
+ return await this.loadToolRulesDefault({
3676
+ root: {
3677
+ relativeDirPath: ".",
3678
+ relativeFilePath: "CLAUDE.md",
3679
+ fromFile: (params) => ClaudecodeRule.fromFile(params)
3680
+ },
3681
+ nonRoot: {
3682
+ relativeFilePath: ".claude/memories",
3683
+ fromFile: (params) => ClaudecodeRule.fromFile(params),
3684
+ extension: "md"
3628
3685
  }
3629
- }
3630
- logger.info(`Successfully loaded ${toolRules.length} Claude Code memory files`);
3631
- return toolRules;
3686
+ });
3632
3687
  }
3633
3688
  /**
3634
3689
  * Load Cline rule configurations from .clinerules/ directory
3635
3690
  */
3636
3691
  async loadClineRules() {
3637
- return this.loadToolRulesFromDirectory(
3638
- join7(this.baseDir, ".clinerules"),
3639
- (filePath, relativeFilePath) => ClineRule.fromFilePath({
3640
- baseDir: this.baseDir,
3641
- relativeDirPath: ".clinerules",
3642
- relativeFilePath,
3643
- filePath,
3644
- validate: true
3645
- }),
3646
- "Cline"
3647
- );
3692
+ return await this.loadToolRulesDefault({
3693
+ nonRoot: {
3694
+ relativeFilePath: ".clinerules",
3695
+ fromFile: (params) => ClineRule.fromFile(params),
3696
+ extension: "md"
3697
+ }
3698
+ });
3648
3699
  }
3649
3700
  /**
3650
3701
  * Load OpenAI Codex CLI rule configuration from AGENTS.md and .codex/memories/*.md files
3651
3702
  */
3652
3703
  async loadCodexcliRules() {
3653
- const rules = [];
3654
- const agentsFile = join7(this.baseDir, "AGENTS.md");
3655
- if (await fileExists(agentsFile)) {
3656
- try {
3657
- const codexcliRule = await CodexcliRule.fromFilePath({
3658
- baseDir: this.baseDir,
3659
- relativeDirPath: ".",
3660
- relativeFilePath: "AGENTS.md",
3661
- filePath: agentsFile,
3662
- validate: true
3663
- });
3664
- rules.push(codexcliRule);
3665
- logger.info(`Successfully loaded OpenAI Codex CLI agents file`);
3666
- } catch (error) {
3667
- logger.warn(`Failed to load OpenAI Codex CLI agents file ${agentsFile}:`, error);
3668
- }
3669
- }
3670
- const memoriesDir = join7(this.baseDir, ".codex", "memories");
3671
- if (await directoryExists(memoriesDir)) {
3672
- try {
3673
- const entries = await listDirectoryFiles(memoriesDir);
3674
- const mdFiles = entries.filter((file) => file.endsWith(".md"));
3675
- for (const mdFile of mdFiles) {
3676
- const filePath = join7(memoriesDir, mdFile);
3677
- try {
3678
- const codexcliRule = await CodexcliRule.fromFilePath({
3679
- baseDir: this.baseDir,
3680
- relativeDirPath: join7(".codex", "memories"),
3681
- relativeFilePath: mdFile,
3682
- filePath,
3683
- validate: true
3684
- });
3685
- rules.push(codexcliRule);
3686
- } catch (error) {
3687
- logger.warn(`Failed to load Codex CLI memories file ${filePath}:`, error);
3688
- }
3689
- }
3690
- if (mdFiles.length > 0) {
3691
- logger.info(`Successfully loaded ${mdFiles.length} OpenAI Codex CLI memory files`);
3692
- }
3693
- } catch (error) {
3694
- logger.warn(`Failed to read OpenAI Codex CLI memories directory ${memoriesDir}:`, error);
3704
+ return await this.loadToolRulesDefault({
3705
+ root: {
3706
+ relativeDirPath: ".",
3707
+ relativeFilePath: "AGENTS.md",
3708
+ fromFile: (params) => CodexcliRule.fromFile(params)
3709
+ },
3710
+ nonRoot: {
3711
+ relativeFilePath: ".codex/memories",
3712
+ fromFile: (params) => CodexcliRule.fromFile(params),
3713
+ extension: "md"
3695
3714
  }
3696
- }
3697
- if (rules.length === 0) {
3698
- logger.warn(`No OpenAI Codex CLI rule files found`);
3699
- }
3700
- return rules;
3715
+ });
3701
3716
  }
3702
3717
  /**
3703
3718
  * Load GitHub Copilot rule configuration from .github/copilot-instructions.md file
3704
3719
  */
3705
3720
  async loadCopilotRules() {
3706
- const copilotFile = join7(this.baseDir, ".github", "copilot-instructions.md");
3707
- if (!await fileExists(copilotFile)) {
3708
- logger.warn(`GitHub Copilot instructions file not found: ${copilotFile}`);
3709
- return [];
3710
- }
3711
- try {
3712
- const copilotRule = await CopilotRule.fromFilePath({
3713
- baseDir: this.baseDir,
3714
- relativeDirPath: ".github",
3715
- relativeFilePath: "copilot-instructions.md",
3716
- filePath: copilotFile,
3717
- validate: true
3718
- });
3719
- logger.info(`Successfully loaded GitHub Copilot instructions file`);
3720
- return [copilotRule];
3721
- } catch (error) {
3722
- logger.warn(`Failed to load GitHub Copilot instructions file ${copilotFile}:`, error);
3723
- return [];
3724
- }
3721
+ return await this.loadToolRulesDefault({
3722
+ root: {
3723
+ relativeDirPath: ".",
3724
+ relativeFilePath: ".github/copilot-instructions.md",
3725
+ fromFile: (params) => CopilotRule.fromFile(params)
3726
+ },
3727
+ nonRoot: {
3728
+ relativeFilePath: ".github/instructions",
3729
+ fromFile: (params) => CopilotRule.fromFile(params),
3730
+ extension: "md"
3731
+ }
3732
+ });
3725
3733
  }
3726
3734
  /**
3727
3735
  * Load Cursor rule configurations from .cursor/rules/ directory
3728
3736
  */
3729
3737
  async loadCursorRules() {
3730
- return this.loadToolRulesFromDirectory(
3731
- join7(this.baseDir, ".cursor", "rules"),
3732
- (filePath) => CursorRule.fromFilePath({
3733
- filePath,
3734
- validate: true
3735
- }),
3736
- "Cursor"
3737
- );
3738
+ return await this.loadToolRulesDefault({
3739
+ nonRoot: {
3740
+ relativeFilePath: ".cursor/rules",
3741
+ fromFile: (params) => CursorRule.fromFile(params),
3742
+ extension: "md"
3743
+ }
3744
+ });
3738
3745
  }
3739
3746
  /**
3740
3747
  * Load Gemini CLI rule configuration from GEMINI.md file
3741
3748
  */
3742
3749
  async loadGeminicliRules() {
3743
- const geminiFile = join7(this.baseDir, "GEMINI.md");
3744
- if (!await fileExists(geminiFile)) {
3745
- logger.warn(`Gemini CLI memory file not found: ${geminiFile}`);
3746
- return [];
3747
- }
3748
- try {
3749
- const geminicliRule = await GeminiCliRule.fromFilePath({
3750
- baseDir: this.baseDir,
3750
+ return await this.loadToolRulesDefault({
3751
+ root: {
3751
3752
  relativeDirPath: ".",
3752
3753
  relativeFilePath: "GEMINI.md",
3753
- filePath: geminiFile,
3754
- validate: true
3755
- });
3756
- logger.info(`Successfully loaded Gemini CLI memory file`);
3757
- return [geminicliRule];
3758
- } catch (error) {
3759
- logger.warn(`Failed to load Gemini CLI memory file ${geminiFile}:`, error);
3760
- return [];
3761
- }
3754
+ fromFile: (params) => GeminiCliRule.fromFile(params)
3755
+ },
3756
+ nonRoot: {
3757
+ relativeFilePath: ".gemini/memories",
3758
+ fromFile: (params) => GeminiCliRule.fromFile(params),
3759
+ extension: "md"
3760
+ }
3761
+ });
3762
3762
  }
3763
3763
  /**
3764
3764
  * Load JetBrains Junie rule configuration from .junie/guidelines.md file
3765
3765
  */
3766
3766
  async loadJunieRules() {
3767
- const guidelinesFile = join7(this.baseDir, ".junie", "guidelines.md");
3768
- if (!await fileExists(guidelinesFile)) {
3769
- return [];
3770
- }
3771
- const junieRule = await JunieRule.fromFilePath({
3772
- baseDir: this.baseDir,
3773
- relativeDirPath: ".junie",
3774
- relativeFilePath: "guidelines.md",
3775
- filePath: guidelinesFile,
3776
- validate: true
3767
+ return await this.loadToolRulesDefault({
3768
+ root: {
3769
+ relativeDirPath: ".",
3770
+ relativeFilePath: ".junie/guidelines.md",
3771
+ fromFile: (params) => JunieRule.fromFile(params)
3772
+ },
3773
+ nonRoot: {
3774
+ relativeFilePath: ".junie/memories",
3775
+ fromFile: (params) => JunieRule.fromFile(params),
3776
+ extension: "md"
3777
+ }
3777
3778
  });
3778
- logger.info(`Successfully loaded JetBrains Junie guidelines file`);
3779
- return [junieRule];
3780
3779
  }
3781
3780
  /**
3782
3781
  * Load Kiro rule configurations from .kiro/steering/ directory
3783
3782
  */
3784
3783
  async loadKiroRules() {
3785
- return this.loadToolRulesFromDirectory(
3786
- join7(this.baseDir, ".kiro", "steering"),
3787
- (filePath, relativeFilePath) => KiroRule.fromFilePath({
3788
- baseDir: this.baseDir,
3789
- relativeDirPath: ".kiro/steering",
3790
- relativeFilePath,
3791
- filePath,
3792
- validate: true
3793
- }),
3794
- "Kiro"
3795
- );
3784
+ return await this.loadToolRulesDefault({
3785
+ nonRoot: {
3786
+ relativeFilePath: ".kiro/steering",
3787
+ fromFile: (params) => KiroRule.fromFile(params),
3788
+ extension: "md"
3789
+ }
3790
+ });
3796
3791
  }
3797
3792
  /**
3798
3793
  * Load OpenCode rule configuration from AGENTS.md file and .opencode/memories/*.md files
3799
3794
  */
3800
3795
  async loadOpencodeRules() {
3801
- const rules = [];
3802
- const agentsFile = join7(this.baseDir, "AGENTS.md");
3803
- if (await fileExists(agentsFile)) {
3804
- try {
3805
- const opencodeRule = await OpenCodeRule.fromFilePath({
3806
- baseDir: this.baseDir,
3807
- relativeDirPath: ".",
3808
- relativeFilePath: "AGENTS.md",
3809
- filePath: agentsFile,
3810
- validate: true
3811
- });
3812
- rules.push(opencodeRule);
3813
- logger.info(`Successfully loaded OpenCode agents file`);
3814
- } catch (error) {
3815
- logger.warn(`Failed to load OpenCode agents file ${agentsFile}:`, error);
3816
- }
3817
- }
3818
- const memoriesDir = join7(this.baseDir, ".opencode", "memories");
3819
- if (await directoryExists(memoriesDir)) {
3820
- try {
3821
- const entries = await listDirectoryFiles(memoriesDir);
3822
- const mdFiles = entries.filter((file) => file.endsWith(".md"));
3823
- for (const mdFile of mdFiles) {
3824
- const filePath = join7(memoriesDir, mdFile);
3825
- try {
3826
- const opencodeRule = await OpenCodeRule.fromFilePath({
3827
- baseDir: this.baseDir,
3828
- relativeDirPath: join7(".opencode", "memories"),
3829
- relativeFilePath: mdFile,
3830
- filePath,
3831
- validate: true
3832
- });
3833
- rules.push(opencodeRule);
3834
- } catch (error) {
3835
- logger.warn(`Failed to load OpenCode memories file ${filePath}:`, error);
3836
- }
3837
- }
3838
- if (mdFiles.length > 0) {
3839
- logger.info(`Successfully loaded ${mdFiles.length} OpenCode memory files`);
3840
- }
3841
- } catch (error) {
3842
- logger.warn(`Failed to read OpenCode memories directory ${memoriesDir}:`, error);
3796
+ return await this.loadToolRulesDefault({
3797
+ root: {
3798
+ relativeDirPath: ".",
3799
+ relativeFilePath: "AGENTS.md",
3800
+ fromFile: (params) => OpenCodeRule.fromFile(params)
3801
+ },
3802
+ nonRoot: {
3803
+ relativeFilePath: ".opencode/memories",
3804
+ fromFile: (params) => OpenCodeRule.fromFile(params),
3805
+ extension: "md"
3843
3806
  }
3844
- }
3845
- if (rules.length === 0) {
3846
- logger.warn(`No OpenCode rule files found`);
3847
- }
3848
- return rules;
3807
+ });
3849
3808
  }
3850
3809
  /**
3851
3810
  * Load Qwen Code rule configuration from QWEN.md file and .qwen/memories/*.md files
3852
3811
  */
3853
3812
  async loadQwencodeRules() {
3854
- const rules = [];
3855
- const qwenFile = join7(this.baseDir, "QWEN.md");
3856
- if (await fileExists(qwenFile)) {
3857
- try {
3858
- const qwencodeRule = await QwencodeRule.fromFilePath({
3859
- baseDir: this.baseDir,
3860
- relativeDirPath: ".",
3861
- relativeFilePath: "QWEN.md",
3862
- filePath: qwenFile,
3863
- validate: true
3864
- });
3865
- rules.push(qwencodeRule);
3866
- logger.info(`Successfully loaded Qwen Code memory file`);
3867
- } catch (error) {
3868
- logger.warn(`Failed to load Qwen Code memory file ${qwenFile}:`, error);
3869
- }
3870
- }
3871
- const memoriesDir = join7(this.baseDir, ".qwen", "memories");
3872
- if (await directoryExists(memoriesDir)) {
3873
- try {
3874
- const entries = await listDirectoryFiles(memoriesDir);
3875
- const mdFiles = entries.filter((file) => file.endsWith(".md"));
3876
- for (const mdFile of mdFiles) {
3877
- const filePath = join7(memoriesDir, mdFile);
3878
- try {
3879
- const qwencodeRule = await QwencodeRule.fromFilePath({
3880
- baseDir: this.baseDir,
3881
- relativeDirPath: join7(".qwen", "memories"),
3882
- relativeFilePath: mdFile,
3883
- filePath,
3884
- validate: true
3885
- });
3886
- rules.push(qwencodeRule);
3887
- } catch (error) {
3888
- logger.warn(`Failed to load Qwen Code memories file ${filePath}:`, error);
3889
- }
3890
- }
3891
- if (mdFiles.length > 0) {
3892
- logger.info(`Successfully loaded ${mdFiles.length} Qwen Code memory files`);
3893
- }
3894
- } catch (error) {
3895
- logger.warn(`Failed to read Qwen Code memories directory ${memoriesDir}:`, error);
3813
+ return await this.loadToolRulesDefault({
3814
+ root: {
3815
+ relativeDirPath: ".",
3816
+ relativeFilePath: "QWEN.md",
3817
+ fromFile: (params) => QwencodeRule.fromFile(params)
3818
+ },
3819
+ nonRoot: {
3820
+ relativeFilePath: ".qwen/memories",
3821
+ fromFile: (params) => QwencodeRule.fromFile(params),
3822
+ extension: "md"
3896
3823
  }
3897
- }
3898
- if (rules.length === 0) {
3899
- logger.warn(`No Qwen Code rule files found`);
3900
- }
3901
- return rules;
3824
+ });
3902
3825
  }
3903
3826
  /**
3904
3827
  * Load Roo Code rule configurations from .roo/rules/ directory
3905
3828
  */
3906
3829
  async loadRooRules() {
3907
- return this.loadToolRulesFromDirectory(
3908
- join7(this.baseDir, ".roo", "rules"),
3909
- (filePath, relativeFilePath) => RooRule.fromFilePath({
3910
- baseDir: this.baseDir,
3911
- relativeDirPath: ".roo/rules",
3912
- relativeFilePath,
3913
- filePath,
3914
- validate: true
3915
- }),
3916
- "Roo Code"
3917
- );
3830
+ return await this.loadToolRulesDefault({
3831
+ nonRoot: {
3832
+ relativeFilePath: ".roo/rules",
3833
+ fromFile: (params) => RooRule.fromFile(params),
3834
+ extension: "md"
3835
+ }
3836
+ });
3918
3837
  }
3919
3838
  /**
3920
3839
  * Load Windsurf rule configurations from .windsurf/rules/ directory
3921
3840
  */
3922
3841
  async loadWindsurfRules() {
3923
- return this.loadToolRulesFromDirectory(
3924
- join7(this.baseDir, ".windsurf", "rules"),
3925
- (filePath, relativeFilePath) => WindsurfRule.fromFilePath({
3926
- baseDir: this.baseDir,
3927
- relativeDirPath: ".windsurf/rules",
3928
- relativeFilePath,
3929
- filePath,
3930
- validate: true
3931
- }),
3932
- "Windsurf"
3933
- );
3934
- }
3935
- /**
3936
- * Common helper method to load tool rules from a directory with parallel processing
3937
- */
3938
- async loadToolRulesFromDirectory(dirPath, ruleFactory, toolName) {
3939
- if (!await directoryExists(dirPath)) {
3940
- logger.warn(`${toolName} rules directory not found: ${dirPath}`);
3941
- return [];
3942
- }
3943
- const entries = await listDirectoryFiles(dirPath);
3944
- const mdFiles = entries.filter((file) => file.endsWith(".md") || file.endsWith(".mdc"));
3945
- if (mdFiles.length === 0) {
3946
- logger.info(`No rule files found in ${dirPath}`);
3947
- return [];
3948
- }
3949
- logger.info(`Found ${mdFiles.length} ${toolName} rule files in ${dirPath}`);
3950
- const results = await Promise.allSettled(
3951
- mdFiles.map(async (mdFile) => {
3952
- const filepath = join7(dirPath, mdFile);
3953
- return {
3954
- rule: await ruleFactory(filepath, mdFile),
3955
- filename: mdFile
3956
- };
3957
- })
3958
- );
3959
- const toolRules = [];
3960
- for (const [index, result] of results.entries()) {
3961
- if (result.status === "fulfilled") {
3962
- toolRules.push(result.value.rule);
3963
- logger.debug(`Successfully loaded ${toolName} rule: ${result.value.filename}`);
3964
- } else {
3965
- logger.warn(`Failed to load ${toolName} rule file ${mdFiles[index]}:`, result.reason);
3842
+ return await this.loadToolRulesDefault({
3843
+ nonRoot: {
3844
+ relativeFilePath: ".windsurf/rules",
3845
+ fromFile: (params) => WindsurfRule.fromFile(params),
3846
+ extension: "md"
3966
3847
  }
3967
- }
3968
- logger.info(`Successfully loaded ${toolRules.length} ${toolName} rules`);
3969
- return toolRules;
3970
- }
3971
- async writeToolRulesFromRulesyncRules(rulesyncRules) {
3972
- const toolRules = await this.convertRulesyncFilesToToolFiles(rulesyncRules);
3973
- await this.writeAiFiles(toolRules);
3974
- }
3975
- async writeRulesyncRulesFromToolRules(toolRules) {
3976
- const rulesyncRules = await this.convertToolFilesToRulesyncFiles(toolRules);
3977
- await this.writeAiFiles(rulesyncRules);
3848
+ });
3978
3849
  }
3979
3850
  /**
3980
3851
  * Implementation of abstract method from FeatureProcessor
@@ -3983,30 +3854,6 @@ var RulesProcessor = class extends FeatureProcessor {
3983
3854
  static getToolTargets() {
3984
3855
  return rulesProcessorToolTargets;
3985
3856
  }
3986
- /**
3987
- * Get all supported tools
3988
- */
3989
- static getSupportedTools() {
3990
- const allTools = [
3991
- "agentsmd",
3992
- "amazonqcli",
3993
- "augmentcode",
3994
- "augmentcode-legacy",
3995
- "claudecode",
3996
- "cline",
3997
- "codexcli",
3998
- "copilot",
3999
- "cursor",
4000
- "geminicli",
4001
- "junie",
4002
- "kiro",
4003
- "opencode",
4004
- "qwencode",
4005
- "roo",
4006
- "windsurf"
4007
- ];
4008
- return allTools;
4009
- }
4010
3857
  generateXmlReferencesSection(toolRules) {
4011
3858
  const toolRulesWithoutRoot = toolRules.filter((rule) => !rule.isRoot());
4012
3859
  if (toolRulesWithoutRoot.length === 0) {
@@ -4067,14 +3914,15 @@ var RulesProcessor = class extends FeatureProcessor {
4067
3914
  };
4068
3915
 
4069
3916
  // src/subagents/subagents-processor.ts
4070
- import { join as join8 } from "path";
3917
+ import { basename as basename11, join as join46 } from "path";
4071
3918
  import { z as z19 } from "zod/mini";
4072
3919
 
4073
3920
  // src/subagents/claudecode-subagent.ts
3921
+ import { join as join45 } from "path";
4074
3922
  import { z as z18 } from "zod/mini";
4075
3923
 
4076
3924
  // src/subagents/rulesync-subagent.ts
4077
- import { basename as basename10 } from "path";
3925
+ import { basename as basename10, join as join44 } from "path";
4078
3926
  import { z as z17 } from "zod/mini";
4079
3927
  var RulesyncSubagentModelSchema = z17.enum(["opus", "sonnet", "haiku", "inherit"]);
4080
3928
  var RulesyncSubagentFrontmatterSchema = z17.object({
@@ -4120,14 +3968,16 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
4120
3968
  return { success: false, error: result.error };
4121
3969
  }
4122
3970
  }
4123
- static async fromFilePath({ filePath }) {
4124
- const fileContent = await readFileContent(filePath);
3971
+ static async fromFile({
3972
+ relativeFilePath
3973
+ }) {
3974
+ const fileContent = await readFileContent(join44(RULESYNC_SUBAGENTS_DIR, relativeFilePath));
4125
3975
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
4126
3976
  const result = RulesyncSubagentFrontmatterSchema.safeParse(frontmatter);
4127
3977
  if (!result.success) {
4128
- throw new Error(`Invalid frontmatter in ${filePath}: ${result.error.message}`);
3978
+ throw new Error(`Invalid frontmatter in ${relativeFilePath}: ${result.error.message}`);
4129
3979
  }
4130
- const filename = basename10(filePath);
3980
+ const filename = basename10(relativeFilePath);
4131
3981
  return new _RulesyncSubagent({
4132
3982
  baseDir: ".",
4133
3983
  relativeDirPath: ".rulesync/subagents",
@@ -4141,7 +3991,7 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
4141
3991
 
4142
3992
  // src/subagents/tool-subagent.ts
4143
3993
  var ToolSubagent = class extends ToolFile {
4144
- static async fromFilePath(_params) {
3994
+ static async fromFile(_params) {
4145
3995
  throw new Error("Please implement this method in the subclass.");
4146
3996
  }
4147
3997
  static fromRulesyncSubagent(_params) {
@@ -4202,7 +4052,6 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4202
4052
  static fromRulesyncSubagent({
4203
4053
  baseDir = ".",
4204
4054
  rulesyncSubagent,
4205
- relativeDirPath,
4206
4055
  validate = true
4207
4056
  }) {
4208
4057
  const rulesyncFrontmatter = rulesyncSubagent.getFrontmatter();
@@ -4217,7 +4066,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4217
4066
  baseDir,
4218
4067
  frontmatter: claudecodeFrontmatter,
4219
4068
  body,
4220
- relativeDirPath,
4069
+ relativeDirPath: ".claude/agents",
4221
4070
  relativeFilePath: rulesyncSubagent.getRelativeFilePath(),
4222
4071
  fileContent,
4223
4072
  validate
@@ -4234,22 +4083,20 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4234
4083
  return { success: false, error: result.error };
4235
4084
  }
4236
4085
  }
4237
- static async fromFilePath({
4086
+ static async fromFile({
4238
4087
  baseDir = ".",
4239
- relativeDirPath,
4240
4088
  relativeFilePath,
4241
- filePath,
4242
4089
  validate = true
4243
4090
  }) {
4244
- const fileContent = await readFileContent(filePath);
4091
+ const fileContent = await readFileContent(join45(baseDir, ".claude/agents", relativeFilePath));
4245
4092
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
4246
4093
  const result = ClaudecodeSubagentFrontmatterSchema.safeParse(frontmatter);
4247
4094
  if (!result.success) {
4248
- throw new Error(`Invalid frontmatter in ${filePath}: ${result.error.message}`);
4095
+ throw new Error(`Invalid frontmatter in ${relativeFilePath}: ${result.error.message}`);
4249
4096
  }
4250
4097
  return new _ClaudecodeSubagent({
4251
4098
  baseDir,
4252
- relativeDirPath,
4099
+ relativeDirPath: ".claude/agents",
4253
4100
  relativeFilePath,
4254
4101
  frontmatter: result.data,
4255
4102
  body: content.trim(),
@@ -4303,7 +4150,7 @@ var SubagentsProcessor = class extends FeatureProcessor {
4303
4150
  * Load and parse rulesync subagent files from .rulesync/subagents/ directory
4304
4151
  */
4305
4152
  async loadRulesyncFiles() {
4306
- const subagentsDir = join8(this.baseDir, ".rulesync", "subagents");
4153
+ const subagentsDir = join46(this.baseDir, ".rulesync", "subagents");
4307
4154
  const dirExists = await directoryExists(subagentsDir);
4308
4155
  if (!dirExists) {
4309
4156
  logger.debug(`Rulesync subagents directory not found: ${subagentsDir}`);
@@ -4318,10 +4165,11 @@ var SubagentsProcessor = class extends FeatureProcessor {
4318
4165
  logger.info(`Found ${mdFiles.length} subagent files in ${subagentsDir}`);
4319
4166
  const rulesyncSubagents = [];
4320
4167
  for (const mdFile of mdFiles) {
4321
- const filepath = join8(subagentsDir, mdFile);
4168
+ const filepath = join46(subagentsDir, mdFile);
4322
4169
  try {
4323
- const rulesyncSubagent = await RulesyncSubagent.fromFilePath({
4324
- filePath: filepath
4170
+ const rulesyncSubagent = await RulesyncSubagent.fromFile({
4171
+ relativeFilePath: mdFile,
4172
+ validate: true
4325
4173
  });
4326
4174
  rulesyncSubagents.push(rulesyncSubagent);
4327
4175
  logger.debug(`Successfully loaded subagent: ${mdFile}`);
@@ -4353,43 +4201,19 @@ var SubagentsProcessor = class extends FeatureProcessor {
4353
4201
  * Load Claude Code subagent configurations from .claude/agents/ directory
4354
4202
  */
4355
4203
  async loadClaudecodeSubagents() {
4356
- const agentsDir = join8(this.baseDir, ".claude", "agents");
4357
- if (!await directoryExists(agentsDir)) {
4358
- logger.warn(`Claude Code agents directory not found: ${agentsDir}`);
4359
- return [];
4360
- }
4361
- let entries;
4362
- try {
4363
- entries = await listDirectoryFiles(agentsDir);
4364
- } catch (error) {
4365
- logger.warn(`Failed to read Claude Code agents directory ${agentsDir}:`, error);
4366
- return [];
4367
- }
4368
- const mdFiles = entries.filter((file) => file.endsWith(".md"));
4369
- if (mdFiles.length === 0) {
4370
- logger.info(`No JSON agent files found in ${agentsDir}`);
4371
- return [];
4372
- }
4373
- logger.info(`Found ${mdFiles.length} Claude Code agent files in ${agentsDir}`);
4374
- const toolSubagents = [];
4375
- for (const mdFile of mdFiles) {
4376
- const filepath = join8(agentsDir, mdFile);
4377
- try {
4378
- const claudecodeSubagent = await ClaudecodeSubagent.fromFilePath({
4379
- baseDir: this.baseDir,
4380
- relativeDirPath: ".claude/agents",
4381
- relativeFilePath: mdFile,
4382
- filePath: filepath
4383
- });
4384
- toolSubagents.push(claudecodeSubagent);
4385
- logger.debug(`Successfully loaded Claude Code agent: ${mdFile}`);
4386
- } catch (error) {
4387
- logger.warn(`Failed to load Claude Code agent file ${filepath}:`, error);
4388
- continue;
4389
- }
4390
- }
4391
- logger.info(`Successfully loaded ${toolSubagents.length} Claude Code subagents`);
4392
- return toolSubagents;
4204
+ return await this.loadToolSubagentsDefault({
4205
+ relativeDirPath: ".claude/agents",
4206
+ fromFile: (relativeFilePath) => ClaudecodeSubagent.fromFile({ relativeFilePath })
4207
+ });
4208
+ }
4209
+ async loadToolSubagentsDefault({
4210
+ relativeDirPath,
4211
+ fromFile
4212
+ }) {
4213
+ const paths = await findFilesByGlobs(join46(this.baseDir, relativeDirPath, "*.md"));
4214
+ const subagents = (await Promise.allSettled(paths.map((path2) => fromFile(basename11(path2))))).filter((r) => r.status === "fulfilled").map((r) => r.value);
4215
+ logger.info(`Successfully loaded ${subagents.length} ${relativeDirPath} subagents`);
4216
+ return subagents;
4393
4217
  }
4394
4218
  /**
4395
4219
  * Implementation of abstract method from FeatureProcessor
@@ -4425,7 +4249,7 @@ async function generateCommand(options) {
4425
4249
  }
4426
4250
  let rulesyncFiles = await processor.loadRulesyncFiles();
4427
4251
  if (rulesyncFiles.length === 0) {
4428
- rulesyncFiles = await processor.loadLegacyRulesyncFiles();
4252
+ rulesyncFiles = await processor.loadRulesyncFilesLegacy();
4429
4253
  }
4430
4254
  const toolFiles = await processor.convertRulesyncFilesToToolFiles(rulesyncFiles);
4431
4255
  const writtenCount = await processor.writeAiFiles(toolFiles);
@@ -4579,9 +4403,9 @@ async function generateCommand(options) {
4579
4403
  }
4580
4404
 
4581
4405
  // src/cli/commands/gitignore.ts
4582
- import { join as join9 } from "path";
4406
+ import { join as join47 } from "path";
4583
4407
  var gitignoreCommand = async () => {
4584
- const gitignorePath = join9(process.cwd(), ".gitignore");
4408
+ const gitignorePath = join47(process.cwd(), ".gitignore");
4585
4409
  const rulesFilesToIgnore = [
4586
4410
  "# Generated by rulesync - AI tool configuration files",
4587
4411
  "**/.amazonq/rules/",
@@ -4710,6 +4534,24 @@ async function importCommand(options) {
4710
4534
  logger.success(`Created ${ignoreFileCreated} ignore files`);
4711
4535
  }
4712
4536
  }
4537
+ let mcpCreated = 0;
4538
+ if (config.getFeatures().includes("mcp")) {
4539
+ if (McpProcessor.getToolTargets().includes(tool)) {
4540
+ const mcpProcessor = new McpProcessor({
4541
+ baseDir: ".",
4542
+ toolTarget: tool
4543
+ });
4544
+ const toolFiles = await mcpProcessor.loadToolFiles();
4545
+ if (toolFiles.length > 0) {
4546
+ const rulesyncFiles = await mcpProcessor.convertToolFilesToRulesyncFiles(toolFiles);
4547
+ const writtenCount = await mcpProcessor.writeAiFiles(rulesyncFiles);
4548
+ mcpCreated = writtenCount;
4549
+ }
4550
+ }
4551
+ }
4552
+ if (config.getVerbose() && mcpCreated > 0) {
4553
+ logger.success(`Created ${mcpCreated} MCP files`);
4554
+ }
4713
4555
  let subagentsCreated = 0;
4714
4556
  if (config.getFeatures().includes("subagents")) {
4715
4557
  if (SubagentsProcessor.getToolTargets().includes(tool)) {
@@ -4750,7 +4592,7 @@ async function importCommand(options) {
4750
4592
  }
4751
4593
 
4752
4594
  // src/cli/commands/init.ts
4753
- import { join as join10 } from "path";
4595
+ import { join as join48 } from "path";
4754
4596
  async function initCommand() {
4755
4597
  logger.info("Initializing rulesync...");
4756
4598
  await ensureDir(RULESYNC_DIR);
@@ -4796,7 +4638,7 @@ globs: ["**/*"]
4796
4638
  - Follow single responsibility principle
4797
4639
  `
4798
4640
  };
4799
- const filepath = join10(RULESYNC_RULES_DIR, sampleFile.filename);
4641
+ const filepath = join48(RULESYNC_RULES_DIR, sampleFile.filename);
4800
4642
  await ensureDir(RULESYNC_RULES_DIR);
4801
4643
  await ensureDir(RULESYNC_COMMANDS_DIR);
4802
4644
  await ensureDir(RULESYNC_SUBAGENTS_DIR);
@@ -4814,15 +4656,15 @@ var getVersion = async () => {
4814
4656
  let packageJsonPath;
4815
4657
  if (typeof import.meta !== "undefined" && import.meta.url) {
4816
4658
  const __filename = fileURLToPath(import.meta.url);
4817
- const __dirname = join11(__filename, "..");
4818
- packageJsonPath = join11(__dirname, "../../package.json");
4659
+ const __dirname = join49(__filename, "..");
4660
+ packageJsonPath = join49(__dirname, "../../package.json");
4819
4661
  } else {
4820
- packageJsonPath = join11(process.cwd(), "package.json");
4662
+ packageJsonPath = join49(process.cwd(), "package.json");
4821
4663
  }
4822
4664
  const packageJson = await readJsonFile(packageJsonPath);
4823
4665
  return packageJson.version;
4824
4666
  } catch {
4825
- return "0.69.0";
4667
+ return "0.70.0";
4826
4668
  }
4827
4669
  };
4828
4670
  var main = async () => {