rulesync 3.5.2 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3100,8 +3100,82 @@ var CursorMcp = class _CursorMcp extends ToolMcp {
3100
3100
  }
3101
3101
  };
3102
3102
 
3103
- // src/mcp/roo-mcp.ts
3103
+ // src/mcp/geminicli-mcp.ts
3104
3104
  import { join as join31 } from "path";
3105
+ var GeminiCliMcp = class _GeminiCliMcp extends ToolMcp {
3106
+ json;
3107
+ constructor(params) {
3108
+ super(params);
3109
+ this.json = JSON.parse(this.fileContent || "{}");
3110
+ }
3111
+ getJson() {
3112
+ return this.json;
3113
+ }
3114
+ static getSettablePaths({ global } = {}) {
3115
+ if (global) {
3116
+ return {
3117
+ relativeDirPath: ".gemini",
3118
+ relativeFilePath: "settings.json"
3119
+ };
3120
+ }
3121
+ return {
3122
+ relativeDirPath: ".gemini",
3123
+ relativeFilePath: "settings.json"
3124
+ };
3125
+ }
3126
+ static async fromFile({
3127
+ baseDir = ".",
3128
+ validate = true,
3129
+ global = false
3130
+ }) {
3131
+ const paths = this.getSettablePaths({ global });
3132
+ const fileContent = await readOrInitializeFileContent(
3133
+ join31(baseDir, paths.relativeDirPath, paths.relativeFilePath),
3134
+ JSON.stringify({ mcpServers: {} }, null, 2)
3135
+ );
3136
+ const json = JSON.parse(fileContent);
3137
+ const newJson = { ...json, mcpServers: json.mcpServers ?? {} };
3138
+ return new _GeminiCliMcp({
3139
+ baseDir,
3140
+ relativeDirPath: paths.relativeDirPath,
3141
+ relativeFilePath: paths.relativeFilePath,
3142
+ fileContent: JSON.stringify(newJson, null, 2),
3143
+ validate
3144
+ });
3145
+ }
3146
+ static async fromRulesyncMcp({
3147
+ baseDir = ".",
3148
+ rulesyncMcp,
3149
+ validate = true,
3150
+ global = false
3151
+ }) {
3152
+ const paths = this.getSettablePaths({ global });
3153
+ const fileContent = await readOrInitializeFileContent(
3154
+ join31(baseDir, paths.relativeDirPath, paths.relativeFilePath),
3155
+ JSON.stringify({ mcpServers: {} }, null, 2)
3156
+ );
3157
+ const json = JSON.parse(fileContent);
3158
+ const newJson = { ...json, mcpServers: rulesyncMcp.getJson().mcpServers };
3159
+ return new _GeminiCliMcp({
3160
+ baseDir,
3161
+ relativeDirPath: paths.relativeDirPath,
3162
+ relativeFilePath: paths.relativeFilePath,
3163
+ fileContent: JSON.stringify(newJson, null, 2),
3164
+ validate
3165
+ });
3166
+ }
3167
+ toRulesyncMcp() {
3168
+ return this.toRulesyncMcpDefault({
3169
+ fileContent: JSON.stringify({ mcpServers: this.json.mcpServers }, null, 2)
3170
+ });
3171
+ }
3172
+ validate() {
3173
+ return { success: true, error: null };
3174
+ }
3175
+ };
3176
+
3177
+ // src/mcp/roo-mcp.ts
3178
+ import { join as join32 } from "path";
3105
3179
  var RooMcp = class _RooMcp extends ToolMcp {
3106
3180
  json;
3107
3181
  constructor(params) {
@@ -3122,7 +3196,7 @@ var RooMcp = class _RooMcp extends ToolMcp {
3122
3196
  validate = true
3123
3197
  }) {
3124
3198
  const fileContent = await readFileContent(
3125
- join31(
3199
+ join32(
3126
3200
  baseDir,
3127
3201
  this.getSettablePaths().relativeDirPath,
3128
3202
  this.getSettablePaths().relativeFilePath
@@ -3165,13 +3239,14 @@ var mcpProcessorToolTargets = [
3165
3239
  "cline",
3166
3240
  "copilot",
3167
3241
  "cursor",
3242
+ "geminicli",
3168
3243
  "roo"
3169
3244
  ];
3170
3245
  var McpProcessorToolTargetSchema = z12.enum(
3171
3246
  // codexcli is not in the list of tool targets but we add it here because it is a valid tool target for global mode generation
3172
3247
  mcpProcessorToolTargets.concat("codexcli")
3173
3248
  );
3174
- var mcpProcessorToolTargetsGlobal = ["claudecode", "codexcli"];
3249
+ var mcpProcessorToolTargetsGlobal = ["claudecode", "codexcli", "geminicli"];
3175
3250
  var McpProcessor = class extends FeatureProcessor {
3176
3251
  toolTarget;
3177
3252
  global;
@@ -3268,6 +3343,15 @@ var McpProcessor = class extends FeatureProcessor {
3268
3343
  })
3269
3344
  ];
3270
3345
  }
3346
+ case "geminicli": {
3347
+ return [
3348
+ await GeminiCliMcp.fromFile({
3349
+ baseDir: this.baseDir,
3350
+ validate: true,
3351
+ global: this.global
3352
+ })
3353
+ ];
3354
+ }
3271
3355
  case "roo": {
3272
3356
  return [
3273
3357
  await RooMcp.fromFile({
@@ -3333,6 +3417,12 @@ var McpProcessor = class extends FeatureProcessor {
3333
3417
  rulesyncMcp: rulesyncMcp2,
3334
3418
  global: this.global
3335
3419
  });
3420
+ case "geminicli":
3421
+ return GeminiCliMcp.fromRulesyncMcp({
3422
+ baseDir: this.baseDir,
3423
+ rulesyncMcp: rulesyncMcp2,
3424
+ global: this.global
3425
+ });
3336
3426
  case "roo":
3337
3427
  return RooMcp.fromRulesyncMcp({
3338
3428
  baseDir: this.baseDir,
@@ -3369,12 +3459,12 @@ var McpProcessor = class extends FeatureProcessor {
3369
3459
  };
3370
3460
 
3371
3461
  // src/rules/rules-processor.ts
3372
- import { basename as basename17, join as join55 } from "path";
3462
+ import { basename as basename17, join as join56 } from "path";
3373
3463
  import { XMLBuilder } from "fast-xml-parser";
3374
3464
  import { z as z21 } from "zod/mini";
3375
3465
 
3376
3466
  // src/subagents/simulated-subagent.ts
3377
- import { basename as basename12, join as join32 } from "path";
3467
+ import { basename as basename12, join as join33 } from "path";
3378
3468
  import { z as z13 } from "zod/mini";
3379
3469
 
3380
3470
  // src/subagents/tool-subagent.ts
@@ -3422,7 +3512,7 @@ var SimulatedSubagent = class extends ToolSubagent {
3422
3512
  const result = SimulatedSubagentFrontmatterSchema.safeParse(frontmatter);
3423
3513
  if (!result.success) {
3424
3514
  throw new Error(
3425
- `Invalid frontmatter in ${join32(rest.relativeDirPath, rest.relativeFilePath)}: ${result.error.message}`
3515
+ `Invalid frontmatter in ${join33(rest.relativeDirPath, rest.relativeFilePath)}: ${result.error.message}`
3426
3516
  );
3427
3517
  }
3428
3518
  }
@@ -3473,7 +3563,7 @@ var SimulatedSubagent = class extends ToolSubagent {
3473
3563
  return {
3474
3564
  success: false,
3475
3565
  error: new Error(
3476
- `Invalid frontmatter in ${join32(this.relativeDirPath, this.relativeFilePath)}: ${result.error.message}`
3566
+ `Invalid frontmatter in ${join33(this.relativeDirPath, this.relativeFilePath)}: ${result.error.message}`
3477
3567
  )
3478
3568
  };
3479
3569
  }
@@ -3483,7 +3573,7 @@ var SimulatedSubagent = class extends ToolSubagent {
3483
3573
  relativeFilePath,
3484
3574
  validate = true
3485
3575
  }) {
3486
- const filePath = join32(baseDir, this.getSettablePaths().relativeDirPath, relativeFilePath);
3576
+ const filePath = join33(baseDir, this.getSettablePaths().relativeDirPath, relativeFilePath);
3487
3577
  const fileContent = await readFileContent(filePath);
3488
3578
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
3489
3579
  const result = SimulatedSubagentFrontmatterSchema.safeParse(frontmatter);
@@ -3640,15 +3730,15 @@ var RooSubagent = class _RooSubagent extends SimulatedSubagent {
3640
3730
  };
3641
3731
 
3642
3732
  // src/subagents/subagents-processor.ts
3643
- import { basename as basename14, join as join35 } from "path";
3733
+ import { basename as basename14, join as join36 } from "path";
3644
3734
  import { z as z16 } from "zod/mini";
3645
3735
 
3646
3736
  // src/subagents/claudecode-subagent.ts
3647
- import { join as join34 } from "path";
3737
+ import { join as join35 } from "path";
3648
3738
  import { z as z15 } from "zod/mini";
3649
3739
 
3650
3740
  // src/subagents/rulesync-subagent.ts
3651
- import { basename as basename13, join as join33 } from "path";
3741
+ import { basename as basename13, join as join34 } from "path";
3652
3742
  import { z as z14 } from "zod/mini";
3653
3743
  var RulesyncSubagentModelSchema = z14.enum(["opus", "sonnet", "haiku", "inherit"]);
3654
3744
  var RulesyncSubagentFrontmatterSchema = z14.object({
@@ -3669,7 +3759,7 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
3669
3759
  const result = RulesyncSubagentFrontmatterSchema.safeParse(frontmatter);
3670
3760
  if (!result.success) {
3671
3761
  throw new Error(
3672
- `Invalid frontmatter in ${join33(rest.relativeDirPath, rest.relativeFilePath)}: ${result.error.message}`
3762
+ `Invalid frontmatter in ${join34(rest.relativeDirPath, rest.relativeFilePath)}: ${result.error.message}`
3673
3763
  );
3674
3764
  }
3675
3765
  }
@@ -3701,7 +3791,7 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
3701
3791
  return {
3702
3792
  success: false,
3703
3793
  error: new Error(
3704
- `Invalid frontmatter in ${join33(this.relativeDirPath, this.relativeFilePath)}: ${result.error.message}`
3794
+ `Invalid frontmatter in ${join34(this.relativeDirPath, this.relativeFilePath)}: ${result.error.message}`
3705
3795
  )
3706
3796
  };
3707
3797
  }
@@ -3709,7 +3799,7 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
3709
3799
  static async fromFile({
3710
3800
  relativeFilePath
3711
3801
  }) {
3712
- const fileContent = await readFileContent(join33(".rulesync/subagents", relativeFilePath));
3802
+ const fileContent = await readFileContent(join34(".rulesync/subagents", relativeFilePath));
3713
3803
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
3714
3804
  const result = RulesyncSubagentFrontmatterSchema.safeParse(frontmatter);
3715
3805
  if (!result.success) {
@@ -3741,7 +3831,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
3741
3831
  const result = ClaudecodeSubagentFrontmatterSchema.safeParse(frontmatter);
3742
3832
  if (!result.success) {
3743
3833
  throw new Error(
3744
- `Invalid frontmatter in ${join34(rest.relativeDirPath, rest.relativeFilePath)}: ${result.error.message}`
3834
+ `Invalid frontmatter in ${join35(rest.relativeDirPath, rest.relativeFilePath)}: ${result.error.message}`
3745
3835
  );
3746
3836
  }
3747
3837
  }
@@ -3753,7 +3843,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
3753
3843
  }
3754
3844
  static getSettablePaths(_options = {}) {
3755
3845
  return {
3756
- relativeDirPath: join34(".claude", "agents")
3846
+ relativeDirPath: join35(".claude", "agents")
3757
3847
  };
3758
3848
  }
3759
3849
  getFrontmatter() {
@@ -3821,7 +3911,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
3821
3911
  return {
3822
3912
  success: false,
3823
3913
  error: new Error(
3824
- `Invalid frontmatter in ${join34(this.relativeDirPath, this.relativeFilePath)}: ${result.error.message}`
3914
+ `Invalid frontmatter in ${join35(this.relativeDirPath, this.relativeFilePath)}: ${result.error.message}`
3825
3915
  )
3826
3916
  };
3827
3917
  }
@@ -3839,7 +3929,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
3839
3929
  global = false
3840
3930
  }) {
3841
3931
  const paths = this.getSettablePaths({ global });
3842
- const filePath = join34(baseDir, paths.relativeDirPath, relativeFilePath);
3932
+ const filePath = join35(baseDir, paths.relativeDirPath, relativeFilePath);
3843
3933
  const fileContent = await readFileContent(filePath);
3844
3934
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
3845
3935
  const result = ClaudecodeSubagentFrontmatterSchema.safeParse(frontmatter);
@@ -3993,7 +4083,7 @@ var SubagentsProcessor = class extends FeatureProcessor {
3993
4083
  * Load and parse rulesync subagent files from .rulesync/subagents/ directory
3994
4084
  */
3995
4085
  async loadRulesyncFiles() {
3996
- const subagentsDir = join35(RulesyncSubagent.getSettablePaths().relativeDirPath);
4086
+ const subagentsDir = join36(RulesyncSubagent.getSettablePaths().relativeDirPath);
3997
4087
  const dirExists = await directoryExists(subagentsDir);
3998
4088
  if (!dirExists) {
3999
4089
  logger.debug(`Rulesync subagents directory not found: ${subagentsDir}`);
@@ -4008,7 +4098,7 @@ var SubagentsProcessor = class extends FeatureProcessor {
4008
4098
  logger.info(`Found ${mdFiles.length} subagent files in ${subagentsDir}`);
4009
4099
  const rulesyncSubagents = [];
4010
4100
  for (const mdFile of mdFiles) {
4011
- const filepath = join35(subagentsDir, mdFile);
4101
+ const filepath = join36(subagentsDir, mdFile);
4012
4102
  try {
4013
4103
  const rulesyncSubagent = await RulesyncSubagent.fromFile({
4014
4104
  relativeFilePath: mdFile,
@@ -4127,7 +4217,7 @@ var SubagentsProcessor = class extends FeatureProcessor {
4127
4217
  relativeDirPath,
4128
4218
  fromFile
4129
4219
  }) {
4130
- const paths = await findFilesByGlobs(join35(this.baseDir, relativeDirPath, "*.md"));
4220
+ const paths = await findFilesByGlobs(join36(this.baseDir, relativeDirPath, "*.md"));
4131
4221
  const subagents = (await Promise.allSettled(paths.map((path2) => fromFile(basename14(path2))))).filter((r) => r.status === "fulfilled").map((r) => r.value);
4132
4222
  logger.info(`Successfully loaded ${subagents.length} ${relativeDirPath} subagents`);
4133
4223
  return subagents;
@@ -4155,13 +4245,13 @@ var SubagentsProcessor = class extends FeatureProcessor {
4155
4245
  };
4156
4246
 
4157
4247
  // src/rules/agentsmd-rule.ts
4158
- import { join as join38 } from "path";
4248
+ import { join as join39 } from "path";
4159
4249
 
4160
4250
  // src/rules/tool-rule.ts
4161
- import { join as join37 } from "path";
4251
+ import { join as join38 } from "path";
4162
4252
 
4163
4253
  // src/rules/rulesync-rule.ts
4164
- import { basename as basename15, join as join36 } from "path";
4254
+ import { basename as basename15, join as join37 } from "path";
4165
4255
  import { z as z17 } from "zod/mini";
4166
4256
  var RulesyncRuleFrontmatterSchema = z17.object({
4167
4257
  root: z17.optional(z17.optional(z17.boolean())),
@@ -4190,7 +4280,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
4190
4280
  const result = RulesyncRuleFrontmatterSchema.safeParse(frontmatter);
4191
4281
  if (!result.success) {
4192
4282
  throw new Error(
4193
- `Invalid frontmatter in ${join36(rest.relativeDirPath, rest.relativeFilePath)}: ${result.error.message}`
4283
+ `Invalid frontmatter in ${join37(rest.relativeDirPath, rest.relativeFilePath)}: ${result.error.message}`
4194
4284
  );
4195
4285
  }
4196
4286
  }
@@ -4225,7 +4315,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
4225
4315
  return {
4226
4316
  success: false,
4227
4317
  error: new Error(
4228
- `Invalid frontmatter in ${join36(this.relativeDirPath, this.relativeFilePath)}: ${result.error.message}`
4318
+ `Invalid frontmatter in ${join37(this.relativeDirPath, this.relativeFilePath)}: ${result.error.message}`
4229
4319
  )
4230
4320
  };
4231
4321
  }
@@ -4234,7 +4324,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
4234
4324
  relativeFilePath,
4235
4325
  validate = true
4236
4326
  }) {
4237
- const filePath = join36(this.getSettablePaths().legacy.relativeDirPath, relativeFilePath);
4327
+ const filePath = join37(this.getSettablePaths().legacy.relativeDirPath, relativeFilePath);
4238
4328
  const fileContent = await readFileContent(filePath);
4239
4329
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
4240
4330
  const result = RulesyncRuleFrontmatterSchema.safeParse(frontmatter);
@@ -4263,7 +4353,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
4263
4353
  relativeFilePath,
4264
4354
  validate = true
4265
4355
  }) {
4266
- const filePath = join36(this.getSettablePaths().recommended.relativeDirPath, relativeFilePath);
4356
+ const filePath = join37(this.getSettablePaths().recommended.relativeDirPath, relativeFilePath);
4267
4357
  const fileContent = await readFileContent(filePath);
4268
4358
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
4269
4359
  const result = RulesyncRuleFrontmatterSchema.safeParse(frontmatter);
@@ -4364,7 +4454,7 @@ var ToolRule = class extends ToolFile {
4364
4454
  });
4365
4455
  const rulesyncFrontmatter = rulesyncRule.getFrontmatter();
4366
4456
  if (!rulesyncFrontmatter.root && rulesyncFrontmatter.agentsmd?.subprojectPath) {
4367
- params.relativeDirPath = join37(rulesyncFrontmatter.agentsmd.subprojectPath);
4457
+ params.relativeDirPath = join38(rulesyncFrontmatter.agentsmd.subprojectPath);
4368
4458
  params.relativeFilePath = "AGENTS.md";
4369
4459
  }
4370
4460
  return params;
@@ -4440,8 +4530,8 @@ var AgentsMdRule = class _AgentsMdRule extends ToolRule {
4440
4530
  validate = true
4441
4531
  }) {
4442
4532
  const isRoot = relativeFilePath === "AGENTS.md";
4443
- const relativePath = isRoot ? "AGENTS.md" : join38(".agents/memories", relativeFilePath);
4444
- const fileContent = await readFileContent(join38(baseDir, relativePath));
4533
+ const relativePath = isRoot ? "AGENTS.md" : join39(".agents/memories", relativeFilePath);
4534
+ const fileContent = await readFileContent(join39(baseDir, relativePath));
4445
4535
  return new _AgentsMdRule({
4446
4536
  baseDir,
4447
4537
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -4481,7 +4571,7 @@ var AgentsMdRule = class _AgentsMdRule extends ToolRule {
4481
4571
  };
4482
4572
 
4483
4573
  // src/rules/amazonqcli-rule.ts
4484
- import { join as join39 } from "path";
4574
+ import { join as join40 } from "path";
4485
4575
  var AmazonQCliRule = class _AmazonQCliRule extends ToolRule {
4486
4576
  static getSettablePaths() {
4487
4577
  return {
@@ -4496,7 +4586,7 @@ var AmazonQCliRule = class _AmazonQCliRule extends ToolRule {
4496
4586
  validate = true
4497
4587
  }) {
4498
4588
  const fileContent = await readFileContent(
4499
- join39(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
4589
+ join40(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
4500
4590
  );
4501
4591
  return new _AmazonQCliRule({
4502
4592
  baseDir,
@@ -4536,7 +4626,7 @@ var AmazonQCliRule = class _AmazonQCliRule extends ToolRule {
4536
4626
  };
4537
4627
 
4538
4628
  // src/rules/augmentcode-legacy-rule.ts
4539
- import { join as join40 } from "path";
4629
+ import { join as join41 } from "path";
4540
4630
  var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
4541
4631
  toRulesyncRule() {
4542
4632
  const rulesyncFrontmatter = {
@@ -4597,8 +4687,8 @@ var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
4597
4687
  }) {
4598
4688
  const settablePaths = this.getSettablePaths();
4599
4689
  const isRoot = relativeFilePath === settablePaths.root.relativeFilePath;
4600
- const relativePath = isRoot ? settablePaths.root.relativeFilePath : join40(settablePaths.nonRoot.relativeDirPath, relativeFilePath);
4601
- const fileContent = await readFileContent(join40(baseDir, relativePath));
4690
+ const relativePath = isRoot ? settablePaths.root.relativeFilePath : join41(settablePaths.nonRoot.relativeDirPath, relativeFilePath);
4691
+ const fileContent = await readFileContent(join41(baseDir, relativePath));
4602
4692
  return new _AugmentcodeLegacyRule({
4603
4693
  baseDir,
4604
4694
  relativeDirPath: isRoot ? settablePaths.root.relativeDirPath : settablePaths.nonRoot.relativeDirPath,
@@ -4611,7 +4701,7 @@ var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
4611
4701
  };
4612
4702
 
4613
4703
  // src/rules/augmentcode-rule.ts
4614
- import { join as join41 } from "path";
4704
+ import { join as join42 } from "path";
4615
4705
  var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
4616
4706
  toRulesyncRule() {
4617
4707
  return this.toRulesyncRuleDefault();
@@ -4643,7 +4733,7 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
4643
4733
  validate = true
4644
4734
  }) {
4645
4735
  const fileContent = await readFileContent(
4646
- join41(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
4736
+ join42(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
4647
4737
  );
4648
4738
  const { body: content } = parseFrontmatter(fileContent);
4649
4739
  return new _AugmentcodeRule({
@@ -4666,7 +4756,7 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
4666
4756
  };
4667
4757
 
4668
4758
  // src/rules/claudecode-rule.ts
4669
- import { join as join42 } from "path";
4759
+ import { join as join43 } from "path";
4670
4760
  var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
4671
4761
  static getSettablePaths({
4672
4762
  global
@@ -4685,7 +4775,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
4685
4775
  relativeFilePath: "CLAUDE.md"
4686
4776
  },
4687
4777
  nonRoot: {
4688
- relativeDirPath: join42(".claude", "memories")
4778
+ relativeDirPath: join43(".claude", "memories")
4689
4779
  }
4690
4780
  };
4691
4781
  }
@@ -4700,7 +4790,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
4700
4790
  if (isRoot) {
4701
4791
  const relativePath2 = paths.root.relativeFilePath;
4702
4792
  const fileContent2 = await readFileContent(
4703
- join42(baseDir, paths.root.relativeDirPath, relativePath2)
4793
+ join43(baseDir, paths.root.relativeDirPath, relativePath2)
4704
4794
  );
4705
4795
  return new _ClaudecodeRule({
4706
4796
  baseDir,
@@ -4714,8 +4804,8 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
4714
4804
  if (!paths.nonRoot) {
4715
4805
  throw new Error("nonRoot path is not set");
4716
4806
  }
4717
- const relativePath = join42(paths.nonRoot.relativeDirPath, relativeFilePath);
4718
- const fileContent = await readFileContent(join42(baseDir, relativePath));
4807
+ const relativePath = join43(paths.nonRoot.relativeDirPath, relativeFilePath);
4808
+ const fileContent = await readFileContent(join43(baseDir, relativePath));
4719
4809
  return new _ClaudecodeRule({
4720
4810
  baseDir,
4721
4811
  relativeDirPath: paths.nonRoot.relativeDirPath,
@@ -4757,7 +4847,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
4757
4847
  };
4758
4848
 
4759
4849
  // src/rules/cline-rule.ts
4760
- import { join as join43 } from "path";
4850
+ import { join as join44 } from "path";
4761
4851
  import { z as z18 } from "zod/mini";
4762
4852
  var ClineRuleFrontmatterSchema = z18.object({
4763
4853
  description: z18.string()
@@ -4802,7 +4892,7 @@ var ClineRule = class _ClineRule extends ToolRule {
4802
4892
  validate = true
4803
4893
  }) {
4804
4894
  const fileContent = await readFileContent(
4805
- join43(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
4895
+ join44(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
4806
4896
  );
4807
4897
  return new _ClineRule({
4808
4898
  baseDir,
@@ -4815,7 +4905,7 @@ var ClineRule = class _ClineRule extends ToolRule {
4815
4905
  };
4816
4906
 
4817
4907
  // src/rules/codexcli-rule.ts
4818
- import { join as join44 } from "path";
4908
+ import { join as join45 } from "path";
4819
4909
  var CodexcliRule = class _CodexcliRule extends ToolRule {
4820
4910
  static getSettablePaths({
4821
4911
  global
@@ -4849,7 +4939,7 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
4849
4939
  if (isRoot) {
4850
4940
  const relativePath2 = paths.root.relativeFilePath;
4851
4941
  const fileContent2 = await readFileContent(
4852
- join44(baseDir, paths.root.relativeDirPath, relativePath2)
4942
+ join45(baseDir, paths.root.relativeDirPath, relativePath2)
4853
4943
  );
4854
4944
  return new _CodexcliRule({
4855
4945
  baseDir,
@@ -4863,8 +4953,8 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
4863
4953
  if (!paths.nonRoot) {
4864
4954
  throw new Error("nonRoot path is not set");
4865
4955
  }
4866
- const relativePath = join44(paths.nonRoot.relativeDirPath, relativeFilePath);
4867
- const fileContent = await readFileContent(join44(baseDir, relativePath));
4956
+ const relativePath = join45(paths.nonRoot.relativeDirPath, relativeFilePath);
4957
+ const fileContent = await readFileContent(join45(baseDir, relativePath));
4868
4958
  return new _CodexcliRule({
4869
4959
  baseDir,
4870
4960
  relativeDirPath: paths.nonRoot.relativeDirPath,
@@ -4906,7 +4996,7 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
4906
4996
  };
4907
4997
 
4908
4998
  // src/rules/copilot-rule.ts
4909
- import { join as join45 } from "path";
4999
+ import { join as join46 } from "path";
4910
5000
  import { z as z19 } from "zod/mini";
4911
5001
  var CopilotRuleFrontmatterSchema = z19.object({
4912
5002
  description: z19.optional(z19.string()),
@@ -4931,7 +5021,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
4931
5021
  const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
4932
5022
  if (!result.success) {
4933
5023
  throw new Error(
4934
- `Invalid frontmatter in ${join45(rest.relativeDirPath, rest.relativeFilePath)}: ${result.error.message}`
5024
+ `Invalid frontmatter in ${join46(rest.relativeDirPath, rest.relativeFilePath)}: ${result.error.message}`
4935
5025
  );
4936
5026
  }
4937
5027
  }
@@ -5003,11 +5093,11 @@ var CopilotRule = class _CopilotRule extends ToolRule {
5003
5093
  validate = true
5004
5094
  }) {
5005
5095
  const isRoot = relativeFilePath === "copilot-instructions.md";
5006
- const relativePath = isRoot ? join45(
5096
+ const relativePath = isRoot ? join46(
5007
5097
  this.getSettablePaths().root.relativeDirPath,
5008
5098
  this.getSettablePaths().root.relativeFilePath
5009
- ) : join45(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
5010
- const fileContent = await readFileContent(join45(baseDir, relativePath));
5099
+ ) : join46(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
5100
+ const fileContent = await readFileContent(join46(baseDir, relativePath));
5011
5101
  if (isRoot) {
5012
5102
  return new _CopilotRule({
5013
5103
  baseDir,
@@ -5026,7 +5116,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
5026
5116
  const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
5027
5117
  if (!result.success) {
5028
5118
  throw new Error(
5029
- `Invalid frontmatter in ${join45(baseDir, relativeFilePath)}: ${result.error.message}`
5119
+ `Invalid frontmatter in ${join46(baseDir, relativeFilePath)}: ${result.error.message}`
5030
5120
  );
5031
5121
  }
5032
5122
  return new _CopilotRule({
@@ -5050,7 +5140,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
5050
5140
  return {
5051
5141
  success: false,
5052
5142
  error: new Error(
5053
- `Invalid frontmatter in ${join45(this.relativeDirPath, this.relativeFilePath)}: ${result.error.message}`
5143
+ `Invalid frontmatter in ${join46(this.relativeDirPath, this.relativeFilePath)}: ${result.error.message}`
5054
5144
  )
5055
5145
  };
5056
5146
  }
@@ -5070,7 +5160,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
5070
5160
  };
5071
5161
 
5072
5162
  // src/rules/cursor-rule.ts
5073
- import { basename as basename16, join as join46 } from "path";
5163
+ import { basename as basename16, join as join47 } from "path";
5074
5164
  import { z as z20 } from "zod/mini";
5075
5165
  var CursorRuleFrontmatterSchema = z20.object({
5076
5166
  description: z20.optional(z20.string()),
@@ -5092,7 +5182,7 @@ var CursorRule = class _CursorRule extends ToolRule {
5092
5182
  const result = CursorRuleFrontmatterSchema.safeParse(frontmatter);
5093
5183
  if (!result.success) {
5094
5184
  throw new Error(
5095
- `Invalid frontmatter in ${join46(rest.relativeDirPath, rest.relativeFilePath)}: ${result.error.message}`
5185
+ `Invalid frontmatter in ${join47(rest.relativeDirPath, rest.relativeFilePath)}: ${result.error.message}`
5096
5186
  );
5097
5187
  }
5098
5188
  }
@@ -5169,6 +5259,16 @@ var CursorRule = class _CursorRule extends ToolRule {
5169
5259
  validate: true
5170
5260
  });
5171
5261
  }
5262
+ /**
5263
+ * Resolve cursor globs with priority: cursor-specific > parent
5264
+ * Returns comma-separated string for Cursor format, or undefined if no globs
5265
+ * @param cursorSpecificGlobs - Cursor-specific globs (takes priority if defined)
5266
+ * @param parentGlobs - Parent globs (used if cursorSpecificGlobs is undefined)
5267
+ */
5268
+ static resolveCursorGlobs(cursorSpecificGlobs, parentGlobs) {
5269
+ const targetGlobs = cursorSpecificGlobs !== void 0 ? cursorSpecificGlobs : parentGlobs;
5270
+ return targetGlobs && targetGlobs.length > 0 ? targetGlobs.join(",") : void 0;
5271
+ }
5172
5272
  static fromRulesyncRule({
5173
5273
  baseDir = ".",
5174
5274
  rulesyncRule,
@@ -5177,7 +5277,7 @@ var CursorRule = class _CursorRule extends ToolRule {
5177
5277
  const rulesyncFrontmatter = rulesyncRule.getFrontmatter();
5178
5278
  const cursorFrontmatter = {
5179
5279
  description: rulesyncFrontmatter.description,
5180
- globs: rulesyncFrontmatter.globs?.length ?? 0 > 0 ? rulesyncFrontmatter.globs?.join(",") : void 0,
5280
+ globs: this.resolveCursorGlobs(rulesyncFrontmatter.cursor?.globs, rulesyncFrontmatter.globs),
5181
5281
  alwaysApply: rulesyncFrontmatter.cursor?.alwaysApply ?? void 0
5182
5282
  };
5183
5283
  const body = rulesyncRule.getBody();
@@ -5199,13 +5299,13 @@ var CursorRule = class _CursorRule extends ToolRule {
5199
5299
  validate = true
5200
5300
  }) {
5201
5301
  const fileContent = await readFileContent(
5202
- join46(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5302
+ join47(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5203
5303
  );
5204
5304
  const { frontmatter, body: content } = _CursorRule.parseCursorFrontmatter(fileContent);
5205
5305
  const result = CursorRuleFrontmatterSchema.safeParse(frontmatter);
5206
5306
  if (!result.success) {
5207
5307
  throw new Error(
5208
- `Invalid frontmatter in ${join46(baseDir, relativeFilePath)}: ${result.error.message}`
5308
+ `Invalid frontmatter in ${join47(baseDir, relativeFilePath)}: ${result.error.message}`
5209
5309
  );
5210
5310
  }
5211
5311
  return new _CursorRule({
@@ -5228,7 +5328,7 @@ var CursorRule = class _CursorRule extends ToolRule {
5228
5328
  return {
5229
5329
  success: false,
5230
5330
  error: new Error(
5231
- `Invalid frontmatter in ${join46(this.relativeDirPath, this.relativeFilePath)}: ${result.error.message}`
5331
+ `Invalid frontmatter in ${join47(this.relativeDirPath, this.relativeFilePath)}: ${result.error.message}`
5232
5332
  )
5233
5333
  };
5234
5334
  }
@@ -5248,7 +5348,7 @@ var CursorRule = class _CursorRule extends ToolRule {
5248
5348
  };
5249
5349
 
5250
5350
  // src/rules/geminicli-rule.ts
5251
- import { join as join47 } from "path";
5351
+ import { join as join48 } from "path";
5252
5352
  var GeminiCliRule = class _GeminiCliRule extends ToolRule {
5253
5353
  static getSettablePaths({
5254
5354
  global
@@ -5282,7 +5382,7 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
5282
5382
  if (isRoot) {
5283
5383
  const relativePath2 = paths.root.relativeFilePath;
5284
5384
  const fileContent2 = await readFileContent(
5285
- join47(baseDir, paths.root.relativeDirPath, relativePath2)
5385
+ join48(baseDir, paths.root.relativeDirPath, relativePath2)
5286
5386
  );
5287
5387
  return new _GeminiCliRule({
5288
5388
  baseDir,
@@ -5296,8 +5396,8 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
5296
5396
  if (!paths.nonRoot) {
5297
5397
  throw new Error("nonRoot path is not set");
5298
5398
  }
5299
- const relativePath = join47(paths.nonRoot.relativeDirPath, relativeFilePath);
5300
- const fileContent = await readFileContent(join47(baseDir, relativePath));
5399
+ const relativePath = join48(paths.nonRoot.relativeDirPath, relativeFilePath);
5400
+ const fileContent = await readFileContent(join48(baseDir, relativePath));
5301
5401
  return new _GeminiCliRule({
5302
5402
  baseDir,
5303
5403
  relativeDirPath: paths.nonRoot.relativeDirPath,
@@ -5339,7 +5439,7 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
5339
5439
  };
5340
5440
 
5341
5441
  // src/rules/junie-rule.ts
5342
- import { join as join48 } from "path";
5442
+ import { join as join49 } from "path";
5343
5443
  var JunieRule = class _JunieRule extends ToolRule {
5344
5444
  static getSettablePaths() {
5345
5445
  return {
@@ -5358,8 +5458,8 @@ var JunieRule = class _JunieRule extends ToolRule {
5358
5458
  validate = true
5359
5459
  }) {
5360
5460
  const isRoot = relativeFilePath === "guidelines.md";
5361
- const relativePath = isRoot ? "guidelines.md" : join48(".junie/memories", relativeFilePath);
5362
- const fileContent = await readFileContent(join48(baseDir, relativePath));
5461
+ const relativePath = isRoot ? "guidelines.md" : join49(".junie/memories", relativeFilePath);
5462
+ const fileContent = await readFileContent(join49(baseDir, relativePath));
5363
5463
  return new _JunieRule({
5364
5464
  baseDir,
5365
5465
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -5399,7 +5499,7 @@ var JunieRule = class _JunieRule extends ToolRule {
5399
5499
  };
5400
5500
 
5401
5501
  // src/rules/kiro-rule.ts
5402
- import { join as join49 } from "path";
5502
+ import { join as join50 } from "path";
5403
5503
  var KiroRule = class _KiroRule extends ToolRule {
5404
5504
  static getSettablePaths() {
5405
5505
  return {
@@ -5414,7 +5514,7 @@ var KiroRule = class _KiroRule extends ToolRule {
5414
5514
  validate = true
5415
5515
  }) {
5416
5516
  const fileContent = await readFileContent(
5417
- join49(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5517
+ join50(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5418
5518
  );
5419
5519
  return new _KiroRule({
5420
5520
  baseDir,
@@ -5454,7 +5554,7 @@ var KiroRule = class _KiroRule extends ToolRule {
5454
5554
  };
5455
5555
 
5456
5556
  // src/rules/opencode-rule.ts
5457
- import { join as join50 } from "path";
5557
+ import { join as join51 } from "path";
5458
5558
  var OpenCodeRule = class _OpenCodeRule extends ToolRule {
5459
5559
  static getSettablePaths() {
5460
5560
  return {
@@ -5473,8 +5573,8 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
5473
5573
  validate = true
5474
5574
  }) {
5475
5575
  const isRoot = relativeFilePath === "AGENTS.md";
5476
- const relativePath = isRoot ? "AGENTS.md" : join50(".opencode/memories", relativeFilePath);
5477
- const fileContent = await readFileContent(join50(baseDir, relativePath));
5576
+ const relativePath = isRoot ? "AGENTS.md" : join51(".opencode/memories", relativeFilePath);
5577
+ const fileContent = await readFileContent(join51(baseDir, relativePath));
5478
5578
  return new _OpenCodeRule({
5479
5579
  baseDir,
5480
5580
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -5514,7 +5614,7 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
5514
5614
  };
5515
5615
 
5516
5616
  // src/rules/qwencode-rule.ts
5517
- import { join as join51 } from "path";
5617
+ import { join as join52 } from "path";
5518
5618
  var QwencodeRule = class _QwencodeRule extends ToolRule {
5519
5619
  static getSettablePaths() {
5520
5620
  return {
@@ -5533,8 +5633,8 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
5533
5633
  validate = true
5534
5634
  }) {
5535
5635
  const isRoot = relativeFilePath === "QWEN.md";
5536
- const relativePath = isRoot ? "QWEN.md" : join51(".qwen/memories", relativeFilePath);
5537
- const fileContent = await readFileContent(join51(baseDir, relativePath));
5636
+ const relativePath = isRoot ? "QWEN.md" : join52(".qwen/memories", relativeFilePath);
5637
+ const fileContent = await readFileContent(join52(baseDir, relativePath));
5538
5638
  return new _QwencodeRule({
5539
5639
  baseDir,
5540
5640
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -5571,7 +5671,7 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
5571
5671
  };
5572
5672
 
5573
5673
  // src/rules/roo-rule.ts
5574
- import { join as join52 } from "path";
5674
+ import { join as join53 } from "path";
5575
5675
  var RooRule = class _RooRule extends ToolRule {
5576
5676
  static getSettablePaths() {
5577
5677
  return {
@@ -5586,7 +5686,7 @@ var RooRule = class _RooRule extends ToolRule {
5586
5686
  validate = true
5587
5687
  }) {
5588
5688
  const fileContent = await readFileContent(
5589
- join52(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5689
+ join53(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5590
5690
  );
5591
5691
  return new _RooRule({
5592
5692
  baseDir,
@@ -5641,7 +5741,7 @@ var RooRule = class _RooRule extends ToolRule {
5641
5741
  };
5642
5742
 
5643
5743
  // src/rules/warp-rule.ts
5644
- import { join as join53 } from "path";
5744
+ import { join as join54 } from "path";
5645
5745
  var WarpRule = class _WarpRule extends ToolRule {
5646
5746
  constructor({ fileContent, root, ...rest }) {
5647
5747
  super({
@@ -5667,8 +5767,8 @@ var WarpRule = class _WarpRule extends ToolRule {
5667
5767
  validate = true
5668
5768
  }) {
5669
5769
  const isRoot = relativeFilePath === this.getSettablePaths().root.relativeFilePath;
5670
- const relativePath = isRoot ? this.getSettablePaths().root.relativeFilePath : join53(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
5671
- const fileContent = await readFileContent(join53(baseDir, relativePath));
5770
+ const relativePath = isRoot ? this.getSettablePaths().root.relativeFilePath : join54(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
5771
+ const fileContent = await readFileContent(join54(baseDir, relativePath));
5672
5772
  return new _WarpRule({
5673
5773
  baseDir,
5674
5774
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : ".warp",
@@ -5708,7 +5808,7 @@ var WarpRule = class _WarpRule extends ToolRule {
5708
5808
  };
5709
5809
 
5710
5810
  // src/rules/windsurf-rule.ts
5711
- import { join as join54 } from "path";
5811
+ import { join as join55 } from "path";
5712
5812
  var WindsurfRule = class _WindsurfRule extends ToolRule {
5713
5813
  static getSettablePaths() {
5714
5814
  return {
@@ -5723,7 +5823,7 @@ var WindsurfRule = class _WindsurfRule extends ToolRule {
5723
5823
  validate = true
5724
5824
  }) {
5725
5825
  const fileContent = await readFileContent(
5726
- join54(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5826
+ join55(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5727
5827
  );
5728
5828
  return new _WindsurfRule({
5729
5829
  baseDir,
@@ -6123,7 +6223,7 @@ var RulesProcessor = class extends FeatureProcessor {
6123
6223
  * Load and parse rulesync rule files from .rulesync/rules/ directory
6124
6224
  */
6125
6225
  async loadRulesyncFiles() {
6126
- const files = await findFilesByGlobs(join55(".rulesync/rules", "*.md"));
6226
+ const files = await findFilesByGlobs(join56(".rulesync/rules", "*.md"));
6127
6227
  logger.debug(`Found ${files.length} rulesync files`);
6128
6228
  const rulesyncRules = await Promise.all(
6129
6229
  files.map((file) => RulesyncRule.fromFile({ relativeFilePath: basename17(file) }))
@@ -6144,7 +6244,7 @@ var RulesProcessor = class extends FeatureProcessor {
6144
6244
  return rulesyncRules;
6145
6245
  }
6146
6246
  async loadRulesyncFilesLegacy() {
6147
- const legacyFiles = await findFilesByGlobs(join55(".rulesync", "*.md"));
6247
+ const legacyFiles = await findFilesByGlobs(join56(".rulesync", "*.md"));
6148
6248
  logger.debug(`Found ${legacyFiles.length} legacy rulesync files`);
6149
6249
  return Promise.all(
6150
6250
  legacyFiles.map((file) => RulesyncRule.fromFileLegacy({ relativeFilePath: basename17(file) }))
@@ -6211,7 +6311,7 @@ var RulesProcessor = class extends FeatureProcessor {
6211
6311
  return [];
6212
6312
  }
6213
6313
  const rootFilePaths = await findFilesByGlobs(
6214
- join55(this.baseDir, root.relativeDirPath ?? ".", root.relativeFilePath)
6314
+ join56(this.baseDir, root.relativeDirPath ?? ".", root.relativeFilePath)
6215
6315
  );
6216
6316
  return await Promise.all(
6217
6317
  rootFilePaths.map(
@@ -6229,7 +6329,7 @@ var RulesProcessor = class extends FeatureProcessor {
6229
6329
  return [];
6230
6330
  }
6231
6331
  const nonRootFilePaths = await findFilesByGlobs(
6232
- join55(this.baseDir, nonRoot.relativeDirPath, `*.${nonRoot.extension}`)
6332
+ join56(this.baseDir, nonRoot.relativeDirPath, `*.${nonRoot.extension}`)
6233
6333
  );
6234
6334
  return await Promise.all(
6235
6335
  nonRootFilePaths.map(
@@ -6605,14 +6705,14 @@ s/<command> [arguments]
6605
6705
  This syntax employs a double slash (\`s/\`) to prevent conflicts with built-in slash commands.
6606
6706
  The \`s\` in \`s/\` stands for *simulate*. Because custom slash commands are not built-in, this syntax provides a pseudo way to invoke them.
6607
6707
 
6608
- When users call a custom slash command, you have to look for the markdown file, \`${join55(commands.relativeDirPath, "{command}.md")}\`, then execute the contents of that file as the block of operations.` : "";
6708
+ When users call a custom slash command, you have to look for the markdown file, \`${join56(commands.relativeDirPath, "{command}.md")}\`, then execute the contents of that file as the block of operations.` : "";
6609
6709
  const subagentsSection = subagents ? `## Simulated Subagents
6610
6710
 
6611
6711
  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.
6612
6712
 
6613
- When users call a simulated subagent, it will look for the corresponding markdown file, \`${join55(subagents.relativeDirPath, "{subagent}.md")}\`, and execute its contents as the block of operations.
6713
+ When users call a simulated subagent, it will look for the corresponding markdown file, \`${join56(subagents.relativeDirPath, "{subagent}.md")}\`, and execute its contents as the block of operations.
6614
6714
 
6615
- For example, if the user instructs \`Call planner subagent to plan the refactoring\`, you have to look for the markdown file, \`${join55(subagents.relativeDirPath, "planner.md")}\`, and execute its contents as the block of operations.` : "";
6715
+ For example, if the user instructs \`Call planner subagent to plan the refactoring\`, you have to look for the markdown file, \`${join56(subagents.relativeDirPath, "planner.md")}\`, and execute its contents as the block of operations.` : "";
6616
6716
  const result = [
6617
6717
  overview,
6618
6718
  ...this.simulateCommands && CommandsProcessor.getToolTargetsSimulated().includes(this.toolTarget) ? [commandsSection] : [],
@@ -6822,58 +6922,69 @@ async function generateSubagents(config) {
6822
6922
  }
6823
6923
 
6824
6924
  // src/cli/commands/gitignore.ts
6825
- import { join as join56 } from "path";
6925
+ import { join as join57 } from "path";
6826
6926
  var gitignoreCommand = async () => {
6827
- const gitignorePath = join56(process.cwd(), ".gitignore");
6927
+ const gitignorePath = join57(process.cwd(), ".gitignore");
6828
6928
  const rulesFilesToIgnore = [
6829
6929
  "# Generated by rulesync - AI tool configuration files",
6930
+ // AGENTS.md
6931
+ "**/AGENTS.md",
6932
+ "**/.agents/",
6933
+ // Amazon Q
6830
6934
  "**/.amazonq/",
6831
- "**/.github/copilot-instructions.md",
6832
- "**/.github/instructions/",
6833
- "**/.github/prompts/",
6834
- "**/.cursor/",
6835
- "**/.cursorignore",
6836
- "**/.clinerules/",
6837
- "**/.clineignore",
6935
+ // Augment
6936
+ "**/.augmentignore",
6937
+ "**/.augment/rules/",
6938
+ "**/.augment-guidelines",
6939
+ // Claude Code
6838
6940
  "**/CLAUDE.md",
6839
6941
  "**/.claude/memories/",
6840
6942
  "**/.claude/commands/",
6841
6943
  "**/.claude/agents/",
6842
6944
  "**/.claude/settings.local.json",
6843
- "**/AGENTS.md",
6844
- "**/.agents/",
6845
- "**/.roo/rules/",
6846
- "**/.rooignore",
6847
- "**/.copilotignore",
6945
+ "**/.mcp.json",
6946
+ // Cline
6947
+ "**/.clinerules/",
6948
+ "**/.clineignore",
6949
+ "**/.cline/mcp.json",
6950
+ // Codex
6951
+ "**/.codexignore",
6952
+ "**/.codex/",
6953
+ // Cursor
6954
+ "**/.cursor/",
6955
+ "**/.cursorignore",
6956
+ "**/.cursor/mcp.json",
6957
+ // Gemini
6848
6958
  "**/GEMINI.md",
6849
6959
  "**/.gemini/memories/",
6850
6960
  "**/.gemini/commands/",
6851
6961
  "**/.gemini/subagents/",
6852
- "**/QWEN.md",
6853
- "**/.qwen/memories/",
6854
- "**/.aiexclude",
6855
- "**/.aiignore",
6856
- "**/.augmentignore",
6857
- "**/.kiro/steering/",
6858
- "**/.augment/rules/",
6859
- "**/.augment-guidelines",
6962
+ // GitHub Copilot
6963
+ "**/.github/copilot-instructions.md",
6964
+ "**/.github/instructions/",
6965
+ "**/.github/prompts/",
6966
+ "**/.github/subagents/",
6967
+ "**/.vscode/mcp.json",
6968
+ // Junie
6860
6969
  "**/.junie/guidelines.md",
6861
- "**/.noai",
6970
+ // Kiro
6971
+ "**/.kiro/steering/",
6972
+ "**/.aiignore",
6973
+ // OpenCode
6862
6974
  "**/.opencode/memories/",
6863
6975
  "**/.opencode/commands/",
6864
6976
  "**/opencode.json",
6865
- "**/.mcp.json",
6866
- "**/.cursor/mcp.json",
6867
- "**/.cline/mcp.json",
6977
+ // Qwen
6978
+ "**/QWEN.md",
6979
+ "**/.qwen/memories/",
6980
+ // Roo
6981
+ "**/.roo/rules/",
6982
+ "**/.rooignore",
6868
6983
  "**/.roo/mcp.json",
6869
6984
  "**/.roo/subagents/",
6870
- "**/.vscode/mcp.json",
6871
- "**/.github/commands/",
6872
- "**/.github/subagents/",
6985
+ // Warp
6873
6986
  "**/.warp/",
6874
- "**/WARP.md",
6875
- "**/.codexignore",
6876
- "**/.codex/"
6987
+ "**/WARP.md"
6877
6988
  ];
6878
6989
  let gitignoreContent = "";
6879
6990
  if (await fileExists(gitignorePath)) {
@@ -7052,7 +7163,7 @@ async function importSubagents(config, tool) {
7052
7163
  }
7053
7164
 
7054
7165
  // src/cli/commands/init.ts
7055
- import { join as join57 } from "path";
7166
+ import { join as join58 } from "path";
7056
7167
  async function initCommand() {
7057
7168
  logger.info("Initializing rulesync...");
7058
7169
  await ensureDir(".rulesync");
@@ -7060,7 +7171,7 @@ async function initCommand() {
7060
7171
  await createConfigFile();
7061
7172
  logger.success("rulesync initialized successfully!");
7062
7173
  logger.info("Next steps:");
7063
- logger.info(`1. Edit rule files in .rulesync/rules/`);
7174
+ logger.info(`1. Edit .rulesync/**/*.md, .rulesync/.mcp.json and .rulesyncignore`);
7064
7175
  logger.info("2. Run 'rulesync generate' to create configuration files");
7065
7176
  }
7066
7177
  async function createConfigFile() {
@@ -7088,7 +7199,7 @@ async function createConfigFile() {
7088
7199
  logger.success("Created rulesync.jsonc");
7089
7200
  }
7090
7201
  async function createSampleFiles() {
7091
- const sampleFile = {
7202
+ const sampleRuleFile = {
7092
7203
  filename: "overview.md",
7093
7204
  content: `---
7094
7205
  root: true
@@ -7123,20 +7234,134 @@ globs: ["**/*"]
7123
7234
  - Follow single responsibility principle
7124
7235
  `
7125
7236
  };
7126
- const filepath = join57(".rulesync/rules", sampleFile.filename);
7127
- await ensureDir(".rulesync/rules");
7128
- await ensureDir(RulesyncCommand.getSettablePaths().relativeDirPath);
7129
- await ensureDir(".rulesync/subagents");
7130
- if (!await fileExists(filepath)) {
7131
- await writeFileContent(filepath, sampleFile.content);
7132
- logger.success(`Created ${filepath}`);
7237
+ const sampleMcpFile = {
7238
+ filename: ".mcp.json",
7239
+ content: `{
7240
+ "mcpServers": {
7241
+ "serena": {
7242
+ "type": "stdio",
7243
+ "command": "uvx",
7244
+ "args": [
7245
+ "--from",
7246
+ "git+https://github.com/oraios/serena",
7247
+ "serena",
7248
+ "start-mcp-server",
7249
+ "--context",
7250
+ "ide-assistant",
7251
+ "--enable-web-dashboard",
7252
+ "false",
7253
+ "--project",
7254
+ "."
7255
+ ],
7256
+ "env": {}
7257
+ },
7258
+ "context7": {
7259
+ "type": "stdio",
7260
+ "command": "npx",
7261
+ "args": [
7262
+ "-y",
7263
+ "@upstash/context7-mcp"
7264
+ ],
7265
+ "env": {}
7266
+ }
7267
+ }
7268
+ }
7269
+ `
7270
+ };
7271
+ const sampleCommandFile = {
7272
+ filename: "review-pr.md",
7273
+ content: `---
7274
+ description: 'Review a pull request'
7275
+ targets: ["*"]
7276
+ ---
7277
+
7278
+ target_pr = $ARGUMENTS
7279
+
7280
+ If target_pr is not provided, use the PR of the current branch.
7281
+
7282
+ Execute the following in parallel:
7283
+
7284
+ 1. Check code quality and style consistency
7285
+ 2. Review test coverage
7286
+ 3. Verify documentation updates
7287
+ 4. Check for potential bugs or security issues
7288
+
7289
+ Then provide a summary of findings and suggestions for improvement.
7290
+ `
7291
+ };
7292
+ const sampleSubagentFile = {
7293
+ filename: "planner.md",
7294
+ content: `---
7295
+ name: planner
7296
+ targets: ["*"]
7297
+ description: >-
7298
+ This is the general-purpose planner. The user asks the agent to plan to
7299
+ suggest a specification, implement a new feature, refactor the codebase, or
7300
+ fix a bug. This agent can be called by the user explicitly only.
7301
+ claudecode:
7302
+ model: inherit
7303
+ ---
7304
+
7305
+ You are the planner for any tasks.
7306
+
7307
+ Based on the user's instruction, create a plan while analyzing the related files. Then, report the plan in detail. You can output files to @tmp/ if needed.
7308
+
7309
+ Attention, again, you are just the planner, so though you can read any files and run any commands for analysis, please don't write any code.
7310
+ `
7311
+ };
7312
+ const sampleIgnoreFile = {
7313
+ content: `credentials/
7314
+ `
7315
+ };
7316
+ const rulePaths = RulesyncRule.getSettablePaths();
7317
+ const mcpPaths = RulesyncMcp.getSettablePaths();
7318
+ const commandPaths = RulesyncCommand.getSettablePaths();
7319
+ const subagentPaths = RulesyncSubagent.getSettablePaths();
7320
+ const ignorePaths = RulesyncIgnore.getSettablePaths();
7321
+ await ensureDir(rulePaths.recommended.relativeDirPath);
7322
+ await ensureDir(mcpPaths.relativeDirPath);
7323
+ await ensureDir(commandPaths.relativeDirPath);
7324
+ await ensureDir(subagentPaths.relativeDirPath);
7325
+ await ensureDir(ignorePaths.relativeDirPath);
7326
+ const ruleFilepath = join58(rulePaths.recommended.relativeDirPath, sampleRuleFile.filename);
7327
+ if (!await fileExists(ruleFilepath)) {
7328
+ await writeFileContent(ruleFilepath, sampleRuleFile.content);
7329
+ logger.success(`Created ${ruleFilepath}`);
7330
+ } else {
7331
+ logger.info(`Skipped ${ruleFilepath} (already exists)`);
7332
+ }
7333
+ const mcpFilepath = join58(mcpPaths.relativeDirPath, mcpPaths.relativeFilePath);
7334
+ if (!await fileExists(mcpFilepath)) {
7335
+ await writeFileContent(mcpFilepath, sampleMcpFile.content);
7336
+ logger.success(`Created ${mcpFilepath}`);
7337
+ } else {
7338
+ logger.info(`Skipped ${mcpFilepath} (already exists)`);
7339
+ }
7340
+ const commandFilepath = join58(commandPaths.relativeDirPath, sampleCommandFile.filename);
7341
+ if (!await fileExists(commandFilepath)) {
7342
+ await writeFileContent(commandFilepath, sampleCommandFile.content);
7343
+ logger.success(`Created ${commandFilepath}`);
7344
+ } else {
7345
+ logger.info(`Skipped ${commandFilepath} (already exists)`);
7346
+ }
7347
+ const subagentFilepath = join58(subagentPaths.relativeDirPath, sampleSubagentFile.filename);
7348
+ if (!await fileExists(subagentFilepath)) {
7349
+ await writeFileContent(subagentFilepath, sampleSubagentFile.content);
7350
+ logger.success(`Created ${subagentFilepath}`);
7351
+ } else {
7352
+ logger.info(`Skipped ${subagentFilepath} (already exists)`);
7353
+ }
7354
+ const ignoreFilepath = join58(ignorePaths.relativeDirPath, ignorePaths.relativeFilePath);
7355
+ if (!await fileExists(ignoreFilepath)) {
7356
+ await writeFileContent(ignoreFilepath, sampleIgnoreFile.content);
7357
+ logger.success(`Created ${ignoreFilepath}`);
7133
7358
  } else {
7134
- logger.info(`Skipped ${filepath} (already exists)`);
7359
+ logger.info(`Skipped ${ignoreFilepath} (already exists)`);
7135
7360
  }
7136
7361
  }
7137
7362
 
7138
7363
  // src/cli/index.ts
7139
- var getVersion = () => "3.5.2";
7364
+ var getVersion = () => "3.7.0";
7140
7365
  var main = async () => {
7141
7366
  const program = new Command();
7142
7367
  const version = getVersion();