rulesync 0.68.1 → 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 +916 -983
  3. package/dist/index.js +912 -979
  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
 
@@ -29,6 +29,7 @@ var ALL_TOOL_TARGETS = [
29
29
  "geminicli",
30
30
  "kiro",
31
31
  "junie",
32
+ "warp",
32
33
  "windsurf"
33
34
  ];
34
35
  var ALL_TOOL_TARGETS_WITH_WILDCARD = [...ALL_TOOL_TARGETS, "*"];
@@ -193,14 +194,6 @@ async function listDirectoryFiles(dir) {
193
194
  return [];
194
195
  }
195
196
  }
196
- async function findFiles(dir, extension = ".md") {
197
- try {
198
- const files = await readdir(dir);
199
- return files.filter((file) => file.endsWith(extension)).map((file) => join(dir, file));
200
- } catch {
201
- return [];
202
- }
203
- }
204
197
  async function findFilesByGlobs(globs) {
205
198
  return globSync(globs);
206
199
  }
@@ -250,7 +243,7 @@ async function initConfig() {
250
243
  import { intersection } from "es-toolkit";
251
244
 
252
245
  // src/commands/commands-processor.ts
253
- import { basename as basename6, join as join3 } from "path";
246
+ import { basename as basename6, join as join7 } from "path";
254
247
  import { z as z7 } from "zod/mini";
255
248
 
256
249
  // src/types/feature-processor.ts
@@ -283,15 +276,48 @@ var FeatureProcessor = class {
283
276
  };
284
277
 
285
278
  // src/commands/claudecode-command.ts
286
- import { basename as basename3, join as join2 } from "path";
279
+ import { basename as basename3, join as join4 } from "path";
287
280
  import { z as z4 } from "zod/mini";
288
281
 
289
282
  // src/utils/frontmatter.ts
290
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
+ }
291
319
  function stringifyFrontmatter(body, frontmatter) {
292
- const cleanFrontmatter = Object.fromEntries(
293
- Object.entries(frontmatter).filter(([, value]) => value !== null && value !== void 0)
294
- );
320
+ const cleanFrontmatter = deepRemoveNullishObject(frontmatter);
295
321
  return matter.stringify(body, cleanFrontmatter);
296
322
  }
297
323
  function parseFrontmatter(content) {
@@ -300,9 +326,18 @@ function parseFrontmatter(content) {
300
326
  }
301
327
 
302
328
  // src/commands/rulesync-command.ts
303
- import { basename as basename2 } from "path";
329
+ import { basename as basename2, join as join3 } from "path";
304
330
  import { z as z3 } from "zod/mini";
305
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
+
306
341
  // src/types/ai-file.ts
307
342
  import path from "path";
308
343
  var AiFile = class {
@@ -340,7 +375,7 @@ var AiFile = class {
340
375
  }
341
376
  }
342
377
  }
343
- static async fromFilePath(_params) {
378
+ static async fromFile(_params) {
344
379
  throw new Error("Please implement this method in the subclass.");
345
380
  }
346
381
  getBaseDir() {
@@ -368,13 +403,10 @@ var AiFile = class {
368
403
 
369
404
  // src/types/rulesync-file.ts
370
405
  var RulesyncFile = class extends AiFile {
371
- static async fromFilePath(_params) {
372
- throw new Error("Please implement this method in the subclass.");
373
- }
374
406
  static async fromFile(_params) {
375
407
  throw new Error("Please implement this method in the subclass.");
376
408
  }
377
- static async fromLegacyFile(_params) {
409
+ static async fromFileLegacy(_params) {
378
410
  throw new Error("Please implement this method in the subclass.");
379
411
  }
380
412
  };
@@ -418,14 +450,16 @@ var RulesyncCommand = class _RulesyncCommand extends RulesyncFile {
418
450
  return { success: false, error: result.error };
419
451
  }
420
452
  }
421
- static async fromFilePath({ filePath }) {
422
- const fileContent = await readFileContent(filePath);
453
+ static async fromFile({
454
+ relativeFilePath
455
+ }) {
456
+ const fileContent = await readFileContent(join3(RULESYNC_COMMANDS_DIR, relativeFilePath));
423
457
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
424
458
  const result = RulesyncCommandFrontmatterSchema.safeParse(frontmatter);
425
459
  if (!result.success) {
426
- throw new Error(`Invalid frontmatter in ${filePath}: ${result.error.message}`);
460
+ throw new Error(`Invalid frontmatter in ${relativeFilePath}: ${result.error.message}`);
427
461
  }
428
- const filename = basename2(filePath);
462
+ const filename = basename2(relativeFilePath);
429
463
  return new _RulesyncCommand({
430
464
  baseDir: ".",
431
465
  relativeDirPath: ".rulesync/commands",
@@ -451,7 +485,7 @@ var ToolCommand = class extends AiFile {
451
485
  * @param params - Parameters including the file path to load
452
486
  * @returns Promise resolving to a concrete ToolCommand instance
453
487
  */
454
- static async fromFilePath(_params) {
488
+ static async fromFile(_params) {
455
489
  throw new Error("Please implement this method in the subclass.");
456
490
  }
457
491
  /**
@@ -528,7 +562,7 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
528
562
  baseDir,
529
563
  frontmatter: claudecodeFrontmatter,
530
564
  body,
531
- relativeDirPath: join2(".claude", "commands"),
565
+ relativeDirPath: join4(".claude", "commands"),
532
566
  relativeFilePath: rulesyncCommand.getRelativeFilePath(),
533
567
  validate
534
568
  });
@@ -544,11 +578,12 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
544
578
  return { success: false, error: result.error };
545
579
  }
546
580
  }
547
- static async fromFilePath({
581
+ static async fromFile({
548
582
  baseDir = ".",
549
- filePath,
583
+ relativeFilePath,
550
584
  validate = true
551
585
  }) {
586
+ const filePath = join4(baseDir, ".claude", "commands", relativeFilePath);
552
587
  const fileContent = await readFileContent(filePath);
553
588
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
554
589
  const result = ClaudecodeCommandFrontmatterSchema.safeParse(frontmatter);
@@ -558,7 +593,7 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
558
593
  return new _ClaudecodeCommand({
559
594
  baseDir,
560
595
  relativeDirPath: ".claude/commands",
561
- relativeFilePath: basename3(filePath),
596
+ relativeFilePath: basename3(relativeFilePath),
562
597
  frontmatter: result.data,
563
598
  body: content.trim(),
564
599
  validate
@@ -567,7 +602,7 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
567
602
  };
568
603
 
569
604
  // src/commands/geminicli-command.ts
570
- import { basename as basename4 } from "path";
605
+ import { basename as basename4, join as join5 } from "path";
571
606
  import { parse as parseToml } from "smol-toml";
572
607
  import { z as z5 } from "zod/mini";
573
608
  var GeminiCliCommandFrontmatterSchema = z5.object({
@@ -653,16 +688,17 @@ ${geminiFrontmatter.prompt}
653
688
  validate
654
689
  });
655
690
  }
656
- static async fromFilePath({
691
+ static async fromFile({
657
692
  baseDir = ".",
658
- filePath,
693
+ relativeFilePath,
659
694
  validate = true
660
695
  }) {
696
+ const filePath = join5(baseDir, ".gemini", "commands", relativeFilePath);
661
697
  const fileContent = await readFileContent(filePath);
662
698
  return new _GeminiCliCommand({
663
699
  baseDir,
664
700
  relativeDirPath: ".gemini/commands",
665
- relativeFilePath: basename4(filePath),
701
+ relativeFilePath: basename4(relativeFilePath),
666
702
  fileContent,
667
703
  validate
668
704
  });
@@ -675,26 +711,10 @@ ${geminiFrontmatter.prompt}
675
711
  return { success: false, error: error instanceof Error ? error : new Error(String(error)) };
676
712
  }
677
713
  }
678
- async processContent(content, args) {
679
- let processedContent = content;
680
- processedContent = this.processArgumentPlaceholder(processedContent, args);
681
- return processedContent;
682
- }
683
- processArgumentPlaceholder(content, args) {
684
- if (content.includes("{{args}}")) {
685
- return content.replace(/\{\{args\}\}/g, args || "");
686
- }
687
- if (args) {
688
- return `${content}
689
-
690
- ${args}`;
691
- }
692
- return content;
693
- }
694
714
  };
695
715
 
696
716
  // src/commands/roo-command.ts
697
- import { basename as basename5 } from "path";
717
+ import { basename as basename5, join as join6 } from "path";
698
718
  import { optional, z as z6 } from "zod/mini";
699
719
  var RooCommandFrontmatterSchema = z6.object({
700
720
  description: z6.string(),
@@ -771,11 +791,12 @@ var RooCommand = class _RooCommand extends ToolCommand {
771
791
  return { success: false, error: result.error };
772
792
  }
773
793
  }
774
- static async fromFilePath({
794
+ static async fromFile({
775
795
  baseDir = ".",
776
- filePath,
796
+ relativeFilePath,
777
797
  validate = true
778
798
  }) {
799
+ const filePath = join6(baseDir, ".roo", "commands", relativeFilePath);
779
800
  const fileContent = await readFileContent(filePath);
780
801
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
781
802
  const result = RooCommandFrontmatterSchema.safeParse(frontmatter);
@@ -785,7 +806,7 @@ var RooCommand = class _RooCommand extends ToolCommand {
785
806
  return new _RooCommand({
786
807
  baseDir,
787
808
  relativeDirPath: ".roo/commands",
788
- relativeFilePath: basename5(filePath),
809
+ relativeFilePath: basename5(relativeFilePath),
789
810
  frontmatter: result.data,
790
811
  body: content.trim(),
791
812
  fileContent,
@@ -847,37 +868,12 @@ var CommandsProcessor = class extends FeatureProcessor {
847
868
  * Load and parse rulesync command files from .rulesync/commands/ directory
848
869
  */
849
870
  async loadRulesyncFiles() {
850
- const commandsDir = join3(this.baseDir, ".rulesync", "commands");
851
- const dirExists = await directoryExists(commandsDir);
852
- if (!dirExists) {
853
- logger.debug(`Rulesync commands directory not found: ${commandsDir}`);
854
- return [];
855
- }
856
- const allMdFiles = await findFiles(commandsDir, ".md");
857
- const mdFiles = allMdFiles.map((f) => basename6(f));
858
- if (mdFiles.length === 0) {
859
- logger.debug(`No markdown files found in rulesync commands directory: ${commandsDir}`);
860
- return [];
861
- }
862
- logger.info(`Found ${mdFiles.length} command files in ${commandsDir}`);
863
- const rulesyncCommands = [];
864
- for (const mdFile of mdFiles) {
865
- const filepath = join3(commandsDir, mdFile);
866
- try {
867
- const rulesyncCommand = await RulesyncCommand.fromFilePath({
868
- filePath: filepath
869
- });
870
- rulesyncCommands.push(rulesyncCommand);
871
- logger.debug(`Successfully loaded command: ${mdFile}`);
872
- } catch (error) {
873
- logger.warn(`Failed to load command file ${filepath}:`, error);
874
- continue;
875
- }
876
- }
877
- if (rulesyncCommands.length === 0) {
878
- logger.debug(`No valid commands found in ${commandsDir}`);
879
- return [];
880
- }
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);
881
877
  logger.info(`Successfully loaded ${rulesyncCommands.length} rulesync commands`);
882
878
  return rulesyncCommands;
883
879
  }
@@ -890,122 +886,67 @@ var CommandsProcessor = class extends FeatureProcessor {
890
886
  case "claudecode":
891
887
  return await this.loadClaudecodeCommands();
892
888
  case "geminicli":
893
- return await this.loadGeminiCliCommands();
889
+ return await this.loadGeminicliCommands();
894
890
  case "roo":
895
891
  return await this.loadRooCommands();
896
892
  default:
897
893
  throw new Error(`Unsupported tool target: ${this.toolTarget}`);
898
894
  }
899
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
+ }
900
921
  /**
901
922
  * Load Claude Code command configurations from .claude/commands/ directory
902
923
  */
903
924
  async loadClaudecodeCommands() {
904
- const commandsDir = join3(this.baseDir, ".claude", "commands");
905
- if (!await directoryExists(commandsDir)) {
906
- logger.warn(`Claude Code commands directory not found: ${commandsDir}`);
907
- return [];
908
- }
909
- const allMdFiles = await findFiles(commandsDir, ".md");
910
- const mdFiles = allMdFiles.map((f) => basename6(f));
911
- if (mdFiles.length === 0) {
912
- logger.info(`No markdown command files found in ${commandsDir}`);
913
- return [];
914
- }
915
- logger.info(`Found ${mdFiles.length} Claude Code command files in ${commandsDir}`);
916
- const toolCommands = [];
917
- for (const mdFile of mdFiles) {
918
- const filepath = join3(commandsDir, mdFile);
919
- try {
920
- const claudecodeCommand = await ClaudecodeCommand.fromFilePath({
921
- baseDir: this.baseDir,
922
- filePath: filepath
923
- });
924
- toolCommands.push(claudecodeCommand);
925
- logger.debug(`Successfully loaded Claude Code command: ${mdFile}`);
926
- } catch (error) {
927
- logger.warn(`Failed to load Claude Code command file ${filepath}:`, error);
928
- continue;
929
- }
930
- }
931
- logger.info(`Successfully loaded ${toolCommands.length} Claude Code commands`);
932
- return toolCommands;
925
+ return await this.loadToolCommandDefault({
926
+ toolTarget: "claudecode",
927
+ relativeDirPath: ".claude/commands",
928
+ extension: "md"
929
+ });
933
930
  }
934
931
  /**
935
932
  * Load Gemini CLI command configurations from .gemini/commands/ directory
936
933
  */
937
- async loadGeminiCliCommands() {
938
- const commandsDir = join3(this.baseDir, ".gemini", "commands");
939
- if (!await directoryExists(commandsDir)) {
940
- logger.warn(`Gemini CLI commands directory not found: ${commandsDir}`);
941
- return [];
942
- }
943
- const allFiles = await listDirectoryFiles(commandsDir);
944
- const tomlFiles = allFiles.filter((file) => file.endsWith(".toml"));
945
- if (tomlFiles.length === 0) {
946
- logger.info(`No TOML command files found in ${commandsDir}`);
947
- return [];
948
- }
949
- logger.info(`Found ${tomlFiles.length} Gemini CLI command files in ${commandsDir}`);
950
- const toolCommands = [];
951
- for (const tomlFile of tomlFiles) {
952
- const filepath = join3(commandsDir, tomlFile);
953
- try {
954
- const geminiCliCommand = await GeminiCliCommand.fromFilePath({
955
- baseDir: this.baseDir,
956
- filePath: filepath
957
- });
958
- toolCommands.push(geminiCliCommand);
959
- logger.debug(`Successfully loaded Gemini CLI command: ${tomlFile}`);
960
- } catch (error) {
961
- logger.warn(`Failed to load Gemini CLI command file ${filepath}:`, error);
962
- continue;
963
- }
964
- }
965
- logger.info(`Successfully loaded ${toolCommands.length} Gemini CLI commands`);
966
- return toolCommands;
934
+ async loadGeminicliCommands() {
935
+ return await this.loadToolCommandDefault({
936
+ toolTarget: "geminicli",
937
+ relativeDirPath: ".gemini/commands",
938
+ extension: "md"
939
+ });
967
940
  }
968
941
  /**
969
942
  * Load Roo Code command configurations from .roo/commands/ directory
970
943
  */
971
944
  async loadRooCommands() {
972
- const commandsDir = join3(this.baseDir, ".roo", "commands");
973
- if (!await directoryExists(commandsDir)) {
974
- logger.warn(`Roo Code commands directory not found: ${commandsDir}`);
975
- return [];
976
- }
977
- const allMdFiles = await findFiles(commandsDir, ".md");
978
- const mdFiles = allMdFiles.map((f) => basename6(f));
979
- if (mdFiles.length === 0) {
980
- logger.info(`No markdown command files found in ${commandsDir}`);
981
- return [];
982
- }
983
- logger.info(`Found ${mdFiles.length} Roo Code command files in ${commandsDir}`);
984
- const toolCommands = [];
985
- for (const mdFile of mdFiles) {
986
- const filepath = join3(commandsDir, mdFile);
987
- try {
988
- const rooCommand = await RooCommand.fromFilePath({
989
- baseDir: this.baseDir,
990
- filePath: filepath
991
- });
992
- toolCommands.push(rooCommand);
993
- logger.debug(`Successfully loaded Roo Code command: ${mdFile}`);
994
- } catch (error) {
995
- logger.warn(`Failed to load Roo Code command file ${filepath}:`, error);
996
- continue;
997
- }
998
- }
999
- logger.info(`Successfully loaded ${toolCommands.length} Roo Code commands`);
1000
- return toolCommands;
1001
- }
1002
- async writeToolCommandsFromRulesyncCommands(rulesyncCommands) {
1003
- const toolCommands = await this.convertRulesyncFilesToToolFiles(rulesyncCommands);
1004
- await this.writeAiFiles(toolCommands);
1005
- }
1006
- async writeRulesyncCommandsFromToolCommands(toolCommands) {
1007
- const rulesyncCommands = await this.convertToolFilesToRulesyncFiles(toolCommands);
1008
- await this.writeAiFiles(rulesyncCommands);
945
+ return await this.loadToolCommandDefault({
946
+ toolTarget: "roo",
947
+ relativeDirPath: ".roo/commands",
948
+ extension: "md"
949
+ });
1009
950
  }
1010
951
  /**
1011
952
  * Implementation of abstract method from FeatureProcessor
@@ -1117,6 +1058,9 @@ var ConfigResolver = class {
1117
1058
  // src/ignore/ignore-processor.ts
1118
1059
  import { z as z9 } from "zod/mini";
1119
1060
 
1061
+ // src/ignore/augmentcode-ignore.ts
1062
+ import { join as join8 } from "path";
1063
+
1120
1064
  // src/types/tool-file.ts
1121
1065
  var ToolFile = class extends AiFile {
1122
1066
  };
@@ -1135,9 +1079,6 @@ var RulesyncIgnore = class _RulesyncIgnore extends RulesyncFile {
1135
1079
  fileContent
1136
1080
  });
1137
1081
  }
1138
- static async fromFilePath(_params) {
1139
- throw new Error("Please use the fromFile method instead.");
1140
- }
1141
1082
  };
1142
1083
 
1143
1084
  // src/ignore/tool-ignore.ts
@@ -1174,12 +1115,9 @@ var ToolIgnore = class extends ToolFile {
1174
1115
  fileContent: this.fileContent
1175
1116
  });
1176
1117
  }
1177
- static async fromFile() {
1118
+ static async fromFile(_params) {
1178
1119
  throw new Error("Please implement this method in the subclass.");
1179
1120
  }
1180
- static async fromFilePath(_params) {
1181
- throw new Error("Please use the fromFile method instead.");
1182
- }
1183
1121
  };
1184
1122
 
1185
1123
  // src/ignore/augmentcode-ignore.ts
@@ -1209,18 +1147,23 @@ var AugmentcodeIgnore = class _AugmentcodeIgnore extends ToolIgnore {
1209
1147
  * Create AugmentcodeIgnore from file path
1210
1148
  * Reads and parses .augmentignore file
1211
1149
  */
1212
- static async fromFile() {
1213
- const fileContent = await readFileContent(".augmentignore");
1150
+ static async fromFile({
1151
+ baseDir = ".",
1152
+ validate = true
1153
+ }) {
1154
+ const fileContent = await readFileContent(join8(baseDir, ".augmentignore"));
1214
1155
  return new _AugmentcodeIgnore({
1215
- baseDir: ".",
1156
+ baseDir,
1216
1157
  relativeDirPath: ".",
1217
1158
  relativeFilePath: ".augmentignore",
1218
- fileContent
1159
+ fileContent,
1160
+ validate
1219
1161
  });
1220
1162
  }
1221
1163
  };
1222
1164
 
1223
1165
  // src/ignore/cline-ignore.ts
1166
+ import { join as join9 } from "path";
1224
1167
  var ClineIgnore = class _ClineIgnore extends ToolIgnore {
1225
1168
  /**
1226
1169
  * Convert ClineIgnore to RulesyncIgnore format
@@ -1246,18 +1189,23 @@ var ClineIgnore = class _ClineIgnore extends ToolIgnore {
1246
1189
  /**
1247
1190
  * Load ClineIgnore from .clineignore file
1248
1191
  */
1249
- static async fromFile() {
1250
- const fileContent = await readFileContent(".clineignore");
1192
+ static async fromFile({
1193
+ baseDir = ".",
1194
+ validate = true
1195
+ }) {
1196
+ const fileContent = await readFileContent(join9(baseDir, ".clineignore"));
1251
1197
  return new _ClineIgnore({
1252
- baseDir: ".",
1198
+ baseDir,
1253
1199
  relativeDirPath: ".",
1254
1200
  relativeFilePath: ".clineignore",
1255
- fileContent
1201
+ fileContent,
1202
+ validate
1256
1203
  });
1257
1204
  }
1258
1205
  };
1259
1206
 
1260
1207
  // src/ignore/codexcli-ignore.ts
1208
+ import { join as join10 } from "path";
1261
1209
  var CodexcliIgnore = class _CodexcliIgnore extends ToolIgnore {
1262
1210
  toRulesyncIgnore() {
1263
1211
  return this.toRulesyncIgnoreDefault();
@@ -1276,20 +1224,23 @@ var CodexcliIgnore = class _CodexcliIgnore extends ToolIgnore {
1276
1224
  // Skip validation to allow empty patterns
1277
1225
  });
1278
1226
  }
1279
- static async fromFile() {
1280
- const fileContent = await readFileContent(".codexignore");
1227
+ static async fromFile({
1228
+ baseDir = ".",
1229
+ validate = true
1230
+ }) {
1231
+ const fileContent = await readFileContent(join10(baseDir, ".codexignore"));
1281
1232
  return new _CodexcliIgnore({
1282
- baseDir: ".",
1233
+ baseDir,
1283
1234
  relativeDirPath: ".",
1284
1235
  relativeFilePath: ".codexignore",
1285
1236
  fileContent,
1286
- validate: true
1287
- // Skip validation to allow empty patterns
1237
+ validate
1288
1238
  });
1289
1239
  }
1290
1240
  };
1291
1241
 
1292
1242
  // src/ignore/cursor-ignore.ts
1243
+ import { join as join11 } from "path";
1293
1244
  var CursorIgnore = class _CursorIgnore extends ToolIgnore {
1294
1245
  toRulesyncIgnore() {
1295
1246
  return new RulesyncIgnore({
@@ -1311,18 +1262,23 @@ var CursorIgnore = class _CursorIgnore extends ToolIgnore {
1311
1262
  fileContent: body
1312
1263
  });
1313
1264
  }
1314
- static async fromFile() {
1315
- const fileContent = await readFileContent(".cursorignore");
1265
+ static async fromFile({
1266
+ baseDir = ".",
1267
+ validate = true
1268
+ }) {
1269
+ const fileContent = await readFileContent(join11(baseDir, ".cursorignore"));
1316
1270
  return new _CursorIgnore({
1317
- baseDir: ".",
1271
+ baseDir,
1318
1272
  relativeDirPath: ".",
1319
1273
  relativeFilePath: ".cursorignore",
1320
- fileContent
1274
+ fileContent,
1275
+ validate
1321
1276
  });
1322
1277
  }
1323
1278
  };
1324
1279
 
1325
1280
  // src/ignore/geminicli-ignore.ts
1281
+ import { join as join12 } from "path";
1326
1282
  var GeminiCliIgnore = class _GeminiCliIgnore extends ToolIgnore {
1327
1283
  toRulesyncIgnore() {
1328
1284
  return this.toRulesyncIgnoreDefault();
@@ -1338,18 +1294,23 @@ var GeminiCliIgnore = class _GeminiCliIgnore extends ToolIgnore {
1338
1294
  fileContent: rulesyncIgnore.getFileContent()
1339
1295
  });
1340
1296
  }
1341
- static async fromFile() {
1342
- const fileContent = await readFileContent(".aiexclude");
1297
+ static async fromFile({
1298
+ baseDir = ".",
1299
+ validate = true
1300
+ }) {
1301
+ const fileContent = await readFileContent(join12(baseDir, ".aiexclude"));
1343
1302
  return new _GeminiCliIgnore({
1344
- baseDir: ".",
1303
+ baseDir,
1345
1304
  relativeDirPath: ".",
1346
1305
  relativeFilePath: ".aiexclude",
1347
- fileContent
1306
+ fileContent,
1307
+ validate
1348
1308
  });
1349
1309
  }
1350
1310
  };
1351
1311
 
1352
1312
  // src/ignore/junie-ignore.ts
1313
+ import { join as join13 } from "path";
1353
1314
  var JunieIgnore = class _JunieIgnore extends ToolIgnore {
1354
1315
  toRulesyncIgnore() {
1355
1316
  return this.toRulesyncIgnoreDefault();
@@ -1365,18 +1326,23 @@ var JunieIgnore = class _JunieIgnore extends ToolIgnore {
1365
1326
  fileContent: rulesyncIgnore.getFileContent()
1366
1327
  });
1367
1328
  }
1368
- static async fromFile() {
1369
- const fileContent = await readFileContent(".junieignore");
1329
+ static async fromFile({
1330
+ baseDir = ".",
1331
+ validate = true
1332
+ }) {
1333
+ const fileContent = await readFileContent(join13(baseDir, ".junieignore"));
1370
1334
  return new _JunieIgnore({
1371
- baseDir: ".",
1335
+ baseDir,
1372
1336
  relativeDirPath: ".",
1373
1337
  relativeFilePath: ".junieignore",
1374
- fileContent
1338
+ fileContent,
1339
+ validate
1375
1340
  });
1376
1341
  }
1377
1342
  };
1378
1343
 
1379
1344
  // src/ignore/kiro-ignore.ts
1345
+ import { join as join14 } from "path";
1380
1346
  var KiroIgnore = class _KiroIgnore extends ToolIgnore {
1381
1347
  toRulesyncIgnore() {
1382
1348
  return this.toRulesyncIgnoreDefault();
@@ -1392,18 +1358,23 @@ var KiroIgnore = class _KiroIgnore extends ToolIgnore {
1392
1358
  fileContent: rulesyncIgnore.getFileContent()
1393
1359
  });
1394
1360
  }
1395
- static async fromFile() {
1396
- const fileContent = await readFileContent(".aiignore");
1361
+ static async fromFile({
1362
+ baseDir = ".",
1363
+ validate = true
1364
+ }) {
1365
+ const fileContent = await readFileContent(join14(baseDir, ".aiignore"));
1397
1366
  return new _KiroIgnore({
1398
- baseDir: ".",
1367
+ baseDir,
1399
1368
  relativeDirPath: ".",
1400
1369
  relativeFilePath: ".aiignore",
1401
- fileContent
1370
+ fileContent,
1371
+ validate
1402
1372
  });
1403
1373
  }
1404
1374
  };
1405
1375
 
1406
1376
  // src/ignore/qwencode-ignore.ts
1377
+ import { join as join15 } from "path";
1407
1378
  var QwencodeIgnore = class _QwencodeIgnore extends ToolIgnore {
1408
1379
  toRulesyncIgnore() {
1409
1380
  return this.toRulesyncIgnoreDefault();
@@ -1419,18 +1390,23 @@ var QwencodeIgnore = class _QwencodeIgnore extends ToolIgnore {
1419
1390
  fileContent: rulesyncIgnore.getFileContent()
1420
1391
  });
1421
1392
  }
1422
- static async fromFile() {
1423
- const fileContent = await readFileContent(".geminiignore");
1393
+ static async fromFile({
1394
+ baseDir = ".",
1395
+ validate = true
1396
+ }) {
1397
+ const fileContent = await readFileContent(join15(baseDir, ".geminiignore"));
1424
1398
  return new _QwencodeIgnore({
1425
- baseDir: ".",
1399
+ baseDir,
1426
1400
  relativeDirPath: ".",
1427
1401
  relativeFilePath: ".geminiignore",
1428
- fileContent
1402
+ fileContent,
1403
+ validate
1429
1404
  });
1430
1405
  }
1431
1406
  };
1432
1407
 
1433
1408
  // src/ignore/roo-ignore.ts
1409
+ import { join as join16 } from "path";
1434
1410
  var RooIgnore = class _RooIgnore extends ToolIgnore {
1435
1411
  toRulesyncIgnore() {
1436
1412
  return this.toRulesyncIgnoreDefault();
@@ -1446,18 +1422,23 @@ var RooIgnore = class _RooIgnore extends ToolIgnore {
1446
1422
  fileContent: rulesyncIgnore.getFileContent()
1447
1423
  });
1448
1424
  }
1449
- static async fromFile() {
1450
- const fileContent = await readFileContent(".rooignore");
1425
+ static async fromFile({
1426
+ baseDir = ".",
1427
+ validate = true
1428
+ }) {
1429
+ const fileContent = await readFileContent(join16(baseDir, ".rooignore"));
1451
1430
  return new _RooIgnore({
1452
- baseDir: ".",
1431
+ baseDir,
1453
1432
  relativeDirPath: ".",
1454
1433
  relativeFilePath: ".rooignore",
1455
- fileContent
1434
+ fileContent,
1435
+ validate
1456
1436
  });
1457
1437
  }
1458
1438
  };
1459
1439
 
1460
1440
  // src/ignore/windsurf-ignore.ts
1441
+ import { join as join17 } from "path";
1461
1442
  var WindsurfIgnore = class _WindsurfIgnore extends ToolIgnore {
1462
1443
  toRulesyncIgnore() {
1463
1444
  return this.toRulesyncIgnoreDefault();
@@ -1473,6 +1454,19 @@ var WindsurfIgnore = class _WindsurfIgnore extends ToolIgnore {
1473
1454
  fileContent: rulesyncIgnore.getFileContent()
1474
1455
  });
1475
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
+ }
1476
1470
  };
1477
1471
 
1478
1472
  // src/ignore/ignore-processor.ts
@@ -1530,25 +1524,25 @@ var IgnoreProcessor = class extends FeatureProcessor {
1530
1524
  async loadToolIgnores() {
1531
1525
  switch (this.toolTarget) {
1532
1526
  case "augmentcode":
1533
- return [await AugmentcodeIgnore.fromFile()];
1527
+ return [await AugmentcodeIgnore.fromFile({ baseDir: this.baseDir })];
1534
1528
  case "cline":
1535
- return [await ClineIgnore.fromFile()];
1529
+ return [await ClineIgnore.fromFile({ baseDir: this.baseDir })];
1536
1530
  case "codexcli":
1537
- return [await CodexcliIgnore.fromFile()];
1531
+ return [await CodexcliIgnore.fromFile({ baseDir: this.baseDir })];
1538
1532
  case "cursor":
1539
- return [await CursorIgnore.fromFile()];
1533
+ return [await CursorIgnore.fromFile({ baseDir: this.baseDir })];
1540
1534
  case "geminicli":
1541
- return [await GeminiCliIgnore.fromFile()];
1535
+ return [await GeminiCliIgnore.fromFile({ baseDir: this.baseDir })];
1542
1536
  case "junie":
1543
- return [await JunieIgnore.fromFile()];
1537
+ return [await JunieIgnore.fromFile({ baseDir: this.baseDir })];
1544
1538
  case "kiro":
1545
- return [await KiroIgnore.fromFile()];
1539
+ return [await KiroIgnore.fromFile({ baseDir: this.baseDir })];
1546
1540
  case "qwencode":
1547
- return [await QwencodeIgnore.fromFile()];
1541
+ return [await QwencodeIgnore.fromFile({ baseDir: this.baseDir })];
1548
1542
  case "roo":
1549
- return [await RooIgnore.fromFile()];
1543
+ return [await RooIgnore.fromFile({ baseDir: this.baseDir })];
1550
1544
  case "windsurf":
1551
- return [await WindsurfIgnore.fromFile()];
1545
+ return [await WindsurfIgnore.fromFile({ baseDir: this.baseDir })];
1552
1546
  default:
1553
1547
  throw new Error(`Unsupported tool target: ${this.toolTarget}`);
1554
1548
  }
@@ -1643,9 +1637,14 @@ var IgnoreProcessor = class extends FeatureProcessor {
1643
1637
  };
1644
1638
 
1645
1639
  // src/mcp/mcp-processor.ts
1646
- import { join as join4 } from "path";
1647
1640
  import { z as z11 } from "zod/mini";
1648
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
+
1649
1648
  // src/types/mcp.ts
1650
1649
  import { z as z10 } from "zod/mini";
1651
1650
  var McpTransportTypeSchema = z10.enum(["stdio", "sse", "http"]);
@@ -1694,14 +1693,14 @@ var RulesyncMcp = class _RulesyncMcp extends RulesyncFile {
1694
1693
  validate() {
1695
1694
  return { success: true, error: null };
1696
1695
  }
1697
- static async fromFilePath({ filePath }) {
1698
- const fileContent = await readFileContent(filePath);
1696
+ static async fromFile({ validate = true }) {
1697
+ const fileContent = await readFileContent(join18(RULESYNC_DIR, ".mcp.json"));
1699
1698
  return new _RulesyncMcp({
1700
1699
  baseDir: ".",
1701
- relativeDirPath: ".rulesync",
1700
+ relativeDirPath: RULESYNC_DIR,
1702
1701
  relativeFilePath: ".mcp.json",
1703
1702
  fileContent,
1704
- validate: true
1703
+ validate
1705
1704
  });
1706
1705
  }
1707
1706
  getJson() {
@@ -1737,7 +1736,7 @@ var ToolMcp = class extends ToolFile {
1737
1736
  fileContent: this.fileContent
1738
1737
  });
1739
1738
  }
1740
- static async fromFilePath(_params) {
1739
+ static async fromFile(_params) {
1741
1740
  throw new Error("Please implement this method in the subclass.");
1742
1741
  }
1743
1742
  static fromRulesyncMcp(_params) {
@@ -1747,14 +1746,17 @@ var ToolMcp = class extends ToolFile {
1747
1746
 
1748
1747
  // src/mcp/amazonqcli-mcp.ts
1749
1748
  var AmazonqcliMcp = class _AmazonqcliMcp extends ToolMcp {
1750
- static async fromFilePath({ filePath }) {
1751
- 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"));
1752
1754
  return new _AmazonqcliMcp({
1753
- baseDir: ".",
1755
+ baseDir,
1754
1756
  relativeDirPath: ".amazonq",
1755
- relativeFilePath: ".mcp.json",
1757
+ relativeFilePath: "mcp.json",
1756
1758
  fileContent,
1757
- validate: true
1759
+ validate
1758
1760
  });
1759
1761
  }
1760
1762
  static fromRulesyncMcp({
@@ -1779,15 +1781,19 @@ var AmazonqcliMcp = class _AmazonqcliMcp extends ToolMcp {
1779
1781
  };
1780
1782
 
1781
1783
  // src/mcp/claudecode-mcp.ts
1784
+ import { join as join20 } from "path";
1782
1785
  var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
1783
- static async fromFilePath({ filePath }) {
1784
- const fileContent = await readFileContent(filePath);
1786
+ static async fromFile({
1787
+ baseDir = ".",
1788
+ validate = true
1789
+ }) {
1790
+ const fileContent = await readFileContent(join20(baseDir, ".mcp.json"));
1785
1791
  return new _ClaudecodeMcp({
1786
1792
  baseDir: ".",
1787
1793
  relativeDirPath: ".",
1788
1794
  relativeFilePath: ".mcp.json",
1789
1795
  fileContent,
1790
- validate: true
1796
+ validate
1791
1797
  });
1792
1798
  }
1793
1799
  static fromRulesyncMcp({
@@ -1812,15 +1818,19 @@ var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
1812
1818
  };
1813
1819
 
1814
1820
  // src/mcp/cline-mcp.ts
1821
+ import { join as join21 } from "path";
1815
1822
  var ClineMcp = class _ClineMcp extends ToolMcp {
1816
- static async fromFilePath({ filePath }) {
1817
- 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"));
1818
1828
  return new _ClineMcp({
1819
1829
  baseDir: ".",
1820
1830
  relativeDirPath: ".cline",
1821
1831
  relativeFilePath: "mcp.json",
1822
1832
  fileContent,
1823
- validate: true
1833
+ validate
1824
1834
  });
1825
1835
  }
1826
1836
  static fromRulesyncMcp({
@@ -1845,15 +1855,19 @@ var ClineMcp = class _ClineMcp extends ToolMcp {
1845
1855
  };
1846
1856
 
1847
1857
  // src/mcp/copilot-mcp.ts
1858
+ import { join as join22 } from "path";
1848
1859
  var CopilotMcp = class _CopilotMcp extends ToolMcp {
1849
- static async fromFilePath({ filePath }) {
1850
- 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"));
1851
1865
  return new _CopilotMcp({
1852
1866
  baseDir: ".",
1853
1867
  relativeDirPath: ".vscode",
1854
1868
  relativeFilePath: "mcp.json",
1855
1869
  fileContent,
1856
- validate: true
1870
+ validate
1857
1871
  });
1858
1872
  }
1859
1873
  static fromRulesyncMcp({
@@ -1878,15 +1892,19 @@ var CopilotMcp = class _CopilotMcp extends ToolMcp {
1878
1892
  };
1879
1893
 
1880
1894
  // src/mcp/cursor-mcp.ts
1895
+ import { join as join23 } from "path";
1881
1896
  var CursorMcp = class _CursorMcp extends ToolMcp {
1882
- static async fromFilePath({ filePath }) {
1883
- 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"));
1884
1902
  return new _CursorMcp({
1885
1903
  baseDir: ".",
1886
1904
  relativeDirPath: ".cursor",
1887
1905
  relativeFilePath: "mcp.json",
1888
1906
  fileContent,
1889
- validate: true
1907
+ validate
1890
1908
  });
1891
1909
  }
1892
1910
  static fromRulesyncMcp({
@@ -1922,15 +1940,19 @@ var CursorMcp = class _CursorMcp extends ToolMcp {
1922
1940
  };
1923
1941
 
1924
1942
  // src/mcp/roo-mcp.ts
1943
+ import { join as join24 } from "path";
1925
1944
  var RooMcp = class _RooMcp extends ToolMcp {
1926
- static async fromFilePath({ filePath }) {
1927
- const fileContent = await readFileContent(filePath);
1928
- return new _RooMcp({
1945
+ static async fromFile({
1946
+ baseDir = ".",
1947
+ validate = true
1948
+ }) {
1949
+ const fileContent = await readFileContent(join24(baseDir, ".roo/mcp.json"));
1950
+ return new _RooMcp({
1929
1951
  baseDir: ".",
1930
1952
  relativeDirPath: ".roo",
1931
1953
  relativeFilePath: "mcp.json",
1932
1954
  fileContent,
1933
- validate: true
1955
+ validate
1934
1956
  });
1935
1957
  }
1936
1958
  static fromRulesyncMcp({
@@ -1980,9 +2002,7 @@ var McpProcessor = class extends FeatureProcessor {
1980
2002
  */
1981
2003
  async loadRulesyncFiles() {
1982
2004
  try {
1983
- return [
1984
- await RulesyncMcp.fromFilePath({ filePath: join4(this.baseDir, ".rulesync", ".mcp.json") })
1985
- ];
2005
+ return [await RulesyncMcp.fromFile({})];
1986
2006
  } catch (error) {
1987
2007
  logger.debug(`No MCP files found for tool target: ${this.toolTarget}`, error);
1988
2008
  return [];
@@ -1994,42 +2014,62 @@ var McpProcessor = class extends FeatureProcessor {
1994
2014
  */
1995
2015
  async loadToolFiles() {
1996
2016
  try {
1997
- switch (this.toolTarget) {
1998
- case "amazonqcli": {
1999
- return [
2000
- await AmazonqcliMcp.fromFilePath({
2001
- filePath: join4(this.baseDir, ".amazonq", "mcp.json")
2002
- })
2003
- ];
2004
- }
2005
- case "claudecode": {
2006
- return [
2007
- await ClaudecodeMcp.fromFilePath({
2008
- filePath: join4(this.baseDir, ".mcp.json")
2009
- })
2010
- ];
2011
- }
2012
- case "cline": {
2013
- return [
2014
- await ClineMcp.fromFilePath({ filePath: join4(this.baseDir, ".cline", "mcp.json") })
2015
- ];
2016
- }
2017
- case "copilot": {
2018
- return [
2019
- await CopilotMcp.fromFilePath({ filePath: join4(this.baseDir, ".vscode", "mcp.json") })
2020
- ];
2021
- }
2022
- case "cursor": {
2023
- return [
2024
- await CursorMcp.fromFilePath({ filePath: join4(this.baseDir, ".cursor", "mcp.json") })
2025
- ];
2026
- }
2027
- case "roo": {
2028
- 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}`);
2029
2069
  }
2030
- default:
2031
- throw new Error(`Unsupported tool target: ${this.toolTarget}`);
2032
- }
2070
+ })();
2071
+ logger.info(`Successfully loaded ${toolMcps.length} ${this.toolTarget} MCP files`);
2072
+ return toolMcps;
2033
2073
  } catch (error) {
2034
2074
  logger.debug(`No MCP files found for tool target: ${this.toolTarget}`, error);
2035
2075
  return [];
@@ -2105,21 +2145,15 @@ var McpProcessor = class extends FeatureProcessor {
2105
2145
  };
2106
2146
 
2107
2147
  // src/rules/rules-processor.ts
2108
- import { basename as basename9, join as join7 } from "path";
2148
+ import { basename as basename9, join as join43 } from "path";
2109
2149
  import { XMLBuilder } from "fast-xml-parser";
2110
2150
  import { z as z16 } from "zod/mini";
2111
2151
 
2112
- // src/constants/paths.ts
2113
- import { join as join5 } from "path";
2114
- var RULESYNC_DIR = ".rulesync";
2115
- var RULESYNC_RULES_DIR = join5(".rulesync", "rules");
2116
- var RULESYNC_RULES_DIR_LEGACY = ".rulesync";
2117
- var RULESYNC_MCP_FILE = join5(".rulesync", ".mcp.json");
2118
- var RULESYNC_COMMANDS_DIR = join5(".rulesync", "commands");
2119
- var RULESYNC_SUBAGENTS_DIR = join5(".rulesync", "subagents");
2152
+ // src/rules/agentsmd-rule.ts
2153
+ import { join as join26 } from "path";
2120
2154
 
2121
2155
  // src/rules/rulesync-rule.ts
2122
- import { basename as basename7, join as join6 } from "path";
2156
+ import { basename as basename7, join as join25 } from "path";
2123
2157
  import { z as z12 } from "zod/mini";
2124
2158
  var RulesyncRuleFrontmatterSchema = z12.object({
2125
2159
  root: z12.optional(z12.optional(z12.boolean())),
@@ -2165,10 +2199,11 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
2165
2199
  return { success: false, error: result.error };
2166
2200
  }
2167
2201
  }
2168
- static async fromLegacyFile({
2169
- relativeFilePath
2202
+ static async fromFileLegacy({
2203
+ relativeFilePath,
2204
+ validate = true
2170
2205
  }) {
2171
- const filePath = join6(RULESYNC_RULES_DIR_LEGACY, relativeFilePath);
2206
+ const filePath = join25(RULESYNC_RULES_DIR_LEGACY, relativeFilePath);
2172
2207
  const fileContent = await readFileContent(filePath);
2173
2208
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
2174
2209
  const result = RulesyncRuleFrontmatterSchema.safeParse(frontmatter);
@@ -2188,10 +2223,15 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
2188
2223
  relativeDirPath: RULESYNC_RULES_DIR,
2189
2224
  relativeFilePath: filename,
2190
2225
  frontmatter: validatedFrontmatter,
2191
- body: content.trim()
2226
+ body: content.trim(),
2227
+ validate
2192
2228
  });
2193
2229
  }
2194
- static async fromFilePath({ filePath }) {
2230
+ static async fromFile({
2231
+ relativeFilePath,
2232
+ validate = true
2233
+ }) {
2234
+ const filePath = join25(RULESYNC_RULES_DIR, relativeFilePath);
2195
2235
  const fileContent = await readFileContent(filePath);
2196
2236
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
2197
2237
  const result = RulesyncRuleFrontmatterSchema.safeParse(frontmatter);
@@ -2211,7 +2251,8 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
2211
2251
  relativeDirPath: RULESYNC_RULES_DIR,
2212
2252
  relativeFilePath: filename,
2213
2253
  frontmatter: validatedFrontmatter,
2214
- body: content.trim()
2254
+ body: content.trim(),
2255
+ validate
2215
2256
  });
2216
2257
  }
2217
2258
  getBody() {
@@ -2226,7 +2267,7 @@ var ToolRule = class extends ToolFile {
2226
2267
  super(rest);
2227
2268
  this.root = root;
2228
2269
  }
2229
- static async fromFilePath(_params) {
2270
+ static async fromFile(_params) {
2230
2271
  throw new Error("Please implement this method in the subclass.");
2231
2272
  }
2232
2273
  static fromRulesyncRule(_params) {
@@ -2277,19 +2318,18 @@ var AgentsMdRule = class _AgentsMdRule extends ToolRule {
2277
2318
  root: root ?? false
2278
2319
  });
2279
2320
  }
2280
- static async fromFilePath({
2321
+ static async fromFile({
2281
2322
  baseDir = ".",
2282
- relativeDirPath,
2283
2323
  relativeFilePath,
2284
- filePath,
2285
2324
  validate = true
2286
2325
  }) {
2287
- const fileContent = await readFileContent(filePath);
2288
2326
  const isRoot = relativeFilePath === "AGENTS.md";
2327
+ const relativePath = isRoot ? "AGENTS.md" : join26(".agents/memories", relativeFilePath);
2328
+ const fileContent = await readFileContent(join26(baseDir, relativePath));
2289
2329
  return new _AgentsMdRule({
2290
2330
  baseDir,
2291
- relativeDirPath,
2292
- relativeFilePath,
2331
+ relativeDirPath: isRoot ? "." : ".agents/memories",
2332
+ relativeFilePath: isRoot ? "AGENTS.md" : relativeFilePath,
2293
2333
  fileContent,
2294
2334
  validate,
2295
2335
  root: isRoot
@@ -2317,15 +2357,20 @@ var AgentsMdRule = class _AgentsMdRule extends ToolRule {
2317
2357
  };
2318
2358
 
2319
2359
  // src/rules/amazonqcli-rule.ts
2360
+ import { join as join27 } from "path";
2320
2361
  var AmazonQCliRule = class _AmazonQCliRule extends ToolRule {
2321
- static async fromFilePath(params) {
2322
- 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));
2323
2368
  return new _AmazonQCliRule({
2324
- baseDir: params.baseDir || ".",
2325
- relativeDirPath: params.relativeDirPath,
2326
- relativeFilePath: params.relativeFilePath,
2369
+ baseDir,
2370
+ relativeDirPath: ".amazonq/rules",
2371
+ relativeFilePath,
2327
2372
  fileContent,
2328
- validate: params.validate ?? false,
2373
+ validate,
2329
2374
  root: false
2330
2375
  });
2331
2376
  }
@@ -2352,6 +2397,7 @@ var AmazonQCliRule = class _AmazonQCliRule extends ToolRule {
2352
2397
  };
2353
2398
 
2354
2399
  // src/rules/augmentcode-legacy-rule.ts
2400
+ import { join as join28 } from "path";
2355
2401
  var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
2356
2402
  toRulesyncRule() {
2357
2403
  const rulesyncFrontmatter = {
@@ -2387,19 +2433,18 @@ var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
2387
2433
  validate() {
2388
2434
  return { success: true, error: null };
2389
2435
  }
2390
- static async fromFilePath({
2436
+ static async fromFile({
2391
2437
  baseDir = ".",
2392
- relativeDirPath,
2393
2438
  relativeFilePath,
2394
- filePath,
2395
2439
  validate = true
2396
2440
  }) {
2397
- const fileContent = await readFileContent(filePath);
2398
2441
  const isRoot = relativeFilePath === ".augment-guidelines";
2442
+ const relativePath = isRoot ? ".augment-guidelines" : join28(".augment/rules", relativeFilePath);
2443
+ const fileContent = await readFileContent(join28(baseDir, relativePath));
2399
2444
  return new _AugmentcodeLegacyRule({
2400
2445
  baseDir,
2401
- relativeDirPath,
2402
- relativeFilePath,
2446
+ relativeDirPath: isRoot ? "." : ".augment/rules",
2447
+ relativeFilePath: isRoot ? ".augment-guidelines" : relativeFilePath,
2403
2448
  fileContent,
2404
2449
  validate,
2405
2450
  root: isRoot
@@ -2408,6 +2453,7 @@ var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
2408
2453
  };
2409
2454
 
2410
2455
  // src/rules/augmentcode-rule.ts
2456
+ import { join as join29 } from "path";
2411
2457
  var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
2412
2458
  toRulesyncRule() {
2413
2459
  return this.toRulesyncRuleDefault();
@@ -2426,18 +2472,16 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
2426
2472
  })
2427
2473
  );
2428
2474
  }
2429
- static async fromFilePath({
2475
+ static async fromFile({
2430
2476
  baseDir = ".",
2431
- relativeDirPath,
2432
2477
  relativeFilePath,
2433
- filePath,
2434
2478
  validate = true
2435
2479
  }) {
2436
- const fileContent = await readFileContent(filePath);
2480
+ const fileContent = await readFileContent(join29(baseDir, ".augment/rules", relativeFilePath));
2437
2481
  const { body: content } = parseFrontmatter(fileContent);
2438
2482
  return new _AugmentcodeRule({
2439
2483
  baseDir,
2440
- relativeDirPath,
2484
+ relativeDirPath: ".augment/rules",
2441
2485
  relativeFilePath,
2442
2486
  fileContent: content.trim(),
2443
2487
  validate
@@ -2449,16 +2493,23 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
2449
2493
  };
2450
2494
 
2451
2495
  // src/rules/claudecode-rule.ts
2496
+ import { join as join30 } from "path";
2452
2497
  var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
2453
- static async fromFilePath(params) {
2454
- 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));
2455
2506
  return new _ClaudecodeRule({
2456
- baseDir: params.baseDir || process.cwd(),
2457
- relativeDirPath: params.relativeDirPath,
2458
- relativeFilePath: params.relativeFilePath,
2507
+ baseDir,
2508
+ relativeDirPath: isRoot ? "." : ".claude/memories",
2509
+ relativeFilePath: isRoot ? "CLAUDE.md" : relativeFilePath,
2459
2510
  fileContent,
2460
- validate: params.validate ?? true,
2461
- root: params.relativeFilePath === "CLAUDE.md"
2511
+ validate,
2512
+ root: isRoot
2462
2513
  });
2463
2514
  }
2464
2515
  static fromRulesyncRule({
@@ -2485,6 +2536,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
2485
2536
  };
2486
2537
 
2487
2538
  // src/rules/cline-rule.ts
2539
+ import { join as join31 } from "path";
2488
2540
  import { z as z13 } from "zod/mini";
2489
2541
  var ClineRuleFrontmatterSchema = z13.object({
2490
2542
  description: z13.string()
@@ -2510,17 +2562,15 @@ var ClineRule = class _ClineRule extends ToolRule {
2510
2562
  validate() {
2511
2563
  return { success: true, error: null };
2512
2564
  }
2513
- static async fromFilePath({
2565
+ static async fromFile({
2514
2566
  baseDir = ".",
2515
- relativeDirPath,
2516
2567
  relativeFilePath,
2517
- filePath,
2518
2568
  validate = true
2519
2569
  }) {
2520
- const fileContent = await readFileContent(filePath);
2570
+ const fileContent = await readFileContent(join31(baseDir, ".clinerules", relativeFilePath));
2521
2571
  return new _ClineRule({
2522
2572
  baseDir,
2523
- relativeDirPath,
2573
+ relativeDirPath: ".clinerules",
2524
2574
  relativeFilePath,
2525
2575
  fileContent,
2526
2576
  validate
@@ -2529,16 +2579,23 @@ var ClineRule = class _ClineRule extends ToolRule {
2529
2579
  };
2530
2580
 
2531
2581
  // src/rules/codexcli-rule.ts
2582
+ import { join as join32 } from "path";
2532
2583
  var CodexcliRule = class _CodexcliRule extends ToolRule {
2533
- static async fromFilePath(params) {
2534
- 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));
2535
2592
  return new _CodexcliRule({
2536
- baseDir: params.baseDir || process.cwd(),
2537
- relativeDirPath: params.relativeDirPath,
2538
- relativeFilePath: params.relativeFilePath,
2593
+ baseDir,
2594
+ relativeDirPath: isRoot ? "." : ".codex/memories",
2595
+ relativeFilePath: isRoot ? "AGENTS.md" : relativeFilePath,
2539
2596
  fileContent,
2540
- validate: params.validate ?? true,
2541
- root: params.relativeFilePath === "AGENTS.md"
2597
+ validate,
2598
+ root: isRoot
2542
2599
  });
2543
2600
  }
2544
2601
  static fromRulesyncRule({
@@ -2565,6 +2622,7 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
2565
2622
  };
2566
2623
 
2567
2624
  // src/rules/copilot-rule.ts
2625
+ import { join as join33 } from "path";
2568
2626
  import { z as z14 } from "zod/mini";
2569
2627
  var CopilotRuleFrontmatterSchema = z14.object({
2570
2628
  description: z14.optional(z14.string()),
@@ -2639,45 +2697,43 @@ var CopilotRule = class _CopilotRule extends ToolRule {
2639
2697
  root
2640
2698
  });
2641
2699
  }
2642
- static async fromFilePath({
2700
+ static async fromFile({
2643
2701
  baseDir = ".",
2644
- relativeDirPath,
2645
2702
  relativeFilePath,
2646
- filePath,
2647
2703
  validate = true
2648
2704
  }) {
2649
- const fileContent = await readFileContent(filePath);
2650
- const root = relativeFilePath === "copilot-instructions.md";
2651
- 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) {
2652
2709
  return new _CopilotRule({
2653
2710
  baseDir,
2654
- relativeDirPath,
2655
- relativeFilePath,
2711
+ relativeDirPath: ".github",
2712
+ relativeFilePath: isRoot ? "copilot-instructions.md" : relativeFilePath,
2656
2713
  frontmatter: {
2657
2714
  description: "",
2658
2715
  applyTo: "**"
2659
2716
  },
2660
2717
  body: fileContent.trim(),
2661
2718
  validate,
2662
- root
2719
+ root: isRoot
2663
2720
  });
2664
2721
  }
2665
2722
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
2666
2723
  const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
2667
2724
  if (!result.success) {
2668
- 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
+ );
2669
2728
  }
2670
2729
  return new _CopilotRule({
2671
2730
  baseDir,
2672
- relativeDirPath,
2673
- relativeFilePath,
2674
- frontmatter: {
2675
- ...result.data,
2676
- applyTo: result.data.applyTo || "**"
2677
- },
2731
+ relativeDirPath: ".github/instructions",
2732
+ relativeFilePath: relativeFilePath.replace(/\.md$/, ".instructions.md"),
2733
+ frontmatter: result.data,
2678
2734
  body: content.trim(),
2679
2735
  validate,
2680
- root
2736
+ root: isRoot
2681
2737
  });
2682
2738
  }
2683
2739
  validate() {
@@ -2700,7 +2756,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
2700
2756
  };
2701
2757
 
2702
2758
  // src/rules/cursor-rule.ts
2703
- import { basename as basename8 } from "path";
2759
+ import { basename as basename8, join as join34 } from "path";
2704
2760
  import { z as z15 } from "zod/mini";
2705
2761
  var CursorRuleFrontmatterSchema = z15.object({
2706
2762
  description: z15.optional(z15.string()),
@@ -2719,11 +2775,49 @@ var CursorRule = class _CursorRule extends ToolRule {
2719
2775
  }
2720
2776
  super({
2721
2777
  ...rest,
2722
- fileContent: stringifyFrontmatter(body, frontmatter)
2778
+ fileContent: _CursorRule.stringifyCursorFrontmatter(body, frontmatter)
2723
2779
  });
2724
2780
  this.frontmatter = frontmatter;
2725
2781
  this.body = body;
2726
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
+ }
2727
2821
  toRulesyncRule() {
2728
2822
  const targets = ["*"];
2729
2823
  const isAlways = this.frontmatter.alwaysApply === true;
@@ -2740,13 +2834,18 @@ var CursorRule = class _CursorRule extends ToolRule {
2740
2834
  targets,
2741
2835
  root: false,
2742
2836
  description: this.frontmatter.description,
2743
- globs
2837
+ globs,
2838
+ cursor: {
2839
+ alwaysApply: this.frontmatter.alwaysApply,
2840
+ description: this.frontmatter.description,
2841
+ globs: globs.length > 0 ? globs : void 0
2842
+ }
2744
2843
  };
2745
2844
  return new RulesyncRule({
2746
2845
  frontmatter: rulesyncFrontmatter,
2747
2846
  body: this.body,
2748
2847
  relativeDirPath: ".rulesync/rules",
2749
- relativeFilePath: this.relativeFilePath,
2848
+ relativeFilePath: this.relativeFilePath.replace(/\.mdc$/, ".md"),
2750
2849
  validate: true
2751
2850
  });
2752
2851
  }
@@ -2774,20 +2873,23 @@ var CursorRule = class _CursorRule extends ToolRule {
2774
2873
  validate
2775
2874
  });
2776
2875
  }
2777
- static async fromFilePath({
2778
- filePath,
2876
+ static async fromFile({
2877
+ baseDir = ".",
2878
+ relativeFilePath,
2779
2879
  validate = true
2780
2880
  }) {
2781
- const fileContent = await readFileContent(filePath);
2782
- const { frontmatter, body: content } = parseFrontmatter(fileContent);
2881
+ const fileContent = await readFileContent(join34(baseDir, ".cursor/rules", relativeFilePath));
2882
+ const { frontmatter, body: content } = _CursorRule.parseCursorFrontmatter(fileContent);
2783
2883
  const result = CursorRuleFrontmatterSchema.safeParse(frontmatter);
2784
2884
  if (!result.success) {
2785
- 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
+ );
2786
2888
  }
2787
2889
  return new _CursorRule({
2788
- baseDir: ".",
2890
+ baseDir,
2789
2891
  relativeDirPath: ".cursor/rules",
2790
- relativeFilePath: basename8(filePath),
2892
+ relativeFilePath: basename8(relativeFilePath),
2791
2893
  frontmatter: result.data,
2792
2894
  body: content.trim(),
2793
2895
  validate
@@ -2813,16 +2915,23 @@ var CursorRule = class _CursorRule extends ToolRule {
2813
2915
  };
2814
2916
 
2815
2917
  // src/rules/geminicli-rule.ts
2918
+ import { join as join35 } from "path";
2816
2919
  var GeminiCliRule = class _GeminiCliRule extends ToolRule {
2817
- static async fromFilePath(params) {
2818
- 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));
2819
2928
  return new _GeminiCliRule({
2820
- baseDir: params.baseDir || process.cwd(),
2821
- relativeDirPath: params.relativeDirPath,
2822
- relativeFilePath: params.relativeFilePath,
2929
+ baseDir,
2930
+ relativeDirPath: isRoot ? "." : ".gemini/memories",
2931
+ relativeFilePath: isRoot ? "GEMINI.md" : relativeFilePath,
2823
2932
  fileContent,
2824
- validate: params.validate ?? true,
2825
- root: params.relativeFilePath === "GEMINI.md"
2933
+ validate,
2934
+ root: isRoot
2826
2935
  });
2827
2936
  }
2828
2937
  static fromRulesyncRule({
@@ -2849,15 +2958,22 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
2849
2958
  };
2850
2959
 
2851
2960
  // src/rules/junie-rule.ts
2961
+ import { join as join36 } from "path";
2852
2962
  var JunieRule = class _JunieRule extends ToolRule {
2853
- static async fromFilePath(params) {
2854
- 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));
2855
2971
  return new _JunieRule({
2856
- baseDir: params.baseDir || ".",
2857
- relativeDirPath: params.relativeDirPath,
2858
- relativeFilePath: params.relativeFilePath,
2972
+ baseDir,
2973
+ relativeDirPath: isRoot ? ".junie" : ".junie/memories",
2974
+ relativeFilePath: isRoot ? "guidelines.md" : relativeFilePath,
2859
2975
  fileContent,
2860
- validate: params.validate ?? true
2976
+ validate
2861
2977
  });
2862
2978
  }
2863
2979
  static fromRulesyncRule({
@@ -2870,8 +2986,8 @@ var JunieRule = class _JunieRule extends ToolRule {
2870
2986
  baseDir,
2871
2987
  rulesyncRule,
2872
2988
  validate,
2873
- rootPath: { relativeDirPath: ".", relativeFilePath: "guidelines.md" },
2874
- nonRootPath: { relativeDirPath: ".junie/guidelines" }
2989
+ rootPath: { relativeDirPath: ".junie", relativeFilePath: "guidelines.md" },
2990
+ nonRootPath: { relativeDirPath: ".junie/memories" }
2875
2991
  })
2876
2992
  );
2877
2993
  }
@@ -2884,15 +3000,20 @@ var JunieRule = class _JunieRule extends ToolRule {
2884
3000
  };
2885
3001
 
2886
3002
  // src/rules/kiro-rule.ts
3003
+ import { join as join37 } from "path";
2887
3004
  var KiroRule = class _KiroRule extends ToolRule {
2888
- static async fromFilePath(params) {
2889
- 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));
2890
3011
  return new _KiroRule({
2891
- baseDir: params.baseDir || ".",
2892
- relativeDirPath: params.relativeDirPath,
2893
- relativeFilePath: params.relativeFilePath,
3012
+ baseDir,
3013
+ relativeDirPath: ".kiro/steering",
3014
+ relativeFilePath,
2894
3015
  fileContent,
2895
- validate: params.validate ?? true,
3016
+ validate,
2896
3017
  root: false
2897
3018
  });
2898
3019
  }
@@ -2919,21 +3040,22 @@ var KiroRule = class _KiroRule extends ToolRule {
2919
3040
  };
2920
3041
 
2921
3042
  // src/rules/opencode-rule.ts
3043
+ import { join as join38 } from "path";
2922
3044
  var OpenCodeRule = class _OpenCodeRule extends ToolRule {
2923
- static async fromFilePath({
3045
+ static async fromFile({
2924
3046
  baseDir = ".",
2925
- relativeDirPath,
2926
3047
  relativeFilePath,
2927
- filePath,
2928
3048
  validate = true
2929
3049
  }) {
2930
- 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));
2931
3053
  return new _OpenCodeRule({
2932
3054
  baseDir,
2933
- relativeDirPath,
2934
- relativeFilePath,
3055
+ relativeDirPath: isRoot ? "." : ".opencode/memories",
3056
+ relativeFilePath: isRoot ? "AGENTS.md" : relativeFilePath,
2935
3057
  validate,
2936
- root: relativeFilePath === "AGENTS.md",
3058
+ root: isRoot,
2937
3059
  fileContent
2938
3060
  });
2939
3061
  }
@@ -2959,16 +3081,23 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
2959
3081
  };
2960
3082
 
2961
3083
  // src/rules/qwencode-rule.ts
3084
+ import { join as join39 } from "path";
2962
3085
  var QwencodeRule = class _QwencodeRule extends ToolRule {
2963
- static async fromFilePath(params) {
2964
- 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));
2965
3094
  return new _QwencodeRule({
2966
- baseDir: params.baseDir || process.cwd(),
2967
- relativeDirPath: params.relativeDirPath,
2968
- relativeFilePath: params.relativeFilePath,
3095
+ baseDir,
3096
+ relativeDirPath: isRoot ? "." : ".qwencode/memories",
3097
+ relativeFilePath: isRoot ? "QWEN.md" : relativeFilePath,
2969
3098
  fileContent,
2970
- validate: params.validate ?? true,
2971
- root: params.relativeFilePath === "QWEN.md"
3099
+ validate,
3100
+ root: isRoot
2972
3101
  });
2973
3102
  }
2974
3103
  static fromRulesyncRule(params) {
@@ -2989,15 +3118,21 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
2989
3118
  };
2990
3119
 
2991
3120
  // src/rules/roo-rule.ts
3121
+ import { join as join40 } from "path";
2992
3122
  var RooRule = class _RooRule extends ToolRule {
2993
- static async fromFilePath(params) {
2994
- 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));
2995
3129
  return new _RooRule({
2996
- baseDir: params.baseDir || ".",
2997
- relativeDirPath: params.relativeDirPath,
2998
- relativeFilePath: params.relativeFilePath,
3130
+ baseDir,
3131
+ relativeDirPath: ".roo/rules",
3132
+ relativeFilePath,
2999
3133
  fileContent,
3000
- validate: params.validate ?? true
3134
+ validate,
3135
+ root: false
3001
3136
  });
3002
3137
  }
3003
3138
  static fromRulesyncRule({
@@ -3037,15 +3172,71 @@ var RooRule = class _RooRule extends ToolRule {
3037
3172
  }
3038
3173
  };
3039
3174
 
3175
+ // src/rules/warp-rule.ts
3176
+ import { join as join41 } from "path";
3177
+ var WarpRule = class _WarpRule extends ToolRule {
3178
+ constructor({ fileContent, root, ...rest }) {
3179
+ super({
3180
+ ...rest,
3181
+ fileContent,
3182
+ root: root ?? false
3183
+ });
3184
+ }
3185
+ static async fromFile({
3186
+ baseDir = ".",
3187
+ relativeFilePath,
3188
+ validate = true
3189
+ }) {
3190
+ const isRoot = relativeFilePath === "WARP.md";
3191
+ const relativePath = isRoot ? "WARP.md" : join41(".warp/memories", relativeFilePath);
3192
+ const fileContent = await readFileContent(join41(baseDir, relativePath));
3193
+ return new _WarpRule({
3194
+ baseDir,
3195
+ relativeDirPath: isRoot ? "." : ".warp",
3196
+ relativeFilePath: isRoot ? "WARP.md" : relativeFilePath,
3197
+ fileContent,
3198
+ validate,
3199
+ root: isRoot
3200
+ });
3201
+ }
3202
+ static fromRulesyncRule({
3203
+ baseDir = ".",
3204
+ rulesyncRule,
3205
+ validate = true
3206
+ }) {
3207
+ return new _WarpRule(
3208
+ this.buildToolRuleParamsDefault({
3209
+ baseDir,
3210
+ rulesyncRule,
3211
+ validate,
3212
+ rootPath: { relativeDirPath: ".", relativeFilePath: "WARP.md" },
3213
+ nonRootPath: { relativeDirPath: ".warp/memories" }
3214
+ })
3215
+ );
3216
+ }
3217
+ toRulesyncRule() {
3218
+ return this.toRulesyncRuleDefault();
3219
+ }
3220
+ validate() {
3221
+ return { success: true, error: null };
3222
+ }
3223
+ };
3224
+
3040
3225
  // src/rules/windsurf-rule.ts
3226
+ import { join as join42 } from "path";
3041
3227
  var WindsurfRule = class _WindsurfRule extends ToolRule {
3042
- static async fromFilePath(params) {
3043
- 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));
3044
3234
  return new _WindsurfRule({
3045
- baseDir: params.baseDir || ".",
3046
- relativeDirPath: params.relativeDirPath,
3047
- relativeFilePath: params.relativeFilePath,
3048
- fileContent
3235
+ baseDir,
3236
+ relativeDirPath: ".windsurf/rules",
3237
+ relativeFilePath,
3238
+ fileContent,
3239
+ validate
3049
3240
  });
3050
3241
  }
3051
3242
  static fromRulesyncRule({
@@ -3087,6 +3278,7 @@ var rulesProcessorToolTargets = [
3087
3278
  "opencode",
3088
3279
  "qwencode",
3089
3280
  "roo",
3281
+ "warp",
3090
3282
  "windsurf"
3091
3283
  ];
3092
3284
  var RulesProcessorToolTargetSchema = z16.enum(rulesProcessorToolTargets);
@@ -3195,6 +3387,12 @@ var RulesProcessor = class extends FeatureProcessor {
3195
3387
  rulesyncRule,
3196
3388
  validate: true
3197
3389
  });
3390
+ case "warp":
3391
+ return WarpRule.fromRulesyncRule({
3392
+ baseDir: this.baseDir,
3393
+ rulesyncRule,
3394
+ validate: true
3395
+ });
3198
3396
  case "windsurf":
3199
3397
  return WindsurfRule.fromRulesyncRule({
3200
3398
  baseDir: this.baseDir,
@@ -3273,6 +3471,13 @@ var RulesProcessor = class extends FeatureProcessor {
3273
3471
  );
3274
3472
  return toolRules;
3275
3473
  }
3474
+ case "warp": {
3475
+ const rootRule = toolRules[rootRuleIndex];
3476
+ rootRule?.setFileContent(
3477
+ this.generateXmlReferencesSection(toolRules) + rootRule.getFileContent()
3478
+ );
3479
+ return toolRules;
3480
+ }
3276
3481
  default:
3277
3482
  return toolRules;
3278
3483
  }
@@ -3289,57 +3494,18 @@ var RulesProcessor = class extends FeatureProcessor {
3289
3494
  * Load and parse rulesync rule files from .rulesync/rules/ directory
3290
3495
  */
3291
3496
  async loadRulesyncFiles() {
3292
- try {
3293
- const rulesDir = join7(this.baseDir, ".rulesync", "rules");
3294
- const dirExists = await directoryExists(rulesDir);
3295
- if (!dirExists) {
3296
- logger.debug(`Rulesync rules directory not found: ${rulesDir}`);
3297
- return [];
3298
- }
3299
- const entries = await listDirectoryFiles(rulesDir);
3300
- const mdFiles = entries.filter((file) => file.endsWith(".md"));
3301
- if (mdFiles.length === 0) {
3302
- logger.debug(`No markdown files found in rulesync rules directory: ${rulesDir}`);
3303
- return [];
3304
- }
3305
- logger.info(`Found ${mdFiles.length} rule files in ${rulesDir}`);
3306
- const rulesyncRules = [];
3307
- for (const mdFile of mdFiles) {
3308
- const filepath = join7(rulesDir, mdFile);
3309
- try {
3310
- const rulesyncRule = await RulesyncRule.fromFilePath({
3311
- filePath: filepath
3312
- });
3313
- rulesyncRules.push(rulesyncRule);
3314
- logger.debug(`Successfully loaded rule: ${mdFile}`);
3315
- } catch (error) {
3316
- logger.warn(`Failed to load rule file ${filepath}:`, error);
3317
- continue;
3318
- }
3319
- }
3320
- if (rulesyncRules.length === 0) {
3321
- logger.debug(`No valid rules found in ${rulesDir}`);
3322
- return [];
3323
- }
3324
- logger.info(`Successfully loaded ${rulesyncRules.length} rulesync rules`);
3325
- return rulesyncRules;
3326
- } catch (error) {
3327
- logger.debug(`No rulesync files found`, error);
3328
- return [];
3329
- }
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
+ );
3330
3502
  }
3331
- async loadLegacyRulesyncFiles() {
3332
- try {
3333
- const legacyFiles = await findFilesByGlobs(join7(RULESYNC_RULES_DIR_LEGACY, "*.md"));
3334
- return Promise.all(
3335
- legacyFiles.map(
3336
- (file) => RulesyncRule.fromLegacyFile({ relativeFilePath: basename9(file) })
3337
- )
3338
- );
3339
- } catch (error) {
3340
- logger.debug(`No legacy rulesync files found`, error);
3341
- return [];
3342
- }
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
+ );
3343
3509
  }
3344
3510
  /**
3345
3511
  * Implementation of abstract method from FeatureProcessor
@@ -3378,6 +3544,8 @@ var RulesProcessor = class extends FeatureProcessor {
3378
3544
  return await this.loadQwencodeRules();
3379
3545
  case "roo":
3380
3546
  return await this.loadRooRules();
3547
+ case "warp":
3548
+ return await this.loadWarpRules();
3381
3549
  case "windsurf":
3382
3550
  return await this.loadWindsurfRules();
3383
3551
  default:
@@ -3388,502 +3556,296 @@ var RulesProcessor = class extends FeatureProcessor {
3388
3556
  return [];
3389
3557
  }
3390
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
+ }
3391
3599
  /**
3392
3600
  * Load AGENTS.md rule configuration
3393
3601
  */
3394
3602
  async loadAgentsmdRules() {
3395
- const agentsFile = join7(this.baseDir, "AGENTS.md");
3396
- if (!await fileExists(agentsFile)) {
3397
- logger.warn(`AGENTS.md file not found: ${agentsFile}`);
3398
- return [];
3399
- }
3400
- try {
3401
- const agentsmdRule = await AgentsMdRule.fromFilePath({
3402
- baseDir: this.baseDir,
3603
+ return await this.loadToolRulesDefault({
3604
+ root: {
3403
3605
  relativeDirPath: ".",
3404
3606
  relativeFilePath: "AGENTS.md",
3405
- filePath: agentsFile,
3406
- validate: true
3407
- });
3408
- logger.info(`Successfully loaded AGENTS.md rule`);
3409
- return [agentsmdRule];
3410
- } catch (error) {
3411
- logger.warn(`Failed to load AGENTS.md file ${agentsFile}:`, error);
3412
- return [];
3413
- }
3607
+ fromFile: (params) => AgentsMdRule.fromFile(params)
3608
+ },
3609
+ nonRoot: {
3610
+ relativeFilePath: ".agents/memories",
3611
+ fromFile: (params) => AgentsMdRule.fromFile(params),
3612
+ extension: "md"
3613
+ }
3614
+ });
3615
+ }
3616
+ async loadWarpRules() {
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
+ });
3414
3629
  }
3415
3630
  /**
3416
3631
  * Load Amazon Q Developer CLI rule configurations from .amazonq/rules/ directory
3417
3632
  */
3418
3633
  async loadAmazonqcliRules() {
3419
- return this.loadToolRulesFromDirectory(
3420
- join7(this.baseDir, ".amazonq", "rules"),
3421
- (filePath, relativeFilePath) => AmazonQCliRule.fromFilePath({
3422
- baseDir: this.baseDir,
3423
- relativeDirPath: ".amazonq/rules",
3424
- relativeFilePath,
3425
- filePath,
3426
- validate: true
3427
- }),
3428
- "Amazon Q Developer CLI"
3429
- );
3634
+ return await this.loadToolRulesDefault({
3635
+ nonRoot: {
3636
+ relativeFilePath: ".amazonq/rules",
3637
+ fromFile: (params) => AmazonQCliRule.fromFile(params),
3638
+ extension: "md"
3639
+ }
3640
+ });
3430
3641
  }
3431
3642
  /**
3432
3643
  * Load AugmentCode rule configurations from .augment/rules/ directory
3433
3644
  */
3434
3645
  async loadAugmentcodeRules() {
3435
- return this.loadToolRulesFromDirectory(
3436
- join7(this.baseDir, ".augment", "rules"),
3437
- (filePath, relativeFilePath) => AugmentcodeRule.fromFilePath({
3438
- baseDir: this.baseDir,
3439
- relativeDirPath: ".augment/rules",
3440
- relativeFilePath,
3441
- filePath,
3442
- validate: true
3443
- }),
3444
- "AugmentCode"
3445
- );
3646
+ return await this.loadToolRulesDefault({
3647
+ nonRoot: {
3648
+ relativeFilePath: ".augment/rules",
3649
+ fromFile: (params) => AugmentcodeRule.fromFile(params),
3650
+ extension: "md"
3651
+ }
3652
+ });
3446
3653
  }
3447
3654
  /**
3448
3655
  * Load AugmentCode legacy rule configuration from .augment-guidelines file and .augment/rules/ directory
3449
3656
  */
3450
3657
  async loadAugmentcodeLegacyRules() {
3451
- const toolRules = [];
3452
- const guidelinesFile = join7(this.baseDir, ".augment-guidelines");
3453
- if (await fileExists(guidelinesFile)) {
3454
- try {
3455
- const augmentcodeLegacyRule = await AugmentcodeLegacyRule.fromFilePath({
3456
- baseDir: this.baseDir,
3457
- relativeDirPath: ".",
3458
- relativeFilePath: ".augment-guidelines",
3459
- filePath: guidelinesFile,
3460
- validate: true
3461
- });
3462
- toolRules.push(augmentcodeLegacyRule);
3463
- logger.info(`Successfully loaded AugmentCode legacy guidelines`);
3464
- } catch (error) {
3465
- 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"
3466
3668
  }
3467
- }
3468
- const rulesDir = join7(this.baseDir, ".augment", "rules");
3469
- if (await directoryExists(rulesDir)) {
3470
- const dirRules = await this.loadToolRulesFromDirectory(
3471
- rulesDir,
3472
- (filePath, relativeFilePath) => AugmentcodeLegacyRule.fromFilePath({
3473
- baseDir: this.baseDir,
3474
- relativeDirPath: join7(".augment", "rules"),
3475
- relativeFilePath,
3476
- filePath,
3477
- validate: true
3478
- }),
3479
- "AugmentCode Legacy"
3480
- );
3481
- toolRules.push(...dirRules);
3482
- }
3483
- return toolRules;
3669
+ });
3484
3670
  }
3485
3671
  /**
3486
3672
  * Load Claude Code rule configuration from CLAUDE.md file
3487
3673
  */
3488
3674
  async loadClaudecodeRules() {
3489
- const claudeMemoriesDir = join7(this.baseDir, ".claude", "memories");
3490
- if (!await directoryExists(claudeMemoriesDir)) {
3491
- logger.debug(`Claude Code memories directory not found: ${claudeMemoriesDir}`);
3492
- const claudeFile = join7(this.baseDir, "CLAUDE.md");
3493
- if (!await fileExists(claudeFile)) {
3494
- logger.debug(`Claude Code memory file not found: ${claudeFile}`);
3495
- return [];
3496
- }
3497
- try {
3498
- const claudecodeRule = await ClaudecodeRule.fromFilePath({
3499
- baseDir: this.baseDir,
3500
- relativeDirPath: ".",
3501
- relativeFilePath: "CLAUDE.md",
3502
- filePath: claudeFile,
3503
- validate: true
3504
- });
3505
- logger.info(`Successfully loaded Claude Code memory file`);
3506
- return [claudecodeRule];
3507
- } catch (error) {
3508
- logger.warn(`Failed to load Claude Code memory file ${claudeFile}:`, error);
3509
- return [];
3510
- }
3511
- }
3512
- const entries = await listDirectoryFiles(claudeMemoriesDir);
3513
- const mdFiles = entries.filter((file) => file.endsWith(".md"));
3514
- if (mdFiles.length === 0) {
3515
- logger.debug(
3516
- `No markdown files found in Claude Code memories directory: ${claudeMemoriesDir}`
3517
- );
3518
- return [];
3519
- }
3520
- logger.info(`Found ${mdFiles.length} Claude Code memory files in ${claudeMemoriesDir}`);
3521
- const toolRules = [];
3522
- for (const mdFile of mdFiles) {
3523
- const filePath = join7(claudeMemoriesDir, mdFile);
3524
- try {
3525
- const claudecodeRule = await ClaudecodeRule.fromFilePath({
3526
- baseDir: this.baseDir,
3527
- relativeDirPath: join7(".claude", "memories"),
3528
- relativeFilePath: mdFile,
3529
- filePath,
3530
- validate: true
3531
- });
3532
- toolRules.push(claudecodeRule);
3533
- logger.debug(`Successfully loaded Claude Code memory file: ${mdFile}`);
3534
- } catch (error) {
3535
- logger.warn(`Failed to load Claude Code memory file ${filePath}:`, error);
3536
- 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"
3537
3685
  }
3538
- }
3539
- logger.info(`Successfully loaded ${toolRules.length} Claude Code memory files`);
3540
- return toolRules;
3686
+ });
3541
3687
  }
3542
3688
  /**
3543
3689
  * Load Cline rule configurations from .clinerules/ directory
3544
3690
  */
3545
3691
  async loadClineRules() {
3546
- return this.loadToolRulesFromDirectory(
3547
- join7(this.baseDir, ".clinerules"),
3548
- (filePath, relativeFilePath) => ClineRule.fromFilePath({
3549
- baseDir: this.baseDir,
3550
- relativeDirPath: ".clinerules",
3551
- relativeFilePath,
3552
- filePath,
3553
- validate: true
3554
- }),
3555
- "Cline"
3556
- );
3692
+ return await this.loadToolRulesDefault({
3693
+ nonRoot: {
3694
+ relativeFilePath: ".clinerules",
3695
+ fromFile: (params) => ClineRule.fromFile(params),
3696
+ extension: "md"
3697
+ }
3698
+ });
3557
3699
  }
3558
3700
  /**
3559
3701
  * Load OpenAI Codex CLI rule configuration from AGENTS.md and .codex/memories/*.md files
3560
3702
  */
3561
3703
  async loadCodexcliRules() {
3562
- const rules = [];
3563
- const agentsFile = join7(this.baseDir, "AGENTS.md");
3564
- if (await fileExists(agentsFile)) {
3565
- try {
3566
- const codexcliRule = await CodexcliRule.fromFilePath({
3567
- baseDir: this.baseDir,
3568
- relativeDirPath: ".",
3569
- relativeFilePath: "AGENTS.md",
3570
- filePath: agentsFile,
3571
- validate: true
3572
- });
3573
- rules.push(codexcliRule);
3574
- logger.info(`Successfully loaded OpenAI Codex CLI agents file`);
3575
- } catch (error) {
3576
- logger.warn(`Failed to load OpenAI Codex CLI agents file ${agentsFile}:`, error);
3577
- }
3578
- }
3579
- const memoriesDir = join7(this.baseDir, ".codex", "memories");
3580
- if (await directoryExists(memoriesDir)) {
3581
- try {
3582
- const entries = await listDirectoryFiles(memoriesDir);
3583
- const mdFiles = entries.filter((file) => file.endsWith(".md"));
3584
- for (const mdFile of mdFiles) {
3585
- const filePath = join7(memoriesDir, mdFile);
3586
- try {
3587
- const codexcliRule = await CodexcliRule.fromFilePath({
3588
- baseDir: this.baseDir,
3589
- relativeDirPath: join7(".codex", "memories"),
3590
- relativeFilePath: mdFile,
3591
- filePath,
3592
- validate: true
3593
- });
3594
- rules.push(codexcliRule);
3595
- } catch (error) {
3596
- logger.warn(`Failed to load Codex CLI memories file ${filePath}:`, error);
3597
- }
3598
- }
3599
- if (mdFiles.length > 0) {
3600
- logger.info(`Successfully loaded ${mdFiles.length} OpenAI Codex CLI memory files`);
3601
- }
3602
- } catch (error) {
3603
- 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"
3604
3714
  }
3605
- }
3606
- if (rules.length === 0) {
3607
- logger.warn(`No OpenAI Codex CLI rule files found`);
3608
- }
3609
- return rules;
3715
+ });
3610
3716
  }
3611
3717
  /**
3612
3718
  * Load GitHub Copilot rule configuration from .github/copilot-instructions.md file
3613
3719
  */
3614
3720
  async loadCopilotRules() {
3615
- const copilotFile = join7(this.baseDir, ".github", "copilot-instructions.md");
3616
- if (!await fileExists(copilotFile)) {
3617
- logger.warn(`GitHub Copilot instructions file not found: ${copilotFile}`);
3618
- return [];
3619
- }
3620
- try {
3621
- const copilotRule = await CopilotRule.fromFilePath({
3622
- baseDir: this.baseDir,
3623
- relativeDirPath: ".github",
3624
- relativeFilePath: "copilot-instructions.md",
3625
- filePath: copilotFile,
3626
- validate: true
3627
- });
3628
- logger.info(`Successfully loaded GitHub Copilot instructions file`);
3629
- return [copilotRule];
3630
- } catch (error) {
3631
- logger.warn(`Failed to load GitHub Copilot instructions file ${copilotFile}:`, error);
3632
- return [];
3633
- }
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
+ });
3634
3733
  }
3635
3734
  /**
3636
3735
  * Load Cursor rule configurations from .cursor/rules/ directory
3637
3736
  */
3638
3737
  async loadCursorRules() {
3639
- return this.loadToolRulesFromDirectory(
3640
- join7(this.baseDir, ".cursor", "rules"),
3641
- (filePath) => CursorRule.fromFilePath({
3642
- filePath,
3643
- validate: true
3644
- }),
3645
- "Cursor"
3646
- );
3738
+ return await this.loadToolRulesDefault({
3739
+ nonRoot: {
3740
+ relativeFilePath: ".cursor/rules",
3741
+ fromFile: (params) => CursorRule.fromFile(params),
3742
+ extension: "md"
3743
+ }
3744
+ });
3647
3745
  }
3648
3746
  /**
3649
3747
  * Load Gemini CLI rule configuration from GEMINI.md file
3650
3748
  */
3651
3749
  async loadGeminicliRules() {
3652
- const geminiFile = join7(this.baseDir, "GEMINI.md");
3653
- if (!await fileExists(geminiFile)) {
3654
- logger.warn(`Gemini CLI memory file not found: ${geminiFile}`);
3655
- return [];
3656
- }
3657
- try {
3658
- const geminicliRule = await GeminiCliRule.fromFilePath({
3659
- baseDir: this.baseDir,
3750
+ return await this.loadToolRulesDefault({
3751
+ root: {
3660
3752
  relativeDirPath: ".",
3661
3753
  relativeFilePath: "GEMINI.md",
3662
- filePath: geminiFile,
3663
- validate: true
3664
- });
3665
- logger.info(`Successfully loaded Gemini CLI memory file`);
3666
- return [geminicliRule];
3667
- } catch (error) {
3668
- logger.warn(`Failed to load Gemini CLI memory file ${geminiFile}:`, error);
3669
- return [];
3670
- }
3754
+ fromFile: (params) => GeminiCliRule.fromFile(params)
3755
+ },
3756
+ nonRoot: {
3757
+ relativeFilePath: ".gemini/memories",
3758
+ fromFile: (params) => GeminiCliRule.fromFile(params),
3759
+ extension: "md"
3760
+ }
3761
+ });
3671
3762
  }
3672
3763
  /**
3673
3764
  * Load JetBrains Junie rule configuration from .junie/guidelines.md file
3674
3765
  */
3675
3766
  async loadJunieRules() {
3676
- const guidelinesFile = join7(this.baseDir, ".junie", "guidelines.md");
3677
- if (!await fileExists(guidelinesFile)) {
3678
- return [];
3679
- }
3680
- const junieRule = await JunieRule.fromFilePath({
3681
- baseDir: this.baseDir,
3682
- relativeDirPath: ".junie",
3683
- relativeFilePath: "guidelines.md",
3684
- filePath: guidelinesFile,
3685
- 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
+ }
3686
3778
  });
3687
- logger.info(`Successfully loaded JetBrains Junie guidelines file`);
3688
- return [junieRule];
3689
3779
  }
3690
3780
  /**
3691
3781
  * Load Kiro rule configurations from .kiro/steering/ directory
3692
3782
  */
3693
3783
  async loadKiroRules() {
3694
- return this.loadToolRulesFromDirectory(
3695
- join7(this.baseDir, ".kiro", "steering"),
3696
- (filePath, relativeFilePath) => KiroRule.fromFilePath({
3697
- baseDir: this.baseDir,
3698
- relativeDirPath: ".kiro/steering",
3699
- relativeFilePath,
3700
- filePath,
3701
- validate: true
3702
- }),
3703
- "Kiro"
3704
- );
3784
+ return await this.loadToolRulesDefault({
3785
+ nonRoot: {
3786
+ relativeFilePath: ".kiro/steering",
3787
+ fromFile: (params) => KiroRule.fromFile(params),
3788
+ extension: "md"
3789
+ }
3790
+ });
3705
3791
  }
3706
3792
  /**
3707
3793
  * Load OpenCode rule configuration from AGENTS.md file and .opencode/memories/*.md files
3708
3794
  */
3709
3795
  async loadOpencodeRules() {
3710
- const rules = [];
3711
- const agentsFile = join7(this.baseDir, "AGENTS.md");
3712
- if (await fileExists(agentsFile)) {
3713
- try {
3714
- const opencodeRule = await OpenCodeRule.fromFilePath({
3715
- baseDir: this.baseDir,
3716
- relativeDirPath: ".",
3717
- relativeFilePath: "AGENTS.md",
3718
- filePath: agentsFile,
3719
- validate: true
3720
- });
3721
- rules.push(opencodeRule);
3722
- logger.info(`Successfully loaded OpenCode agents file`);
3723
- } catch (error) {
3724
- logger.warn(`Failed to load OpenCode agents file ${agentsFile}:`, error);
3725
- }
3726
- }
3727
- const memoriesDir = join7(this.baseDir, ".opencode", "memories");
3728
- if (await directoryExists(memoriesDir)) {
3729
- try {
3730
- const entries = await listDirectoryFiles(memoriesDir);
3731
- const mdFiles = entries.filter((file) => file.endsWith(".md"));
3732
- for (const mdFile of mdFiles) {
3733
- const filePath = join7(memoriesDir, mdFile);
3734
- try {
3735
- const opencodeRule = await OpenCodeRule.fromFilePath({
3736
- baseDir: this.baseDir,
3737
- relativeDirPath: join7(".opencode", "memories"),
3738
- relativeFilePath: mdFile,
3739
- filePath,
3740
- validate: true
3741
- });
3742
- rules.push(opencodeRule);
3743
- } catch (error) {
3744
- logger.warn(`Failed to load OpenCode memories file ${filePath}:`, error);
3745
- }
3746
- }
3747
- if (mdFiles.length > 0) {
3748
- logger.info(`Successfully loaded ${mdFiles.length} OpenCode memory files`);
3749
- }
3750
- } catch (error) {
3751
- 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"
3752
3806
  }
3753
- }
3754
- if (rules.length === 0) {
3755
- logger.warn(`No OpenCode rule files found`);
3756
- }
3757
- return rules;
3807
+ });
3758
3808
  }
3759
3809
  /**
3760
3810
  * Load Qwen Code rule configuration from QWEN.md file and .qwen/memories/*.md files
3761
3811
  */
3762
3812
  async loadQwencodeRules() {
3763
- const rules = [];
3764
- const qwenFile = join7(this.baseDir, "QWEN.md");
3765
- if (await fileExists(qwenFile)) {
3766
- try {
3767
- const qwencodeRule = await QwencodeRule.fromFilePath({
3768
- baseDir: this.baseDir,
3769
- relativeDirPath: ".",
3770
- relativeFilePath: "QWEN.md",
3771
- filePath: qwenFile,
3772
- validate: true
3773
- });
3774
- rules.push(qwencodeRule);
3775
- logger.info(`Successfully loaded Qwen Code memory file`);
3776
- } catch (error) {
3777
- logger.warn(`Failed to load Qwen Code memory file ${qwenFile}:`, error);
3778
- }
3779
- }
3780
- const memoriesDir = join7(this.baseDir, ".qwen", "memories");
3781
- if (await directoryExists(memoriesDir)) {
3782
- try {
3783
- const entries = await listDirectoryFiles(memoriesDir);
3784
- const mdFiles = entries.filter((file) => file.endsWith(".md"));
3785
- for (const mdFile of mdFiles) {
3786
- const filePath = join7(memoriesDir, mdFile);
3787
- try {
3788
- const qwencodeRule = await QwencodeRule.fromFilePath({
3789
- baseDir: this.baseDir,
3790
- relativeDirPath: join7(".qwen", "memories"),
3791
- relativeFilePath: mdFile,
3792
- filePath,
3793
- validate: true
3794
- });
3795
- rules.push(qwencodeRule);
3796
- } catch (error) {
3797
- logger.warn(`Failed to load Qwen Code memories file ${filePath}:`, error);
3798
- }
3799
- }
3800
- if (mdFiles.length > 0) {
3801
- logger.info(`Successfully loaded ${mdFiles.length} Qwen Code memory files`);
3802
- }
3803
- } catch (error) {
3804
- 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"
3805
3823
  }
3806
- }
3807
- if (rules.length === 0) {
3808
- logger.warn(`No Qwen Code rule files found`);
3809
- }
3810
- return rules;
3824
+ });
3811
3825
  }
3812
3826
  /**
3813
3827
  * Load Roo Code rule configurations from .roo/rules/ directory
3814
3828
  */
3815
3829
  async loadRooRules() {
3816
- return this.loadToolRulesFromDirectory(
3817
- join7(this.baseDir, ".roo", "rules"),
3818
- (filePath, relativeFilePath) => RooRule.fromFilePath({
3819
- baseDir: this.baseDir,
3820
- relativeDirPath: ".roo/rules",
3821
- relativeFilePath,
3822
- filePath,
3823
- validate: true
3824
- }),
3825
- "Roo Code"
3826
- );
3830
+ return await this.loadToolRulesDefault({
3831
+ nonRoot: {
3832
+ relativeFilePath: ".roo/rules",
3833
+ fromFile: (params) => RooRule.fromFile(params),
3834
+ extension: "md"
3835
+ }
3836
+ });
3827
3837
  }
3828
3838
  /**
3829
3839
  * Load Windsurf rule configurations from .windsurf/rules/ directory
3830
3840
  */
3831
3841
  async loadWindsurfRules() {
3832
- return this.loadToolRulesFromDirectory(
3833
- join7(this.baseDir, ".windsurf", "rules"),
3834
- (filePath, relativeFilePath) => WindsurfRule.fromFilePath({
3835
- baseDir: this.baseDir,
3836
- relativeDirPath: ".windsurf/rules",
3837
- relativeFilePath,
3838
- filePath,
3839
- validate: true
3840
- }),
3841
- "Windsurf"
3842
- );
3843
- }
3844
- /**
3845
- * Common helper method to load tool rules from a directory with parallel processing
3846
- */
3847
- async loadToolRulesFromDirectory(dirPath, ruleFactory, toolName) {
3848
- if (!await directoryExists(dirPath)) {
3849
- logger.warn(`${toolName} rules directory not found: ${dirPath}`);
3850
- return [];
3851
- }
3852
- const entries = await listDirectoryFiles(dirPath);
3853
- const mdFiles = entries.filter((file) => file.endsWith(".md") || file.endsWith(".mdc"));
3854
- if (mdFiles.length === 0) {
3855
- logger.info(`No rule files found in ${dirPath}`);
3856
- return [];
3857
- }
3858
- logger.info(`Found ${mdFiles.length} ${toolName} rule files in ${dirPath}`);
3859
- const results = await Promise.allSettled(
3860
- mdFiles.map(async (mdFile) => {
3861
- const filepath = join7(dirPath, mdFile);
3862
- return {
3863
- rule: await ruleFactory(filepath, mdFile),
3864
- filename: mdFile
3865
- };
3866
- })
3867
- );
3868
- const toolRules = [];
3869
- for (const [index, result] of results.entries()) {
3870
- if (result.status === "fulfilled") {
3871
- toolRules.push(result.value.rule);
3872
- logger.debug(`Successfully loaded ${toolName} rule: ${result.value.filename}`);
3873
- } else {
3874
- 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"
3875
3847
  }
3876
- }
3877
- logger.info(`Successfully loaded ${toolRules.length} ${toolName} rules`);
3878
- return toolRules;
3879
- }
3880
- async writeToolRulesFromRulesyncRules(rulesyncRules) {
3881
- const toolRules = await this.convertRulesyncFilesToToolFiles(rulesyncRules);
3882
- await this.writeAiFiles(toolRules);
3883
- }
3884
- async writeRulesyncRulesFromToolRules(toolRules) {
3885
- const rulesyncRules = await this.convertToolFilesToRulesyncFiles(toolRules);
3886
- await this.writeAiFiles(rulesyncRules);
3848
+ });
3887
3849
  }
3888
3850
  /**
3889
3851
  * Implementation of abstract method from FeatureProcessor
@@ -3892,30 +3854,6 @@ var RulesProcessor = class extends FeatureProcessor {
3892
3854
  static getToolTargets() {
3893
3855
  return rulesProcessorToolTargets;
3894
3856
  }
3895
- /**
3896
- * Get all supported tools
3897
- */
3898
- static getSupportedTools() {
3899
- const allTools = [
3900
- "agentsmd",
3901
- "amazonqcli",
3902
- "augmentcode",
3903
- "augmentcode-legacy",
3904
- "claudecode",
3905
- "cline",
3906
- "codexcli",
3907
- "copilot",
3908
- "cursor",
3909
- "geminicli",
3910
- "junie",
3911
- "kiro",
3912
- "opencode",
3913
- "qwencode",
3914
- "roo",
3915
- "windsurf"
3916
- ];
3917
- return allTools;
3918
- }
3919
3857
  generateXmlReferencesSection(toolRules) {
3920
3858
  const toolRulesWithoutRoot = toolRules.filter((rule) => !rule.isRoot());
3921
3859
  if (toolRulesWithoutRoot.length === 0) {
@@ -3976,14 +3914,15 @@ var RulesProcessor = class extends FeatureProcessor {
3976
3914
  };
3977
3915
 
3978
3916
  // src/subagents/subagents-processor.ts
3979
- import { join as join8 } from "path";
3917
+ import { basename as basename11, join as join46 } from "path";
3980
3918
  import { z as z19 } from "zod/mini";
3981
3919
 
3982
3920
  // src/subagents/claudecode-subagent.ts
3921
+ import { join as join45 } from "path";
3983
3922
  import { z as z18 } from "zod/mini";
3984
3923
 
3985
3924
  // src/subagents/rulesync-subagent.ts
3986
- import { basename as basename10 } from "path";
3925
+ import { basename as basename10, join as join44 } from "path";
3987
3926
  import { z as z17 } from "zod/mini";
3988
3927
  var RulesyncSubagentModelSchema = z17.enum(["opus", "sonnet", "haiku", "inherit"]);
3989
3928
  var RulesyncSubagentFrontmatterSchema = z17.object({
@@ -4029,14 +3968,16 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
4029
3968
  return { success: false, error: result.error };
4030
3969
  }
4031
3970
  }
4032
- static async fromFilePath({ filePath }) {
4033
- const fileContent = await readFileContent(filePath);
3971
+ static async fromFile({
3972
+ relativeFilePath
3973
+ }) {
3974
+ const fileContent = await readFileContent(join44(RULESYNC_SUBAGENTS_DIR, relativeFilePath));
4034
3975
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
4035
3976
  const result = RulesyncSubagentFrontmatterSchema.safeParse(frontmatter);
4036
3977
  if (!result.success) {
4037
- throw new Error(`Invalid frontmatter in ${filePath}: ${result.error.message}`);
3978
+ throw new Error(`Invalid frontmatter in ${relativeFilePath}: ${result.error.message}`);
4038
3979
  }
4039
- const filename = basename10(filePath);
3980
+ const filename = basename10(relativeFilePath);
4040
3981
  return new _RulesyncSubagent({
4041
3982
  baseDir: ".",
4042
3983
  relativeDirPath: ".rulesync/subagents",
@@ -4050,7 +3991,7 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
4050
3991
 
4051
3992
  // src/subagents/tool-subagent.ts
4052
3993
  var ToolSubagent = class extends ToolFile {
4053
- static async fromFilePath(_params) {
3994
+ static async fromFile(_params) {
4054
3995
  throw new Error("Please implement this method in the subclass.");
4055
3996
  }
4056
3997
  static fromRulesyncSubagent(_params) {
@@ -4111,7 +4052,6 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4111
4052
  static fromRulesyncSubagent({
4112
4053
  baseDir = ".",
4113
4054
  rulesyncSubagent,
4114
- relativeDirPath,
4115
4055
  validate = true
4116
4056
  }) {
4117
4057
  const rulesyncFrontmatter = rulesyncSubagent.getFrontmatter();
@@ -4126,7 +4066,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4126
4066
  baseDir,
4127
4067
  frontmatter: claudecodeFrontmatter,
4128
4068
  body,
4129
- relativeDirPath,
4069
+ relativeDirPath: ".claude/agents",
4130
4070
  relativeFilePath: rulesyncSubagent.getRelativeFilePath(),
4131
4071
  fileContent,
4132
4072
  validate
@@ -4143,22 +4083,20 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4143
4083
  return { success: false, error: result.error };
4144
4084
  }
4145
4085
  }
4146
- static async fromFilePath({
4086
+ static async fromFile({
4147
4087
  baseDir = ".",
4148
- relativeDirPath,
4149
4088
  relativeFilePath,
4150
- filePath,
4151
4089
  validate = true
4152
4090
  }) {
4153
- const fileContent = await readFileContent(filePath);
4091
+ const fileContent = await readFileContent(join45(baseDir, ".claude/agents", relativeFilePath));
4154
4092
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
4155
4093
  const result = ClaudecodeSubagentFrontmatterSchema.safeParse(frontmatter);
4156
4094
  if (!result.success) {
4157
- throw new Error(`Invalid frontmatter in ${filePath}: ${result.error.message}`);
4095
+ throw new Error(`Invalid frontmatter in ${relativeFilePath}: ${result.error.message}`);
4158
4096
  }
4159
4097
  return new _ClaudecodeSubagent({
4160
4098
  baseDir,
4161
- relativeDirPath,
4099
+ relativeDirPath: ".claude/agents",
4162
4100
  relativeFilePath,
4163
4101
  frontmatter: result.data,
4164
4102
  body: content.trim(),
@@ -4212,7 +4150,7 @@ var SubagentsProcessor = class extends FeatureProcessor {
4212
4150
  * Load and parse rulesync subagent files from .rulesync/subagents/ directory
4213
4151
  */
4214
4152
  async loadRulesyncFiles() {
4215
- const subagentsDir = join8(this.baseDir, ".rulesync", "subagents");
4153
+ const subagentsDir = join46(this.baseDir, ".rulesync", "subagents");
4216
4154
  const dirExists = await directoryExists(subagentsDir);
4217
4155
  if (!dirExists) {
4218
4156
  logger.debug(`Rulesync subagents directory not found: ${subagentsDir}`);
@@ -4227,10 +4165,11 @@ var SubagentsProcessor = class extends FeatureProcessor {
4227
4165
  logger.info(`Found ${mdFiles.length} subagent files in ${subagentsDir}`);
4228
4166
  const rulesyncSubagents = [];
4229
4167
  for (const mdFile of mdFiles) {
4230
- const filepath = join8(subagentsDir, mdFile);
4168
+ const filepath = join46(subagentsDir, mdFile);
4231
4169
  try {
4232
- const rulesyncSubagent = await RulesyncSubagent.fromFilePath({
4233
- filePath: filepath
4170
+ const rulesyncSubagent = await RulesyncSubagent.fromFile({
4171
+ relativeFilePath: mdFile,
4172
+ validate: true
4234
4173
  });
4235
4174
  rulesyncSubagents.push(rulesyncSubagent);
4236
4175
  logger.debug(`Successfully loaded subagent: ${mdFile}`);
@@ -4262,43 +4201,19 @@ var SubagentsProcessor = class extends FeatureProcessor {
4262
4201
  * Load Claude Code subagent configurations from .claude/agents/ directory
4263
4202
  */
4264
4203
  async loadClaudecodeSubagents() {
4265
- const agentsDir = join8(this.baseDir, ".claude", "agents");
4266
- if (!await directoryExists(agentsDir)) {
4267
- logger.warn(`Claude Code agents directory not found: ${agentsDir}`);
4268
- return [];
4269
- }
4270
- let entries;
4271
- try {
4272
- entries = await listDirectoryFiles(agentsDir);
4273
- } catch (error) {
4274
- logger.warn(`Failed to read Claude Code agents directory ${agentsDir}:`, error);
4275
- return [];
4276
- }
4277
- const mdFiles = entries.filter((file) => file.endsWith(".md"));
4278
- if (mdFiles.length === 0) {
4279
- logger.info(`No JSON agent files found in ${agentsDir}`);
4280
- return [];
4281
- }
4282
- logger.info(`Found ${mdFiles.length} Claude Code agent files in ${agentsDir}`);
4283
- const toolSubagents = [];
4284
- for (const mdFile of mdFiles) {
4285
- const filepath = join8(agentsDir, mdFile);
4286
- try {
4287
- const claudecodeSubagent = await ClaudecodeSubagent.fromFilePath({
4288
- baseDir: this.baseDir,
4289
- relativeDirPath: ".claude/agents",
4290
- relativeFilePath: mdFile,
4291
- filePath: filepath
4292
- });
4293
- toolSubagents.push(claudecodeSubagent);
4294
- logger.debug(`Successfully loaded Claude Code agent: ${mdFile}`);
4295
- } catch (error) {
4296
- logger.warn(`Failed to load Claude Code agent file ${filepath}:`, error);
4297
- continue;
4298
- }
4299
- }
4300
- logger.info(`Successfully loaded ${toolSubagents.length} Claude Code subagents`);
4301
- 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;
4302
4217
  }
4303
4218
  /**
4304
4219
  * Implementation of abstract method from FeatureProcessor
@@ -4334,7 +4249,7 @@ async function generateCommand(options) {
4334
4249
  }
4335
4250
  let rulesyncFiles = await processor.loadRulesyncFiles();
4336
4251
  if (rulesyncFiles.length === 0) {
4337
- rulesyncFiles = await processor.loadLegacyRulesyncFiles();
4252
+ rulesyncFiles = await processor.loadRulesyncFilesLegacy();
4338
4253
  }
4339
4254
  const toolFiles = await processor.convertRulesyncFilesToToolFiles(rulesyncFiles);
4340
4255
  const writtenCount = await processor.writeAiFiles(toolFiles);
@@ -4488,9 +4403,9 @@ async function generateCommand(options) {
4488
4403
  }
4489
4404
 
4490
4405
  // src/cli/commands/gitignore.ts
4491
- import { join as join9 } from "path";
4406
+ import { join as join47 } from "path";
4492
4407
  var gitignoreCommand = async () => {
4493
- const gitignorePath = join9(process.cwd(), ".gitignore");
4408
+ const gitignorePath = join47(process.cwd(), ".gitignore");
4494
4409
  const rulesFilesToIgnore = [
4495
4410
  "# Generated by rulesync - AI tool configuration files",
4496
4411
  "**/.amazonq/rules/",
@@ -4619,6 +4534,24 @@ async function importCommand(options) {
4619
4534
  logger.success(`Created ${ignoreFileCreated} ignore files`);
4620
4535
  }
4621
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
+ }
4622
4555
  let subagentsCreated = 0;
4623
4556
  if (config.getFeatures().includes("subagents")) {
4624
4557
  if (SubagentsProcessor.getToolTargets().includes(tool)) {
@@ -4659,7 +4592,7 @@ async function importCommand(options) {
4659
4592
  }
4660
4593
 
4661
4594
  // src/cli/commands/init.ts
4662
- import { join as join10 } from "path";
4595
+ import { join as join48 } from "path";
4663
4596
  async function initCommand() {
4664
4597
  logger.info("Initializing rulesync...");
4665
4598
  await ensureDir(RULESYNC_DIR);
@@ -4705,7 +4638,7 @@ globs: ["**/*"]
4705
4638
  - Follow single responsibility principle
4706
4639
  `
4707
4640
  };
4708
- const filepath = join10(RULESYNC_RULES_DIR, sampleFile.filename);
4641
+ const filepath = join48(RULESYNC_RULES_DIR, sampleFile.filename);
4709
4642
  await ensureDir(RULESYNC_RULES_DIR);
4710
4643
  await ensureDir(RULESYNC_COMMANDS_DIR);
4711
4644
  await ensureDir(RULESYNC_SUBAGENTS_DIR);
@@ -4723,15 +4656,15 @@ var getVersion = async () => {
4723
4656
  let packageJsonPath;
4724
4657
  if (typeof import.meta !== "undefined" && import.meta.url) {
4725
4658
  const __filename = fileURLToPath(import.meta.url);
4726
- const __dirname = join11(__filename, "..");
4727
- packageJsonPath = join11(__dirname, "../../package.json");
4659
+ const __dirname = join49(__filename, "..");
4660
+ packageJsonPath = join49(__dirname, "../../package.json");
4728
4661
  } else {
4729
- packageJsonPath = join11(process.cwd(), "package.json");
4662
+ packageJsonPath = join49(process.cwd(), "package.json");
4730
4663
  }
4731
4664
  const packageJson = await readJsonFile(packageJsonPath);
4732
4665
  return packageJson.version;
4733
4666
  } catch {
4734
- return "0.68.1";
4667
+ return "0.70.0";
4735
4668
  }
4736
4669
  };
4737
4670
  var main = async () => {