rulesync 0.74.0 → 0.76.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 +9 -5
  2. package/dist/index.cjs +1559 -1202
  3. package/dist/index.js +1563 -1206
  4. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -8,98 +8,13 @@ import { Command } from "commander";
8
8
  // src/constants/announcements.ts
9
9
  var ANNOUNCEMENT = "".trim();
10
10
 
11
- // src/types/config-options.ts
12
- import { z as z2 } from "zod/mini";
13
-
14
- // src/types/tool-targets.ts
11
+ // src/types/features.ts
15
12
  import { z } from "zod/mini";
16
- var ALL_TOOL_TARGETS = [
17
- "agentsmd",
18
- "amazonqcli",
19
- "augmentcode",
20
- "augmentcode-legacy",
21
- "copilot",
22
- "cursor",
23
- "cline",
24
- "claudecode",
25
- "codexcli",
26
- "opencode",
27
- "qwencode",
28
- "roo",
29
- "geminicli",
30
- "kiro",
31
- "junie",
32
- "warp",
33
- "windsurf"
34
- ];
35
- var ALL_TOOL_TARGETS_WITH_WILDCARD = [...ALL_TOOL_TARGETS, "*"];
36
- var ToolTargetSchema = z.enum(ALL_TOOL_TARGETS);
37
- var ToolTargetsSchema = z.array(ToolTargetSchema);
38
- var RulesyncTargetsSchema = z.array(z.enum(ALL_TOOL_TARGETS_WITH_WILDCARD));
39
-
40
- // src/types/config-options.ts
41
- var FEATURE_TYPES = ["rules", "commands", "mcp", "ignore", "subagents"];
42
- var FeatureTypeSchema = z2.enum(FEATURE_TYPES);
43
- var FeaturesSchema = z2.union([z2.array(FeatureTypeSchema), z2.literal("*")]);
44
- var OutputPathsSchema = z2.object({
45
- agentsmd: z2.optional(z2.string()),
46
- amazonqcli: z2.optional(z2.string()),
47
- augmentcode: z2.optional(z2.string()),
48
- "augmentcode-legacy": z2.optional(z2.string()),
49
- copilot: z2.optional(z2.string()),
50
- cursor: z2.optional(z2.string()),
51
- cline: z2.optional(z2.string()),
52
- claudecode: z2.optional(z2.string()),
53
- codexcli: z2.optional(z2.string()),
54
- opencode: z2.optional(z2.string()),
55
- qwencode: z2.optional(z2.string()),
56
- roo: z2.optional(z2.string()),
57
- geminicli: z2.optional(z2.string()),
58
- kiro: z2.optional(z2.string()),
59
- junie: z2.optional(z2.string()),
60
- windsurf: z2.optional(z2.string())
61
- });
62
- var ConfigOptionsSchema = z2.object({
63
- aiRulesDir: z2.optional(z2.string()),
64
- outputPaths: z2.optional(OutputPathsSchema),
65
- watchEnabled: z2.optional(z2.boolean()),
66
- defaultTargets: z2.optional(ToolTargetsSchema),
67
- targets: z2.optional(z2.array(ToolTargetSchema)),
68
- exclude: z2.optional(z2.array(ToolTargetSchema)),
69
- features: z2.optional(FeaturesSchema),
70
- verbose: z2.optional(z2.boolean()),
71
- delete: z2.optional(z2.boolean()),
72
- baseDir: z2.optional(z2.union([z2.string(), z2.array(z2.string())])),
73
- legacy: z2.optional(z2.boolean()),
74
- watch: z2.optional(
75
- z2.object({
76
- enabled: z2.optional(z2.boolean()),
77
- interval: z2.optional(z2.number()),
78
- ignore: z2.optional(z2.array(z2.string()))
79
- })
80
- )
81
- });
82
- var MergedConfigSchema = z2.object({
83
- aiRulesDir: z2.string(),
84
- outputPaths: z2.record(ToolTargetSchema, z2.string()),
85
- watchEnabled: z2.boolean(),
86
- defaultTargets: ToolTargetsSchema,
87
- targets: z2.optional(z2.array(ToolTargetSchema)),
88
- exclude: z2.optional(z2.array(ToolTargetSchema)),
89
- features: z2.optional(FeaturesSchema),
90
- verbose: z2.optional(z2.boolean()),
91
- delete: z2.optional(z2.boolean()),
92
- baseDir: z2.optional(z2.union([z2.string(), z2.array(z2.string())])),
93
- configPath: z2.optional(z2.string()),
94
- legacy: z2.optional(z2.boolean()),
95
- watch: z2.optional(
96
- z2.object({
97
- enabled: z2.optional(z2.boolean()),
98
- interval: z2.optional(z2.number()),
99
- ignore: z2.optional(z2.array(z2.string()))
100
- })
101
- )
102
- });
13
+ var ALL_FEATURES = ["rules", "ignore", "mcp", "subagents", "commands"];
14
+ var ALL_FEATURES_WITH_WILDCARD = [...ALL_FEATURES, "*"];
15
+ var FeatureSchema = z.enum(ALL_FEATURES);
16
+ var FeaturesSchema = z.array(FeatureSchema);
17
+ var RulesyncFeaturesSchema = z.array(z.enum(ALL_FEATURES_WITH_WILDCARD));
103
18
 
104
19
  // src/utils/file.ts
105
20
  import { globSync } from "fs";
@@ -407,6 +322,32 @@ var RulesyncFile = class extends AiFile {
407
322
  }
408
323
  };
409
324
 
325
+ // src/types/tool-targets.ts
326
+ import { z as z2 } from "zod/mini";
327
+ var ALL_TOOL_TARGETS = [
328
+ "agentsmd",
329
+ "amazonqcli",
330
+ "augmentcode",
331
+ "augmentcode-legacy",
332
+ "copilot",
333
+ "cursor",
334
+ "cline",
335
+ "claudecode",
336
+ "codexcli",
337
+ "opencode",
338
+ "qwencode",
339
+ "roo",
340
+ "geminicli",
341
+ "kiro",
342
+ "junie",
343
+ "warp",
344
+ "windsurf"
345
+ ];
346
+ var ALL_TOOL_TARGETS_WITH_WILDCARD = [...ALL_TOOL_TARGETS, "*"];
347
+ var ToolTargetSchema = z2.enum(ALL_TOOL_TARGETS);
348
+ var ToolTargetsSchema = z2.array(ToolTargetSchema);
349
+ var RulesyncTargetsSchema = z2.array(z2.enum(ALL_TOOL_TARGETS_WITH_WILDCARD));
350
+
410
351
  // src/commands/rulesync-command.ts
411
352
  var RulesyncCommandFrontmatterSchema = z3.object({
412
353
  targets: RulesyncTargetsSchema,
@@ -509,6 +450,39 @@ var ToolCommand = class extends AiFile {
509
450
  static fromRulesyncCommand(_params) {
510
451
  throw new Error("Please implement this method in the subclass.");
511
452
  }
453
+ /**
454
+ * Check if this tool is targeted by a RulesyncCommand based on its targets field.
455
+ * Subclasses should override this to provide specific targeting logic.
456
+ *
457
+ * @param rulesyncCommand - The RulesyncCommand to check
458
+ * @returns True if this tool is targeted by the command
459
+ */
460
+ static isTargetedByRulesyncCommand(_rulesyncCommand) {
461
+ throw new Error("Please implement this method in the subclass.");
462
+ }
463
+ /**
464
+ * Default implementation for checking if a tool is targeted by a RulesyncCommand.
465
+ * Checks if the command's targets include the tool target or a wildcard.
466
+ *
467
+ * @param params - Parameters including the RulesyncCommand and tool target
468
+ * @returns True if the tool target is included in the command's targets
469
+ */
470
+ static isTargetedByRulesyncCommandDefault({
471
+ rulesyncCommand,
472
+ toolTarget
473
+ }) {
474
+ const targets = rulesyncCommand.getFrontmatter().targets;
475
+ if (!targets) {
476
+ return true;
477
+ }
478
+ if (targets.includes("*")) {
479
+ return true;
480
+ }
481
+ if (targets.includes(toolTarget)) {
482
+ return true;
483
+ }
484
+ return false;
485
+ }
512
486
  };
513
487
 
514
488
  // src/commands/claudecode-command.ts
@@ -589,6 +563,12 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
589
563
  return { success: false, error: result.error };
590
564
  }
591
565
  }
566
+ static isTargetedByRulesyncCommand(rulesyncCommand) {
567
+ return this.isTargetedByRulesyncCommandDefault({
568
+ rulesyncCommand,
569
+ toolTarget: "claudecode"
570
+ });
571
+ }
592
572
  static async fromFile({
593
573
  baseDir = ".",
594
574
  relativeFilePath,
@@ -749,6 +729,12 @@ var CodexCliCommand = class _CodexCliCommand extends SimulatedCommand {
749
729
  validate
750
730
  });
751
731
  }
732
+ static isTargetedByRulesyncCommand(rulesyncCommand) {
733
+ return this.isTargetedByRulesyncCommandDefault({
734
+ rulesyncCommand,
735
+ toolTarget: "codexcli"
736
+ });
737
+ }
752
738
  };
753
739
 
754
740
  // src/commands/copilot-command.ts
@@ -756,7 +742,7 @@ import { basename as basename6, join as join6 } from "path";
756
742
  var CopilotCommand = class _CopilotCommand extends SimulatedCommand {
757
743
  static getSettablePaths() {
758
744
  return {
759
- relativeDirPath: ".copilot/commands"
745
+ relativeDirPath: ".github/commands"
760
746
  };
761
747
  }
762
748
  static fromRulesyncCommand({
@@ -793,6 +779,12 @@ var CopilotCommand = class _CopilotCommand extends SimulatedCommand {
793
779
  validate
794
780
  });
795
781
  }
782
+ static isTargetedByRulesyncCommand(rulesyncCommand) {
783
+ return this.isTargetedByRulesyncCommandDefault({
784
+ rulesyncCommand,
785
+ toolTarget: "copilot"
786
+ });
787
+ }
796
788
  };
797
789
 
798
790
  // src/commands/cursor-command.ts
@@ -837,6 +829,12 @@ var CursorCommand = class _CursorCommand extends SimulatedCommand {
837
829
  validate
838
830
  });
839
831
  }
832
+ static isTargetedByRulesyncCommand(rulesyncCommand) {
833
+ return this.isTargetedByRulesyncCommandDefault({
834
+ rulesyncCommand,
835
+ toolTarget: "cursor"
836
+ });
837
+ }
840
838
  };
841
839
 
842
840
  // src/commands/geminicli-command.ts
@@ -873,17 +871,6 @@ var GeminiCliCommand = class _GeminiCliCommand extends ToolCommand {
873
871
  throw new Error(`Failed to parse TOML command file: ${error}`);
874
872
  }
875
873
  }
876
- parseCommandFile(content) {
877
- const parsed = this.parseTomlContent(content);
878
- return {
879
- filename: "unknown.toml",
880
- filepath: "unknown.toml",
881
- frontmatter: {
882
- description: parsed.description
883
- },
884
- content: parsed.prompt
885
- };
886
- }
887
874
  getBody() {
888
875
  return this.body;
889
876
  }
@@ -958,6 +945,12 @@ ${geminiFrontmatter.prompt}
958
945
  return { success: false, error: error instanceof Error ? error : new Error(String(error)) };
959
946
  }
960
947
  }
948
+ static isTargetedByRulesyncCommand(rulesyncCommand) {
949
+ return this.isTargetedByRulesyncCommandDefault({
950
+ rulesyncCommand,
951
+ toolTarget: "geminicli"
952
+ });
953
+ }
961
954
  };
962
955
 
963
956
  // src/commands/roo-command.ts
@@ -1043,6 +1036,12 @@ var RooCommand = class _RooCommand extends ToolCommand {
1043
1036
  return { success: false, error: result.error };
1044
1037
  }
1045
1038
  }
1039
+ static isTargetedByRulesyncCommand(rulesyncCommand) {
1040
+ return this.isTargetedByRulesyncCommandDefault({
1041
+ rulesyncCommand,
1042
+ toolTarget: "roo"
1043
+ });
1044
+ }
1046
1045
  static async fromFile({
1047
1046
  baseDir = ".",
1048
1047
  relativeFilePath,
@@ -1094,31 +1093,49 @@ var CommandsProcessor = class extends FeatureProcessor {
1094
1093
  const toolCommands = rulesyncCommands.map((rulesyncCommand) => {
1095
1094
  switch (this.toolTarget) {
1096
1095
  case "claudecode":
1096
+ if (!ClaudecodeCommand.isTargetedByRulesyncCommand(rulesyncCommand)) {
1097
+ return null;
1098
+ }
1097
1099
  return ClaudecodeCommand.fromRulesyncCommand({
1098
1100
  baseDir: this.baseDir,
1099
1101
  rulesyncCommand
1100
1102
  });
1101
1103
  case "geminicli":
1104
+ if (!GeminiCliCommand.isTargetedByRulesyncCommand(rulesyncCommand)) {
1105
+ return null;
1106
+ }
1102
1107
  return GeminiCliCommand.fromRulesyncCommand({
1103
1108
  baseDir: this.baseDir,
1104
1109
  rulesyncCommand
1105
1110
  });
1106
1111
  case "roo":
1112
+ if (!RooCommand.isTargetedByRulesyncCommand(rulesyncCommand)) {
1113
+ return null;
1114
+ }
1107
1115
  return RooCommand.fromRulesyncCommand({
1108
1116
  baseDir: this.baseDir,
1109
1117
  rulesyncCommand
1110
1118
  });
1111
1119
  case "copilot":
1120
+ if (!CopilotCommand.isTargetedByRulesyncCommand(rulesyncCommand)) {
1121
+ return null;
1122
+ }
1112
1123
  return CopilotCommand.fromRulesyncCommand({
1113
1124
  baseDir: this.baseDir,
1114
1125
  rulesyncCommand
1115
1126
  });
1116
1127
  case "cursor":
1128
+ if (!CursorCommand.isTargetedByRulesyncCommand(rulesyncCommand)) {
1129
+ return null;
1130
+ }
1117
1131
  return CursorCommand.fromRulesyncCommand({
1118
1132
  baseDir: this.baseDir,
1119
1133
  rulesyncCommand
1120
1134
  });
1121
1135
  case "codexcli":
1136
+ if (!CodexCliCommand.isTargetedByRulesyncCommand(rulesyncCommand)) {
1137
+ return null;
1138
+ }
1122
1139
  return CodexCliCommand.fromRulesyncCommand({
1123
1140
  baseDir: this.baseDir,
1124
1141
  rulesyncCommand
@@ -1126,7 +1143,9 @@ var CommandsProcessor = class extends FeatureProcessor {
1126
1143
  default:
1127
1144
  throw new Error(`Unsupported tool target: ${this.toolTarget}`);
1128
1145
  }
1129
- });
1146
+ }).filter(
1147
+ (command) => command !== null
1148
+ );
1130
1149
  return toolCommands;
1131
1150
  }
1132
1151
  async convertToolFilesToRulesyncFiles(toolFiles) {
@@ -1281,19 +1300,14 @@ var CommandsProcessor = class extends FeatureProcessor {
1281
1300
  }
1282
1301
  return commandsProcessorToolTargets;
1283
1302
  }
1303
+ static getToolTargetsSimulated() {
1304
+ return commandsProcessorToolTargetsSimulated;
1305
+ }
1284
1306
  };
1285
1307
 
1286
1308
  // src/config/config-resolver.ts
1287
1309
  import { loadConfig } from "c12";
1288
1310
 
1289
- // src/types/features.ts
1290
- import { z as z9 } from "zod/mini";
1291
- var ALL_FEATURES = ["rules", "ignore", "mcp", "subagents", "commands"];
1292
- var ALL_FEATURES_WITH_WILDCARD = [...ALL_FEATURES, "*"];
1293
- var FeatureSchema = z9.enum(ALL_FEATURES);
1294
- var FeaturesSchema2 = z9.array(FeatureSchema);
1295
- var RulesyncFeaturesSchema = z9.array(z9.enum(ALL_FEATURES_WITH_WILDCARD));
1296
-
1297
1311
  // src/config/config.ts
1298
1312
  var Config = class {
1299
1313
  baseDirs;
@@ -1408,7 +1422,7 @@ var ConfigResolver = class {
1408
1422
  };
1409
1423
 
1410
1424
  // src/ignore/ignore-processor.ts
1411
- import { z as z10 } from "zod/mini";
1425
+ import { z as z9 } from "zod/mini";
1412
1426
 
1413
1427
  // src/ignore/amazonqcli-ignore.ts
1414
1428
  import { join as join11 } from "path";
@@ -2020,7 +2034,7 @@ var ignoreProcessorToolTargets = [
2020
2034
  "roo",
2021
2035
  "windsurf"
2022
2036
  ];
2023
- var IgnoreProcessorToolTargetSchema = z10.enum(ignoreProcessorToolTargets);
2037
+ var IgnoreProcessorToolTargetSchema = z9.enum(ignoreProcessorToolTargets);
2024
2038
  var IgnoreProcessor = class extends FeatureProcessor {
2025
2039
  toolTarget;
2026
2040
  constructor({
@@ -2182,47 +2196,40 @@ var IgnoreProcessor = class extends FeatureProcessor {
2182
2196
  };
2183
2197
 
2184
2198
  // src/mcp/mcp-processor.ts
2185
- import { z as z12 } from "zod/mini";
2199
+ import { z as z11 } from "zod/mini";
2186
2200
 
2187
2201
  // src/mcp/amazonqcli-mcp.ts
2188
2202
  import { join as join23 } from "path";
2189
2203
 
2190
2204
  // src/mcp/rulesync-mcp.ts
2191
2205
  import { join as join22 } from "path";
2192
-
2193
- // src/types/mcp.ts
2194
- import { z as z11 } from "zod/mini";
2195
- var McpTransportTypeSchema = z11.enum(["stdio", "sse", "http"]);
2196
- var McpServerBaseSchema = z11.object({
2197
- type: z11.optional(z11.enum(["stdio", "sse", "http"])),
2198
- command: z11.optional(z11.union([z11.string(), z11.array(z11.string())])),
2199
- args: z11.optional(z11.array(z11.string())),
2200
- url: z11.optional(z11.string()),
2201
- httpUrl: z11.optional(z11.string()),
2202
- env: z11.optional(z11.record(z11.string(), z11.string())),
2203
- disabled: z11.optional(z11.boolean()),
2204
- networkTimeout: z11.optional(z11.number()),
2205
- timeout: z11.optional(z11.number()),
2206
- trust: z11.optional(z11.boolean()),
2207
- cwd: z11.optional(z11.string()),
2208
- transport: z11.optional(McpTransportTypeSchema),
2209
- alwaysAllow: z11.optional(z11.array(z11.string())),
2210
- tools: z11.optional(z11.array(z11.string())),
2211
- kiroAutoApprove: z11.optional(z11.array(z11.string())),
2212
- kiroAutoBlock: z11.optional(z11.array(z11.string())),
2213
- headers: z11.optional(z11.record(z11.string(), z11.string()))
2214
- });
2215
- var RulesyncMcpServerSchema = z11.extend(McpServerBaseSchema, {
2216
- targets: z11.optional(RulesyncTargetsSchema)
2206
+ import { z as z10 } from "zod/mini";
2207
+ var McpTransportTypeSchema = z10.enum(["stdio", "sse", "http"]);
2208
+ var McpServerBaseSchema = z10.object({
2209
+ type: z10.optional(z10.enum(["stdio", "sse", "http"])),
2210
+ command: z10.optional(z10.union([z10.string(), z10.array(z10.string())])),
2211
+ args: z10.optional(z10.array(z10.string())),
2212
+ url: z10.optional(z10.string()),
2213
+ httpUrl: z10.optional(z10.string()),
2214
+ env: z10.optional(z10.record(z10.string(), z10.string())),
2215
+ disabled: z10.optional(z10.boolean()),
2216
+ networkTimeout: z10.optional(z10.number()),
2217
+ timeout: z10.optional(z10.number()),
2218
+ trust: z10.optional(z10.boolean()),
2219
+ cwd: z10.optional(z10.string()),
2220
+ transport: z10.optional(McpTransportTypeSchema),
2221
+ alwaysAllow: z10.optional(z10.array(z10.string())),
2222
+ tools: z10.optional(z10.array(z10.string())),
2223
+ kiroAutoApprove: z10.optional(z10.array(z10.string())),
2224
+ kiroAutoBlock: z10.optional(z10.array(z10.string())),
2225
+ headers: z10.optional(z10.record(z10.string(), z10.string()))
2217
2226
  });
2218
- var McpConfigSchema = z11.object({
2219
- mcpServers: z11.record(z11.string(), McpServerBaseSchema)
2227
+ var RulesyncMcpServerSchema = z10.extend(McpServerBaseSchema, {
2228
+ targets: z10.optional(RulesyncTargetsSchema)
2220
2229
  });
2221
- var RulesyncMcpConfigSchema = z11.object({
2222
- mcpServers: z11.record(z11.string(), RulesyncMcpServerSchema)
2230
+ var RulesyncMcpConfigSchema = z10.object({
2231
+ mcpServers: z10.record(z10.string(), RulesyncMcpServerSchema)
2223
2232
  });
2224
-
2225
- // src/mcp/rulesync-mcp.ts
2226
2233
  var RulesyncMcp = class _RulesyncMcp extends RulesyncFile {
2227
2234
  json;
2228
2235
  constructor({ ...rest }) {
@@ -2614,7 +2621,7 @@ var mcpProcessorToolTargets = [
2614
2621
  "cursor",
2615
2622
  "roo"
2616
2623
  ];
2617
- var McpProcessorToolTargetSchema = z12.enum(mcpProcessorToolTargets);
2624
+ var McpProcessorToolTargetSchema = z11.enum(mcpProcessorToolTargets);
2618
2625
  var McpProcessor = class extends FeatureProcessor {
2619
2626
  toolTarget;
2620
2627
  constructor({
@@ -2773,9 +2780,9 @@ var McpProcessor = class extends FeatureProcessor {
2773
2780
  };
2774
2781
 
2775
2782
  // src/rules/rules-processor.ts
2776
- import { basename as basename14, join as join49 } from "path";
2783
+ import { basename as basename16, join as join52 } from "path";
2777
2784
  import { XMLBuilder } from "fast-xml-parser";
2778
- import { z as z18 } from "zod/mini";
2785
+ import { z as z20 } from "zod/mini";
2779
2786
 
2780
2787
  // src/constants/paths.ts
2781
2788
  import { join as join29 } from "path";
@@ -2787,7 +2794,7 @@ var RULESYNC_SUBAGENTS_DIR = join29(".rulesync", "subagents");
2787
2794
 
2788
2795
  // src/subagents/simulated-subagent.ts
2789
2796
  import { basename as basename11, join as join30 } from "path";
2790
- import { z as z13 } from "zod/mini";
2797
+ import { z as z12 } from "zod/mini";
2791
2798
 
2792
2799
  // src/subagents/tool-subagent.ts
2793
2800
  var ToolSubagent = class extends ToolFile {
@@ -2800,12 +2807,31 @@ var ToolSubagent = class extends ToolFile {
2800
2807
  static fromRulesyncSubagent(_params) {
2801
2808
  throw new Error("Please implement this method in the subclass.");
2802
2809
  }
2810
+ static isTargetedByRulesyncSubagent(_rulesyncSubagent) {
2811
+ throw new Error("Please implement this method in the subclass.");
2812
+ }
2813
+ static isTargetedByRulesyncSubagentDefault({
2814
+ rulesyncSubagent,
2815
+ toolTarget
2816
+ }) {
2817
+ const targets = rulesyncSubagent.getFrontmatter().targets;
2818
+ if (!targets) {
2819
+ return true;
2820
+ }
2821
+ if (targets.includes("*")) {
2822
+ return true;
2823
+ }
2824
+ if (targets.includes(toolTarget)) {
2825
+ return true;
2826
+ }
2827
+ return false;
2828
+ }
2803
2829
  };
2804
2830
 
2805
2831
  // src/subagents/simulated-subagent.ts
2806
- var SimulatedSubagentFrontmatterSchema = z13.object({
2807
- name: z13.string(),
2808
- description: z13.string()
2832
+ var SimulatedSubagentFrontmatterSchema = z12.object({
2833
+ name: z12.string(),
2834
+ description: z12.string()
2809
2835
  });
2810
2836
  var SimulatedSubagent = class extends ToolSubagent {
2811
2837
  frontmatter;
@@ -2902,13 +2928,19 @@ var CodexCliSubagent = class _CodexCliSubagent extends SimulatedSubagent {
2902
2928
  const baseParams = this.fromRulesyncSubagentDefault(params);
2903
2929
  return new _CodexCliSubagent(baseParams);
2904
2930
  }
2931
+ static isTargetedByRulesyncSubagent(rulesyncSubagent) {
2932
+ return this.isTargetedByRulesyncSubagentDefault({
2933
+ rulesyncSubagent,
2934
+ toolTarget: "codexcli"
2935
+ });
2936
+ }
2905
2937
  };
2906
2938
 
2907
2939
  // src/subagents/copilot-subagent.ts
2908
2940
  var CopilotSubagent = class _CopilotSubagent extends SimulatedSubagent {
2909
2941
  static getSettablePaths() {
2910
2942
  return {
2911
- relativeDirPath: ".copilot/subagents"
2943
+ relativeDirPath: ".github/subagents"
2912
2944
  };
2913
2945
  }
2914
2946
  static async fromFile(params) {
@@ -2919,6 +2951,12 @@ var CopilotSubagent = class _CopilotSubagent extends SimulatedSubagent {
2919
2951
  const baseParams = this.fromRulesyncSubagentDefault(params);
2920
2952
  return new _CopilotSubagent(baseParams);
2921
2953
  }
2954
+ static isTargetedByRulesyncSubagent(rulesyncSubagent) {
2955
+ return this.isTargetedByRulesyncSubagentDefault({
2956
+ rulesyncSubagent,
2957
+ toolTarget: "copilot"
2958
+ });
2959
+ }
2922
2960
  };
2923
2961
 
2924
2962
  // src/subagents/cursor-subagent.ts
@@ -2936,359 +2974,899 @@ var CursorSubagent = class _CursorSubagent extends SimulatedSubagent {
2936
2974
  const baseParams = this.fromRulesyncSubagentDefault(params);
2937
2975
  return new _CursorSubagent(baseParams);
2938
2976
  }
2977
+ static isTargetedByRulesyncSubagent(rulesyncSubagent) {
2978
+ return this.isTargetedByRulesyncSubagentDefault({
2979
+ rulesyncSubagent,
2980
+ toolTarget: "cursor"
2981
+ });
2982
+ }
2939
2983
  };
2940
2984
 
2941
- // src/rules/agentsmd-rule.ts
2985
+ // src/subagents/geminicli-subagent.ts
2986
+ var GeminiCliSubagent = class _GeminiCliSubagent extends SimulatedSubagent {
2987
+ static getSettablePaths() {
2988
+ return {
2989
+ relativeDirPath: ".gemini/subagents"
2990
+ };
2991
+ }
2992
+ static async fromFile(params) {
2993
+ const baseParams = await this.fromFileDefault(params);
2994
+ return new _GeminiCliSubagent(baseParams);
2995
+ }
2996
+ static fromRulesyncSubagent(params) {
2997
+ const baseParams = this.fromRulesyncSubagentDefault(params);
2998
+ return new _GeminiCliSubagent(baseParams);
2999
+ }
3000
+ static isTargetedByRulesyncSubagent(rulesyncSubagent) {
3001
+ return this.isTargetedByRulesyncSubagentDefault({
3002
+ rulesyncSubagent,
3003
+ toolTarget: "geminicli"
3004
+ });
3005
+ }
3006
+ };
3007
+
3008
+ // src/subagents/roo-subagent.ts
3009
+ var RooSubagent = class _RooSubagent extends SimulatedSubagent {
3010
+ static getSettablePaths() {
3011
+ return {
3012
+ relativeDirPath: ".roo/subagents"
3013
+ };
3014
+ }
3015
+ static async fromFile(params) {
3016
+ const baseParams = await this.fromFileDefault(params);
3017
+ return new _RooSubagent(baseParams);
3018
+ }
3019
+ static fromRulesyncSubagent(params) {
3020
+ const baseParams = this.fromRulesyncSubagentDefault(params);
3021
+ return new _RooSubagent(baseParams);
3022
+ }
3023
+ static isTargetedByRulesyncSubagent(rulesyncSubagent) {
3024
+ return this.isTargetedByRulesyncSubagentDefault({
3025
+ rulesyncSubagent,
3026
+ toolTarget: "roo"
3027
+ });
3028
+ }
3029
+ };
3030
+
3031
+ // src/subagents/subagents-processor.ts
3032
+ import { basename as basename13, join as join33 } from "path";
3033
+ import { z as z15 } from "zod/mini";
3034
+
3035
+ // src/subagents/claudecode-subagent.ts
2942
3036
  import { join as join32 } from "path";
3037
+ import { z as z14 } from "zod/mini";
2943
3038
 
2944
- // src/rules/rulesync-rule.ts
3039
+ // src/subagents/rulesync-subagent.ts
2945
3040
  import { basename as basename12, join as join31 } from "path";
2946
- import { z as z14 } from "zod/mini";
2947
- var RulesyncRuleFrontmatterSchema = z14.object({
2948
- root: z14.optional(z14.optional(z14.boolean())),
2949
- targets: z14.optional(RulesyncTargetsSchema),
2950
- description: z14.optional(z14.string()),
2951
- globs: z14.optional(z14.array(z14.string())),
2952
- cursor: z14.optional(
2953
- z14.object({
2954
- alwaysApply: z14.optional(z14.boolean()),
2955
- description: z14.optional(z14.string()),
2956
- globs: z14.optional(z14.array(z14.string()))
3041
+ import { z as z13 } from "zod/mini";
3042
+ var RulesyncSubagentModelSchema = z13.enum(["opus", "sonnet", "haiku", "inherit"]);
3043
+ var RulesyncSubagentFrontmatterSchema = z13.object({
3044
+ targets: RulesyncTargetsSchema,
3045
+ name: z13.string(),
3046
+ description: z13.string(),
3047
+ claudecode: z13.optional(
3048
+ z13.object({
3049
+ model: RulesyncSubagentModelSchema
2957
3050
  })
2958
3051
  )
2959
3052
  });
2960
- var RulesyncRule = class _RulesyncRule extends RulesyncFile {
3053
+ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
2961
3054
  frontmatter;
2962
3055
  body;
2963
3056
  constructor({ frontmatter, body, ...rest }) {
2964
3057
  if (rest.validate !== false) {
2965
- const result = RulesyncRuleFrontmatterSchema.safeParse(frontmatter);
3058
+ const result = RulesyncSubagentFrontmatterSchema.safeParse(frontmatter);
2966
3059
  if (!result.success) {
2967
3060
  throw result.error;
2968
3061
  }
2969
3062
  }
2970
3063
  super({
2971
- ...rest,
2972
- fileContent: stringifyFrontmatter(body, frontmatter)
3064
+ ...rest
2973
3065
  });
2974
3066
  this.frontmatter = frontmatter;
2975
3067
  this.body = body;
2976
3068
  }
2977
3069
  static getSettablePaths() {
2978
3070
  return {
2979
- recommended: {
2980
- relativeDirPath: ".rulesync/rules"
2981
- },
2982
- legacy: {
2983
- relativeDirPath: ".rulesync"
2984
- }
3071
+ relativeDirPath: ".rulesync/subagents"
2985
3072
  };
2986
3073
  }
2987
3074
  getFrontmatter() {
2988
3075
  return this.frontmatter;
2989
3076
  }
3077
+ getBody() {
3078
+ return this.body;
3079
+ }
2990
3080
  validate() {
2991
3081
  if (!this.frontmatter) {
2992
3082
  return { success: true, error: null };
2993
3083
  }
2994
- const result = RulesyncRuleFrontmatterSchema.safeParse(this.frontmatter);
3084
+ const result = RulesyncSubagentFrontmatterSchema.safeParse(this.frontmatter);
2995
3085
  if (result.success) {
2996
3086
  return { success: true, error: null };
2997
3087
  } else {
2998
3088
  return { success: false, error: result.error };
2999
3089
  }
3000
3090
  }
3001
- static async fromFileLegacy({
3002
- relativeFilePath,
3003
- validate = true
3004
- }) {
3005
- const filePath = join31(this.getSettablePaths().legacy.relativeDirPath, relativeFilePath);
3006
- const fileContent = await readFileContent(filePath);
3007
- const { frontmatter, body: content } = parseFrontmatter(fileContent);
3008
- const result = RulesyncRuleFrontmatterSchema.safeParse(frontmatter);
3009
- if (!result.success) {
3010
- throw new Error(`Invalid frontmatter in ${filePath}: ${result.error.message}`);
3011
- }
3012
- const validatedFrontmatter = {
3013
- root: result.data.root ?? false,
3014
- targets: result.data.targets ?? ["*"],
3015
- description: result.data.description ?? "",
3016
- globs: result.data.globs ?? [],
3017
- cursor: result.data.cursor
3018
- };
3019
- const filename = basename12(filePath);
3020
- return new _RulesyncRule({
3021
- baseDir: ".",
3022
- relativeDirPath: this.getSettablePaths().recommended.relativeDirPath,
3023
- relativeFilePath: filename,
3024
- frontmatter: validatedFrontmatter,
3025
- body: content.trim(),
3026
- validate
3027
- });
3028
- }
3029
3091
  static async fromFile({
3030
- relativeFilePath,
3031
- validate = true
3092
+ relativeFilePath
3032
3093
  }) {
3033
- const filePath = join31(this.getSettablePaths().recommended.relativeDirPath, relativeFilePath);
3034
- const fileContent = await readFileContent(filePath);
3094
+ const fileContent = await readFileContent(join31(RULESYNC_SUBAGENTS_DIR, relativeFilePath));
3035
3095
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
3036
- const result = RulesyncRuleFrontmatterSchema.safeParse(frontmatter);
3096
+ const result = RulesyncSubagentFrontmatterSchema.safeParse(frontmatter);
3037
3097
  if (!result.success) {
3038
- throw new Error(`Invalid frontmatter in ${filePath}: ${result.error.message}`);
3098
+ throw new Error(`Invalid frontmatter in ${relativeFilePath}: ${result.error.message}`);
3039
3099
  }
3040
- const validatedFrontmatter = {
3041
- root: result.data.root ?? false,
3042
- targets: result.data.targets ?? ["*"],
3043
- description: result.data.description ?? "",
3044
- globs: result.data.globs ?? [],
3045
- cursor: result.data.cursor
3046
- };
3047
- const filename = basename12(filePath);
3048
- return new _RulesyncRule({
3100
+ const filename = basename12(relativeFilePath);
3101
+ return new _RulesyncSubagent({
3049
3102
  baseDir: ".",
3050
- relativeDirPath: this.getSettablePaths().recommended.relativeDirPath,
3103
+ relativeDirPath: this.getSettablePaths().relativeDirPath,
3051
3104
  relativeFilePath: filename,
3052
- frontmatter: validatedFrontmatter,
3105
+ frontmatter: result.data,
3053
3106
  body: content.trim(),
3054
- validate
3107
+ fileContent
3055
3108
  });
3056
3109
  }
3057
- getBody() {
3058
- return this.body;
3059
- }
3060
3110
  };
3061
3111
 
3062
- // src/rules/tool-rule.ts
3063
- var ToolRule = class extends ToolFile {
3064
- root;
3065
- constructor({ root = false, ...rest }) {
3066
- super(rest);
3067
- this.root = root;
3068
- }
3069
- static async fromFile(_params) {
3070
- throw new Error("Please implement this method in the subclass.");
3071
- }
3072
- static fromRulesyncRule(_params) {
3073
- throw new Error("Please implement this method in the subclass.");
3074
- }
3075
- static buildToolRuleParamsDefault({
3076
- baseDir = ".",
3077
- rulesyncRule,
3078
- validate = true,
3079
- rootPath = { relativeDirPath: ".", relativeFilePath: "AGENTS.md" },
3080
- nonRootPath = { relativeDirPath: ".agents/memories" }
3081
- }) {
3082
- const fileContent = rulesyncRule.getBody();
3083
- return {
3084
- baseDir,
3085
- relativeDirPath: rulesyncRule.getFrontmatter().root ? rootPath.relativeDirPath : nonRootPath.relativeDirPath,
3086
- relativeFilePath: rulesyncRule.getFrontmatter().root ? rootPath.relativeFilePath : rulesyncRule.getRelativeFilePath(),
3087
- fileContent,
3088
- validate,
3089
- root: rulesyncRule.getFrontmatter().root ?? false
3090
- };
3091
- }
3092
- toRulesyncRuleDefault() {
3093
- return new RulesyncRule({
3094
- baseDir: this.getBaseDir(),
3095
- relativeDirPath: RULESYNC_RULES_DIR,
3096
- relativeFilePath: this.getRelativeFilePath(),
3097
- frontmatter: {
3098
- root: this.isRoot(),
3099
- targets: ["*"],
3100
- description: "",
3101
- globs: this.isRoot() ? ["**/*"] : []
3102
- },
3103
- body: this.getFileContent()
3104
- });
3105
- }
3106
- isRoot() {
3107
- return this.root;
3108
- }
3109
- };
3110
-
3111
- // src/rules/agentsmd-rule.ts
3112
- var AgentsMdRule = class _AgentsMdRule extends ToolRule {
3113
- constructor({ fileContent, root, ...rest }) {
3112
+ // src/subagents/claudecode-subagent.ts
3113
+ var ClaudecodeSubagentFrontmatterSchema = z14.object({
3114
+ name: z14.string(),
3115
+ description: z14.string(),
3116
+ model: z14.optional(z14.enum(["opus", "sonnet", "haiku", "inherit"]))
3117
+ });
3118
+ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
3119
+ frontmatter;
3120
+ body;
3121
+ constructor({ frontmatter, body, ...rest }) {
3122
+ if (rest.validate !== false) {
3123
+ const result = ClaudecodeSubagentFrontmatterSchema.safeParse(frontmatter);
3124
+ if (!result.success) {
3125
+ throw result.error;
3126
+ }
3127
+ }
3114
3128
  super({
3115
- ...rest,
3116
- fileContent,
3117
- root: root ?? false
3129
+ ...rest
3118
3130
  });
3131
+ this.frontmatter = frontmatter;
3132
+ this.body = body;
3119
3133
  }
3120
3134
  static getSettablePaths() {
3121
3135
  return {
3122
- root: {
3123
- relativeDirPath: ".",
3124
- relativeFilePath: "AGENTS.md"
3125
- },
3126
- nonRoot: {
3127
- relativeDirPath: ".agents/memories"
3128
- }
3136
+ relativeDirPath: ".claude/agents"
3129
3137
  };
3130
3138
  }
3131
- static async fromFile({
3132
- baseDir = ".",
3133
- relativeFilePath,
3134
- validate = true
3135
- }) {
3136
- const isRoot = relativeFilePath === "AGENTS.md";
3137
- const relativePath = isRoot ? "AGENTS.md" : join32(".agents/memories", relativeFilePath);
3138
- const fileContent = await readFileContent(join32(baseDir, relativePath));
3139
- return new _AgentsMdRule({
3140
- baseDir,
3141
- relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
3142
- relativeFilePath: isRoot ? "AGENTS.md" : relativeFilePath,
3143
- fileContent,
3144
- validate,
3145
- root: isRoot
3146
- });
3147
- }
3148
- static fromRulesyncRule({
3149
- baseDir = ".",
3150
- rulesyncRule,
3151
- validate = true
3152
- }) {
3153
- return new _AgentsMdRule(
3154
- this.buildToolRuleParamsDefault({
3155
- baseDir,
3156
- rulesyncRule,
3157
- validate,
3158
- rootPath: this.getSettablePaths().root,
3159
- nonRootPath: this.getSettablePaths().nonRoot
3160
- })
3161
- );
3162
- }
3163
- toRulesyncRule() {
3164
- return this.toRulesyncRuleDefault();
3139
+ getFrontmatter() {
3140
+ return this.frontmatter;
3165
3141
  }
3166
- validate() {
3167
- return { success: true, error: null };
3142
+ getBody() {
3143
+ return this.body;
3168
3144
  }
3169
- };
3170
-
3171
- // src/rules/amazonqcli-rule.ts
3172
- import { join as join33 } from "path";
3173
- var AmazonQCliRule = class _AmazonQCliRule extends ToolRule {
3174
- static getSettablePaths() {
3175
- return {
3176
- nonRoot: {
3177
- relativeDirPath: ".amazonq/rules"
3145
+ toRulesyncSubagent() {
3146
+ const rulesyncFrontmatter = {
3147
+ targets: ["claudecode"],
3148
+ name: this.frontmatter.name,
3149
+ description: this.frontmatter.description,
3150
+ ...this.frontmatter.model && {
3151
+ claudecode: {
3152
+ model: this.frontmatter.model
3153
+ }
3178
3154
  }
3179
3155
  };
3156
+ const fileContent = stringifyFrontmatter(this.body, rulesyncFrontmatter);
3157
+ return new RulesyncSubagent({
3158
+ frontmatter: rulesyncFrontmatter,
3159
+ body: this.body,
3160
+ baseDir: this.baseDir,
3161
+ relativeDirPath: ".rulesync/subagents",
3162
+ relativeFilePath: this.getRelativeFilePath(),
3163
+ fileContent,
3164
+ validate: true
3165
+ });
3180
3166
  }
3181
- static async fromFile({
3167
+ static fromRulesyncSubagent({
3182
3168
  baseDir = ".",
3183
- relativeFilePath,
3169
+ rulesyncSubagent,
3184
3170
  validate = true
3185
3171
  }) {
3186
- const fileContent = await readFileContent(
3187
- join33(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
3188
- );
3189
- return new _AmazonQCliRule({
3172
+ const rulesyncFrontmatter = rulesyncSubagent.getFrontmatter();
3173
+ const claudecodeFrontmatter = {
3174
+ name: rulesyncFrontmatter.name,
3175
+ description: rulesyncFrontmatter.description,
3176
+ model: rulesyncFrontmatter.claudecode?.model
3177
+ };
3178
+ const body = rulesyncSubagent.getBody();
3179
+ const fileContent = stringifyFrontmatter(body, claudecodeFrontmatter);
3180
+ return new _ClaudecodeSubagent({
3190
3181
  baseDir,
3191
- relativeDirPath: this.getSettablePaths().nonRoot.relativeDirPath,
3192
- relativeFilePath,
3182
+ frontmatter: claudecodeFrontmatter,
3183
+ body,
3184
+ relativeDirPath: ".claude/agents",
3185
+ relativeFilePath: rulesyncSubagent.getRelativeFilePath(),
3193
3186
  fileContent,
3194
- validate,
3195
- root: false
3187
+ validate
3196
3188
  });
3197
3189
  }
3198
- static fromRulesyncRule({
3199
- baseDir = ".",
3200
- rulesyncRule,
3201
- validate = true
3202
- }) {
3203
- return new _AmazonQCliRule(
3204
- this.buildToolRuleParamsDefault({
3205
- baseDir,
3206
- rulesyncRule,
3207
- validate,
3208
- nonRootPath: this.getSettablePaths().nonRoot
3209
- })
3210
- );
3211
- }
3212
- toRulesyncRule() {
3213
- return this.toRulesyncRuleDefault();
3214
- }
3215
3190
  validate() {
3216
- return { success: true, error: null };
3191
+ if (!this.frontmatter) {
3192
+ return { success: true, error: null };
3193
+ }
3194
+ const result = ClaudecodeSubagentFrontmatterSchema.safeParse(this.frontmatter);
3195
+ if (result.success) {
3196
+ return { success: true, error: null };
3197
+ } else {
3198
+ return { success: false, error: result.error };
3199
+ }
3217
3200
  }
3218
- };
3219
-
3220
- // src/rules/augmentcode-legacy-rule.ts
3221
- import { join as join34 } from "path";
3222
- var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
3223
- toRulesyncRule() {
3224
- const rulesyncFrontmatter = {
3225
- root: this.isRoot(),
3226
- targets: ["*"],
3227
- description: "",
3228
- globs: this.isRoot() ? ["**/*"] : []
3229
- };
3230
- return new RulesyncRule({
3231
- baseDir: this.getBaseDir(),
3232
- frontmatter: rulesyncFrontmatter,
3233
- body: this.getFileContent(),
3234
- relativeDirPath: RULESYNC_RULES_DIR,
3235
- relativeFilePath: this.getRelativeFilePath(),
3236
- validate: true
3201
+ static isTargetedByRulesyncSubagent(rulesyncSubagent) {
3202
+ return this.isTargetedByRulesyncSubagentDefault({
3203
+ rulesyncSubagent,
3204
+ toolTarget: "claudecode"
3237
3205
  });
3238
3206
  }
3239
- static getSettablePaths() {
3240
- return {
3241
- root: {
3242
- relativeDirPath: ".",
3243
- relativeFilePath: ".augment-guidelines"
3244
- },
3245
- nonRoot: {
3246
- relativeDirPath: ".augment/rules"
3247
- }
3248
- };
3249
- }
3250
- static fromRulesyncRule({
3251
- baseDir = ".",
3252
- rulesyncRule,
3253
- validate = true
3254
- }) {
3255
- return new _AugmentcodeLegacyRule(
3256
- this.buildToolRuleParamsDefault({
3257
- baseDir,
3258
- rulesyncRule,
3259
- validate,
3260
- rootPath: this.getSettablePaths().root,
3261
- nonRootPath: this.getSettablePaths().nonRoot
3262
- })
3263
- );
3264
- }
3265
- validate() {
3266
- return { success: true, error: null };
3267
- }
3268
3207
  static async fromFile({
3269
3208
  baseDir = ".",
3270
3209
  relativeFilePath,
3271
3210
  validate = true
3272
3211
  }) {
3273
- const settablePaths = this.getSettablePaths();
3274
- const isRoot = relativeFilePath === settablePaths.root.relativeFilePath;
3275
- const relativePath = isRoot ? settablePaths.root.relativeFilePath : join34(settablePaths.nonRoot.relativeDirPath, relativeFilePath);
3276
- const fileContent = await readFileContent(join34(baseDir, relativePath));
3277
- return new _AugmentcodeLegacyRule({
3212
+ const fileContent = await readFileContent(join32(baseDir, ".claude/agents", relativeFilePath));
3213
+ const { frontmatter, body: content } = parseFrontmatter(fileContent);
3214
+ const result = ClaudecodeSubagentFrontmatterSchema.safeParse(frontmatter);
3215
+ if (!result.success) {
3216
+ throw new Error(`Invalid frontmatter in ${relativeFilePath}: ${result.error.message}`);
3217
+ }
3218
+ return new _ClaudecodeSubagent({
3278
3219
  baseDir,
3279
- relativeDirPath: isRoot ? settablePaths.root.relativeDirPath : settablePaths.nonRoot.relativeDirPath,
3280
- relativeFilePath: isRoot ? settablePaths.root.relativeFilePath : relativeFilePath,
3220
+ relativeDirPath: ".claude/agents",
3221
+ relativeFilePath,
3222
+ frontmatter: result.data,
3223
+ body: content.trim(),
3281
3224
  fileContent,
3282
- validate,
3283
- root: isRoot
3225
+ validate
3284
3226
  });
3285
3227
  }
3286
3228
  };
3287
3229
 
3288
- // src/rules/augmentcode-rule.ts
3289
- import { join as join35 } from "path";
3290
- var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
3291
- toRulesyncRule() {
3230
+ // src/subagents/subagents-processor.ts
3231
+ var subagentsProcessorToolTargets = [
3232
+ "claudecode",
3233
+ "copilot",
3234
+ "cursor",
3235
+ "codexcli",
3236
+ "geminicli",
3237
+ "roo"
3238
+ ];
3239
+ var subagentsProcessorToolTargetsSimulated = [
3240
+ "copilot",
3241
+ "cursor",
3242
+ "codexcli",
3243
+ "geminicli",
3244
+ "roo"
3245
+ ];
3246
+ var SubagentsProcessorToolTargetSchema = z15.enum(subagentsProcessorToolTargets);
3247
+ var SubagentsProcessor = class extends FeatureProcessor {
3248
+ toolTarget;
3249
+ constructor({
3250
+ baseDir = ".",
3251
+ toolTarget
3252
+ }) {
3253
+ super({ baseDir });
3254
+ this.toolTarget = SubagentsProcessorToolTargetSchema.parse(toolTarget);
3255
+ }
3256
+ async convertRulesyncFilesToToolFiles(rulesyncFiles) {
3257
+ const rulesyncSubagents = rulesyncFiles.filter(
3258
+ (file) => file instanceof RulesyncSubagent
3259
+ );
3260
+ const toolSubagents = rulesyncSubagents.map((rulesyncSubagent) => {
3261
+ switch (this.toolTarget) {
3262
+ case "claudecode":
3263
+ if (!ClaudecodeSubagent.isTargetedByRulesyncSubagent(rulesyncSubagent)) {
3264
+ return null;
3265
+ }
3266
+ return ClaudecodeSubagent.fromRulesyncSubagent({
3267
+ baseDir: this.baseDir,
3268
+ relativeDirPath: RulesyncSubagent.getSettablePaths().relativeDirPath,
3269
+ rulesyncSubagent
3270
+ });
3271
+ case "copilot":
3272
+ if (!CopilotSubagent.isTargetedByRulesyncSubagent(rulesyncSubagent)) {
3273
+ return null;
3274
+ }
3275
+ return CopilotSubagent.fromRulesyncSubagent({
3276
+ baseDir: this.baseDir,
3277
+ relativeDirPath: RulesyncSubagent.getSettablePaths().relativeDirPath,
3278
+ rulesyncSubagent
3279
+ });
3280
+ case "cursor":
3281
+ if (!CursorSubagent.isTargetedByRulesyncSubagent(rulesyncSubagent)) {
3282
+ return null;
3283
+ }
3284
+ return CursorSubagent.fromRulesyncSubagent({
3285
+ baseDir: this.baseDir,
3286
+ relativeDirPath: RulesyncSubagent.getSettablePaths().relativeDirPath,
3287
+ rulesyncSubagent
3288
+ });
3289
+ case "codexcli":
3290
+ if (!CodexCliSubagent.isTargetedByRulesyncSubagent(rulesyncSubagent)) {
3291
+ return null;
3292
+ }
3293
+ return CodexCliSubagent.fromRulesyncSubagent({
3294
+ baseDir: this.baseDir,
3295
+ relativeDirPath: RulesyncSubagent.getSettablePaths().relativeDirPath,
3296
+ rulesyncSubagent
3297
+ });
3298
+ case "geminicli":
3299
+ if (!GeminiCliSubagent.isTargetedByRulesyncSubagent(rulesyncSubagent)) {
3300
+ return null;
3301
+ }
3302
+ return GeminiCliSubagent.fromRulesyncSubagent({
3303
+ baseDir: this.baseDir,
3304
+ relativeDirPath: RulesyncSubagent.getSettablePaths().relativeDirPath,
3305
+ rulesyncSubagent
3306
+ });
3307
+ case "roo":
3308
+ if (!RooSubagent.isTargetedByRulesyncSubagent(rulesyncSubagent)) {
3309
+ return null;
3310
+ }
3311
+ return RooSubagent.fromRulesyncSubagent({
3312
+ baseDir: this.baseDir,
3313
+ relativeDirPath: RulesyncSubagent.getSettablePaths().relativeDirPath,
3314
+ rulesyncSubagent
3315
+ });
3316
+ default:
3317
+ throw new Error(`Unsupported tool target: ${this.toolTarget}`);
3318
+ }
3319
+ }).filter((subagent) => subagent !== null);
3320
+ return toolSubagents;
3321
+ }
3322
+ async convertToolFilesToRulesyncFiles(toolFiles) {
3323
+ const toolSubagents = toolFiles.filter(
3324
+ (file) => file instanceof ToolSubagent
3325
+ );
3326
+ const rulesyncSubagents = [];
3327
+ for (const toolSubagent of toolSubagents) {
3328
+ if (toolSubagent instanceof SimulatedSubagent) {
3329
+ logger.debug(
3330
+ `Skipping simulated subagent conversion: ${toolSubagent.getRelativeFilePath()}`
3331
+ );
3332
+ continue;
3333
+ }
3334
+ rulesyncSubagents.push(toolSubagent.toRulesyncSubagent());
3335
+ }
3336
+ return rulesyncSubagents;
3337
+ }
3338
+ /**
3339
+ * Implementation of abstract method from Processor
3340
+ * Load and parse rulesync subagent files from .rulesync/subagents/ directory
3341
+ */
3342
+ async loadRulesyncFiles() {
3343
+ const subagentsDir = join33(this.baseDir, RulesyncSubagent.getSettablePaths().relativeDirPath);
3344
+ const dirExists = await directoryExists(subagentsDir);
3345
+ if (!dirExists) {
3346
+ logger.debug(`Rulesync subagents directory not found: ${subagentsDir}`);
3347
+ return [];
3348
+ }
3349
+ const entries = await listDirectoryFiles(subagentsDir);
3350
+ const mdFiles = entries.filter((file) => file.endsWith(".md"));
3351
+ if (mdFiles.length === 0) {
3352
+ logger.debug(`No markdown files found in rulesync subagents directory: ${subagentsDir}`);
3353
+ return [];
3354
+ }
3355
+ logger.info(`Found ${mdFiles.length} subagent files in ${subagentsDir}`);
3356
+ const rulesyncSubagents = [];
3357
+ for (const mdFile of mdFiles) {
3358
+ const filepath = join33(subagentsDir, mdFile);
3359
+ try {
3360
+ const rulesyncSubagent = await RulesyncSubagent.fromFile({
3361
+ relativeFilePath: mdFile,
3362
+ validate: true
3363
+ });
3364
+ rulesyncSubagents.push(rulesyncSubagent);
3365
+ logger.debug(`Successfully loaded subagent: ${mdFile}`);
3366
+ } catch (error) {
3367
+ logger.warn(`Failed to load subagent file ${filepath}:`, error);
3368
+ continue;
3369
+ }
3370
+ }
3371
+ if (rulesyncSubagents.length === 0) {
3372
+ logger.debug(`No valid subagents found in ${subagentsDir}`);
3373
+ return [];
3374
+ }
3375
+ logger.info(`Successfully loaded ${rulesyncSubagents.length} rulesync subagents`);
3376
+ return rulesyncSubagents;
3377
+ }
3378
+ /**
3379
+ * Implementation of abstract method from Processor
3380
+ * Load tool-specific subagent configurations and parse them into ToolSubagent instances
3381
+ */
3382
+ async loadToolFiles() {
3383
+ switch (this.toolTarget) {
3384
+ case "claudecode":
3385
+ return await this.loadClaudecodeSubagents();
3386
+ case "copilot":
3387
+ return await this.loadCopilotSubagents();
3388
+ case "cursor":
3389
+ return await this.loadCursorSubagents();
3390
+ case "codexcli":
3391
+ return await this.loadCodexCliSubagents();
3392
+ case "geminicli":
3393
+ return await this.loadGeminiCliSubagents();
3394
+ case "roo":
3395
+ return await this.loadRooSubagents();
3396
+ default:
3397
+ throw new Error(`Unsupported tool target: ${this.toolTarget}`);
3398
+ }
3399
+ }
3400
+ /**
3401
+ * Load Claude Code subagent configurations from .claude/agents/ directory
3402
+ */
3403
+ async loadClaudecodeSubagents() {
3404
+ return await this.loadToolSubagentsDefault({
3405
+ relativeDirPath: ClaudecodeSubagent.getSettablePaths().relativeDirPath,
3406
+ fromFile: (relativeFilePath) => ClaudecodeSubagent.fromFile({ relativeFilePath })
3407
+ });
3408
+ }
3409
+ /**
3410
+ * Load Copilot subagent configurations from .github/subagents/ directory
3411
+ */
3412
+ async loadCopilotSubagents() {
3413
+ return await this.loadToolSubagentsDefault({
3414
+ relativeDirPath: CopilotSubagent.getSettablePaths().relativeDirPath,
3415
+ fromFile: (relativeFilePath) => CopilotSubagent.fromFile({ relativeFilePath })
3416
+ });
3417
+ }
3418
+ /**
3419
+ * Load Cursor subagent configurations from .cursor/subagents/ directory
3420
+ */
3421
+ async loadCursorSubagents() {
3422
+ return await this.loadToolSubagentsDefault({
3423
+ relativeDirPath: CursorSubagent.getSettablePaths().relativeDirPath,
3424
+ fromFile: (relativeFilePath) => CursorSubagent.fromFile({ relativeFilePath })
3425
+ });
3426
+ }
3427
+ /**
3428
+ * Load CodexCli subagent configurations from .codex/subagents/ directory
3429
+ */
3430
+ async loadCodexCliSubagents() {
3431
+ return await this.loadToolSubagentsDefault({
3432
+ relativeDirPath: CodexCliSubagent.getSettablePaths().relativeDirPath,
3433
+ fromFile: (relativeFilePath) => CodexCliSubagent.fromFile({ relativeFilePath })
3434
+ });
3435
+ }
3436
+ /**
3437
+ * Load GeminiCli subagent configurations from .gemini/subagents/ directory
3438
+ */
3439
+ async loadGeminiCliSubagents() {
3440
+ return await this.loadToolSubagentsDefault({
3441
+ relativeDirPath: GeminiCliSubagent.getSettablePaths().relativeDirPath,
3442
+ fromFile: (relativeFilePath) => GeminiCliSubagent.fromFile({ relativeFilePath })
3443
+ });
3444
+ }
3445
+ /**
3446
+ * Load Roo subagent configurations from .roo/subagents/ directory
3447
+ */
3448
+ async loadRooSubagents() {
3449
+ return await this.loadToolSubagentsDefault({
3450
+ relativeDirPath: RooSubagent.getSettablePaths().relativeDirPath,
3451
+ fromFile: (relativeFilePath) => RooSubagent.fromFile({ relativeFilePath })
3452
+ });
3453
+ }
3454
+ async loadToolSubagentsDefault({
3455
+ relativeDirPath,
3456
+ fromFile
3457
+ }) {
3458
+ const paths = await findFilesByGlobs(join33(this.baseDir, relativeDirPath, "*.md"));
3459
+ const subagents = (await Promise.allSettled(paths.map((path2) => fromFile(basename13(path2))))).filter((r) => r.status === "fulfilled").map((r) => r.value);
3460
+ logger.info(`Successfully loaded ${subagents.length} ${relativeDirPath} subagents`);
3461
+ return subagents;
3462
+ }
3463
+ /**
3464
+ * Implementation of abstract method from FeatureProcessor
3465
+ * Return the tool targets that this processor supports
3466
+ */
3467
+ static getToolTargets({
3468
+ includeSimulated = false
3469
+ } = {}) {
3470
+ if (!includeSimulated) {
3471
+ return subagentsProcessorToolTargets.filter(
3472
+ (target) => !subagentsProcessorToolTargetsSimulated.includes(target)
3473
+ );
3474
+ }
3475
+ return subagentsProcessorToolTargets;
3476
+ }
3477
+ static getToolTargetsSimulated() {
3478
+ return subagentsProcessorToolTargetsSimulated;
3479
+ }
3480
+ };
3481
+
3482
+ // src/rules/agentsmd-rule.ts
3483
+ import { join as join35 } from "path";
3484
+
3485
+ // src/rules/rulesync-rule.ts
3486
+ import { basename as basename14, join as join34 } from "path";
3487
+ import { z as z16 } from "zod/mini";
3488
+ var RulesyncRuleFrontmatterSchema = z16.object({
3489
+ root: z16.optional(z16.optional(z16.boolean())),
3490
+ targets: z16.optional(RulesyncTargetsSchema),
3491
+ description: z16.optional(z16.string()),
3492
+ globs: z16.optional(z16.array(z16.string())),
3493
+ cursor: z16.optional(
3494
+ z16.object({
3495
+ alwaysApply: z16.optional(z16.boolean()),
3496
+ description: z16.optional(z16.string()),
3497
+ globs: z16.optional(z16.array(z16.string()))
3498
+ })
3499
+ )
3500
+ });
3501
+ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
3502
+ frontmatter;
3503
+ body;
3504
+ constructor({ frontmatter, body, ...rest }) {
3505
+ if (rest.validate !== false) {
3506
+ const result = RulesyncRuleFrontmatterSchema.safeParse(frontmatter);
3507
+ if (!result.success) {
3508
+ throw result.error;
3509
+ }
3510
+ }
3511
+ super({
3512
+ ...rest,
3513
+ fileContent: stringifyFrontmatter(body, frontmatter)
3514
+ });
3515
+ this.frontmatter = frontmatter;
3516
+ this.body = body;
3517
+ }
3518
+ static getSettablePaths() {
3519
+ return {
3520
+ recommended: {
3521
+ relativeDirPath: ".rulesync/rules"
3522
+ },
3523
+ legacy: {
3524
+ relativeDirPath: ".rulesync"
3525
+ }
3526
+ };
3527
+ }
3528
+ getFrontmatter() {
3529
+ return this.frontmatter;
3530
+ }
3531
+ validate() {
3532
+ if (!this.frontmatter) {
3533
+ return { success: true, error: null };
3534
+ }
3535
+ const result = RulesyncRuleFrontmatterSchema.safeParse(this.frontmatter);
3536
+ if (result.success) {
3537
+ return { success: true, error: null };
3538
+ } else {
3539
+ return { success: false, error: result.error };
3540
+ }
3541
+ }
3542
+ static async fromFileLegacy({
3543
+ relativeFilePath,
3544
+ validate = true
3545
+ }) {
3546
+ const filePath = join34(this.getSettablePaths().legacy.relativeDirPath, relativeFilePath);
3547
+ const fileContent = await readFileContent(filePath);
3548
+ const { frontmatter, body: content } = parseFrontmatter(fileContent);
3549
+ const result = RulesyncRuleFrontmatterSchema.safeParse(frontmatter);
3550
+ if (!result.success) {
3551
+ throw new Error(`Invalid frontmatter in ${filePath}: ${result.error.message}`);
3552
+ }
3553
+ const validatedFrontmatter = {
3554
+ root: result.data.root ?? false,
3555
+ targets: result.data.targets ?? ["*"],
3556
+ description: result.data.description ?? "",
3557
+ globs: result.data.globs ?? [],
3558
+ cursor: result.data.cursor
3559
+ };
3560
+ const filename = basename14(filePath);
3561
+ return new _RulesyncRule({
3562
+ baseDir: ".",
3563
+ relativeDirPath: this.getSettablePaths().recommended.relativeDirPath,
3564
+ relativeFilePath: filename,
3565
+ frontmatter: validatedFrontmatter,
3566
+ body: content.trim(),
3567
+ validate
3568
+ });
3569
+ }
3570
+ static async fromFile({
3571
+ relativeFilePath,
3572
+ validate = true
3573
+ }) {
3574
+ const filePath = join34(this.getSettablePaths().recommended.relativeDirPath, relativeFilePath);
3575
+ const fileContent = await readFileContent(filePath);
3576
+ const { frontmatter, body: content } = parseFrontmatter(fileContent);
3577
+ const result = RulesyncRuleFrontmatterSchema.safeParse(frontmatter);
3578
+ if (!result.success) {
3579
+ throw new Error(`Invalid frontmatter in ${filePath}: ${result.error.message}`);
3580
+ }
3581
+ const validatedFrontmatter = {
3582
+ root: result.data.root ?? false,
3583
+ targets: result.data.targets ?? ["*"],
3584
+ description: result.data.description ?? "",
3585
+ globs: result.data.globs ?? [],
3586
+ cursor: result.data.cursor
3587
+ };
3588
+ const filename = basename14(filePath);
3589
+ return new _RulesyncRule({
3590
+ baseDir: ".",
3591
+ relativeDirPath: this.getSettablePaths().recommended.relativeDirPath,
3592
+ relativeFilePath: filename,
3593
+ frontmatter: validatedFrontmatter,
3594
+ body: content.trim(),
3595
+ validate
3596
+ });
3597
+ }
3598
+ getBody() {
3599
+ return this.body;
3600
+ }
3601
+ };
3602
+
3603
+ // src/rules/tool-rule.ts
3604
+ var ToolRule = class extends ToolFile {
3605
+ root;
3606
+ constructor({ root = false, ...rest }) {
3607
+ super(rest);
3608
+ this.root = root;
3609
+ }
3610
+ static async fromFile(_params) {
3611
+ throw new Error("Please implement this method in the subclass.");
3612
+ }
3613
+ static fromRulesyncRule(_params) {
3614
+ throw new Error("Please implement this method in the subclass.");
3615
+ }
3616
+ static buildToolRuleParamsDefault({
3617
+ baseDir = ".",
3618
+ rulesyncRule,
3619
+ validate = true,
3620
+ rootPath = { relativeDirPath: ".", relativeFilePath: "AGENTS.md" },
3621
+ nonRootPath = { relativeDirPath: ".agents/memories" }
3622
+ }) {
3623
+ const fileContent = rulesyncRule.getBody();
3624
+ return {
3625
+ baseDir,
3626
+ relativeDirPath: rulesyncRule.getFrontmatter().root ? rootPath.relativeDirPath : nonRootPath.relativeDirPath,
3627
+ relativeFilePath: rulesyncRule.getFrontmatter().root ? rootPath.relativeFilePath : rulesyncRule.getRelativeFilePath(),
3628
+ fileContent,
3629
+ validate,
3630
+ root: rulesyncRule.getFrontmatter().root ?? false
3631
+ };
3632
+ }
3633
+ toRulesyncRuleDefault() {
3634
+ return new RulesyncRule({
3635
+ baseDir: this.getBaseDir(),
3636
+ relativeDirPath: RULESYNC_RULES_DIR,
3637
+ relativeFilePath: this.getRelativeFilePath(),
3638
+ frontmatter: {
3639
+ root: this.isRoot(),
3640
+ targets: ["*"],
3641
+ description: "",
3642
+ globs: this.isRoot() ? ["**/*"] : []
3643
+ },
3644
+ body: this.getFileContent()
3645
+ });
3646
+ }
3647
+ isRoot() {
3648
+ return this.root;
3649
+ }
3650
+ static isTargetedByRulesyncRule(_rulesyncRule) {
3651
+ throw new Error("Please implement this method in the subclass.");
3652
+ }
3653
+ static isTargetedByRulesyncRuleDefault({
3654
+ rulesyncRule,
3655
+ toolTarget
3656
+ }) {
3657
+ const targets = rulesyncRule.getFrontmatter().targets;
3658
+ if (!targets) {
3659
+ return true;
3660
+ }
3661
+ if (targets.includes("*")) {
3662
+ return true;
3663
+ }
3664
+ if (targets.includes(toolTarget)) {
3665
+ return true;
3666
+ }
3667
+ return false;
3668
+ }
3669
+ };
3670
+
3671
+ // src/rules/agentsmd-rule.ts
3672
+ var AgentsMdRule = class _AgentsMdRule extends ToolRule {
3673
+ constructor({ fileContent, root, ...rest }) {
3674
+ super({
3675
+ ...rest,
3676
+ fileContent,
3677
+ root: root ?? false
3678
+ });
3679
+ }
3680
+ static getSettablePaths() {
3681
+ return {
3682
+ root: {
3683
+ relativeDirPath: ".",
3684
+ relativeFilePath: "AGENTS.md"
3685
+ },
3686
+ nonRoot: {
3687
+ relativeDirPath: ".agents/memories"
3688
+ }
3689
+ };
3690
+ }
3691
+ static async fromFile({
3692
+ baseDir = ".",
3693
+ relativeFilePath,
3694
+ validate = true
3695
+ }) {
3696
+ const isRoot = relativeFilePath === "AGENTS.md";
3697
+ const relativePath = isRoot ? "AGENTS.md" : join35(".agents/memories", relativeFilePath);
3698
+ const fileContent = await readFileContent(join35(baseDir, relativePath));
3699
+ return new _AgentsMdRule({
3700
+ baseDir,
3701
+ relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
3702
+ relativeFilePath: isRoot ? "AGENTS.md" : relativeFilePath,
3703
+ fileContent,
3704
+ validate,
3705
+ root: isRoot
3706
+ });
3707
+ }
3708
+ static fromRulesyncRule({
3709
+ baseDir = ".",
3710
+ rulesyncRule,
3711
+ validate = true
3712
+ }) {
3713
+ return new _AgentsMdRule(
3714
+ this.buildToolRuleParamsDefault({
3715
+ baseDir,
3716
+ rulesyncRule,
3717
+ validate,
3718
+ rootPath: this.getSettablePaths().root,
3719
+ nonRootPath: this.getSettablePaths().nonRoot
3720
+ })
3721
+ );
3722
+ }
3723
+ toRulesyncRule() {
3724
+ return this.toRulesyncRuleDefault();
3725
+ }
3726
+ validate() {
3727
+ return { success: true, error: null };
3728
+ }
3729
+ static isTargetedByRulesyncRule(rulesyncRule) {
3730
+ return this.isTargetedByRulesyncRuleDefault({
3731
+ rulesyncRule,
3732
+ toolTarget: "agentsmd"
3733
+ });
3734
+ }
3735
+ };
3736
+
3737
+ // src/rules/amazonqcli-rule.ts
3738
+ import { join as join36 } from "path";
3739
+ var AmazonQCliRule = class _AmazonQCliRule extends ToolRule {
3740
+ static getSettablePaths() {
3741
+ return {
3742
+ nonRoot: {
3743
+ relativeDirPath: ".amazonq/rules"
3744
+ }
3745
+ };
3746
+ }
3747
+ static async fromFile({
3748
+ baseDir = ".",
3749
+ relativeFilePath,
3750
+ validate = true
3751
+ }) {
3752
+ const fileContent = await readFileContent(
3753
+ join36(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
3754
+ );
3755
+ return new _AmazonQCliRule({
3756
+ baseDir,
3757
+ relativeDirPath: this.getSettablePaths().nonRoot.relativeDirPath,
3758
+ relativeFilePath,
3759
+ fileContent,
3760
+ validate,
3761
+ root: false
3762
+ });
3763
+ }
3764
+ static fromRulesyncRule({
3765
+ baseDir = ".",
3766
+ rulesyncRule,
3767
+ validate = true
3768
+ }) {
3769
+ return new _AmazonQCliRule(
3770
+ this.buildToolRuleParamsDefault({
3771
+ baseDir,
3772
+ rulesyncRule,
3773
+ validate,
3774
+ nonRootPath: this.getSettablePaths().nonRoot
3775
+ })
3776
+ );
3777
+ }
3778
+ toRulesyncRule() {
3779
+ return this.toRulesyncRuleDefault();
3780
+ }
3781
+ validate() {
3782
+ return { success: true, error: null };
3783
+ }
3784
+ static isTargetedByRulesyncRule(rulesyncRule) {
3785
+ return this.isTargetedByRulesyncRuleDefault({
3786
+ rulesyncRule,
3787
+ toolTarget: "amazonqcli"
3788
+ });
3789
+ }
3790
+ };
3791
+
3792
+ // src/rules/augmentcode-legacy-rule.ts
3793
+ import { join as join37 } from "path";
3794
+ var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
3795
+ toRulesyncRule() {
3796
+ const rulesyncFrontmatter = {
3797
+ root: this.isRoot(),
3798
+ targets: ["*"],
3799
+ description: "",
3800
+ globs: this.isRoot() ? ["**/*"] : []
3801
+ };
3802
+ return new RulesyncRule({
3803
+ baseDir: this.getBaseDir(),
3804
+ frontmatter: rulesyncFrontmatter,
3805
+ body: this.getFileContent(),
3806
+ relativeDirPath: RULESYNC_RULES_DIR,
3807
+ relativeFilePath: this.getRelativeFilePath(),
3808
+ validate: true
3809
+ });
3810
+ }
3811
+ static getSettablePaths() {
3812
+ return {
3813
+ root: {
3814
+ relativeDirPath: ".",
3815
+ relativeFilePath: ".augment-guidelines"
3816
+ },
3817
+ nonRoot: {
3818
+ relativeDirPath: ".augment/rules"
3819
+ }
3820
+ };
3821
+ }
3822
+ static fromRulesyncRule({
3823
+ baseDir = ".",
3824
+ rulesyncRule,
3825
+ validate = true
3826
+ }) {
3827
+ return new _AugmentcodeLegacyRule(
3828
+ this.buildToolRuleParamsDefault({
3829
+ baseDir,
3830
+ rulesyncRule,
3831
+ validate,
3832
+ rootPath: this.getSettablePaths().root,
3833
+ nonRootPath: this.getSettablePaths().nonRoot
3834
+ })
3835
+ );
3836
+ }
3837
+ validate() {
3838
+ return { success: true, error: null };
3839
+ }
3840
+ static isTargetedByRulesyncRule(rulesyncRule) {
3841
+ return this.isTargetedByRulesyncRuleDefault({
3842
+ rulesyncRule,
3843
+ toolTarget: "augmentcode-legacy"
3844
+ });
3845
+ }
3846
+ static async fromFile({
3847
+ baseDir = ".",
3848
+ relativeFilePath,
3849
+ validate = true
3850
+ }) {
3851
+ const settablePaths = this.getSettablePaths();
3852
+ const isRoot = relativeFilePath === settablePaths.root.relativeFilePath;
3853
+ const relativePath = isRoot ? settablePaths.root.relativeFilePath : join37(settablePaths.nonRoot.relativeDirPath, relativeFilePath);
3854
+ const fileContent = await readFileContent(join37(baseDir, relativePath));
3855
+ return new _AugmentcodeLegacyRule({
3856
+ baseDir,
3857
+ relativeDirPath: isRoot ? settablePaths.root.relativeDirPath : settablePaths.nonRoot.relativeDirPath,
3858
+ relativeFilePath: isRoot ? settablePaths.root.relativeFilePath : relativeFilePath,
3859
+ fileContent,
3860
+ validate,
3861
+ root: isRoot
3862
+ });
3863
+ }
3864
+ };
3865
+
3866
+ // src/rules/augmentcode-rule.ts
3867
+ import { join as join38 } from "path";
3868
+ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
3869
+ toRulesyncRule() {
3292
3870
  return this.toRulesyncRuleDefault();
3293
3871
  }
3294
3872
  static getSettablePaths() {
@@ -3318,7 +3896,7 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
3318
3896
  validate = true
3319
3897
  }) {
3320
3898
  const fileContent = await readFileContent(
3321
- join35(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
3899
+ join38(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
3322
3900
  );
3323
3901
  const { body: content } = parseFrontmatter(fileContent);
3324
3902
  return new _AugmentcodeRule({
@@ -3332,10 +3910,16 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
3332
3910
  validate() {
3333
3911
  return { success: true, error: null };
3334
3912
  }
3913
+ static isTargetedByRulesyncRule(rulesyncRule) {
3914
+ return this.isTargetedByRulesyncRuleDefault({
3915
+ rulesyncRule,
3916
+ toolTarget: "augmentcode"
3917
+ });
3918
+ }
3335
3919
  };
3336
3920
 
3337
3921
  // src/rules/claudecode-rule.ts
3338
- import { join as join36 } from "path";
3922
+ import { join as join39 } from "path";
3339
3923
  var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
3340
3924
  static getSettablePaths() {
3341
3925
  return {
@@ -3354,8 +3938,8 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
3354
3938
  validate = true
3355
3939
  }) {
3356
3940
  const isRoot = relativeFilePath === this.getSettablePaths().root.relativeFilePath;
3357
- const relativePath = isRoot ? this.getSettablePaths().root.relativeFilePath : join36(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
3358
- const fileContent = await readFileContent(join36(baseDir, relativePath));
3941
+ const relativePath = isRoot ? this.getSettablePaths().root.relativeFilePath : join39(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
3942
+ const fileContent = await readFileContent(join39(baseDir, relativePath));
3359
3943
  return new _ClaudecodeRule({
3360
3944
  baseDir,
3361
3945
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -3386,13 +3970,19 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
3386
3970
  validate() {
3387
3971
  return { success: true, error: null };
3388
3972
  }
3973
+ static isTargetedByRulesyncRule(rulesyncRule) {
3974
+ return this.isTargetedByRulesyncRuleDefault({
3975
+ rulesyncRule,
3976
+ toolTarget: "claudecode"
3977
+ });
3978
+ }
3389
3979
  };
3390
3980
 
3391
3981
  // src/rules/cline-rule.ts
3392
- import { join as join37 } from "path";
3393
- import { z as z15 } from "zod/mini";
3394
- var ClineRuleFrontmatterSchema = z15.object({
3395
- description: z15.string()
3982
+ import { join as join40 } from "path";
3983
+ import { z as z17 } from "zod/mini";
3984
+ var ClineRuleFrontmatterSchema = z17.object({
3985
+ description: z17.string()
3396
3986
  });
3397
3987
  var ClineRule = class _ClineRule extends ToolRule {
3398
3988
  static getSettablePaths() {
@@ -3422,13 +4012,19 @@ var ClineRule = class _ClineRule extends ToolRule {
3422
4012
  validate() {
3423
4013
  return { success: true, error: null };
3424
4014
  }
4015
+ static isTargetedByRulesyncRule(rulesyncRule) {
4016
+ return this.isTargetedByRulesyncRuleDefault({
4017
+ rulesyncRule,
4018
+ toolTarget: "cline"
4019
+ });
4020
+ }
3425
4021
  static async fromFile({
3426
4022
  baseDir = ".",
3427
4023
  relativeFilePath,
3428
4024
  validate = true
3429
4025
  }) {
3430
4026
  const fileContent = await readFileContent(
3431
- join37(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
4027
+ join40(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
3432
4028
  );
3433
4029
  return new _ClineRule({
3434
4030
  baseDir,
@@ -3441,7 +4037,7 @@ var ClineRule = class _ClineRule extends ToolRule {
3441
4037
  };
3442
4038
 
3443
4039
  // src/rules/codexcli-rule.ts
3444
- import { join as join38 } from "path";
4040
+ import { join as join41 } from "path";
3445
4041
  var CodexcliRule = class _CodexcliRule extends ToolRule {
3446
4042
  static getSettablePaths() {
3447
4043
  return {
@@ -3460,8 +4056,8 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
3460
4056
  validate = true
3461
4057
  }) {
3462
4058
  const isRoot = relativeFilePath === "AGENTS.md";
3463
- const relativePath = isRoot ? "AGENTS.md" : join38(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
3464
- const fileContent = await readFileContent(join38(baseDir, relativePath));
4059
+ const relativePath = isRoot ? "AGENTS.md" : join41(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
4060
+ const fileContent = await readFileContent(join41(baseDir, relativePath));
3465
4061
  return new _CodexcliRule({
3466
4062
  baseDir,
3467
4063
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -3492,14 +4088,20 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
3492
4088
  validate() {
3493
4089
  return { success: true, error: null };
3494
4090
  }
4091
+ static isTargetedByRulesyncRule(rulesyncRule) {
4092
+ return this.isTargetedByRulesyncRuleDefault({
4093
+ rulesyncRule,
4094
+ toolTarget: "codexcli"
4095
+ });
4096
+ }
3495
4097
  };
3496
4098
 
3497
4099
  // src/rules/copilot-rule.ts
3498
- import { join as join39 } from "path";
3499
- import { z as z16 } from "zod/mini";
3500
- var CopilotRuleFrontmatterSchema = z16.object({
3501
- description: z16.optional(z16.string()),
3502
- applyTo: z16.optional(z16.string())
4100
+ import { join as join42 } from "path";
4101
+ import { z as z18 } from "zod/mini";
4102
+ var CopilotRuleFrontmatterSchema = z18.object({
4103
+ description: z18.optional(z18.string()),
4104
+ applyTo: z18.optional(z18.string())
3503
4105
  });
3504
4106
  var CopilotRule = class _CopilotRule extends ToolRule {
3505
4107
  frontmatter;
@@ -3587,11 +4189,11 @@ var CopilotRule = class _CopilotRule extends ToolRule {
3587
4189
  validate = true
3588
4190
  }) {
3589
4191
  const isRoot = relativeFilePath === "copilot-instructions.md";
3590
- const relativePath = isRoot ? join39(
4192
+ const relativePath = isRoot ? join42(
3591
4193
  this.getSettablePaths().root.relativeDirPath,
3592
4194
  this.getSettablePaths().root.relativeFilePath
3593
- ) : join39(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
3594
- const fileContent = await readFileContent(join39(baseDir, relativePath));
4195
+ ) : join42(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
4196
+ const fileContent = await readFileContent(join42(baseDir, relativePath));
3595
4197
  if (isRoot) {
3596
4198
  return new _CopilotRule({
3597
4199
  baseDir,
@@ -3610,7 +4212,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
3610
4212
  const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
3611
4213
  if (!result.success) {
3612
4214
  throw new Error(
3613
- `Invalid frontmatter in ${join39(baseDir, relativeFilePath)}: ${result.error.message}`
4215
+ `Invalid frontmatter in ${join42(baseDir, relativeFilePath)}: ${result.error.message}`
3614
4216
  );
3615
4217
  }
3616
4218
  return new _CopilotRule({
@@ -3640,15 +4242,21 @@ var CopilotRule = class _CopilotRule extends ToolRule {
3640
4242
  getBody() {
3641
4243
  return this.body;
3642
4244
  }
4245
+ static isTargetedByRulesyncRule(rulesyncRule) {
4246
+ return this.isTargetedByRulesyncRuleDefault({
4247
+ rulesyncRule,
4248
+ toolTarget: "copilot"
4249
+ });
4250
+ }
3643
4251
  };
3644
4252
 
3645
4253
  // src/rules/cursor-rule.ts
3646
- import { basename as basename13, join as join40 } from "path";
3647
- import { z as z17 } from "zod/mini";
3648
- var CursorRuleFrontmatterSchema = z17.object({
3649
- description: z17.optional(z17.string()),
3650
- globs: z17.optional(z17.string()),
3651
- alwaysApply: z17.optional(z17.boolean())
4254
+ import { basename as basename15, join as join43 } from "path";
4255
+ import { z as z19 } from "zod/mini";
4256
+ var CursorRuleFrontmatterSchema = z19.object({
4257
+ description: z19.optional(z19.string()),
4258
+ globs: z19.optional(z19.string()),
4259
+ alwaysApply: z19.optional(z19.boolean())
3652
4260
  });
3653
4261
  var CursorRule = class _CursorRule extends ToolRule {
3654
4262
  frontmatter;
@@ -3773,19 +4381,19 @@ var CursorRule = class _CursorRule extends ToolRule {
3773
4381
  validate = true
3774
4382
  }) {
3775
4383
  const fileContent = await readFileContent(
3776
- join40(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
4384
+ join43(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
3777
4385
  );
3778
4386
  const { frontmatter, body: content } = _CursorRule.parseCursorFrontmatter(fileContent);
3779
4387
  const result = CursorRuleFrontmatterSchema.safeParse(frontmatter);
3780
4388
  if (!result.success) {
3781
4389
  throw new Error(
3782
- `Invalid frontmatter in ${join40(baseDir, relativeFilePath)}: ${result.error.message}`
4390
+ `Invalid frontmatter in ${join43(baseDir, relativeFilePath)}: ${result.error.message}`
3783
4391
  );
3784
4392
  }
3785
4393
  return new _CursorRule({
3786
4394
  baseDir,
3787
4395
  relativeDirPath: this.getSettablePaths().nonRoot.relativeDirPath,
3788
- relativeFilePath: basename13(relativeFilePath),
4396
+ relativeFilePath: basename15(relativeFilePath),
3789
4397
  frontmatter: result.data,
3790
4398
  body: content.trim(),
3791
4399
  validate
@@ -3808,10 +4416,16 @@ var CursorRule = class _CursorRule extends ToolRule {
3808
4416
  getBody() {
3809
4417
  return this.body;
3810
4418
  }
4419
+ static isTargetedByRulesyncRule(rulesyncRule) {
4420
+ return this.isTargetedByRulesyncRuleDefault({
4421
+ rulesyncRule,
4422
+ toolTarget: "cursor"
4423
+ });
4424
+ }
3811
4425
  };
3812
4426
 
3813
4427
  // src/rules/geminicli-rule.ts
3814
- import { join as join41 } from "path";
4428
+ import { join as join44 } from "path";
3815
4429
  var GeminiCliRule = class _GeminiCliRule extends ToolRule {
3816
4430
  static getSettablePaths() {
3817
4431
  return {
@@ -3830,8 +4444,8 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
3830
4444
  validate = true
3831
4445
  }) {
3832
4446
  const isRoot = relativeFilePath === "GEMINI.md";
3833
- const relativePath = isRoot ? "GEMINI.md" : join41(".gemini/memories", relativeFilePath);
3834
- const fileContent = await readFileContent(join41(baseDir, relativePath));
4447
+ const relativePath = isRoot ? "GEMINI.md" : join44(".gemini/memories", relativeFilePath);
4448
+ const fileContent = await readFileContent(join44(baseDir, relativePath));
3835
4449
  return new _GeminiCliRule({
3836
4450
  baseDir,
3837
4451
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -3862,10 +4476,16 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
3862
4476
  validate() {
3863
4477
  return { success: true, error: null };
3864
4478
  }
4479
+ static isTargetedByRulesyncRule(rulesyncRule) {
4480
+ return this.isTargetedByRulesyncRuleDefault({
4481
+ rulesyncRule,
4482
+ toolTarget: "geminicli"
4483
+ });
4484
+ }
3865
4485
  };
3866
4486
 
3867
4487
  // src/rules/junie-rule.ts
3868
- import { join as join42 } from "path";
4488
+ import { join as join45 } from "path";
3869
4489
  var JunieRule = class _JunieRule extends ToolRule {
3870
4490
  static getSettablePaths() {
3871
4491
  return {
@@ -3884,8 +4504,8 @@ var JunieRule = class _JunieRule extends ToolRule {
3884
4504
  validate = true
3885
4505
  }) {
3886
4506
  const isRoot = relativeFilePath === "guidelines.md";
3887
- const relativePath = isRoot ? "guidelines.md" : join42(".junie/memories", relativeFilePath);
3888
- const fileContent = await readFileContent(join42(baseDir, relativePath));
4507
+ const relativePath = isRoot ? "guidelines.md" : join45(".junie/memories", relativeFilePath);
4508
+ const fileContent = await readFileContent(join45(baseDir, relativePath));
3889
4509
  return new _JunieRule({
3890
4510
  baseDir,
3891
4511
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -3916,10 +4536,16 @@ var JunieRule = class _JunieRule extends ToolRule {
3916
4536
  validate() {
3917
4537
  return { success: true, error: null };
3918
4538
  }
4539
+ static isTargetedByRulesyncRule(rulesyncRule) {
4540
+ return this.isTargetedByRulesyncRuleDefault({
4541
+ rulesyncRule,
4542
+ toolTarget: "junie"
4543
+ });
4544
+ }
3919
4545
  };
3920
4546
 
3921
4547
  // src/rules/kiro-rule.ts
3922
- import { join as join43 } from "path";
4548
+ import { join as join46 } from "path";
3923
4549
  var KiroRule = class _KiroRule extends ToolRule {
3924
4550
  static getSettablePaths() {
3925
4551
  return {
@@ -3934,7 +4560,7 @@ var KiroRule = class _KiroRule extends ToolRule {
3934
4560
  validate = true
3935
4561
  }) {
3936
4562
  const fileContent = await readFileContent(
3937
- join43(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
4563
+ join46(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
3938
4564
  );
3939
4565
  return new _KiroRule({
3940
4566
  baseDir,
@@ -3965,10 +4591,16 @@ var KiroRule = class _KiroRule extends ToolRule {
3965
4591
  validate() {
3966
4592
  return { success: true, error: null };
3967
4593
  }
4594
+ static isTargetedByRulesyncRule(rulesyncRule) {
4595
+ return this.isTargetedByRulesyncRuleDefault({
4596
+ rulesyncRule,
4597
+ toolTarget: "kiro"
4598
+ });
4599
+ }
3968
4600
  };
3969
4601
 
3970
4602
  // src/rules/opencode-rule.ts
3971
- import { join as join44 } from "path";
4603
+ import { join as join47 } from "path";
3972
4604
  var OpenCodeRule = class _OpenCodeRule extends ToolRule {
3973
4605
  static getSettablePaths() {
3974
4606
  return {
@@ -3987,8 +4619,8 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
3987
4619
  validate = true
3988
4620
  }) {
3989
4621
  const isRoot = relativeFilePath === "AGENTS.md";
3990
- const relativePath = isRoot ? "AGENTS.md" : join44(".opencode/memories", relativeFilePath);
3991
- const fileContent = await readFileContent(join44(baseDir, relativePath));
4622
+ const relativePath = isRoot ? "AGENTS.md" : join47(".opencode/memories", relativeFilePath);
4623
+ const fileContent = await readFileContent(join47(baseDir, relativePath));
3992
4624
  return new _OpenCodeRule({
3993
4625
  baseDir,
3994
4626
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -4019,10 +4651,16 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
4019
4651
  validate() {
4020
4652
  return { success: true, error: null };
4021
4653
  }
4654
+ static isTargetedByRulesyncRule(rulesyncRule) {
4655
+ return this.isTargetedByRulesyncRuleDefault({
4656
+ rulesyncRule,
4657
+ toolTarget: "opencode"
4658
+ });
4659
+ }
4022
4660
  };
4023
4661
 
4024
4662
  // src/rules/qwencode-rule.ts
4025
- import { join as join45 } from "path";
4663
+ import { join as join48 } from "path";
4026
4664
  var QwencodeRule = class _QwencodeRule extends ToolRule {
4027
4665
  static getSettablePaths() {
4028
4666
  return {
@@ -4041,8 +4679,8 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
4041
4679
  validate = true
4042
4680
  }) {
4043
4681
  const isRoot = relativeFilePath === "QWEN.md";
4044
- const relativePath = isRoot ? "QWEN.md" : join45(".qwen/memories", relativeFilePath);
4045
- const fileContent = await readFileContent(join45(baseDir, relativePath));
4682
+ const relativePath = isRoot ? "QWEN.md" : join48(".qwen/memories", relativeFilePath);
4683
+ const fileContent = await readFileContent(join48(baseDir, relativePath));
4046
4684
  return new _QwencodeRule({
4047
4685
  baseDir,
4048
4686
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -4070,10 +4708,16 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
4070
4708
  validate() {
4071
4709
  return { success: true, error: null };
4072
4710
  }
4711
+ static isTargetedByRulesyncRule(rulesyncRule) {
4712
+ return this.isTargetedByRulesyncRuleDefault({
4713
+ rulesyncRule,
4714
+ toolTarget: "qwencode"
4715
+ });
4716
+ }
4073
4717
  };
4074
4718
 
4075
4719
  // src/rules/roo-rule.ts
4076
- import { join as join46 } from "path";
4720
+ import { join as join49 } from "path";
4077
4721
  var RooRule = class _RooRule extends ToolRule {
4078
4722
  static getSettablePaths() {
4079
4723
  return {
@@ -4088,7 +4732,7 @@ var RooRule = class _RooRule extends ToolRule {
4088
4732
  validate = true
4089
4733
  }) {
4090
4734
  const fileContent = await readFileContent(
4091
- join46(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
4735
+ join49(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
4092
4736
  );
4093
4737
  return new _RooRule({
4094
4738
  baseDir,
@@ -4134,10 +4778,16 @@ var RooRule = class _RooRule extends ToolRule {
4134
4778
  validate() {
4135
4779
  return { success: true, error: null };
4136
4780
  }
4781
+ static isTargetedByRulesyncRule(rulesyncRule) {
4782
+ return this.isTargetedByRulesyncRuleDefault({
4783
+ rulesyncRule,
4784
+ toolTarget: "roo"
4785
+ });
4786
+ }
4137
4787
  };
4138
4788
 
4139
4789
  // src/rules/warp-rule.ts
4140
- import { join as join47 } from "path";
4790
+ import { join as join50 } from "path";
4141
4791
  var WarpRule = class _WarpRule extends ToolRule {
4142
4792
  constructor({ fileContent, root, ...rest }) {
4143
4793
  super({
@@ -4163,8 +4813,8 @@ var WarpRule = class _WarpRule extends ToolRule {
4163
4813
  validate = true
4164
4814
  }) {
4165
4815
  const isRoot = relativeFilePath === this.getSettablePaths().root.relativeFilePath;
4166
- const relativePath = isRoot ? this.getSettablePaths().root.relativeFilePath : join47(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
4167
- const fileContent = await readFileContent(join47(baseDir, relativePath));
4816
+ const relativePath = isRoot ? this.getSettablePaths().root.relativeFilePath : join50(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
4817
+ const fileContent = await readFileContent(join50(baseDir, relativePath));
4168
4818
  return new _WarpRule({
4169
4819
  baseDir,
4170
4820
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : ".warp",
@@ -4195,10 +4845,16 @@ var WarpRule = class _WarpRule extends ToolRule {
4195
4845
  validate() {
4196
4846
  return { success: true, error: null };
4197
4847
  }
4848
+ static isTargetedByRulesyncRule(rulesyncRule) {
4849
+ return this.isTargetedByRulesyncRuleDefault({
4850
+ rulesyncRule,
4851
+ toolTarget: "warp"
4852
+ });
4853
+ }
4198
4854
  };
4199
4855
 
4200
4856
  // src/rules/windsurf-rule.ts
4201
- import { join as join48 } from "path";
4857
+ import { join as join51 } from "path";
4202
4858
  var WindsurfRule = class _WindsurfRule extends ToolRule {
4203
4859
  static getSettablePaths() {
4204
4860
  return {
@@ -4213,7 +4869,7 @@ var WindsurfRule = class _WindsurfRule extends ToolRule {
4213
4869
  validate = true
4214
4870
  }) {
4215
4871
  const fileContent = await readFileContent(
4216
- join48(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
4872
+ join51(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
4217
4873
  );
4218
4874
  return new _WindsurfRule({
4219
4875
  baseDir,
@@ -4243,6 +4899,12 @@ var WindsurfRule = class _WindsurfRule extends ToolRule {
4243
4899
  validate() {
4244
4900
  return { success: true, error: null };
4245
4901
  }
4902
+ static isTargetedByRulesyncRule(rulesyncRule) {
4903
+ return this.isTargetedByRulesyncRuleDefault({
4904
+ rulesyncRule,
4905
+ toolTarget: "windsurf"
4906
+ });
4907
+ }
4246
4908
  };
4247
4909
 
4248
4910
  // src/rules/rules-processor.ts
@@ -4265,7 +4927,7 @@ var rulesProcessorToolTargets = [
4265
4927
  "warp",
4266
4928
  "windsurf"
4267
4929
  ];
4268
- var RulesProcessorToolTargetSchema = z18.enum(rulesProcessorToolTargets);
4930
+ var RulesProcessorToolTargetSchema = z20.enum(rulesProcessorToolTargets);
4269
4931
  var RulesProcessor = class extends FeatureProcessor {
4270
4932
  toolTarget;
4271
4933
  simulateCommands;
@@ -4288,102 +4950,153 @@ var RulesProcessor = class extends FeatureProcessor {
4288
4950
  const toolRules = rulesyncRules.map((rulesyncRule) => {
4289
4951
  switch (this.toolTarget) {
4290
4952
  case "agentsmd":
4953
+ if (!AgentsMdRule.isTargetedByRulesyncRule(rulesyncRule)) {
4954
+ return null;
4955
+ }
4291
4956
  return AgentsMdRule.fromRulesyncRule({
4292
4957
  baseDir: this.baseDir,
4293
4958
  rulesyncRule,
4294
4959
  validate: true
4295
4960
  });
4296
4961
  case "amazonqcli":
4962
+ if (!AmazonQCliRule.isTargetedByRulesyncRule(rulesyncRule)) {
4963
+ return null;
4964
+ }
4297
4965
  return AmazonQCliRule.fromRulesyncRule({
4298
4966
  baseDir: this.baseDir,
4299
4967
  rulesyncRule,
4300
4968
  validate: true
4301
4969
  });
4302
4970
  case "augmentcode":
4971
+ if (!AugmentcodeRule.isTargetedByRulesyncRule(rulesyncRule)) {
4972
+ return null;
4973
+ }
4303
4974
  return AugmentcodeRule.fromRulesyncRule({
4304
4975
  baseDir: this.baseDir,
4305
4976
  rulesyncRule,
4306
4977
  validate: true
4307
4978
  });
4308
4979
  case "augmentcode-legacy":
4980
+ if (!AugmentcodeLegacyRule.isTargetedByRulesyncRule(rulesyncRule)) {
4981
+ return null;
4982
+ }
4309
4983
  return AugmentcodeLegacyRule.fromRulesyncRule({
4310
4984
  baseDir: this.baseDir,
4311
4985
  rulesyncRule,
4312
4986
  validate: true
4313
4987
  });
4314
4988
  case "claudecode":
4989
+ if (!ClaudecodeRule.isTargetedByRulesyncRule(rulesyncRule)) {
4990
+ return null;
4991
+ }
4315
4992
  return ClaudecodeRule.fromRulesyncRule({
4316
4993
  baseDir: this.baseDir,
4317
4994
  rulesyncRule,
4318
4995
  validate: true
4319
4996
  });
4320
4997
  case "cline":
4998
+ if (!ClineRule.isTargetedByRulesyncRule(rulesyncRule)) {
4999
+ return null;
5000
+ }
4321
5001
  return ClineRule.fromRulesyncRule({
4322
5002
  baseDir: this.baseDir,
4323
5003
  rulesyncRule,
4324
5004
  validate: true
4325
5005
  });
4326
5006
  case "codexcli":
5007
+ if (!CodexcliRule.isTargetedByRulesyncRule(rulesyncRule)) {
5008
+ return null;
5009
+ }
4327
5010
  return CodexcliRule.fromRulesyncRule({
4328
5011
  baseDir: this.baseDir,
4329
5012
  rulesyncRule,
4330
5013
  validate: true
4331
5014
  });
4332
5015
  case "copilot":
5016
+ if (!CopilotRule.isTargetedByRulesyncRule(rulesyncRule)) {
5017
+ return null;
5018
+ }
4333
5019
  return CopilotRule.fromRulesyncRule({
4334
5020
  baseDir: this.baseDir,
4335
5021
  rulesyncRule,
4336
5022
  validate: true
4337
5023
  });
4338
5024
  case "cursor":
5025
+ if (!CursorRule.isTargetedByRulesyncRule(rulesyncRule)) {
5026
+ return null;
5027
+ }
4339
5028
  return CursorRule.fromRulesyncRule({
4340
5029
  baseDir: this.baseDir,
4341
5030
  rulesyncRule,
4342
5031
  validate: true
4343
5032
  });
4344
5033
  case "geminicli":
5034
+ if (!GeminiCliRule.isTargetedByRulesyncRule(rulesyncRule)) {
5035
+ return null;
5036
+ }
4345
5037
  return GeminiCliRule.fromRulesyncRule({
4346
5038
  baseDir: this.baseDir,
4347
5039
  rulesyncRule,
4348
5040
  validate: true
4349
5041
  });
4350
5042
  case "junie":
5043
+ if (!JunieRule.isTargetedByRulesyncRule(rulesyncRule)) {
5044
+ return null;
5045
+ }
4351
5046
  return JunieRule.fromRulesyncRule({
4352
5047
  baseDir: this.baseDir,
4353
5048
  rulesyncRule,
4354
5049
  validate: true
4355
5050
  });
4356
5051
  case "kiro":
5052
+ if (!KiroRule.isTargetedByRulesyncRule(rulesyncRule)) {
5053
+ return null;
5054
+ }
4357
5055
  return KiroRule.fromRulesyncRule({
4358
5056
  baseDir: this.baseDir,
4359
5057
  rulesyncRule,
4360
5058
  validate: true
4361
5059
  });
4362
5060
  case "opencode":
5061
+ if (!OpenCodeRule.isTargetedByRulesyncRule(rulesyncRule)) {
5062
+ return null;
5063
+ }
4363
5064
  return OpenCodeRule.fromRulesyncRule({
4364
5065
  baseDir: this.baseDir,
4365
5066
  rulesyncRule,
4366
5067
  validate: true
4367
5068
  });
4368
5069
  case "qwencode":
5070
+ if (!QwencodeRule.isTargetedByRulesyncRule(rulesyncRule)) {
5071
+ return null;
5072
+ }
4369
5073
  return QwencodeRule.fromRulesyncRule({
4370
5074
  baseDir: this.baseDir,
4371
5075
  rulesyncRule,
4372
5076
  validate: true
4373
5077
  });
4374
5078
  case "roo":
5079
+ if (!RooRule.isTargetedByRulesyncRule(rulesyncRule)) {
5080
+ return null;
5081
+ }
4375
5082
  return RooRule.fromRulesyncRule({
4376
5083
  baseDir: this.baseDir,
4377
5084
  rulesyncRule,
4378
5085
  validate: true
4379
5086
  });
4380
5087
  case "warp":
5088
+ if (!WarpRule.isTargetedByRulesyncRule(rulesyncRule)) {
5089
+ return null;
5090
+ }
4381
5091
  return WarpRule.fromRulesyncRule({
4382
5092
  baseDir: this.baseDir,
4383
5093
  rulesyncRule,
4384
5094
  validate: true
4385
5095
  });
4386
5096
  case "windsurf":
5097
+ if (!WindsurfRule.isTargetedByRulesyncRule(rulesyncRule)) {
5098
+ return null;
5099
+ }
4387
5100
  return WindsurfRule.fromRulesyncRule({
4388
5101
  baseDir: this.baseDir,
4389
5102
  rulesyncRule,
@@ -4392,8 +5105,9 @@ var RulesProcessor = class extends FeatureProcessor {
4392
5105
  default:
4393
5106
  throw new Error(`Unsupported tool target: ${this.toolTarget}`);
4394
5107
  }
4395
- });
4396
- if (this.toolTarget === "cursor" && (this.simulateCommands || this.simulateSubagents)) {
5108
+ }).filter((rule) => rule !== null);
5109
+ const isSimulated = this.simulateCommands || this.simulateSubagents;
5110
+ if (isSimulated && this.toolTarget === "cursor") {
4397
5111
  toolRules.push(
4398
5112
  new CursorRule({
4399
5113
  baseDir: this.baseDir,
@@ -4412,6 +5126,22 @@ var RulesProcessor = class extends FeatureProcessor {
4412
5126
  })
4413
5127
  );
4414
5128
  }
5129
+ if (isSimulated && this.toolTarget === "roo") {
5130
+ toolRules.push(
5131
+ new RooRule({
5132
+ baseDir: this.baseDir,
5133
+ relativeDirPath: RooRule.getSettablePaths().nonRoot.relativeDirPath,
5134
+ relativeFilePath: "additional-conventions.md",
5135
+ fileContent: this.generateAdditionalConventionsSection({
5136
+ commands: { relativeDirPath: RooCommand.getSettablePaths().relativeDirPath },
5137
+ subagents: {
5138
+ relativeDirPath: RooSubagent.getSettablePaths().relativeDirPath
5139
+ }
5140
+ }),
5141
+ validate: true
5142
+ })
5143
+ );
5144
+ }
4415
5145
  const rootRuleIndex = toolRules.findIndex((rule) => rule.isRoot());
4416
5146
  if (rootRuleIndex === -1) {
4417
5147
  return toolRules;
@@ -4465,7 +5195,12 @@ var RulesProcessor = class extends FeatureProcessor {
4465
5195
  case "geminicli": {
4466
5196
  const rootRule = toolRules[rootRuleIndex];
4467
5197
  rootRule?.setFileContent(
4468
- this.generateXmlReferencesSection(toolRules) + rootRule.getFileContent()
5198
+ this.generateXmlReferencesSection(toolRules) + this.generateAdditionalConventionsSection({
5199
+ commands: { relativeDirPath: GeminiCliCommand.getSettablePaths().relativeDirPath },
5200
+ subagents: {
5201
+ relativeDirPath: GeminiCliSubagent.getSettablePaths().relativeDirPath
5202
+ }
5203
+ }) + rootRule.getFileContent()
4469
5204
  );
4470
5205
  return toolRules;
4471
5206
  }
@@ -4513,17 +5248,17 @@ var RulesProcessor = class extends FeatureProcessor {
4513
5248
  * Load and parse rulesync rule files from .rulesync/rules/ directory
4514
5249
  */
4515
5250
  async loadRulesyncFiles() {
4516
- const files = await findFilesByGlobs(join49(RULESYNC_RULES_DIR, "*.md"));
5251
+ const files = await findFilesByGlobs(join52(RULESYNC_RULES_DIR, "*.md"));
4517
5252
  logger.debug(`Found ${files.length} rulesync files`);
4518
5253
  return Promise.all(
4519
- files.map((file) => RulesyncRule.fromFile({ relativeFilePath: basename14(file) }))
5254
+ files.map((file) => RulesyncRule.fromFile({ relativeFilePath: basename16(file) }))
4520
5255
  );
4521
5256
  }
4522
5257
  async loadRulesyncFilesLegacy() {
4523
- const legacyFiles = await findFilesByGlobs(join49(RULESYNC_RULES_DIR_LEGACY, "*.md"));
5258
+ const legacyFiles = await findFilesByGlobs(join52(RULESYNC_RULES_DIR_LEGACY, "*.md"));
4524
5259
  logger.debug(`Found ${legacyFiles.length} legacy rulesync files`);
4525
5260
  return Promise.all(
4526
- legacyFiles.map((file) => RulesyncRule.fromFileLegacy({ relativeFilePath: basename14(file) }))
5261
+ legacyFiles.map((file) => RulesyncRule.fromFileLegacy({ relativeFilePath: basename16(file) }))
4527
5262
  );
4528
5263
  }
4529
5264
  /**
@@ -4575,794 +5310,414 @@ var RulesProcessor = class extends FeatureProcessor {
4575
5310
  return [];
4576
5311
  }
4577
5312
  }
4578
- async loadToolRulesDefault({
4579
- root,
4580
- nonRoot
4581
- }) {
4582
- const rootToolRules = await (async () => {
4583
- if (!root) {
4584
- return [];
4585
- }
4586
- const rootFilePaths = await findFilesByGlobs(
4587
- join49(this.baseDir, root.relativeDirPath ?? ".", root.relativeFilePath)
4588
- );
4589
- return await Promise.all(
4590
- rootFilePaths.map(
4591
- (filePath) => root.fromFile({
4592
- baseDir: this.baseDir,
4593
- relativeFilePath: basename14(filePath)
4594
- })
4595
- )
4596
- );
4597
- })();
4598
- logger.debug(`Found ${rootToolRules.length} root tool rule files`);
4599
- const nonRootToolRules = await (async () => {
4600
- if (!nonRoot) {
4601
- return [];
4602
- }
4603
- const nonRootFilePaths = await findFilesByGlobs(
4604
- join49(this.baseDir, nonRoot.relativeDirPath, `*.${nonRoot.extension}`)
4605
- );
4606
- return await Promise.all(
4607
- nonRootFilePaths.map(
4608
- (filePath) => nonRoot.fromFile({
4609
- baseDir: this.baseDir,
4610
- relativeFilePath: basename14(filePath)
4611
- })
4612
- )
4613
- );
4614
- })();
4615
- logger.debug(`Found ${nonRootToolRules.length} non-root tool rule files`);
4616
- return [...rootToolRules, ...nonRootToolRules];
4617
- }
4618
- /**
4619
- * Load AGENTS.md rule configuration
4620
- */
4621
- async loadAgentsmdRules() {
4622
- const settablePaths = AgentsMdRule.getSettablePaths();
4623
- return await this.loadToolRulesDefault({
4624
- root: {
4625
- relativeDirPath: settablePaths.root.relativeDirPath,
4626
- relativeFilePath: settablePaths.root.relativeFilePath,
4627
- fromFile: (params) => AgentsMdRule.fromFile(params)
4628
- },
4629
- nonRoot: {
4630
- relativeDirPath: settablePaths.nonRoot.relativeDirPath,
4631
- fromFile: (params) => AgentsMdRule.fromFile(params),
4632
- extension: "md"
4633
- }
4634
- });
4635
- }
4636
- async loadWarpRules() {
4637
- const settablePaths = WarpRule.getSettablePaths();
4638
- return await this.loadToolRulesDefault({
4639
- root: {
4640
- relativeDirPath: settablePaths.root.relativeDirPath,
4641
- relativeFilePath: settablePaths.root.relativeFilePath,
4642
- fromFile: (params) => WarpRule.fromFile(params)
4643
- },
4644
- nonRoot: {
4645
- relativeDirPath: settablePaths.nonRoot.relativeDirPath,
4646
- fromFile: (params) => WarpRule.fromFile(params),
4647
- extension: "md"
4648
- }
4649
- });
4650
- }
4651
- /**
4652
- * Load Amazon Q Developer CLI rule configurations from .amazonq/rules/ directory
4653
- */
4654
- async loadAmazonqcliRules() {
4655
- const settablePaths = AmazonQCliRule.getSettablePaths();
4656
- return await this.loadToolRulesDefault({
4657
- nonRoot: {
4658
- relativeDirPath: settablePaths.nonRoot.relativeDirPath,
4659
- fromFile: (params) => AmazonQCliRule.fromFile(params),
4660
- extension: "md"
4661
- }
4662
- });
4663
- }
4664
- /**
4665
- * Load AugmentCode rule configurations from .augment/rules/ directory
4666
- */
4667
- async loadAugmentcodeRules() {
4668
- const settablePaths = AugmentcodeRule.getSettablePaths();
4669
- return await this.loadToolRulesDefault({
4670
- nonRoot: {
4671
- relativeDirPath: settablePaths.nonRoot.relativeDirPath,
4672
- fromFile: (params) => AugmentcodeRule.fromFile(params),
4673
- extension: "md"
4674
- }
4675
- });
4676
- }
4677
- /**
4678
- * Load AugmentCode legacy rule configuration from .augment-guidelines file and .augment/rules/ directory
4679
- */
4680
- async loadAugmentcodeLegacyRules() {
4681
- const settablePaths = AugmentcodeLegacyRule.getSettablePaths();
4682
- return await this.loadToolRulesDefault({
4683
- root: {
4684
- relativeDirPath: settablePaths.root.relativeDirPath,
4685
- relativeFilePath: settablePaths.root.relativeFilePath,
4686
- fromFile: (params) => AugmentcodeLegacyRule.fromFile(params)
4687
- },
4688
- nonRoot: {
4689
- relativeDirPath: settablePaths.nonRoot.relativeDirPath,
4690
- fromFile: (params) => AugmentcodeLegacyRule.fromFile(params),
4691
- extension: "md"
4692
- }
4693
- });
4694
- }
4695
- /**
4696
- * Load Claude Code rule configuration from CLAUDE.md file
4697
- */
4698
- async loadClaudecodeRules() {
4699
- const settablePaths = ClaudecodeRule.getSettablePaths();
4700
- return await this.loadToolRulesDefault({
4701
- root: {
4702
- relativeDirPath: settablePaths.root.relativeDirPath,
4703
- relativeFilePath: settablePaths.root.relativeFilePath,
4704
- fromFile: (params) => ClaudecodeRule.fromFile(params)
4705
- },
4706
- nonRoot: {
4707
- relativeDirPath: settablePaths.nonRoot.relativeDirPath,
4708
- fromFile: (params) => ClaudecodeRule.fromFile(params),
4709
- extension: "md"
4710
- }
4711
- });
4712
- }
4713
- /**
4714
- * Load Cline rule configurations from .clinerules/ directory
4715
- */
4716
- async loadClineRules() {
4717
- const settablePaths = ClineRule.getSettablePaths();
4718
- return await this.loadToolRulesDefault({
4719
- nonRoot: {
4720
- relativeDirPath: settablePaths.nonRoot.relativeDirPath,
4721
- fromFile: (params) => ClineRule.fromFile(params),
4722
- extension: "md"
4723
- }
4724
- });
4725
- }
4726
- /**
4727
- * Load OpenAI Codex CLI rule configuration from AGENTS.md and .codex/memories/*.md files
4728
- */
4729
- async loadCodexcliRules() {
4730
- const settablePaths = CodexcliRule.getSettablePaths();
4731
- return await this.loadToolRulesDefault({
4732
- root: {
4733
- relativeDirPath: settablePaths.root.relativeDirPath,
4734
- relativeFilePath: settablePaths.root.relativeFilePath,
4735
- fromFile: (params) => CodexcliRule.fromFile(params)
4736
- },
4737
- nonRoot: {
4738
- relativeDirPath: settablePaths.nonRoot.relativeDirPath,
4739
- fromFile: (params) => CodexcliRule.fromFile(params),
4740
- extension: "md"
4741
- }
4742
- });
4743
- }
4744
- /**
4745
- * Load GitHub Copilot rule configuration from .github/copilot-instructions.md file
4746
- */
4747
- async loadCopilotRules() {
4748
- const settablePaths = CopilotRule.getSettablePaths();
4749
- return await this.loadToolRulesDefault({
4750
- root: {
4751
- relativeDirPath: settablePaths.root.relativeDirPath,
4752
- relativeFilePath: settablePaths.root.relativeFilePath,
4753
- fromFile: (params) => CopilotRule.fromFile(params)
4754
- },
4755
- nonRoot: {
4756
- relativeDirPath: settablePaths.nonRoot.relativeDirPath,
4757
- fromFile: (params) => CopilotRule.fromFile(params),
4758
- extension: "md"
4759
- }
4760
- });
4761
- }
4762
- /**
4763
- * Load Cursor rule configurations from .cursor/rules/ directory
4764
- */
4765
- async loadCursorRules() {
4766
- const settablePaths = CursorRule.getSettablePaths();
4767
- return await this.loadToolRulesDefault({
4768
- nonRoot: {
4769
- relativeDirPath: settablePaths.nonRoot.relativeDirPath,
4770
- fromFile: (params) => CursorRule.fromFile(params),
4771
- extension: "mdc"
4772
- }
4773
- });
4774
- }
4775
- /**
4776
- * Load Gemini CLI rule configuration from GEMINI.md file
4777
- */
4778
- async loadGeminicliRules() {
4779
- const settablePaths = GeminiCliRule.getSettablePaths();
4780
- return await this.loadToolRulesDefault({
4781
- root: {
4782
- relativeDirPath: settablePaths.root.relativeDirPath,
4783
- relativeFilePath: settablePaths.root.relativeFilePath,
4784
- fromFile: (params) => GeminiCliRule.fromFile(params)
4785
- },
4786
- nonRoot: {
4787
- relativeDirPath: settablePaths.nonRoot.relativeDirPath,
4788
- fromFile: (params) => GeminiCliRule.fromFile(params),
4789
- extension: "md"
4790
- }
4791
- });
4792
- }
4793
- /**
4794
- * Load JetBrains Junie rule configuration from .junie/guidelines.md file
4795
- */
4796
- async loadJunieRules() {
4797
- const settablePaths = JunieRule.getSettablePaths();
4798
- return await this.loadToolRulesDefault({
4799
- root: {
4800
- relativeDirPath: settablePaths.root.relativeDirPath,
4801
- relativeFilePath: settablePaths.root.relativeFilePath,
4802
- fromFile: (params) => JunieRule.fromFile(params)
4803
- },
4804
- nonRoot: {
4805
- relativeDirPath: settablePaths.nonRoot.relativeDirPath,
4806
- fromFile: (params) => JunieRule.fromFile(params),
4807
- extension: "md"
4808
- }
4809
- });
4810
- }
4811
- /**
4812
- * Load Kiro rule configurations from .kiro/steering/ directory
4813
- */
4814
- async loadKiroRules() {
4815
- const settablePaths = KiroRule.getSettablePaths();
4816
- return await this.loadToolRulesDefault({
4817
- nonRoot: {
4818
- relativeDirPath: settablePaths.nonRoot.relativeDirPath,
4819
- fromFile: (params) => KiroRule.fromFile(params),
4820
- extension: "md"
5313
+ async loadToolRulesDefault({
5314
+ root,
5315
+ nonRoot
5316
+ }) {
5317
+ const rootToolRules = await (async () => {
5318
+ if (!root) {
5319
+ return [];
4821
5320
  }
4822
- });
5321
+ const rootFilePaths = await findFilesByGlobs(
5322
+ join52(this.baseDir, root.relativeDirPath ?? ".", root.relativeFilePath)
5323
+ );
5324
+ return await Promise.all(
5325
+ rootFilePaths.map(
5326
+ (filePath) => root.fromFile({
5327
+ baseDir: this.baseDir,
5328
+ relativeFilePath: basename16(filePath)
5329
+ })
5330
+ )
5331
+ );
5332
+ })();
5333
+ logger.debug(`Found ${rootToolRules.length} root tool rule files`);
5334
+ const nonRootToolRules = await (async () => {
5335
+ if (!nonRoot) {
5336
+ return [];
5337
+ }
5338
+ const nonRootFilePaths = await findFilesByGlobs(
5339
+ join52(this.baseDir, nonRoot.relativeDirPath, `*.${nonRoot.extension}`)
5340
+ );
5341
+ return await Promise.all(
5342
+ nonRootFilePaths.map(
5343
+ (filePath) => nonRoot.fromFile({
5344
+ baseDir: this.baseDir,
5345
+ relativeFilePath: basename16(filePath)
5346
+ })
5347
+ )
5348
+ );
5349
+ })();
5350
+ logger.debug(`Found ${nonRootToolRules.length} non-root tool rule files`);
5351
+ return [...rootToolRules, ...nonRootToolRules];
4823
5352
  }
4824
5353
  /**
4825
- * Load OpenCode rule configuration from AGENTS.md file and .opencode/memories/*.md files
5354
+ * Load AGENTS.md rule configuration
4826
5355
  */
4827
- async loadOpencodeRules() {
4828
- const settablePaths = OpenCodeRule.getSettablePaths();
5356
+ async loadAgentsmdRules() {
5357
+ const settablePaths = AgentsMdRule.getSettablePaths();
4829
5358
  return await this.loadToolRulesDefault({
4830
5359
  root: {
4831
5360
  relativeDirPath: settablePaths.root.relativeDirPath,
4832
5361
  relativeFilePath: settablePaths.root.relativeFilePath,
4833
- fromFile: (params) => OpenCodeRule.fromFile(params)
5362
+ fromFile: (params) => AgentsMdRule.fromFile(params)
4834
5363
  },
4835
5364
  nonRoot: {
4836
5365
  relativeDirPath: settablePaths.nonRoot.relativeDirPath,
4837
- fromFile: (params) => OpenCodeRule.fromFile(params),
5366
+ fromFile: (params) => AgentsMdRule.fromFile(params),
4838
5367
  extension: "md"
4839
5368
  }
4840
5369
  });
4841
5370
  }
4842
- /**
4843
- * Load Qwen Code rule configuration from QWEN.md file and .qwen/memories/*.md files
4844
- */
4845
- async loadQwencodeRules() {
4846
- const settablePaths = QwencodeRule.getSettablePaths();
5371
+ async loadWarpRules() {
5372
+ const settablePaths = WarpRule.getSettablePaths();
4847
5373
  return await this.loadToolRulesDefault({
4848
5374
  root: {
4849
5375
  relativeDirPath: settablePaths.root.relativeDirPath,
4850
5376
  relativeFilePath: settablePaths.root.relativeFilePath,
4851
- fromFile: (params) => QwencodeRule.fromFile(params)
5377
+ fromFile: (params) => WarpRule.fromFile(params)
4852
5378
  },
4853
5379
  nonRoot: {
4854
5380
  relativeDirPath: settablePaths.nonRoot.relativeDirPath,
4855
- fromFile: (params) => QwencodeRule.fromFile(params),
4856
- extension: "md"
4857
- }
4858
- });
4859
- }
4860
- /**
4861
- * Load Roo Code rule configurations from .roo/rules/ directory
4862
- */
4863
- async loadRooRules() {
4864
- const settablePaths = RooRule.getSettablePaths();
4865
- return await this.loadToolRulesDefault({
4866
- nonRoot: {
4867
- relativeDirPath: settablePaths.nonRoot.relativeDirPath,
4868
- fromFile: (params) => RooRule.fromFile(params),
4869
- extension: "md"
4870
- }
4871
- });
4872
- }
4873
- /**
4874
- * Load Windsurf rule configurations from .windsurf/rules/ directory
4875
- */
4876
- async loadWindsurfRules() {
4877
- const settablePaths = WindsurfRule.getSettablePaths();
4878
- return await this.loadToolRulesDefault({
4879
- nonRoot: {
4880
- relativeDirPath: settablePaths.nonRoot.relativeDirPath,
4881
- fromFile: (params) => WindsurfRule.fromFile(params),
4882
- extension: "md"
4883
- }
4884
- });
4885
- }
4886
- /**
4887
- * Implementation of abstract method from FeatureProcessor
4888
- * Return the tool targets that this processor supports
4889
- */
4890
- static getToolTargets() {
4891
- return rulesProcessorToolTargets;
4892
- }
4893
- generateXmlReferencesSection(toolRules) {
4894
- const toolRulesWithoutRoot = toolRules.filter((rule) => !rule.isRoot());
4895
- if (toolRulesWithoutRoot.length === 0) {
4896
- return "";
4897
- }
4898
- const lines = [];
4899
- lines.push(
4900
- "Please also reference the following documents as needed. In this case, `@` stands for the project root directory."
4901
- );
4902
- lines.push("");
4903
- const documentsData = {
4904
- Documents: {
4905
- Document: toolRulesWithoutRoot.map((rule) => {
4906
- const rulesyncRule = rule.toRulesyncRule();
4907
- const frontmatter = rulesyncRule.getFrontmatter();
4908
- const relativePath = `@${rule.getRelativePathFromCwd()}`;
4909
- const document = {
4910
- Path: relativePath
4911
- };
4912
- if (frontmatter.description) {
4913
- document.Description = frontmatter.description;
4914
- }
4915
- if (frontmatter.globs && frontmatter.globs.length > 0) {
4916
- document.FilePatterns = frontmatter.globs.join(", ");
4917
- }
4918
- return document;
4919
- })
4920
- }
4921
- };
4922
- const builder = new XMLBuilder({
4923
- format: true,
4924
- ignoreAttributes: false,
4925
- suppressEmptyNode: false
4926
- });
4927
- const xmlContent = builder.build(documentsData);
4928
- lines.push(xmlContent);
4929
- return lines.join("\n") + "\n";
4930
- }
4931
- generateReferencesSection(toolRules) {
4932
- const toolRulesWithoutRoot = toolRules.filter((rule) => !rule.isRoot());
4933
- if (toolRulesWithoutRoot.length === 0) {
4934
- return "";
4935
- }
4936
- const lines = [];
4937
- lines.push("Please also reference the following documents as needed:");
4938
- lines.push("");
4939
- for (const rule of toolRulesWithoutRoot) {
4940
- const rulesyncRule = rule.toRulesyncRule();
4941
- const frontmatter = rulesyncRule.getFrontmatter();
4942
- const escapedDescription = frontmatter.description?.replace(/"/g, '\\"');
4943
- const globsText = frontmatter.globs?.join(",");
4944
- lines.push(
4945
- `@${rule.getRelativePathFromCwd()} description: "${escapedDescription}" globs: "${globsText}"`
4946
- );
4947
- }
4948
- return lines.join("\n") + "\n";
4949
- }
4950
- generateAdditionalConventionsSection({
4951
- commands,
4952
- subagents
4953
- }) {
4954
- return `# Additional Conventions Beyond the Built-in Functions
4955
-
4956
- As this project's AI coding tool, you must follow the additional conventions below, in addition to the built-in functions.
4957
-
4958
- ${this.simulateCommands ? `## Simulated Custom Slash Commands
4959
-
4960
- Custom slash commands allow you to define frequently-used prompts as Markdown files that you can execute.
4961
-
4962
- ### Syntax
4963
-
4964
- Users can use following syntax to invoke a custom command.
4965
-
4966
- \`\`\`txt
4967
- s/<command> [arguments]
4968
- \`\`\`
4969
-
4970
- This syntax employs a double slash (\`s/\`) to prevent conflicts with built-in slash commands.
4971
- The \`s\` in \`s/\` stands for *simulate*. Because custom slash commands are not built-in, this syntax provides a pseudo way to invoke them.
4972
-
4973
- When users call a custom slash command, you have to look for the markdown file, \`${join49(commands.relativeDirPath, "{command}.md")}\`, then execute the contents of that file as the block of operations.` : ""}
4974
-
4975
- ${this.simulateSubagents ? `## Simulated Subagents
4976
-
4977
- Simulated subagents are specialized AI assistants that can be invoked to handle specific types of tasks. In this case, it can be appear something like simulated custom slash commands simply. Simulated subagents can be called by simulated custom slash commands.
4978
-
4979
- When users call a simulated subagent, it will look for the corresponding markdown file, \`${join49(subagents.relativeDirPath, "{subagent}.md")}\`, and execute its contents as the block of operations.` : ""}`.trim();
4980
- }
4981
- };
4982
-
4983
- // src/subagents/subagents-processor.ts
4984
- import { basename as basename16, join as join52 } from "path";
4985
- import { z as z21 } from "zod/mini";
4986
-
4987
- // src/subagents/claudecode-subagent.ts
4988
- import { join as join51 } from "path";
4989
- import { z as z20 } from "zod/mini";
4990
-
4991
- // src/subagents/rulesync-subagent.ts
4992
- import { basename as basename15, join as join50 } from "path";
4993
- import { z as z19 } from "zod/mini";
4994
- var RulesyncSubagentModelSchema = z19.enum(["opus", "sonnet", "haiku", "inherit"]);
4995
- var RulesyncSubagentFrontmatterSchema = z19.object({
4996
- targets: RulesyncTargetsSchema,
4997
- name: z19.string(),
4998
- description: z19.string(),
4999
- claudecode: z19.optional(
5000
- z19.object({
5001
- model: RulesyncSubagentModelSchema
5002
- })
5003
- )
5004
- });
5005
- var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
5006
- frontmatter;
5007
- body;
5008
- constructor({ frontmatter, body, ...rest }) {
5009
- if (rest.validate !== false) {
5010
- const result = RulesyncSubagentFrontmatterSchema.safeParse(frontmatter);
5011
- if (!result.success) {
5012
- throw result.error;
5013
- }
5014
- }
5015
- super({
5016
- ...rest
5017
- });
5018
- this.frontmatter = frontmatter;
5019
- this.body = body;
5020
- }
5021
- static getSettablePaths() {
5022
- return {
5023
- relativeDirPath: ".rulesync/subagents"
5024
- };
5025
- }
5026
- getFrontmatter() {
5027
- return this.frontmatter;
5028
- }
5029
- getBody() {
5030
- return this.body;
5031
- }
5032
- validate() {
5033
- if (!this.frontmatter) {
5034
- return { success: true, error: null };
5035
- }
5036
- const result = RulesyncSubagentFrontmatterSchema.safeParse(this.frontmatter);
5037
- if (result.success) {
5038
- return { success: true, error: null };
5039
- } else {
5040
- return { success: false, error: result.error };
5041
- }
5042
- }
5043
- static async fromFile({
5044
- relativeFilePath
5045
- }) {
5046
- const fileContent = await readFileContent(join50(RULESYNC_SUBAGENTS_DIR, relativeFilePath));
5047
- const { frontmatter, body: content } = parseFrontmatter(fileContent);
5048
- const result = RulesyncSubagentFrontmatterSchema.safeParse(frontmatter);
5049
- if (!result.success) {
5050
- throw new Error(`Invalid frontmatter in ${relativeFilePath}: ${result.error.message}`);
5051
- }
5052
- const filename = basename15(relativeFilePath);
5053
- return new _RulesyncSubagent({
5054
- baseDir: ".",
5055
- relativeDirPath: this.getSettablePaths().relativeDirPath,
5056
- relativeFilePath: filename,
5057
- frontmatter: result.data,
5058
- body: content.trim(),
5059
- fileContent
5060
- });
5061
- }
5062
- };
5063
-
5064
- // src/subagents/claudecode-subagent.ts
5065
- var ClaudecodeSubagentFrontmatterSchema = z20.object({
5066
- name: z20.string(),
5067
- description: z20.string(),
5068
- model: z20.optional(z20.enum(["opus", "sonnet", "haiku", "inherit"]))
5069
- });
5070
- var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
5071
- frontmatter;
5072
- body;
5073
- constructor({ frontmatter, body, ...rest }) {
5074
- if (rest.validate !== false) {
5075
- const result = ClaudecodeSubagentFrontmatterSchema.safeParse(frontmatter);
5076
- if (!result.success) {
5077
- throw result.error;
5381
+ fromFile: (params) => WarpRule.fromFile(params),
5382
+ extension: "md"
5078
5383
  }
5079
- }
5080
- super({
5081
- ...rest
5082
5384
  });
5083
- this.frontmatter = frontmatter;
5084
- this.body = body;
5085
- }
5086
- static getSettablePaths() {
5087
- return {
5088
- relativeDirPath: ".claude/agents"
5089
- };
5090
5385
  }
5091
- getFrontmatter() {
5092
- return this.frontmatter;
5093
- }
5094
- getBody() {
5095
- return this.body;
5386
+ /**
5387
+ * Load Amazon Q Developer CLI rule configurations from .amazonq/rules/ directory
5388
+ */
5389
+ async loadAmazonqcliRules() {
5390
+ const settablePaths = AmazonQCliRule.getSettablePaths();
5391
+ return await this.loadToolRulesDefault({
5392
+ nonRoot: {
5393
+ relativeDirPath: settablePaths.nonRoot.relativeDirPath,
5394
+ fromFile: (params) => AmazonQCliRule.fromFile(params),
5395
+ extension: "md"
5396
+ }
5397
+ });
5096
5398
  }
5097
- toRulesyncSubagent() {
5098
- const rulesyncFrontmatter = {
5099
- targets: ["claudecode"],
5100
- name: this.frontmatter.name,
5101
- description: this.frontmatter.description,
5102
- ...this.frontmatter.model && {
5103
- claudecode: {
5104
- model: this.frontmatter.model
5105
- }
5399
+ /**
5400
+ * Load AugmentCode rule configurations from .augment/rules/ directory
5401
+ */
5402
+ async loadAugmentcodeRules() {
5403
+ const settablePaths = AugmentcodeRule.getSettablePaths();
5404
+ return await this.loadToolRulesDefault({
5405
+ nonRoot: {
5406
+ relativeDirPath: settablePaths.nonRoot.relativeDirPath,
5407
+ fromFile: (params) => AugmentcodeRule.fromFile(params),
5408
+ extension: "md"
5106
5409
  }
5107
- };
5108
- const fileContent = stringifyFrontmatter(this.body, rulesyncFrontmatter);
5109
- return new RulesyncSubagent({
5110
- frontmatter: rulesyncFrontmatter,
5111
- body: this.body,
5112
- baseDir: this.baseDir,
5113
- relativeDirPath: ".rulesync/subagents",
5114
- relativeFilePath: this.getRelativeFilePath(),
5115
- fileContent,
5116
- validate: true
5117
5410
  });
5118
5411
  }
5119
- static fromRulesyncSubagent({
5120
- baseDir = ".",
5121
- rulesyncSubagent,
5122
- validate = true
5123
- }) {
5124
- const rulesyncFrontmatter = rulesyncSubagent.getFrontmatter();
5125
- const claudecodeFrontmatter = {
5126
- name: rulesyncFrontmatter.name,
5127
- description: rulesyncFrontmatter.description,
5128
- model: rulesyncFrontmatter.claudecode?.model
5129
- };
5130
- const body = rulesyncSubagent.getBody();
5131
- const fileContent = stringifyFrontmatter(body, claudecodeFrontmatter);
5132
- return new _ClaudecodeSubagent({
5133
- baseDir,
5134
- frontmatter: claudecodeFrontmatter,
5135
- body,
5136
- relativeDirPath: ".claude/agents",
5137
- relativeFilePath: rulesyncSubagent.getRelativeFilePath(),
5138
- fileContent,
5139
- validate
5412
+ /**
5413
+ * Load AugmentCode legacy rule configuration from .augment-guidelines file and .augment/rules/ directory
5414
+ */
5415
+ async loadAugmentcodeLegacyRules() {
5416
+ const settablePaths = AugmentcodeLegacyRule.getSettablePaths();
5417
+ return await this.loadToolRulesDefault({
5418
+ root: {
5419
+ relativeDirPath: settablePaths.root.relativeDirPath,
5420
+ relativeFilePath: settablePaths.root.relativeFilePath,
5421
+ fromFile: (params) => AugmentcodeLegacyRule.fromFile(params)
5422
+ },
5423
+ nonRoot: {
5424
+ relativeDirPath: settablePaths.nonRoot.relativeDirPath,
5425
+ fromFile: (params) => AugmentcodeLegacyRule.fromFile(params),
5426
+ extension: "md"
5427
+ }
5140
5428
  });
5141
5429
  }
5142
- validate() {
5143
- if (!this.frontmatter) {
5144
- return { success: true, error: null };
5145
- }
5146
- const result = ClaudecodeSubagentFrontmatterSchema.safeParse(this.frontmatter);
5147
- if (result.success) {
5148
- return { success: true, error: null };
5149
- } else {
5150
- return { success: false, error: result.error };
5151
- }
5430
+ /**
5431
+ * Load Claude Code rule configuration from CLAUDE.md file
5432
+ */
5433
+ async loadClaudecodeRules() {
5434
+ const settablePaths = ClaudecodeRule.getSettablePaths();
5435
+ return await this.loadToolRulesDefault({
5436
+ root: {
5437
+ relativeDirPath: settablePaths.root.relativeDirPath,
5438
+ relativeFilePath: settablePaths.root.relativeFilePath,
5439
+ fromFile: (params) => ClaudecodeRule.fromFile(params)
5440
+ },
5441
+ nonRoot: {
5442
+ relativeDirPath: settablePaths.nonRoot.relativeDirPath,
5443
+ fromFile: (params) => ClaudecodeRule.fromFile(params),
5444
+ extension: "md"
5445
+ }
5446
+ });
5152
5447
  }
5153
- static async fromFile({
5154
- baseDir = ".",
5155
- relativeFilePath,
5156
- validate = true
5157
- }) {
5158
- const fileContent = await readFileContent(join51(baseDir, ".claude/agents", relativeFilePath));
5159
- const { frontmatter, body: content } = parseFrontmatter(fileContent);
5160
- const result = ClaudecodeSubagentFrontmatterSchema.safeParse(frontmatter);
5161
- if (!result.success) {
5162
- throw new Error(`Invalid frontmatter in ${relativeFilePath}: ${result.error.message}`);
5163
- }
5164
- return new _ClaudecodeSubagent({
5165
- baseDir,
5166
- relativeDirPath: ".claude/agents",
5167
- relativeFilePath,
5168
- frontmatter: result.data,
5169
- body: content.trim(),
5170
- fileContent,
5171
- validate
5448
+ /**
5449
+ * Load Cline rule configurations from .clinerules/ directory
5450
+ */
5451
+ async loadClineRules() {
5452
+ const settablePaths = ClineRule.getSettablePaths();
5453
+ return await this.loadToolRulesDefault({
5454
+ nonRoot: {
5455
+ relativeDirPath: settablePaths.nonRoot.relativeDirPath,
5456
+ fromFile: (params) => ClineRule.fromFile(params),
5457
+ extension: "md"
5458
+ }
5172
5459
  });
5173
5460
  }
5174
- };
5175
-
5176
- // src/subagents/subagents-processor.ts
5177
- var subagentsProcessorToolTargets = [
5178
- "claudecode",
5179
- "copilot",
5180
- "cursor",
5181
- "codexcli"
5182
- ];
5183
- var subagentsProcessorToolTargetsSimulated = [
5184
- "copilot",
5185
- "cursor",
5186
- "codexcli"
5187
- ];
5188
- var SubagentsProcessorToolTargetSchema = z21.enum(subagentsProcessorToolTargets);
5189
- var SubagentsProcessor = class extends FeatureProcessor {
5190
- toolTarget;
5191
- constructor({
5192
- baseDir = ".",
5193
- toolTarget
5194
- }) {
5195
- super({ baseDir });
5196
- this.toolTarget = SubagentsProcessorToolTargetSchema.parse(toolTarget);
5461
+ /**
5462
+ * Load OpenAI Codex CLI rule configuration from AGENTS.md and .codex/memories/*.md files
5463
+ */
5464
+ async loadCodexcliRules() {
5465
+ const settablePaths = CodexcliRule.getSettablePaths();
5466
+ return await this.loadToolRulesDefault({
5467
+ root: {
5468
+ relativeDirPath: settablePaths.root.relativeDirPath,
5469
+ relativeFilePath: settablePaths.root.relativeFilePath,
5470
+ fromFile: (params) => CodexcliRule.fromFile(params)
5471
+ },
5472
+ nonRoot: {
5473
+ relativeDirPath: settablePaths.nonRoot.relativeDirPath,
5474
+ fromFile: (params) => CodexcliRule.fromFile(params),
5475
+ extension: "md"
5476
+ }
5477
+ });
5197
5478
  }
5198
- async convertRulesyncFilesToToolFiles(rulesyncFiles) {
5199
- const rulesyncSubagents = rulesyncFiles.filter(
5200
- (file) => file instanceof RulesyncSubagent
5201
- );
5202
- const toolSubagents = rulesyncSubagents.map((rulesyncSubagent) => {
5203
- switch (this.toolTarget) {
5204
- case "claudecode":
5205
- return ClaudecodeSubagent.fromRulesyncSubagent({
5206
- baseDir: this.baseDir,
5207
- relativeDirPath: RulesyncSubagent.getSettablePaths().relativeDirPath,
5208
- rulesyncSubagent
5209
- });
5210
- case "copilot":
5211
- return CopilotSubagent.fromRulesyncSubagent({
5212
- baseDir: this.baseDir,
5213
- relativeDirPath: RulesyncSubagent.getSettablePaths().relativeDirPath,
5214
- rulesyncSubagent
5215
- });
5216
- case "cursor":
5217
- return CursorSubagent.fromRulesyncSubagent({
5218
- baseDir: this.baseDir,
5219
- relativeDirPath: RulesyncSubagent.getSettablePaths().relativeDirPath,
5220
- rulesyncSubagent
5221
- });
5222
- case "codexcli":
5223
- return CodexCliSubagent.fromRulesyncSubagent({
5224
- baseDir: this.baseDir,
5225
- relativeDirPath: RulesyncSubagent.getSettablePaths().relativeDirPath,
5226
- rulesyncSubagent
5227
- });
5228
- default:
5229
- throw new Error(`Unsupported tool target: ${this.toolTarget}`);
5479
+ /**
5480
+ * Load GitHub Copilot rule configuration from .github/copilot-instructions.md file
5481
+ */
5482
+ async loadCopilotRules() {
5483
+ const settablePaths = CopilotRule.getSettablePaths();
5484
+ return await this.loadToolRulesDefault({
5485
+ root: {
5486
+ relativeDirPath: settablePaths.root.relativeDirPath,
5487
+ relativeFilePath: settablePaths.root.relativeFilePath,
5488
+ fromFile: (params) => CopilotRule.fromFile(params)
5489
+ },
5490
+ nonRoot: {
5491
+ relativeDirPath: settablePaths.nonRoot.relativeDirPath,
5492
+ fromFile: (params) => CopilotRule.fromFile(params),
5493
+ extension: "md"
5230
5494
  }
5231
5495
  });
5232
- return toolSubagents;
5233
5496
  }
5234
- async convertToolFilesToRulesyncFiles(toolFiles) {
5235
- const toolSubagents = toolFiles.filter(
5236
- (file) => file instanceof ToolSubagent
5237
- );
5238
- const rulesyncSubagents = [];
5239
- for (const toolSubagent of toolSubagents) {
5240
- if (toolSubagent instanceof SimulatedSubagent) {
5241
- logger.debug(
5242
- `Skipping simulated subagent conversion: ${toolSubagent.getRelativeFilePath()}`
5243
- );
5244
- continue;
5497
+ /**
5498
+ * Load Cursor rule configurations from .cursor/rules/ directory
5499
+ */
5500
+ async loadCursorRules() {
5501
+ const settablePaths = CursorRule.getSettablePaths();
5502
+ return await this.loadToolRulesDefault({
5503
+ nonRoot: {
5504
+ relativeDirPath: settablePaths.nonRoot.relativeDirPath,
5505
+ fromFile: (params) => CursorRule.fromFile(params),
5506
+ extension: "mdc"
5245
5507
  }
5246
- rulesyncSubagents.push(toolSubagent.toRulesyncSubagent());
5247
- }
5248
- return rulesyncSubagents;
5508
+ });
5249
5509
  }
5250
5510
  /**
5251
- * Implementation of abstract method from Processor
5252
- * Load and parse rulesync subagent files from .rulesync/subagents/ directory
5511
+ * Load Gemini CLI rule configuration from GEMINI.md file
5253
5512
  */
5254
- async loadRulesyncFiles() {
5255
- const subagentsDir = join52(this.baseDir, RulesyncSubagent.getSettablePaths().relativeDirPath);
5256
- const dirExists = await directoryExists(subagentsDir);
5257
- if (!dirExists) {
5258
- logger.debug(`Rulesync subagents directory not found: ${subagentsDir}`);
5259
- return [];
5260
- }
5261
- const entries = await listDirectoryFiles(subagentsDir);
5262
- const mdFiles = entries.filter((file) => file.endsWith(".md"));
5263
- if (mdFiles.length === 0) {
5264
- logger.debug(`No markdown files found in rulesync subagents directory: ${subagentsDir}`);
5265
- return [];
5266
- }
5267
- logger.info(`Found ${mdFiles.length} subagent files in ${subagentsDir}`);
5268
- const rulesyncSubagents = [];
5269
- for (const mdFile of mdFiles) {
5270
- const filepath = join52(subagentsDir, mdFile);
5271
- try {
5272
- const rulesyncSubagent = await RulesyncSubagent.fromFile({
5273
- relativeFilePath: mdFile,
5274
- validate: true
5275
- });
5276
- rulesyncSubagents.push(rulesyncSubagent);
5277
- logger.debug(`Successfully loaded subagent: ${mdFile}`);
5278
- } catch (error) {
5279
- logger.warn(`Failed to load subagent file ${filepath}:`, error);
5280
- continue;
5513
+ async loadGeminicliRules() {
5514
+ const settablePaths = GeminiCliRule.getSettablePaths();
5515
+ return await this.loadToolRulesDefault({
5516
+ root: {
5517
+ relativeDirPath: settablePaths.root.relativeDirPath,
5518
+ relativeFilePath: settablePaths.root.relativeFilePath,
5519
+ fromFile: (params) => GeminiCliRule.fromFile(params)
5520
+ },
5521
+ nonRoot: {
5522
+ relativeDirPath: settablePaths.nonRoot.relativeDirPath,
5523
+ fromFile: (params) => GeminiCliRule.fromFile(params),
5524
+ extension: "md"
5281
5525
  }
5282
- }
5283
- if (rulesyncSubagents.length === 0) {
5284
- logger.debug(`No valid subagents found in ${subagentsDir}`);
5285
- return [];
5286
- }
5287
- logger.info(`Successfully loaded ${rulesyncSubagents.length} rulesync subagents`);
5288
- return rulesyncSubagents;
5526
+ });
5289
5527
  }
5290
5528
  /**
5291
- * Implementation of abstract method from Processor
5292
- * Load tool-specific subagent configurations and parse them into ToolSubagent instances
5529
+ * Load JetBrains Junie rule configuration from .junie/guidelines.md file
5293
5530
  */
5294
- async loadToolFiles() {
5295
- switch (this.toolTarget) {
5296
- case "claudecode":
5297
- return await this.loadClaudecodeSubagents();
5298
- case "copilot":
5299
- return await this.loadCopilotSubagents();
5300
- case "cursor":
5301
- return await this.loadCursorSubagents();
5302
- case "codexcli":
5303
- return await this.loadCodexCliSubagents();
5304
- default:
5305
- throw new Error(`Unsupported tool target: ${this.toolTarget}`);
5306
- }
5531
+ async loadJunieRules() {
5532
+ const settablePaths = JunieRule.getSettablePaths();
5533
+ return await this.loadToolRulesDefault({
5534
+ root: {
5535
+ relativeDirPath: settablePaths.root.relativeDirPath,
5536
+ relativeFilePath: settablePaths.root.relativeFilePath,
5537
+ fromFile: (params) => JunieRule.fromFile(params)
5538
+ },
5539
+ nonRoot: {
5540
+ relativeDirPath: settablePaths.nonRoot.relativeDirPath,
5541
+ fromFile: (params) => JunieRule.fromFile(params),
5542
+ extension: "md"
5543
+ }
5544
+ });
5307
5545
  }
5308
5546
  /**
5309
- * Load Claude Code subagent configurations from .claude/agents/ directory
5547
+ * Load Kiro rule configurations from .kiro/steering/ directory
5310
5548
  */
5311
- async loadClaudecodeSubagents() {
5312
- return await this.loadToolSubagentsDefault({
5313
- relativeDirPath: ClaudecodeSubagent.getSettablePaths().relativeDirPath,
5314
- fromFile: (relativeFilePath) => ClaudecodeSubagent.fromFile({ relativeFilePath })
5549
+ async loadKiroRules() {
5550
+ const settablePaths = KiroRule.getSettablePaths();
5551
+ return await this.loadToolRulesDefault({
5552
+ nonRoot: {
5553
+ relativeDirPath: settablePaths.nonRoot.relativeDirPath,
5554
+ fromFile: (params) => KiroRule.fromFile(params),
5555
+ extension: "md"
5556
+ }
5315
5557
  });
5316
5558
  }
5317
5559
  /**
5318
- * Load Copilot subagent configurations from .copilot/subagents/ directory
5560
+ * Load OpenCode rule configuration from AGENTS.md file and .opencode/memories/*.md files
5319
5561
  */
5320
- async loadCopilotSubagents() {
5321
- return await this.loadToolSubagentsDefault({
5322
- relativeDirPath: CopilotSubagent.getSettablePaths().relativeDirPath,
5323
- fromFile: (relativeFilePath) => CopilotSubagent.fromFile({ relativeFilePath })
5562
+ async loadOpencodeRules() {
5563
+ const settablePaths = OpenCodeRule.getSettablePaths();
5564
+ return await this.loadToolRulesDefault({
5565
+ root: {
5566
+ relativeDirPath: settablePaths.root.relativeDirPath,
5567
+ relativeFilePath: settablePaths.root.relativeFilePath,
5568
+ fromFile: (params) => OpenCodeRule.fromFile(params)
5569
+ },
5570
+ nonRoot: {
5571
+ relativeDirPath: settablePaths.nonRoot.relativeDirPath,
5572
+ fromFile: (params) => OpenCodeRule.fromFile(params),
5573
+ extension: "md"
5574
+ }
5324
5575
  });
5325
5576
  }
5326
5577
  /**
5327
- * Load Cursor subagent configurations from .cursor/subagents/ directory
5578
+ * Load Qwen Code rule configuration from QWEN.md file and .qwen/memories/*.md files
5328
5579
  */
5329
- async loadCursorSubagents() {
5330
- return await this.loadToolSubagentsDefault({
5331
- relativeDirPath: CursorSubagent.getSettablePaths().relativeDirPath,
5332
- fromFile: (relativeFilePath) => CursorSubagent.fromFile({ relativeFilePath })
5580
+ async loadQwencodeRules() {
5581
+ const settablePaths = QwencodeRule.getSettablePaths();
5582
+ return await this.loadToolRulesDefault({
5583
+ root: {
5584
+ relativeDirPath: settablePaths.root.relativeDirPath,
5585
+ relativeFilePath: settablePaths.root.relativeFilePath,
5586
+ fromFile: (params) => QwencodeRule.fromFile(params)
5587
+ },
5588
+ nonRoot: {
5589
+ relativeDirPath: settablePaths.nonRoot.relativeDirPath,
5590
+ fromFile: (params) => QwencodeRule.fromFile(params),
5591
+ extension: "md"
5592
+ }
5333
5593
  });
5334
5594
  }
5335
5595
  /**
5336
- * Load CodexCli subagent configurations from .codex/subagents/ directory
5596
+ * Load Roo Code rule configurations from .roo/rules/ directory
5337
5597
  */
5338
- async loadCodexCliSubagents() {
5339
- return await this.loadToolSubagentsDefault({
5340
- relativeDirPath: CodexCliSubagent.getSettablePaths().relativeDirPath,
5341
- fromFile: (relativeFilePath) => CodexCliSubagent.fromFile({ relativeFilePath })
5598
+ async loadRooRules() {
5599
+ const settablePaths = RooRule.getSettablePaths();
5600
+ return await this.loadToolRulesDefault({
5601
+ nonRoot: {
5602
+ relativeDirPath: settablePaths.nonRoot.relativeDirPath,
5603
+ fromFile: (params) => RooRule.fromFile(params),
5604
+ extension: "md"
5605
+ }
5342
5606
  });
5343
5607
  }
5344
- async loadToolSubagentsDefault({
5345
- relativeDirPath,
5346
- fromFile
5347
- }) {
5348
- const paths = await findFilesByGlobs(join52(this.baseDir, relativeDirPath, "*.md"));
5349
- const subagents = (await Promise.allSettled(paths.map((path2) => fromFile(basename16(path2))))).filter((r) => r.status === "fulfilled").map((r) => r.value);
5350
- logger.info(`Successfully loaded ${subagents.length} ${relativeDirPath} subagents`);
5351
- return subagents;
5608
+ /**
5609
+ * Load Windsurf rule configurations from .windsurf/rules/ directory
5610
+ */
5611
+ async loadWindsurfRules() {
5612
+ const settablePaths = WindsurfRule.getSettablePaths();
5613
+ return await this.loadToolRulesDefault({
5614
+ nonRoot: {
5615
+ relativeDirPath: settablePaths.nonRoot.relativeDirPath,
5616
+ fromFile: (params) => WindsurfRule.fromFile(params),
5617
+ extension: "md"
5618
+ }
5619
+ });
5352
5620
  }
5353
5621
  /**
5354
5622
  * Implementation of abstract method from FeatureProcessor
5355
5623
  * Return the tool targets that this processor supports
5356
5624
  */
5357
- static getToolTargets({
5358
- includeSimulated = false
5359
- } = {}) {
5360
- if (!includeSimulated) {
5361
- return subagentsProcessorToolTargets.filter(
5362
- (target) => !subagentsProcessorToolTargetsSimulated.includes(target)
5625
+ static getToolTargets() {
5626
+ return rulesProcessorToolTargets;
5627
+ }
5628
+ generateXmlReferencesSection(toolRules) {
5629
+ const toolRulesWithoutRoot = toolRules.filter((rule) => !rule.isRoot());
5630
+ if (toolRulesWithoutRoot.length === 0) {
5631
+ return "";
5632
+ }
5633
+ const lines = [];
5634
+ lines.push(
5635
+ "Please also reference the following documents as needed. In this case, `@` stands for the project root directory."
5636
+ );
5637
+ lines.push("");
5638
+ const documentsData = {
5639
+ Documents: {
5640
+ Document: toolRulesWithoutRoot.map((rule) => {
5641
+ const rulesyncRule = rule.toRulesyncRule();
5642
+ const frontmatter = rulesyncRule.getFrontmatter();
5643
+ const relativePath = `@${rule.getRelativePathFromCwd()}`;
5644
+ const document = {
5645
+ Path: relativePath
5646
+ };
5647
+ if (frontmatter.description) {
5648
+ document.Description = frontmatter.description;
5649
+ }
5650
+ if (frontmatter.globs && frontmatter.globs.length > 0) {
5651
+ document.FilePatterns = frontmatter.globs.join(", ");
5652
+ }
5653
+ return document;
5654
+ })
5655
+ }
5656
+ };
5657
+ const builder = new XMLBuilder({
5658
+ format: true,
5659
+ ignoreAttributes: false,
5660
+ suppressEmptyNode: false
5661
+ });
5662
+ const xmlContent = builder.build(documentsData);
5663
+ lines.push(xmlContent);
5664
+ return lines.join("\n") + "\n";
5665
+ }
5666
+ generateReferencesSection(toolRules) {
5667
+ const toolRulesWithoutRoot = toolRules.filter((rule) => !rule.isRoot());
5668
+ if (toolRulesWithoutRoot.length === 0) {
5669
+ return "";
5670
+ }
5671
+ const lines = [];
5672
+ lines.push("Please also reference the following documents as needed:");
5673
+ lines.push("");
5674
+ for (const rule of toolRulesWithoutRoot) {
5675
+ const rulesyncRule = rule.toRulesyncRule();
5676
+ const frontmatter = rulesyncRule.getFrontmatter();
5677
+ const escapedDescription = frontmatter.description?.replace(/"/g, '\\"');
5678
+ const globsText = frontmatter.globs?.join(",");
5679
+ lines.push(
5680
+ `@${rule.getRelativePathFromCwd()} description: "${escapedDescription}" globs: "${globsText}"`
5363
5681
  );
5364
5682
  }
5365
- return subagentsProcessorToolTargets;
5683
+ return lines.join("\n") + "\n";
5684
+ }
5685
+ generateAdditionalConventionsSection({
5686
+ commands,
5687
+ subagents
5688
+ }) {
5689
+ const overview = `# Additional Conventions Beyond the Built-in Functions
5690
+
5691
+ As this project's AI coding tool, you must follow the additional conventions below, in addition to the built-in functions.`;
5692
+ const commandsSection = `## Simulated Custom Slash Commands
5693
+
5694
+ Custom slash commands allow you to define frequently-used prompts as Markdown files that you can execute.
5695
+
5696
+ ### Syntax
5697
+
5698
+ Users can use following syntax to invoke a custom command.
5699
+
5700
+ \`\`\`txt
5701
+ s/<command> [arguments]
5702
+ \`\`\`
5703
+
5704
+ This syntax employs a double slash (\`s/\`) to prevent conflicts with built-in slash commands.
5705
+ The \`s\` in \`s/\` stands for *simulate*. Because custom slash commands are not built-in, this syntax provides a pseudo way to invoke them.
5706
+
5707
+ When users call a custom slash command, you have to look for the markdown file, \`${join52(commands.relativeDirPath, "{command}.md")}\`, then execute the contents of that file as the block of operations.`;
5708
+ const subagentsSection = `## Simulated Subagents
5709
+
5710
+ Simulated subagents are specialized AI assistants that can be invoked to handle specific types of tasks. In this case, it can be appear something like custom slash commands simply. Simulated subagents can be called by custom slash commands.
5711
+
5712
+ When users call a simulated subagent, it will look for the corresponding markdown file, \`${join52(subagents.relativeDirPath, "{subagent}.md")}\`, and execute its contents as the block of operations.
5713
+
5714
+ For example, if the user instructs \`Call planner subagent to plan the refactoring\`, you have to look for the markdown file, \`${join52(subagents.relativeDirPath, "planner.md")}\`, and execute its contents as the block of operations.`;
5715
+ const result = [
5716
+ overview,
5717
+ ...this.simulateCommands && CommandsProcessor.getToolTargetsSimulated().includes(this.toolTarget) ? [commandsSection] : [],
5718
+ ...this.simulateSubagents && SubagentsProcessor.getToolTargetsSimulated().includes(this.toolTarget) ? [subagentsSection] : []
5719
+ ].join("\n\n");
5720
+ return result;
5366
5721
  }
5367
5722
  };
5368
5723
 
@@ -5535,7 +5890,7 @@ async function generateCommand(options) {
5535
5890
  const parts = [];
5536
5891
  if (totalRulesOutputs > 0) parts.push(`${totalRulesOutputs} rules`);
5537
5892
  if (totalIgnoreOutputs > 0) parts.push(`${totalIgnoreOutputs} ignore files`);
5538
- if (totalMcpOutputs > 0) parts.push(`${totalMcpOutputs} MCPs`);
5893
+ if (totalMcpOutputs > 0) parts.push(`${totalMcpOutputs} MCP files`);
5539
5894
  if (totalCommandOutputs > 0) parts.push(`${totalCommandOutputs} commands`);
5540
5895
  if (totalSubagentOutputs > 0) parts.push(`${totalSubagentOutputs} subagents`);
5541
5896
  logger.success(`\u{1F389} All done! Generated ${totalGenerated} file(s) total (${parts.join(" + ")})`);
@@ -5567,6 +5922,7 @@ var gitignoreCommand = async () => {
5567
5922
  "**/GEMINI.md",
5568
5923
  "**/.gemini/memories/",
5569
5924
  "**/.gemini/commands/",
5925
+ "**/.gemini/subagents/",
5570
5926
  "**/QWEN.md",
5571
5927
  "**/.qwen/memories/",
5572
5928
  "**/.aiexclude",
@@ -5584,6 +5940,7 @@ var gitignoreCommand = async () => {
5584
5940
  "**/.cursor/mcp.json",
5585
5941
  "**/.cline/mcp.json",
5586
5942
  "**/.roo/mcp.json",
5943
+ "**/.roo/subagents/",
5587
5944
  "**/.vscode/mcp.json",
5588
5945
  "**/.github/commands/",
5589
5946
  "**/.github/subagents/",
@@ -5608,8 +5965,8 @@ var gitignoreCommand = async () => {
5608
5965
  }
5609
5966
  const newContent = gitignoreContent ? `${gitignoreContent.trimEnd()}
5610
5967
 
5611
- ${linesToAdd.join("")}
5612
- ` : `${linesToAdd.join("")}
5968
+ ${linesToAdd.join("\n")}
5969
+ ` : `${linesToAdd.join("\n")}
5613
5970
  `;
5614
5971
  await writeFileContent(gitignorePath, newContent);
5615
5972
  logger.success(`Added ${linesToAdd.length} rules to .gitignore:`);
@@ -5805,7 +6162,7 @@ var getVersion = async () => {
5805
6162
  const packageJson = await readJsonFile(packageJsonPath);
5806
6163
  return packageJson.version;
5807
6164
  } catch {
5808
- return "0.74.0";
6165
+ return "0.76.0";
5809
6166
  }
5810
6167
  };
5811
6168
  var main = async () => {
@@ -5827,7 +6184,7 @@ var main = async () => {
5827
6184
  }
5828
6185
  ).option(
5829
6186
  "-f, --features <features>",
5830
- `Comma-separated list of features to import (${FEATURE_TYPES.join(",")}) or '*' for all`,
6187
+ `Comma-separated list of features to import (${ALL_FEATURES.join(",")}) or '*' for all`,
5831
6188
  (value) => {
5832
6189
  return value.split(",").map((f) => f.trim());
5833
6190
  }
@@ -5852,7 +6209,7 @@ var main = async () => {
5852
6209
  }
5853
6210
  ).option(
5854
6211
  "-f, --features <features>",
5855
- `Comma-separated list of features to generate (${FEATURE_TYPES.join(",")}) or '*' for all`,
6212
+ `Comma-separated list of features to generate (${ALL_FEATURES.join(",")}) or '*' for all`,
5856
6213
  (value) => {
5857
6214
  return value.split(",").map((f) => f.trim());
5858
6215
  }