rulesync 3.31.0 → 3.33.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 +29 -0
  2. package/dist/index.cjs +1292 -835
  3. package/dist/index.js +1283 -826
  4. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -229,17 +229,18 @@ var ALL_TOOL_TARGETS = [
229
229
  "antigravity",
230
230
  "augmentcode",
231
231
  "augmentcode-legacy",
232
- "copilot",
233
- "cursor",
234
- "cline",
235
232
  "claudecode",
233
+ "claudecode-legacy",
234
+ "cline",
236
235
  "codexcli",
236
+ "copilot",
237
+ "cursor",
238
+ "geminicli",
239
+ "junie",
240
+ "kiro",
237
241
  "opencode",
238
242
  "qwencode",
239
243
  "roo",
240
- "geminicli",
241
- "kiro",
242
- "junie",
243
244
  "warp",
244
245
  "windsurf"
245
246
  ];
@@ -272,6 +273,11 @@ var ConfigFileSchema = z3.object({
272
273
  ...z3.partial(ConfigParamsSchema).shape
273
274
  });
274
275
  var RequiredConfigParamsSchema = z3.required(ConfigParamsSchema);
276
+ var CONFLICTING_TARGET_PAIRS = [
277
+ ["augmentcode", "augmentcode-legacy"],
278
+ ["claudecode", "claudecode-legacy"]
279
+ ];
280
+ var LEGACY_TARGETS = ["augmentcode-legacy", "claudecode-legacy"];
275
281
  var Config = class {
276
282
  baseDirs;
277
283
  targets;
@@ -298,6 +304,7 @@ var Config = class {
298
304
  experimentalSimulateCommands,
299
305
  experimentalSimulateSubagents
300
306
  }) {
307
+ this.validateConflictingTargets(targets);
301
308
  this.baseDirs = baseDirs;
302
309
  this.targets = targets;
303
310
  this.features = features;
@@ -309,12 +316,26 @@ var Config = class {
309
316
  this.simulateSkills = simulateSkills ?? false;
310
317
  this.modularMcp = modularMcp ?? false;
311
318
  }
319
+ validateConflictingTargets(targets) {
320
+ for (const [target1, target2] of CONFLICTING_TARGET_PAIRS) {
321
+ const hasTarget1 = targets.includes(target1);
322
+ const hasTarget2 = targets.includes(target2);
323
+ if (hasTarget1 && hasTarget2) {
324
+ throw new Error(
325
+ `Conflicting targets: '${target1}' and '${target2}' cannot be used together. Please choose one.`
326
+ );
327
+ }
328
+ }
329
+ }
312
330
  getBaseDirs() {
313
331
  return this.baseDirs;
314
332
  }
315
333
  getTargets() {
316
334
  if (this.targets.includes("*")) {
317
- return [...ALL_TOOL_TARGETS];
335
+ return ALL_TOOL_TARGETS.filter(
336
+ // eslint-disable-next-line no-type-assertion/no-type-assertion
337
+ (target) => !LEGACY_TARGETS.includes(target)
338
+ );
318
339
  }
319
340
  return this.targets.filter((target) => target !== "*");
320
341
  }
@@ -3492,6 +3513,12 @@ var CodexcliMcp = class _CodexcliMcp extends ToolMcp {
3492
3513
 
3493
3514
  // src/features/mcp/copilot-mcp.ts
3494
3515
  import { join as join33 } from "path";
3516
+ function convertToCopilotFormat(mcpServers) {
3517
+ return { servers: mcpServers };
3518
+ }
3519
+ function convertFromCopilotFormat(copilotConfig) {
3520
+ return copilotConfig.servers ?? {};
3521
+ }
3495
3522
  var CopilotMcp = class _CopilotMcp extends ToolMcp {
3496
3523
  json;
3497
3524
  constructor(params) {
@@ -3531,16 +3558,20 @@ var CopilotMcp = class _CopilotMcp extends ToolMcp {
3531
3558
  rulesyncMcp,
3532
3559
  validate = true
3533
3560
  }) {
3561
+ const copilotConfig = convertToCopilotFormat(rulesyncMcp.getMcpServers());
3534
3562
  return new _CopilotMcp({
3535
3563
  baseDir,
3536
3564
  relativeDirPath: this.getSettablePaths().relativeDirPath,
3537
3565
  relativeFilePath: this.getSettablePaths().relativeFilePath,
3538
- fileContent: rulesyncMcp.getFileContent(),
3566
+ fileContent: JSON.stringify(copilotConfig, null, 2),
3539
3567
  validate
3540
3568
  });
3541
3569
  }
3542
3570
  toRulesyncMcp() {
3543
- return this.toRulesyncMcpDefault();
3571
+ const mcpServers = convertFromCopilotFormat(this.json);
3572
+ return this.toRulesyncMcpDefault({
3573
+ fileContent: JSON.stringify({ mcpServers }, null, 2)
3574
+ });
3544
3575
  }
3545
3576
  validate() {
3546
3577
  return { success: true, error: null };
@@ -3924,6 +3955,37 @@ var OpencodeMcp = class _OpencodeMcp extends ToolMcp {
3924
3955
 
3925
3956
  // src/features/mcp/roo-mcp.ts
3926
3957
  import { join as join38 } from "path";
3958
+ function isRooMcpServers(value) {
3959
+ return value !== void 0 && value !== null && typeof value === "object";
3960
+ }
3961
+ function convertToRooFormat(mcpServers) {
3962
+ return Object.fromEntries(
3963
+ Object.entries(mcpServers).map(([serverName, serverConfig]) => {
3964
+ const converted = { ...serverConfig };
3965
+ if (serverConfig.type === "http") {
3966
+ converted.type = "streamable-http";
3967
+ }
3968
+ if (serverConfig.transport === "http") {
3969
+ converted.transport = "streamable-http";
3970
+ }
3971
+ return [serverName, converted];
3972
+ })
3973
+ );
3974
+ }
3975
+ function convertFromRooFormat(mcpServers) {
3976
+ return Object.fromEntries(
3977
+ Object.entries(mcpServers).map(([serverName, serverConfig]) => {
3978
+ const converted = { ...serverConfig };
3979
+ if (serverConfig.type === "streamable-http") {
3980
+ converted.type = "http";
3981
+ }
3982
+ if (serverConfig.transport === "streamable-http") {
3983
+ converted.transport = "http";
3984
+ }
3985
+ return [serverName, converted];
3986
+ })
3987
+ );
3988
+ }
3927
3989
  var RooMcp = class _RooMcp extends ToolMcp {
3928
3990
  json;
3929
3991
  constructor(params) {
@@ -3963,7 +4025,9 @@ var RooMcp = class _RooMcp extends ToolMcp {
3963
4025
  rulesyncMcp,
3964
4026
  validate = true
3965
4027
  }) {
3966
- const fileContent = rulesyncMcp.getFileContent();
4028
+ const mcpServers = rulesyncMcp.getMcpServers();
4029
+ const convertedMcpServers = convertToRooFormat(mcpServers);
4030
+ const fileContent = JSON.stringify({ mcpServers: convertedMcpServers }, null, 2);
3967
4031
  return new _RooMcp({
3968
4032
  baseDir,
3969
4033
  relativeDirPath: this.getSettablePaths().relativeDirPath,
@@ -3973,7 +4037,11 @@ var RooMcp = class _RooMcp extends ToolMcp {
3973
4037
  });
3974
4038
  }
3975
4039
  toRulesyncMcp() {
3976
- return this.toRulesyncMcpDefault();
4040
+ const rawMcpServers = isRooMcpServers(this.json.mcpServers) ? this.json.mcpServers : {};
4041
+ const convertedMcpServers = convertFromRooFormat(rawMcpServers);
4042
+ return this.toRulesyncMcpDefault({
4043
+ fileContent: JSON.stringify({ mcpServers: convertedMcpServers }, null, 2)
4044
+ });
3977
4045
  }
3978
4046
  validate() {
3979
4047
  return { success: true, error: null };
@@ -4214,21 +4282,23 @@ var McpProcessor = class extends FeatureProcessor {
4214
4282
  };
4215
4283
 
4216
4284
  // src/features/rules/rules-processor.ts
4217
- import { basename as basename21, join as join81 } from "path";
4285
+ import { basename as basename21, join as join82 } from "path";
4218
4286
  import { encode } from "@toon-format/toon";
4219
- import { z as z32 } from "zod/mini";
4220
-
4221
- // src/features/skills/codexcli-skill.ts
4222
- import { join as join42 } from "path";
4223
- import { z as z20 } from "zod/mini";
4287
+ import { z as z33 } from "zod/mini";
4224
4288
 
4225
4289
  // src/constants/general.ts
4226
4290
  var SKILL_FILE_NAME = "SKILL.md";
4227
4291
 
4228
- // src/features/skills/rulesync-skill.ts
4229
- import { join as join40 } from "path";
4292
+ // src/features/skills/agentsmd-skill.ts
4293
+ import { join as join42 } from "path";
4294
+
4295
+ // src/features/skills/simulated-skill.ts
4296
+ import { join as join41 } from "path";
4230
4297
  import { z as z19 } from "zod/mini";
4231
4298
 
4299
+ // src/features/skills/tool-skill.ts
4300
+ import { join as join40 } from "path";
4301
+
4232
4302
  // src/types/ai-dir.ts
4233
4303
  import path2, { basename as basename14, join as join39, relative as relative3, resolve as resolve4 } from "path";
4234
4304
  var AiDir = class {
@@ -4341,113 +4411,7 @@ var AiDir = class {
4341
4411
  }
4342
4412
  };
4343
4413
 
4344
- // src/features/skills/rulesync-skill.ts
4345
- var RulesyncSkillFrontmatterSchemaInternal = z19.object({
4346
- name: z19.string(),
4347
- description: z19.string(),
4348
- targets: z19._default(RulesyncTargetsSchema, ["*"]),
4349
- claudecode: z19.optional(
4350
- z19.object({
4351
- "allowed-tools": z19.optional(z19.array(z19.string()))
4352
- })
4353
- )
4354
- });
4355
- var RulesyncSkillFrontmatterSchema = RulesyncSkillFrontmatterSchemaInternal;
4356
- var RulesyncSkill = class _RulesyncSkill extends AiDir {
4357
- constructor({
4358
- baseDir = process.cwd(),
4359
- relativeDirPath = RULESYNC_SKILLS_RELATIVE_DIR_PATH,
4360
- dirName,
4361
- frontmatter,
4362
- body,
4363
- otherFiles = [],
4364
- validate = true,
4365
- global = false
4366
- }) {
4367
- super({
4368
- baseDir,
4369
- relativeDirPath,
4370
- dirName,
4371
- mainFile: {
4372
- name: SKILL_FILE_NAME,
4373
- body,
4374
- frontmatter: { ...frontmatter }
4375
- },
4376
- otherFiles,
4377
- global
4378
- });
4379
- if (validate) {
4380
- const result = this.validate();
4381
- if (!result.success) {
4382
- throw result.error;
4383
- }
4384
- }
4385
- }
4386
- static getSettablePaths() {
4387
- return {
4388
- relativeDirPath: RULESYNC_SKILLS_RELATIVE_DIR_PATH
4389
- };
4390
- }
4391
- getFrontmatter() {
4392
- if (!this.mainFile?.frontmatter) {
4393
- throw new Error("Frontmatter is not defined");
4394
- }
4395
- const result = RulesyncSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
4396
- return result;
4397
- }
4398
- getBody() {
4399
- return this.mainFile?.body ?? "";
4400
- }
4401
- validate() {
4402
- const result = RulesyncSkillFrontmatterSchema.safeParse(this.mainFile?.frontmatter);
4403
- if (!result.success) {
4404
- return {
4405
- success: false,
4406
- error: new Error(
4407
- `Invalid frontmatter in ${this.getDirPath()}: ${formatError(result.error)}`
4408
- )
4409
- };
4410
- }
4411
- return { success: true, error: null };
4412
- }
4413
- static async fromDir({
4414
- baseDir = process.cwd(),
4415
- relativeDirPath = RULESYNC_SKILLS_RELATIVE_DIR_PATH,
4416
- dirName,
4417
- global = false
4418
- }) {
4419
- const skillDirPath = join40(baseDir, relativeDirPath, dirName);
4420
- const skillFilePath = join40(skillDirPath, SKILL_FILE_NAME);
4421
- if (!await fileExists(skillFilePath)) {
4422
- throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
4423
- }
4424
- const fileContent = await readFileContent(skillFilePath);
4425
- const { frontmatter, body: content } = parseFrontmatter(fileContent);
4426
- const result = RulesyncSkillFrontmatterSchema.safeParse(frontmatter);
4427
- if (!result.success) {
4428
- throw new Error(`Invalid frontmatter in ${skillFilePath}: ${formatError(result.error)}`);
4429
- }
4430
- const otherFiles = await this.collectOtherFiles(
4431
- baseDir,
4432
- relativeDirPath,
4433
- dirName,
4434
- SKILL_FILE_NAME
4435
- );
4436
- return new _RulesyncSkill({
4437
- baseDir,
4438
- relativeDirPath,
4439
- dirName,
4440
- frontmatter: result.data,
4441
- body: content.trim(),
4442
- otherFiles,
4443
- validate: true,
4444
- global
4445
- });
4446
- }
4447
- };
4448
-
4449
4414
  // src/features/skills/tool-skill.ts
4450
- import { join as join41 } from "path";
4451
4415
  var ToolSkill = class extends AiDir {
4452
4416
  /**
4453
4417
  * Get the settable paths for this tool's skill directories.
@@ -4521,8 +4485,8 @@ var ToolSkill = class extends AiDir {
4521
4485
  }) {
4522
4486
  const settablePaths = getSettablePaths({ global });
4523
4487
  const actualRelativeDirPath = relativeDirPath ?? settablePaths.relativeDirPath;
4524
- const skillDirPath = join41(baseDir, actualRelativeDirPath, dirName);
4525
- const skillFilePath = join41(skillDirPath, SKILL_FILE_NAME);
4488
+ const skillDirPath = join40(baseDir, actualRelativeDirPath, dirName);
4489
+ const skillFilePath = join40(skillDirPath, SKILL_FILE_NAME);
4526
4490
  if (!await fileExists(skillFilePath)) {
4527
4491
  throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
4528
4492
  }
@@ -4546,21 +4510,22 @@ var ToolSkill = class extends AiDir {
4546
4510
  }
4547
4511
  };
4548
4512
 
4549
- // src/features/skills/codexcli-skill.ts
4550
- var CodexCliSkillFrontmatterSchema = z20.object({
4551
- name: z20.string(),
4552
- description: z20.string()
4513
+ // src/features/skills/simulated-skill.ts
4514
+ var SimulatedSkillFrontmatterSchema = z19.object({
4515
+ name: z19.string(),
4516
+ description: z19.string()
4553
4517
  });
4554
- var CodexCliSkill = class _CodexCliSkill extends ToolSkill {
4518
+ var SimulatedSkill = class extends ToolSkill {
4519
+ frontmatter;
4520
+ body;
4555
4521
  constructor({
4556
4522
  baseDir = process.cwd(),
4557
- relativeDirPath = join42(".codex", "skills"),
4523
+ relativeDirPath,
4558
4524
  dirName,
4559
4525
  frontmatter,
4560
4526
  body,
4561
4527
  otherFiles = [],
4562
- validate = true,
4563
- global = false
4528
+ validate = true
4564
4529
  }) {
4565
4530
  super({
4566
4531
  baseDir,
@@ -4572,42 +4537,37 @@ var CodexCliSkill = class _CodexCliSkill extends ToolSkill {
4572
4537
  frontmatter: { ...frontmatter }
4573
4538
  },
4574
4539
  otherFiles,
4575
- global
4540
+ global: false
4541
+ // Simulated skills are project mode only
4576
4542
  });
4577
4543
  if (validate) {
4578
- const result = this.validate();
4544
+ const result = SimulatedSkillFrontmatterSchema.safeParse(frontmatter);
4579
4545
  if (!result.success) {
4580
- throw result.error;
4546
+ throw new Error(
4547
+ `Invalid frontmatter in ${join41(relativeDirPath, dirName)}: ${formatError(result.error)}`
4548
+ );
4581
4549
  }
4582
4550
  }
4551
+ this.frontmatter = frontmatter;
4552
+ this.body = body;
4583
4553
  }
4584
- static getSettablePaths({ global = false } = {}) {
4585
- if (!global) {
4586
- throw new Error("CodexCliSkill only supports global mode. Please pass { global: true }.");
4587
- }
4588
- return {
4589
- relativeDirPath: join42(".codex", "skills")
4590
- };
4554
+ getBody() {
4555
+ return this.body;
4591
4556
  }
4592
4557
  getFrontmatter() {
4593
- if (!this.mainFile?.frontmatter) {
4594
- throw new Error("Frontmatter is not defined");
4595
- }
4596
- const result = CodexCliSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
4597
- return result;
4558
+ return this.frontmatter;
4598
4559
  }
4599
- getBody() {
4600
- return this.mainFile?.body ?? "";
4560
+ toRulesyncSkill() {
4561
+ throw new Error("Not implemented because it is a SIMULATED skill.");
4601
4562
  }
4602
4563
  validate() {
4603
- if (!this.mainFile) {
4604
- return {
4605
- success: false,
4606
- error: new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
4607
- };
4564
+ if (!this.frontmatter) {
4565
+ return { success: true, error: null };
4608
4566
  }
4609
- const result = CodexCliSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
4610
- if (!result.success) {
4567
+ const result = SimulatedSkillFrontmatterSchema.safeParse(this.frontmatter);
4568
+ if (result.success) {
4569
+ return { success: true, error: null };
4570
+ } else {
4611
4571
  return {
4612
4572
  success: false,
4613
4573
  error: new Error(
@@ -4615,98 +4575,141 @@ var CodexCliSkill = class _CodexCliSkill extends ToolSkill {
4615
4575
  )
4616
4576
  };
4617
4577
  }
4618
- return { success: true, error: null };
4619
- }
4620
- toRulesyncSkill() {
4621
- const frontmatter = this.getFrontmatter();
4622
- const rulesyncFrontmatter = {
4623
- name: frontmatter.name,
4624
- description: frontmatter.description,
4625
- targets: ["*"]
4626
- };
4627
- return new RulesyncSkill({
4628
- baseDir: this.baseDir,
4629
- relativeDirPath: this.relativeDirPath,
4630
- dirName: this.getDirName(),
4631
- frontmatter: rulesyncFrontmatter,
4632
- body: this.getBody(),
4633
- otherFiles: this.getOtherFiles(),
4634
- validate: true,
4635
- global: this.global
4636
- });
4637
4578
  }
4638
- static fromRulesyncSkill({
4579
+ static fromRulesyncSkillDefault({
4639
4580
  rulesyncSkill,
4640
- validate = true,
4641
- global = false
4581
+ validate = true
4642
4582
  }) {
4643
- const settablePaths = _CodexCliSkill.getSettablePaths({ global });
4644
4583
  const rulesyncFrontmatter = rulesyncSkill.getFrontmatter();
4645
- const codexFrontmatter = {
4584
+ const simulatedFrontmatter = {
4646
4585
  name: rulesyncFrontmatter.name,
4647
4586
  description: rulesyncFrontmatter.description
4648
4587
  };
4649
- return new _CodexCliSkill({
4588
+ return {
4650
4589
  baseDir: rulesyncSkill.getBaseDir(),
4651
- relativeDirPath: settablePaths.relativeDirPath,
4590
+ relativeDirPath: this.getSettablePaths().relativeDirPath,
4652
4591
  dirName: rulesyncSkill.getDirName(),
4653
- frontmatter: codexFrontmatter,
4592
+ frontmatter: simulatedFrontmatter,
4654
4593
  body: rulesyncSkill.getBody(),
4655
4594
  otherFiles: rulesyncSkill.getOtherFiles(),
4656
- validate,
4657
- global
4658
- });
4595
+ validate
4596
+ };
4659
4597
  }
4660
- static isTargetedByRulesyncSkill(rulesyncSkill) {
4661
- const targets = rulesyncSkill.getFrontmatter().targets;
4662
- return targets.includes("*") || targets.includes("codexcli");
4663
- }
4664
- static async fromDir(params) {
4665
- const loaded = await this.loadSkillDirContent({
4666
- ...params,
4667
- getSettablePaths: _CodexCliSkill.getSettablePaths
4668
- });
4669
- const result = CodexCliSkillFrontmatterSchema.safeParse(loaded.frontmatter);
4598
+ static async fromDirDefault({
4599
+ baseDir = process.cwd(),
4600
+ relativeDirPath,
4601
+ dirName
4602
+ }) {
4603
+ const settablePaths = this.getSettablePaths();
4604
+ const actualRelativeDirPath = relativeDirPath ?? settablePaths.relativeDirPath;
4605
+ const skillDirPath = join41(baseDir, actualRelativeDirPath, dirName);
4606
+ const skillFilePath = join41(skillDirPath, SKILL_FILE_NAME);
4607
+ if (!await fileExists(skillFilePath)) {
4608
+ throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
4609
+ }
4610
+ const fileContent = await readFileContent(skillFilePath);
4611
+ const { frontmatter, body: content } = parseFrontmatter(fileContent);
4612
+ const result = SimulatedSkillFrontmatterSchema.safeParse(frontmatter);
4670
4613
  if (!result.success) {
4671
- const skillDirPath = join42(loaded.baseDir, loaded.relativeDirPath, loaded.dirName);
4672
- throw new Error(
4673
- `Invalid frontmatter in ${join42(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`
4674
- );
4614
+ throw new Error(`Invalid frontmatter in ${skillFilePath}: ${formatError(result.error)}`);
4675
4615
  }
4676
- return new _CodexCliSkill({
4677
- baseDir: loaded.baseDir,
4678
- relativeDirPath: loaded.relativeDirPath,
4679
- dirName: loaded.dirName,
4616
+ const otherFiles = await this.collectOtherFiles(
4617
+ baseDir,
4618
+ actualRelativeDirPath,
4619
+ dirName,
4620
+ SKILL_FILE_NAME
4621
+ );
4622
+ return {
4623
+ baseDir,
4624
+ relativeDirPath: actualRelativeDirPath,
4625
+ dirName,
4680
4626
  frontmatter: result.data,
4681
- body: loaded.body,
4682
- otherFiles: loaded.otherFiles,
4683
- validate: true,
4684
- global: loaded.global
4627
+ body: content.trim(),
4628
+ otherFiles,
4629
+ validate: true
4630
+ };
4631
+ }
4632
+ /**
4633
+ * Check if a RulesyncSkill should be converted to this simulated skill type.
4634
+ * Uses the targets field in the RulesyncSkill frontmatter to determine targeting.
4635
+ */
4636
+ static isTargetedByRulesyncSkillDefault({
4637
+ rulesyncSkill,
4638
+ toolTarget
4639
+ }) {
4640
+ const frontmatter = rulesyncSkill.getFrontmatter();
4641
+ const targets = frontmatter.targets;
4642
+ if (targets.includes("*")) {
4643
+ return true;
4644
+ }
4645
+ return targets.includes(toolTarget);
4646
+ }
4647
+ /**
4648
+ * Get the settable paths for this tool's skill directories.
4649
+ * Must be implemented by concrete subclasses.
4650
+ */
4651
+ static getSettablePaths(_options) {
4652
+ throw new Error("Please implement this method in the subclass.");
4653
+ }
4654
+ };
4655
+
4656
+ // src/features/skills/agentsmd-skill.ts
4657
+ var AgentsmdSkill = class _AgentsmdSkill extends SimulatedSkill {
4658
+ static getSettablePaths(options) {
4659
+ if (options?.global) {
4660
+ throw new Error("AgentsmdSkill does not support global mode.");
4661
+ }
4662
+ return {
4663
+ relativeDirPath: join42(".agents", "skills")
4664
+ };
4665
+ }
4666
+ static async fromDir(params) {
4667
+ const baseParams = await this.fromDirDefault(params);
4668
+ return new _AgentsmdSkill(baseParams);
4669
+ }
4670
+ static fromRulesyncSkill(params) {
4671
+ const baseParams = {
4672
+ ...this.fromRulesyncSkillDefault(params),
4673
+ relativeDirPath: this.getSettablePaths().relativeDirPath
4674
+ };
4675
+ return new _AgentsmdSkill(baseParams);
4676
+ }
4677
+ static isTargetedByRulesyncSkill(rulesyncSkill) {
4678
+ return this.isTargetedByRulesyncSkillDefault({
4679
+ rulesyncSkill,
4680
+ toolTarget: "agentsmd"
4685
4681
  });
4686
4682
  }
4687
4683
  };
4688
4684
 
4689
- // src/features/skills/copilot-skill.ts
4685
+ // src/features/skills/codexcli-skill.ts
4690
4686
  import { join as join44 } from "path";
4687
+ import { z as z21 } from "zod/mini";
4691
4688
 
4692
- // src/features/skills/simulated-skill.ts
4689
+ // src/features/skills/rulesync-skill.ts
4693
4690
  import { join as join43 } from "path";
4694
- import { z as z21 } from "zod/mini";
4695
- var SimulatedSkillFrontmatterSchema = z21.object({
4696
- name: z21.string(),
4697
- description: z21.string()
4691
+ import { z as z20 } from "zod/mini";
4692
+ var RulesyncSkillFrontmatterSchemaInternal = z20.object({
4693
+ name: z20.string(),
4694
+ description: z20.string(),
4695
+ targets: z20._default(RulesyncTargetsSchema, ["*"]),
4696
+ claudecode: z20.optional(
4697
+ z20.object({
4698
+ "allowed-tools": z20.optional(z20.array(z20.string()))
4699
+ })
4700
+ )
4698
4701
  });
4699
- var SimulatedSkill = class extends ToolSkill {
4700
- frontmatter;
4701
- body;
4702
+ var RulesyncSkillFrontmatterSchema = RulesyncSkillFrontmatterSchemaInternal;
4703
+ var RulesyncSkill = class _RulesyncSkill extends AiDir {
4702
4704
  constructor({
4703
4705
  baseDir = process.cwd(),
4704
- relativeDirPath,
4706
+ relativeDirPath = RULESYNC_SKILLS_RELATIVE_DIR_PATH,
4705
4707
  dirName,
4706
4708
  frontmatter,
4707
4709
  body,
4708
4710
  otherFiles = [],
4709
- validate = true
4711
+ validate = true,
4712
+ global = false
4710
4713
  }) {
4711
4714
  super({
4712
4715
  baseDir,
@@ -4718,37 +4721,33 @@ var SimulatedSkill = class extends ToolSkill {
4718
4721
  frontmatter: { ...frontmatter }
4719
4722
  },
4720
4723
  otherFiles,
4721
- global: false
4722
- // Simulated skills are project mode only
4724
+ global
4723
4725
  });
4724
4726
  if (validate) {
4725
- const result = SimulatedSkillFrontmatterSchema.safeParse(frontmatter);
4727
+ const result = this.validate();
4726
4728
  if (!result.success) {
4727
- throw new Error(
4728
- `Invalid frontmatter in ${join43(relativeDirPath, dirName)}: ${formatError(result.error)}`
4729
- );
4729
+ throw result.error;
4730
4730
  }
4731
4731
  }
4732
- this.frontmatter = frontmatter;
4733
- this.body = body;
4734
4732
  }
4735
- getBody() {
4736
- return this.body;
4733
+ static getSettablePaths() {
4734
+ return {
4735
+ relativeDirPath: RULESYNC_SKILLS_RELATIVE_DIR_PATH
4736
+ };
4737
4737
  }
4738
4738
  getFrontmatter() {
4739
- return this.frontmatter;
4739
+ if (!this.mainFile?.frontmatter) {
4740
+ throw new Error("Frontmatter is not defined");
4741
+ }
4742
+ const result = RulesyncSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
4743
+ return result;
4740
4744
  }
4741
- toRulesyncSkill() {
4742
- throw new Error("Not implemented because it is a SIMULATED skill.");
4745
+ getBody() {
4746
+ return this.mainFile?.body ?? "";
4743
4747
  }
4744
4748
  validate() {
4745
- if (!this.frontmatter) {
4746
- return { success: true, error: null };
4747
- }
4748
- const result = SimulatedSkillFrontmatterSchema.safeParse(this.frontmatter);
4749
- if (result.success) {
4750
- return { success: true, error: null };
4751
- } else {
4749
+ const result = RulesyncSkillFrontmatterSchema.safeParse(this.mainFile?.frontmatter);
4750
+ if (!result.success) {
4752
4751
  return {
4753
4752
  success: false,
4754
4753
  error: new Error(
@@ -4756,139 +4755,270 @@ var SimulatedSkill = class extends ToolSkill {
4756
4755
  )
4757
4756
  };
4758
4757
  }
4758
+ return { success: true, error: null };
4759
4759
  }
4760
- static fromRulesyncSkillDefault({
4761
- rulesyncSkill,
4762
- validate = true
4763
- }) {
4764
- const rulesyncFrontmatter = rulesyncSkill.getFrontmatter();
4765
- const simulatedFrontmatter = {
4766
- name: rulesyncFrontmatter.name,
4767
- description: rulesyncFrontmatter.description
4768
- };
4769
- return {
4770
- baseDir: rulesyncSkill.getBaseDir(),
4771
- relativeDirPath: this.getSettablePaths().relativeDirPath,
4772
- dirName: rulesyncSkill.getDirName(),
4773
- frontmatter: simulatedFrontmatter,
4774
- body: rulesyncSkill.getBody(),
4775
- otherFiles: rulesyncSkill.getOtherFiles(),
4776
- validate
4777
- };
4778
- }
4779
- static async fromDirDefault({
4760
+ static async fromDir({
4780
4761
  baseDir = process.cwd(),
4781
- relativeDirPath,
4782
- dirName
4762
+ relativeDirPath = RULESYNC_SKILLS_RELATIVE_DIR_PATH,
4763
+ dirName,
4764
+ global = false
4783
4765
  }) {
4784
- const settablePaths = this.getSettablePaths();
4785
- const actualRelativeDirPath = relativeDirPath ?? settablePaths.relativeDirPath;
4786
- const skillDirPath = join43(baseDir, actualRelativeDirPath, dirName);
4766
+ const skillDirPath = join43(baseDir, relativeDirPath, dirName);
4787
4767
  const skillFilePath = join43(skillDirPath, SKILL_FILE_NAME);
4788
4768
  if (!await fileExists(skillFilePath)) {
4789
4769
  throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
4790
4770
  }
4791
4771
  const fileContent = await readFileContent(skillFilePath);
4792
4772
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
4793
- const result = SimulatedSkillFrontmatterSchema.safeParse(frontmatter);
4773
+ const result = RulesyncSkillFrontmatterSchema.safeParse(frontmatter);
4794
4774
  if (!result.success) {
4795
4775
  throw new Error(`Invalid frontmatter in ${skillFilePath}: ${formatError(result.error)}`);
4796
4776
  }
4797
4777
  const otherFiles = await this.collectOtherFiles(
4798
4778
  baseDir,
4799
- actualRelativeDirPath,
4779
+ relativeDirPath,
4800
4780
  dirName,
4801
4781
  SKILL_FILE_NAME
4802
4782
  );
4803
- return {
4783
+ return new _RulesyncSkill({
4804
4784
  baseDir,
4805
- relativeDirPath: actualRelativeDirPath,
4785
+ relativeDirPath,
4806
4786
  dirName,
4807
4787
  frontmatter: result.data,
4808
4788
  body: content.trim(),
4809
4789
  otherFiles,
4810
- validate: true
4790
+ validate: true,
4791
+ global
4792
+ });
4793
+ }
4794
+ };
4795
+
4796
+ // src/features/skills/codexcli-skill.ts
4797
+ var CodexCliSkillFrontmatterSchema = z21.object({
4798
+ name: z21.string(),
4799
+ description: z21.string()
4800
+ });
4801
+ var CodexCliSkill = class _CodexCliSkill extends ToolSkill {
4802
+ constructor({
4803
+ baseDir = process.cwd(),
4804
+ relativeDirPath = join44(".codex", "skills"),
4805
+ dirName,
4806
+ frontmatter,
4807
+ body,
4808
+ otherFiles = [],
4809
+ validate = true,
4810
+ global = false
4811
+ }) {
4812
+ super({
4813
+ baseDir,
4814
+ relativeDirPath,
4815
+ dirName,
4816
+ mainFile: {
4817
+ name: SKILL_FILE_NAME,
4818
+ body,
4819
+ frontmatter: { ...frontmatter }
4820
+ },
4821
+ otherFiles,
4822
+ global
4823
+ });
4824
+ if (validate) {
4825
+ const result = this.validate();
4826
+ if (!result.success) {
4827
+ throw result.error;
4828
+ }
4829
+ }
4830
+ }
4831
+ static getSettablePaths({ global = false } = {}) {
4832
+ if (!global) {
4833
+ throw new Error("CodexCliSkill only supports global mode. Please pass { global: true }.");
4834
+ }
4835
+ return {
4836
+ relativeDirPath: join44(".codex", "skills")
4811
4837
  };
4812
4838
  }
4813
- /**
4814
- * Check if a RulesyncSkill should be converted to this simulated skill type.
4815
- * Uses the targets field in the RulesyncSkill frontmatter to determine targeting.
4816
- */
4817
- static isTargetedByRulesyncSkillDefault({
4839
+ getFrontmatter() {
4840
+ if (!this.mainFile?.frontmatter) {
4841
+ throw new Error("Frontmatter is not defined");
4842
+ }
4843
+ const result = CodexCliSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
4844
+ return result;
4845
+ }
4846
+ getBody() {
4847
+ return this.mainFile?.body ?? "";
4848
+ }
4849
+ validate() {
4850
+ if (!this.mainFile) {
4851
+ return {
4852
+ success: false,
4853
+ error: new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
4854
+ };
4855
+ }
4856
+ const result = CodexCliSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
4857
+ if (!result.success) {
4858
+ return {
4859
+ success: false,
4860
+ error: new Error(
4861
+ `Invalid frontmatter in ${this.getDirPath()}: ${formatError(result.error)}`
4862
+ )
4863
+ };
4864
+ }
4865
+ return { success: true, error: null };
4866
+ }
4867
+ toRulesyncSkill() {
4868
+ const frontmatter = this.getFrontmatter();
4869
+ const rulesyncFrontmatter = {
4870
+ name: frontmatter.name,
4871
+ description: frontmatter.description,
4872
+ targets: ["*"]
4873
+ };
4874
+ return new RulesyncSkill({
4875
+ baseDir: this.baseDir,
4876
+ relativeDirPath: this.relativeDirPath,
4877
+ dirName: this.getDirName(),
4878
+ frontmatter: rulesyncFrontmatter,
4879
+ body: this.getBody(),
4880
+ otherFiles: this.getOtherFiles(),
4881
+ validate: true,
4882
+ global: this.global
4883
+ });
4884
+ }
4885
+ static fromRulesyncSkill({
4818
4886
  rulesyncSkill,
4819
- toolTarget
4887
+ validate = true,
4888
+ global = false
4820
4889
  }) {
4821
- const frontmatter = rulesyncSkill.getFrontmatter();
4822
- const targets = frontmatter.targets;
4823
- if (targets.includes("*")) {
4824
- return true;
4825
- }
4826
- return targets.includes(toolTarget);
4890
+ const settablePaths = _CodexCliSkill.getSettablePaths({ global });
4891
+ const rulesyncFrontmatter = rulesyncSkill.getFrontmatter();
4892
+ const codexFrontmatter = {
4893
+ name: rulesyncFrontmatter.name,
4894
+ description: rulesyncFrontmatter.description
4895
+ };
4896
+ return new _CodexCliSkill({
4897
+ baseDir: rulesyncSkill.getBaseDir(),
4898
+ relativeDirPath: settablePaths.relativeDirPath,
4899
+ dirName: rulesyncSkill.getDirName(),
4900
+ frontmatter: codexFrontmatter,
4901
+ body: rulesyncSkill.getBody(),
4902
+ otherFiles: rulesyncSkill.getOtherFiles(),
4903
+ validate,
4904
+ global
4905
+ });
4827
4906
  }
4828
- /**
4829
- * Get the settable paths for this tool's skill directories.
4830
- * Must be implemented by concrete subclasses.
4831
- */
4832
- static getSettablePaths(_options) {
4833
- throw new Error("Please implement this method in the subclass.");
4907
+ static isTargetedByRulesyncSkill(rulesyncSkill) {
4908
+ const targets = rulesyncSkill.getFrontmatter().targets;
4909
+ return targets.includes("*") || targets.includes("codexcli");
4910
+ }
4911
+ static async fromDir(params) {
4912
+ const loaded = await this.loadSkillDirContent({
4913
+ ...params,
4914
+ getSettablePaths: _CodexCliSkill.getSettablePaths
4915
+ });
4916
+ const result = CodexCliSkillFrontmatterSchema.safeParse(loaded.frontmatter);
4917
+ if (!result.success) {
4918
+ const skillDirPath = join44(loaded.baseDir, loaded.relativeDirPath, loaded.dirName);
4919
+ throw new Error(
4920
+ `Invalid frontmatter in ${join44(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`
4921
+ );
4922
+ }
4923
+ return new _CodexCliSkill({
4924
+ baseDir: loaded.baseDir,
4925
+ relativeDirPath: loaded.relativeDirPath,
4926
+ dirName: loaded.dirName,
4927
+ frontmatter: result.data,
4928
+ body: loaded.body,
4929
+ otherFiles: loaded.otherFiles,
4930
+ validate: true,
4931
+ global: loaded.global
4932
+ });
4834
4933
  }
4835
4934
  };
4836
4935
 
4837
4936
  // src/features/skills/copilot-skill.ts
4937
+ import { join as join45 } from "path";
4838
4938
  var CopilotSkill = class _CopilotSkill extends SimulatedSkill {
4839
4939
  static getSettablePaths(options) {
4840
4940
  if (options?.global) {
4841
4941
  throw new Error("CopilotSkill does not support global mode.");
4842
4942
  }
4843
4943
  return {
4844
- relativeDirPath: join44(".github", "skills")
4944
+ relativeDirPath: join45(".github", "skills")
4945
+ };
4946
+ }
4947
+ static async fromDir(params) {
4948
+ const baseParams = await this.fromDirDefault(params);
4949
+ return new _CopilotSkill(baseParams);
4950
+ }
4951
+ static fromRulesyncSkill(params) {
4952
+ const baseParams = {
4953
+ ...this.fromRulesyncSkillDefault(params),
4954
+ relativeDirPath: this.getSettablePaths().relativeDirPath
4955
+ };
4956
+ return new _CopilotSkill(baseParams);
4957
+ }
4958
+ static isTargetedByRulesyncSkill(rulesyncSkill) {
4959
+ return this.isTargetedByRulesyncSkillDefault({
4960
+ rulesyncSkill,
4961
+ toolTarget: "copilot"
4962
+ });
4963
+ }
4964
+ };
4965
+
4966
+ // src/features/skills/cursor-skill.ts
4967
+ import { join as join46 } from "path";
4968
+ var CursorSkill = class _CursorSkill extends SimulatedSkill {
4969
+ static getSettablePaths(options) {
4970
+ if (options?.global) {
4971
+ throw new Error("CursorSkill does not support global mode.");
4972
+ }
4973
+ return {
4974
+ relativeDirPath: join46(".cursor", "skills")
4845
4975
  };
4846
4976
  }
4847
4977
  static async fromDir(params) {
4848
4978
  const baseParams = await this.fromDirDefault(params);
4849
- return new _CopilotSkill(baseParams);
4979
+ return new _CursorSkill(baseParams);
4850
4980
  }
4851
4981
  static fromRulesyncSkill(params) {
4852
4982
  const baseParams = {
4853
4983
  ...this.fromRulesyncSkillDefault(params),
4854
4984
  relativeDirPath: this.getSettablePaths().relativeDirPath
4855
4985
  };
4856
- return new _CopilotSkill(baseParams);
4986
+ return new _CursorSkill(baseParams);
4857
4987
  }
4858
4988
  static isTargetedByRulesyncSkill(rulesyncSkill) {
4859
4989
  return this.isTargetedByRulesyncSkillDefault({
4860
4990
  rulesyncSkill,
4861
- toolTarget: "copilot"
4991
+ toolTarget: "cursor"
4862
4992
  });
4863
4993
  }
4864
4994
  };
4865
4995
 
4866
- // src/features/skills/cursor-skill.ts
4867
- import { join as join45 } from "path";
4868
- var CursorSkill = class _CursorSkill extends SimulatedSkill {
4996
+ // src/features/skills/geminicli-skill.ts
4997
+ import { join as join47 } from "path";
4998
+ var GeminiCliSkill = class _GeminiCliSkill extends SimulatedSkill {
4869
4999
  static getSettablePaths(options) {
4870
5000
  if (options?.global) {
4871
- throw new Error("CursorSkill does not support global mode.");
5001
+ throw new Error("GeminiCliSkill does not support global mode.");
4872
5002
  }
4873
5003
  return {
4874
- relativeDirPath: join45(".cursor", "skills")
5004
+ relativeDirPath: join47(".gemini", "skills")
4875
5005
  };
4876
5006
  }
4877
5007
  static async fromDir(params) {
4878
5008
  const baseParams = await this.fromDirDefault(params);
4879
- return new _CursorSkill(baseParams);
5009
+ return new _GeminiCliSkill(baseParams);
4880
5010
  }
4881
5011
  static fromRulesyncSkill(params) {
4882
5012
  const baseParams = {
4883
5013
  ...this.fromRulesyncSkillDefault(params),
4884
5014
  relativeDirPath: this.getSettablePaths().relativeDirPath
4885
5015
  };
4886
- return new _CursorSkill(baseParams);
5016
+ return new _GeminiCliSkill(baseParams);
4887
5017
  }
4888
5018
  static isTargetedByRulesyncSkill(rulesyncSkill) {
4889
5019
  return this.isTargetedByRulesyncSkillDefault({
4890
5020
  rulesyncSkill,
4891
- toolTarget: "cursor"
5021
+ toolTarget: "geminicli"
4892
5022
  });
4893
5023
  }
4894
5024
  };
@@ -4898,7 +5028,7 @@ import { basename as basename15, join as join50 } from "path";
4898
5028
  import { z as z23 } from "zod/mini";
4899
5029
 
4900
5030
  // src/types/dir-feature-processor.ts
4901
- import { join as join46 } from "path";
5031
+ import { join as join48 } from "path";
4902
5032
  var DirFeatureProcessor = class {
4903
5033
  baseDir;
4904
5034
  constructor({ baseDir = process.cwd() }) {
@@ -4920,14 +5050,14 @@ var DirFeatureProcessor = class {
4920
5050
  await ensureDir(dirPath);
4921
5051
  const mainFile = aiDir.getMainFile();
4922
5052
  if (mainFile) {
4923
- const mainFilePath = join46(dirPath, mainFile.name);
5053
+ const mainFilePath = join48(dirPath, mainFile.name);
4924
5054
  const content = stringifyFrontmatter(mainFile.body, mainFile.frontmatter);
4925
5055
  const contentWithNewline = addTrailingNewline(content);
4926
5056
  await writeFileContent(mainFilePath, contentWithNewline);
4927
5057
  }
4928
5058
  const otherFiles = aiDir.getOtherFiles();
4929
5059
  for (const file of otherFiles) {
4930
- const filePath = join46(dirPath, file.relativeFilePathToDirPath);
5060
+ const filePath = join48(dirPath, file.relativeFilePathToDirPath);
4931
5061
  const contentWithNewline = addTrailingNewline(file.fileBuffer.toString("utf-8"));
4932
5062
  await writeFileContent(filePath, contentWithNewline);
4933
5063
  }
@@ -4941,38 +5071,8 @@ var DirFeatureProcessor = class {
4941
5071
  }
4942
5072
  };
4943
5073
 
4944
- // src/features/skills/agentsmd-skill.ts
4945
- import { join as join47 } from "path";
4946
- var AgentsmdSkill = class _AgentsmdSkill extends SimulatedSkill {
4947
- static getSettablePaths(options) {
4948
- if (options?.global) {
4949
- throw new Error("AgentsmdSkill does not support global mode.");
4950
- }
4951
- return {
4952
- relativeDirPath: join47(".agents", "skills")
4953
- };
4954
- }
4955
- static async fromDir(params) {
4956
- const baseParams = await this.fromDirDefault(params);
4957
- return new _AgentsmdSkill(baseParams);
4958
- }
4959
- static fromRulesyncSkill(params) {
4960
- const baseParams = {
4961
- ...this.fromRulesyncSkillDefault(params),
4962
- relativeDirPath: this.getSettablePaths().relativeDirPath
4963
- };
4964
- return new _AgentsmdSkill(baseParams);
4965
- }
4966
- static isTargetedByRulesyncSkill(rulesyncSkill) {
4967
- return this.isTargetedByRulesyncSkillDefault({
4968
- rulesyncSkill,
4969
- toolTarget: "agentsmd"
4970
- });
4971
- }
4972
- };
4973
-
4974
5074
  // src/features/skills/claudecode-skill.ts
4975
- import { join as join48 } from "path";
5075
+ import { join as join49 } from "path";
4976
5076
  import { z as z22 } from "zod/mini";
4977
5077
  var ClaudecodeSkillFrontmatterSchema = z22.object({
4978
5078
  name: z22.string(),
@@ -4982,7 +5082,7 @@ var ClaudecodeSkillFrontmatterSchema = z22.object({
4982
5082
  var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
4983
5083
  constructor({
4984
5084
  baseDir = process.cwd(),
4985
- relativeDirPath = join48(".claude", "skills"),
5085
+ relativeDirPath = join49(".claude", "skills"),
4986
5086
  dirName,
4987
5087
  frontmatter,
4988
5088
  body,
@@ -5013,7 +5113,7 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
5013
5113
  global: _global = false
5014
5114
  } = {}) {
5015
5115
  return {
5016
- relativeDirPath: join48(".claude", "skills")
5116
+ relativeDirPath: join49(".claude", "skills")
5017
5117
  };
5018
5118
  }
5019
5119
  getFrontmatter() {
@@ -5100,9 +5200,9 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
5100
5200
  });
5101
5201
  const result = ClaudecodeSkillFrontmatterSchema.safeParse(loaded.frontmatter);
5102
5202
  if (!result.success) {
5103
- const skillDirPath = join48(loaded.baseDir, loaded.relativeDirPath, loaded.dirName);
5203
+ const skillDirPath = join49(loaded.baseDir, loaded.relativeDirPath, loaded.dirName);
5104
5204
  throw new Error(
5105
- `Invalid frontmatter in ${join48(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`
5205
+ `Invalid frontmatter in ${join49(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`
5106
5206
  );
5107
5207
  }
5108
5208
  return new _ClaudecodeSkill({
@@ -5118,36 +5218,6 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
5118
5218
  }
5119
5219
  };
5120
5220
 
5121
- // src/features/skills/geminicli-skill.ts
5122
- import { join as join49 } from "path";
5123
- var GeminiCliSkill = class _GeminiCliSkill extends SimulatedSkill {
5124
- static getSettablePaths(options) {
5125
- if (options?.global) {
5126
- throw new Error("GeminiCliSkill does not support global mode.");
5127
- }
5128
- return {
5129
- relativeDirPath: join49(".gemini", "skills")
5130
- };
5131
- }
5132
- static async fromDir(params) {
5133
- const baseParams = await this.fromDirDefault(params);
5134
- return new _GeminiCliSkill(baseParams);
5135
- }
5136
- static fromRulesyncSkill(params) {
5137
- const baseParams = {
5138
- ...this.fromRulesyncSkillDefault(params),
5139
- relativeDirPath: this.getSettablePaths().relativeDirPath
5140
- };
5141
- return new _GeminiCliSkill(baseParams);
5142
- }
5143
- static isTargetedByRulesyncSkill(rulesyncSkill) {
5144
- return this.isTargetedByRulesyncSkillDefault({
5145
- rulesyncSkill,
5146
- toolTarget: "geminicli"
5147
- });
5148
- }
5149
- };
5150
-
5151
5221
  // src/features/skills/skills-processor.ts
5152
5222
  var skillsProcessorToolTargetTuple = [
5153
5223
  "agentsmd",
@@ -6062,6 +6132,13 @@ var RulesyncRuleFrontmatterSchema = z28.object({
6062
6132
  subprojectPath: z28.optional(z28.string())
6063
6133
  })
6064
6134
  ),
6135
+ claudecode: z28.optional(
6136
+ z28.object({
6137
+ // Glob patterns for conditional rules (takes precedence over globs)
6138
+ // @example "src/**/*.ts, tests/**/*.test.ts"
6139
+ paths: z28.optional(z28.string())
6140
+ })
6141
+ ),
6065
6142
  cursor: z28.optional(
6066
6143
  z28.object({
6067
6144
  alwaysApply: z28.optional(z28.boolean()),
@@ -6625,9 +6702,9 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
6625
6702
  }
6626
6703
  };
6627
6704
 
6628
- // src/features/rules/claudecode-rule.ts
6705
+ // src/features/rules/claudecode-legacy-rule.ts
6629
6706
  import { join as join68 } from "path";
6630
- var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
6707
+ var ClaudecodeLegacyRule = class _ClaudecodeLegacyRule extends ToolRule {
6631
6708
  static getSettablePaths({
6632
6709
  global
6633
6710
  } = {}) {
@@ -6662,7 +6739,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
6662
6739
  const fileContent2 = await readFileContent(
6663
6740
  join68(baseDir, paths.root.relativeDirPath, relativePath2)
6664
6741
  );
6665
- return new _ClaudecodeRule({
6742
+ return new _ClaudecodeLegacyRule({
6666
6743
  baseDir,
6667
6744
  relativeDirPath: paths.root.relativeDirPath,
6668
6745
  relativeFilePath: paths.root.relativeFilePath,
@@ -6676,7 +6753,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
6676
6753
  }
6677
6754
  const relativePath = join68(paths.nonRoot.relativeDirPath, relativeFilePath);
6678
6755
  const fileContent = await readFileContent(join68(baseDir, relativePath));
6679
- return new _ClaudecodeRule({
6756
+ return new _ClaudecodeLegacyRule({
6680
6757
  baseDir,
6681
6758
  relativeDirPath: paths.nonRoot.relativeDirPath,
6682
6759
  relativeFilePath,
@@ -6692,7 +6769,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
6692
6769
  global = false
6693
6770
  }) {
6694
6771
  const paths = this.getSettablePaths({ global });
6695
- return new _ClaudecodeRule(
6772
+ return new _ClaudecodeLegacyRule(
6696
6773
  this.buildToolRuleParamsDefault({
6697
6774
  baseDir,
6698
6775
  rulesyncRule,
@@ -6711,16 +6788,208 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
6711
6788
  static isTargetedByRulesyncRule(rulesyncRule) {
6712
6789
  return this.isTargetedByRulesyncRuleDefault({
6713
6790
  rulesyncRule,
6714
- toolTarget: "claudecode"
6791
+ toolTarget: "claudecode-legacy"
6715
6792
  });
6716
6793
  }
6717
6794
  };
6718
6795
 
6719
- // src/features/rules/cline-rule.ts
6796
+ // src/features/rules/claudecode-rule.ts
6720
6797
  import { join as join69 } from "path";
6721
6798
  import { z as z29 } from "zod/mini";
6722
- var ClineRuleFrontmatterSchema = z29.object({
6723
- description: z29.string()
6799
+ var ClaudecodeRuleFrontmatterSchema = z29.object({
6800
+ paths: z29.optional(z29.string())
6801
+ });
6802
+ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
6803
+ frontmatter;
6804
+ body;
6805
+ static getSettablePaths({
6806
+ global
6807
+ } = {}) {
6808
+ if (global) {
6809
+ return {
6810
+ root: {
6811
+ relativeDirPath: ".claude",
6812
+ relativeFilePath: "CLAUDE.md"
6813
+ }
6814
+ };
6815
+ }
6816
+ return {
6817
+ root: {
6818
+ relativeDirPath: ".claude",
6819
+ relativeFilePath: "CLAUDE.md"
6820
+ },
6821
+ nonRoot: {
6822
+ relativeDirPath: join69(".claude", "rules")
6823
+ }
6824
+ };
6825
+ }
6826
+ constructor({ frontmatter, body, ...rest }) {
6827
+ if (rest.validate) {
6828
+ const result = ClaudecodeRuleFrontmatterSchema.safeParse(frontmatter);
6829
+ if (!result.success) {
6830
+ throw new Error(
6831
+ `Invalid frontmatter in ${join69(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
6832
+ );
6833
+ }
6834
+ }
6835
+ super({
6836
+ ...rest,
6837
+ // Root file: no frontmatter; Non-root file: with optional paths frontmatter
6838
+ fileContent: rest.root ? body : _ClaudecodeRule.generateFileContent(body, frontmatter)
6839
+ });
6840
+ this.frontmatter = frontmatter;
6841
+ this.body = body;
6842
+ }
6843
+ static generateFileContent(body, frontmatter) {
6844
+ if (frontmatter.paths) {
6845
+ return stringifyFrontmatter(body, { paths: frontmatter.paths });
6846
+ }
6847
+ return body;
6848
+ }
6849
+ static async fromFile({
6850
+ baseDir = process.cwd(),
6851
+ relativeFilePath,
6852
+ validate = true,
6853
+ global = false
6854
+ }) {
6855
+ const paths = this.getSettablePaths({ global });
6856
+ const isRoot = relativeFilePath === paths.root.relativeFilePath;
6857
+ if (isRoot) {
6858
+ const fileContent2 = await readFileContent(
6859
+ join69(baseDir, paths.root.relativeDirPath, paths.root.relativeFilePath)
6860
+ );
6861
+ return new _ClaudecodeRule({
6862
+ baseDir,
6863
+ relativeDirPath: paths.root.relativeDirPath,
6864
+ relativeFilePath: paths.root.relativeFilePath,
6865
+ frontmatter: {},
6866
+ body: fileContent2.trim(),
6867
+ validate,
6868
+ root: true
6869
+ });
6870
+ }
6871
+ if (!paths.nonRoot) {
6872
+ throw new Error("nonRoot path is not set");
6873
+ }
6874
+ const relativePath = join69(paths.nonRoot.relativeDirPath, relativeFilePath);
6875
+ const fileContent = await readFileContent(join69(baseDir, relativePath));
6876
+ const { frontmatter, body: content } = parseFrontmatter(fileContent);
6877
+ const result = ClaudecodeRuleFrontmatterSchema.safeParse(frontmatter);
6878
+ if (!result.success) {
6879
+ throw new Error(
6880
+ `Invalid frontmatter in ${join69(baseDir, relativePath)}: ${formatError(result.error)}`
6881
+ );
6882
+ }
6883
+ return new _ClaudecodeRule({
6884
+ baseDir,
6885
+ relativeDirPath: paths.nonRoot.relativeDirPath,
6886
+ relativeFilePath,
6887
+ frontmatter: result.data,
6888
+ body: content.trim(),
6889
+ validate,
6890
+ root: false
6891
+ });
6892
+ }
6893
+ static fromRulesyncRule({
6894
+ baseDir = process.cwd(),
6895
+ rulesyncRule,
6896
+ validate = true,
6897
+ global = false
6898
+ }) {
6899
+ const rulesyncFrontmatter = rulesyncRule.getFrontmatter();
6900
+ const root = rulesyncFrontmatter.root ?? false;
6901
+ const paths = this.getSettablePaths({ global });
6902
+ const claudecodePaths = rulesyncFrontmatter.claudecode?.paths;
6903
+ const globs = rulesyncFrontmatter.globs;
6904
+ const pathsValue = claudecodePaths ?? (globs?.length ? globs.join(", ") : void 0);
6905
+ const claudecodeFrontmatter = {
6906
+ paths: root ? void 0 : pathsValue
6907
+ };
6908
+ const body = rulesyncRule.getBody();
6909
+ if (root) {
6910
+ return new _ClaudecodeRule({
6911
+ baseDir,
6912
+ frontmatter: claudecodeFrontmatter,
6913
+ body,
6914
+ relativeDirPath: paths.root.relativeDirPath,
6915
+ relativeFilePath: paths.root.relativeFilePath,
6916
+ validate,
6917
+ root
6918
+ });
6919
+ }
6920
+ if (!paths.nonRoot) {
6921
+ throw new Error("nonRoot path is not set");
6922
+ }
6923
+ return new _ClaudecodeRule({
6924
+ baseDir,
6925
+ frontmatter: claudecodeFrontmatter,
6926
+ body,
6927
+ relativeDirPath: paths.nonRoot.relativeDirPath,
6928
+ relativeFilePath: rulesyncRule.getRelativeFilePath(),
6929
+ validate,
6930
+ root
6931
+ });
6932
+ }
6933
+ toRulesyncRule() {
6934
+ let globs;
6935
+ if (this.isRoot()) {
6936
+ globs = ["**/*"];
6937
+ } else if (this.frontmatter.paths) {
6938
+ globs = this.frontmatter.paths.split(",").map((g) => g.trim());
6939
+ }
6940
+ const rulesyncFrontmatter = {
6941
+ targets: ["*"],
6942
+ root: this.isRoot(),
6943
+ description: this.description,
6944
+ globs,
6945
+ ...this.frontmatter.paths && {
6946
+ claudecode: { paths: this.frontmatter.paths }
6947
+ }
6948
+ };
6949
+ return new RulesyncRule({
6950
+ baseDir: this.getBaseDir(),
6951
+ frontmatter: rulesyncFrontmatter,
6952
+ body: this.body,
6953
+ relativeDirPath: RULESYNC_RULES_RELATIVE_DIR_PATH,
6954
+ relativeFilePath: this.getRelativeFilePath(),
6955
+ validate: true
6956
+ });
6957
+ }
6958
+ validate() {
6959
+ if (!this.frontmatter) {
6960
+ return { success: true, error: null };
6961
+ }
6962
+ const result = ClaudecodeRuleFrontmatterSchema.safeParse(this.frontmatter);
6963
+ if (result.success) {
6964
+ return { success: true, error: null };
6965
+ } else {
6966
+ return {
6967
+ success: false,
6968
+ error: new Error(
6969
+ `Invalid frontmatter in ${join69(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
6970
+ )
6971
+ };
6972
+ }
6973
+ }
6974
+ getFrontmatter() {
6975
+ return this.frontmatter;
6976
+ }
6977
+ getBody() {
6978
+ return this.body;
6979
+ }
6980
+ static isTargetedByRulesyncRule(rulesyncRule) {
6981
+ return this.isTargetedByRulesyncRuleDefault({
6982
+ rulesyncRule,
6983
+ toolTarget: "claudecode"
6984
+ });
6985
+ }
6986
+ };
6987
+
6988
+ // src/features/rules/cline-rule.ts
6989
+ import { join as join70 } from "path";
6990
+ import { z as z30 } from "zod/mini";
6991
+ var ClineRuleFrontmatterSchema = z30.object({
6992
+ description: z30.string()
6724
6993
  });
6725
6994
  var ClineRule = class _ClineRule extends ToolRule {
6726
6995
  static getSettablePaths() {
@@ -6762,7 +7031,7 @@ var ClineRule = class _ClineRule extends ToolRule {
6762
7031
  validate = true
6763
7032
  }) {
6764
7033
  const fileContent = await readFileContent(
6765
- join69(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7034
+ join70(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
6766
7035
  );
6767
7036
  return new _ClineRule({
6768
7037
  baseDir,
@@ -6775,7 +7044,7 @@ var ClineRule = class _ClineRule extends ToolRule {
6775
7044
  };
6776
7045
 
6777
7046
  // src/features/rules/codexcli-rule.ts
6778
- import { join as join70 } from "path";
7047
+ import { join as join71 } from "path";
6779
7048
  var CodexcliRule = class _CodexcliRule extends ToolRule {
6780
7049
  static getSettablePaths({
6781
7050
  global
@@ -6794,7 +7063,7 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
6794
7063
  relativeFilePath: "AGENTS.md"
6795
7064
  },
6796
7065
  nonRoot: {
6797
- relativeDirPath: join70(".codex", "memories")
7066
+ relativeDirPath: join71(".codex", "memories")
6798
7067
  }
6799
7068
  };
6800
7069
  }
@@ -6809,7 +7078,7 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
6809
7078
  if (isRoot) {
6810
7079
  const relativePath2 = paths.root.relativeFilePath;
6811
7080
  const fileContent2 = await readFileContent(
6812
- join70(baseDir, paths.root.relativeDirPath, relativePath2)
7081
+ join71(baseDir, paths.root.relativeDirPath, relativePath2)
6813
7082
  );
6814
7083
  return new _CodexcliRule({
6815
7084
  baseDir,
@@ -6823,8 +7092,8 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
6823
7092
  if (!paths.nonRoot) {
6824
7093
  throw new Error("nonRoot path is not set");
6825
7094
  }
6826
- const relativePath = join70(paths.nonRoot.relativeDirPath, relativeFilePath);
6827
- const fileContent = await readFileContent(join70(baseDir, relativePath));
7095
+ const relativePath = join71(paths.nonRoot.relativeDirPath, relativeFilePath);
7096
+ const fileContent = await readFileContent(join71(baseDir, relativePath));
6828
7097
  return new _CodexcliRule({
6829
7098
  baseDir,
6830
7099
  relativeDirPath: paths.nonRoot.relativeDirPath,
@@ -6866,12 +7135,12 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
6866
7135
  };
6867
7136
 
6868
7137
  // src/features/rules/copilot-rule.ts
6869
- import { join as join71 } from "path";
6870
- import { z as z30 } from "zod/mini";
6871
- var CopilotRuleFrontmatterSchema = z30.object({
6872
- description: z30.optional(z30.string()),
6873
- applyTo: z30.optional(z30.string()),
6874
- excludeAgent: z30.optional(z30.union([z30.literal("code-review"), z30.literal("coding-agent")]))
7138
+ import { join as join72 } from "path";
7139
+ import { z as z31 } from "zod/mini";
7140
+ var CopilotRuleFrontmatterSchema = z31.object({
7141
+ description: z31.optional(z31.string()),
7142
+ applyTo: z31.optional(z31.string()),
7143
+ excludeAgent: z31.optional(z31.union([z31.literal("code-review"), z31.literal("coding-agent")]))
6875
7144
  });
6876
7145
  var CopilotRule = class _CopilotRule extends ToolRule {
6877
7146
  frontmatter;
@@ -6883,7 +7152,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
6883
7152
  relativeFilePath: "copilot-instructions.md"
6884
7153
  },
6885
7154
  nonRoot: {
6886
- relativeDirPath: join71(".github", "instructions")
7155
+ relativeDirPath: join72(".github", "instructions")
6887
7156
  }
6888
7157
  };
6889
7158
  }
@@ -6892,7 +7161,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
6892
7161
  const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
6893
7162
  if (!result.success) {
6894
7163
  throw new Error(
6895
- `Invalid frontmatter in ${join71(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
7164
+ `Invalid frontmatter in ${join72(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
6896
7165
  );
6897
7166
  }
6898
7167
  }
@@ -6974,11 +7243,11 @@ var CopilotRule = class _CopilotRule extends ToolRule {
6974
7243
  validate = true
6975
7244
  }) {
6976
7245
  const isRoot = relativeFilePath === "copilot-instructions.md";
6977
- const relativePath = isRoot ? join71(
7246
+ const relativePath = isRoot ? join72(
6978
7247
  this.getSettablePaths().root.relativeDirPath,
6979
7248
  this.getSettablePaths().root.relativeFilePath
6980
- ) : join71(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
6981
- const fileContent = await readFileContent(join71(baseDir, relativePath));
7249
+ ) : join72(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
7250
+ const fileContent = await readFileContent(join72(baseDir, relativePath));
6982
7251
  if (isRoot) {
6983
7252
  return new _CopilotRule({
6984
7253
  baseDir,
@@ -6994,7 +7263,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
6994
7263
  const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
6995
7264
  if (!result.success) {
6996
7265
  throw new Error(
6997
- `Invalid frontmatter in ${join71(baseDir, relativeFilePath)}: ${formatError(result.error)}`
7266
+ `Invalid frontmatter in ${join72(baseDir, relativeFilePath)}: ${formatError(result.error)}`
6998
7267
  );
6999
7268
  }
7000
7269
  return new _CopilotRule({
@@ -7018,7 +7287,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
7018
7287
  return {
7019
7288
  success: false,
7020
7289
  error: new Error(
7021
- `Invalid frontmatter in ${join71(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
7290
+ `Invalid frontmatter in ${join72(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
7022
7291
  )
7023
7292
  };
7024
7293
  }
@@ -7038,12 +7307,12 @@ var CopilotRule = class _CopilotRule extends ToolRule {
7038
7307
  };
7039
7308
 
7040
7309
  // src/features/rules/cursor-rule.ts
7041
- import { basename as basename20, join as join72 } from "path";
7042
- import { z as z31 } from "zod/mini";
7043
- var CursorRuleFrontmatterSchema = z31.object({
7044
- description: z31.optional(z31.string()),
7045
- globs: z31.optional(z31.string()),
7046
- alwaysApply: z31.optional(z31.boolean())
7310
+ import { basename as basename20, join as join73 } from "path";
7311
+ import { z as z32 } from "zod/mini";
7312
+ var CursorRuleFrontmatterSchema = z32.object({
7313
+ description: z32.optional(z32.string()),
7314
+ globs: z32.optional(z32.string()),
7315
+ alwaysApply: z32.optional(z32.boolean())
7047
7316
  });
7048
7317
  var CursorRule = class _CursorRule extends ToolRule {
7049
7318
  frontmatter;
@@ -7051,7 +7320,7 @@ var CursorRule = class _CursorRule extends ToolRule {
7051
7320
  static getSettablePaths() {
7052
7321
  return {
7053
7322
  nonRoot: {
7054
- relativeDirPath: join72(".cursor", "rules")
7323
+ relativeDirPath: join73(".cursor", "rules")
7055
7324
  }
7056
7325
  };
7057
7326
  }
@@ -7060,7 +7329,7 @@ var CursorRule = class _CursorRule extends ToolRule {
7060
7329
  const result = CursorRuleFrontmatterSchema.safeParse(frontmatter);
7061
7330
  if (!result.success) {
7062
7331
  throw new Error(
7063
- `Invalid frontmatter in ${join72(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
7332
+ `Invalid frontmatter in ${join73(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
7064
7333
  );
7065
7334
  }
7066
7335
  }
@@ -7177,13 +7446,13 @@ var CursorRule = class _CursorRule extends ToolRule {
7177
7446
  validate = true
7178
7447
  }) {
7179
7448
  const fileContent = await readFileContent(
7180
- join72(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7449
+ join73(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7181
7450
  );
7182
7451
  const { frontmatter, body: content } = _CursorRule.parseCursorFrontmatter(fileContent);
7183
7452
  const result = CursorRuleFrontmatterSchema.safeParse(frontmatter);
7184
7453
  if (!result.success) {
7185
7454
  throw new Error(
7186
- `Invalid frontmatter in ${join72(baseDir, relativeFilePath)}: ${formatError(result.error)}`
7455
+ `Invalid frontmatter in ${join73(baseDir, relativeFilePath)}: ${formatError(result.error)}`
7187
7456
  );
7188
7457
  }
7189
7458
  return new _CursorRule({
@@ -7206,7 +7475,7 @@ var CursorRule = class _CursorRule extends ToolRule {
7206
7475
  return {
7207
7476
  success: false,
7208
7477
  error: new Error(
7209
- `Invalid frontmatter in ${join72(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
7478
+ `Invalid frontmatter in ${join73(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
7210
7479
  )
7211
7480
  };
7212
7481
  }
@@ -7226,7 +7495,7 @@ var CursorRule = class _CursorRule extends ToolRule {
7226
7495
  };
7227
7496
 
7228
7497
  // src/features/rules/geminicli-rule.ts
7229
- import { join as join73 } from "path";
7498
+ import { join as join74 } from "path";
7230
7499
  var GeminiCliRule = class _GeminiCliRule extends ToolRule {
7231
7500
  static getSettablePaths({
7232
7501
  global
@@ -7245,7 +7514,7 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
7245
7514
  relativeFilePath: "GEMINI.md"
7246
7515
  },
7247
7516
  nonRoot: {
7248
- relativeDirPath: join73(".gemini", "memories")
7517
+ relativeDirPath: join74(".gemini", "memories")
7249
7518
  }
7250
7519
  };
7251
7520
  }
@@ -7260,7 +7529,7 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
7260
7529
  if (isRoot) {
7261
7530
  const relativePath2 = paths.root.relativeFilePath;
7262
7531
  const fileContent2 = await readFileContent(
7263
- join73(baseDir, paths.root.relativeDirPath, relativePath2)
7532
+ join74(baseDir, paths.root.relativeDirPath, relativePath2)
7264
7533
  );
7265
7534
  return new _GeminiCliRule({
7266
7535
  baseDir,
@@ -7274,8 +7543,8 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
7274
7543
  if (!paths.nonRoot) {
7275
7544
  throw new Error("nonRoot path is not set");
7276
7545
  }
7277
- const relativePath = join73(paths.nonRoot.relativeDirPath, relativeFilePath);
7278
- const fileContent = await readFileContent(join73(baseDir, relativePath));
7546
+ const relativePath = join74(paths.nonRoot.relativeDirPath, relativeFilePath);
7547
+ const fileContent = await readFileContent(join74(baseDir, relativePath));
7279
7548
  return new _GeminiCliRule({
7280
7549
  baseDir,
7281
7550
  relativeDirPath: paths.nonRoot.relativeDirPath,
@@ -7317,7 +7586,7 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
7317
7586
  };
7318
7587
 
7319
7588
  // src/features/rules/junie-rule.ts
7320
- import { join as join74 } from "path";
7589
+ import { join as join75 } from "path";
7321
7590
  var JunieRule = class _JunieRule extends ToolRule {
7322
7591
  static getSettablePaths() {
7323
7592
  return {
@@ -7326,7 +7595,7 @@ var JunieRule = class _JunieRule extends ToolRule {
7326
7595
  relativeFilePath: "guidelines.md"
7327
7596
  },
7328
7597
  nonRoot: {
7329
- relativeDirPath: join74(".junie", "memories")
7598
+ relativeDirPath: join75(".junie", "memories")
7330
7599
  }
7331
7600
  };
7332
7601
  }
@@ -7336,8 +7605,8 @@ var JunieRule = class _JunieRule extends ToolRule {
7336
7605
  validate = true
7337
7606
  }) {
7338
7607
  const isRoot = relativeFilePath === "guidelines.md";
7339
- const relativePath = isRoot ? "guidelines.md" : join74(".junie", "memories", relativeFilePath);
7340
- const fileContent = await readFileContent(join74(baseDir, relativePath));
7608
+ const relativePath = isRoot ? "guidelines.md" : join75(".junie", "memories", relativeFilePath);
7609
+ const fileContent = await readFileContent(join75(baseDir, relativePath));
7341
7610
  return new _JunieRule({
7342
7611
  baseDir,
7343
7612
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -7377,12 +7646,12 @@ var JunieRule = class _JunieRule extends ToolRule {
7377
7646
  };
7378
7647
 
7379
7648
  // src/features/rules/kiro-rule.ts
7380
- import { join as join75 } from "path";
7649
+ import { join as join76 } from "path";
7381
7650
  var KiroRule = class _KiroRule extends ToolRule {
7382
7651
  static getSettablePaths() {
7383
7652
  return {
7384
7653
  nonRoot: {
7385
- relativeDirPath: join75(".kiro", "steering")
7654
+ relativeDirPath: join76(".kiro", "steering")
7386
7655
  }
7387
7656
  };
7388
7657
  }
@@ -7392,7 +7661,7 @@ var KiroRule = class _KiroRule extends ToolRule {
7392
7661
  validate = true
7393
7662
  }) {
7394
7663
  const fileContent = await readFileContent(
7395
- join75(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7664
+ join76(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7396
7665
  );
7397
7666
  return new _KiroRule({
7398
7667
  baseDir,
@@ -7432,7 +7701,7 @@ var KiroRule = class _KiroRule extends ToolRule {
7432
7701
  };
7433
7702
 
7434
7703
  // src/features/rules/opencode-rule.ts
7435
- import { join as join76 } from "path";
7704
+ import { join as join77 } from "path";
7436
7705
  var OpenCodeRule = class _OpenCodeRule extends ToolRule {
7437
7706
  static getSettablePaths() {
7438
7707
  return {
@@ -7441,7 +7710,7 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
7441
7710
  relativeFilePath: "AGENTS.md"
7442
7711
  },
7443
7712
  nonRoot: {
7444
- relativeDirPath: join76(".opencode", "memories")
7713
+ relativeDirPath: join77(".opencode", "memories")
7445
7714
  }
7446
7715
  };
7447
7716
  }
@@ -7451,8 +7720,8 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
7451
7720
  validate = true
7452
7721
  }) {
7453
7722
  const isRoot = relativeFilePath === "AGENTS.md";
7454
- const relativePath = isRoot ? "AGENTS.md" : join76(".opencode", "memories", relativeFilePath);
7455
- const fileContent = await readFileContent(join76(baseDir, relativePath));
7723
+ const relativePath = isRoot ? "AGENTS.md" : join77(".opencode", "memories", relativeFilePath);
7724
+ const fileContent = await readFileContent(join77(baseDir, relativePath));
7456
7725
  return new _OpenCodeRule({
7457
7726
  baseDir,
7458
7727
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -7492,7 +7761,7 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
7492
7761
  };
7493
7762
 
7494
7763
  // src/features/rules/qwencode-rule.ts
7495
- import { join as join77 } from "path";
7764
+ import { join as join78 } from "path";
7496
7765
  var QwencodeRule = class _QwencodeRule extends ToolRule {
7497
7766
  static getSettablePaths() {
7498
7767
  return {
@@ -7501,7 +7770,7 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
7501
7770
  relativeFilePath: "QWEN.md"
7502
7771
  },
7503
7772
  nonRoot: {
7504
- relativeDirPath: join77(".qwen", "memories")
7773
+ relativeDirPath: join78(".qwen", "memories")
7505
7774
  }
7506
7775
  };
7507
7776
  }
@@ -7511,8 +7780,8 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
7511
7780
  validate = true
7512
7781
  }) {
7513
7782
  const isRoot = relativeFilePath === "QWEN.md";
7514
- const relativePath = isRoot ? "QWEN.md" : join77(".qwen", "memories", relativeFilePath);
7515
- const fileContent = await readFileContent(join77(baseDir, relativePath));
7783
+ const relativePath = isRoot ? "QWEN.md" : join78(".qwen", "memories", relativeFilePath);
7784
+ const fileContent = await readFileContent(join78(baseDir, relativePath));
7516
7785
  return new _QwencodeRule({
7517
7786
  baseDir,
7518
7787
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -7549,12 +7818,12 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
7549
7818
  };
7550
7819
 
7551
7820
  // src/features/rules/roo-rule.ts
7552
- import { join as join78 } from "path";
7821
+ import { join as join79 } from "path";
7553
7822
  var RooRule = class _RooRule extends ToolRule {
7554
7823
  static getSettablePaths() {
7555
7824
  return {
7556
7825
  nonRoot: {
7557
- relativeDirPath: join78(".roo", "rules")
7826
+ relativeDirPath: join79(".roo", "rules")
7558
7827
  }
7559
7828
  };
7560
7829
  }
@@ -7564,7 +7833,7 @@ var RooRule = class _RooRule extends ToolRule {
7564
7833
  validate = true
7565
7834
  }) {
7566
7835
  const fileContent = await readFileContent(
7567
- join78(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7836
+ join79(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7568
7837
  );
7569
7838
  return new _RooRule({
7570
7839
  baseDir,
@@ -7619,7 +7888,7 @@ var RooRule = class _RooRule extends ToolRule {
7619
7888
  };
7620
7889
 
7621
7890
  // src/features/rules/warp-rule.ts
7622
- import { join as join79 } from "path";
7891
+ import { join as join80 } from "path";
7623
7892
  var WarpRule = class _WarpRule extends ToolRule {
7624
7893
  constructor({ fileContent, root, ...rest }) {
7625
7894
  super({
@@ -7635,7 +7904,7 @@ var WarpRule = class _WarpRule extends ToolRule {
7635
7904
  relativeFilePath: "WARP.md"
7636
7905
  },
7637
7906
  nonRoot: {
7638
- relativeDirPath: join79(".warp", "memories")
7907
+ relativeDirPath: join80(".warp", "memories")
7639
7908
  }
7640
7909
  };
7641
7910
  }
@@ -7645,8 +7914,8 @@ var WarpRule = class _WarpRule extends ToolRule {
7645
7914
  validate = true
7646
7915
  }) {
7647
7916
  const isRoot = relativeFilePath === this.getSettablePaths().root.relativeFilePath;
7648
- const relativePath = isRoot ? this.getSettablePaths().root.relativeFilePath : join79(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
7649
- const fileContent = await readFileContent(join79(baseDir, relativePath));
7917
+ const relativePath = isRoot ? this.getSettablePaths().root.relativeFilePath : join80(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
7918
+ const fileContent = await readFileContent(join80(baseDir, relativePath));
7650
7919
  return new _WarpRule({
7651
7920
  baseDir,
7652
7921
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : ".warp",
@@ -7686,12 +7955,12 @@ var WarpRule = class _WarpRule extends ToolRule {
7686
7955
  };
7687
7956
 
7688
7957
  // src/features/rules/windsurf-rule.ts
7689
- import { join as join80 } from "path";
7958
+ import { join as join81 } from "path";
7690
7959
  var WindsurfRule = class _WindsurfRule extends ToolRule {
7691
7960
  static getSettablePaths() {
7692
7961
  return {
7693
7962
  nonRoot: {
7694
- relativeDirPath: join80(".windsurf", "rules")
7963
+ relativeDirPath: join81(".windsurf", "rules")
7695
7964
  }
7696
7965
  };
7697
7966
  }
@@ -7701,7 +7970,7 @@ var WindsurfRule = class _WindsurfRule extends ToolRule {
7701
7970
  validate = true
7702
7971
  }) {
7703
7972
  const fileContent = await readFileContent(
7704
- join80(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7973
+ join81(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7705
7974
  );
7706
7975
  return new _WindsurfRule({
7707
7976
  baseDir,
@@ -7747,6 +8016,7 @@ var rulesProcessorToolTargets = [
7747
8016
  "augmentcode",
7748
8017
  "augmentcode-legacy",
7749
8018
  "claudecode",
8019
+ "claudecode-legacy",
7750
8020
  "cline",
7751
8021
  "codexcli",
7752
8022
  "copilot",
@@ -7760,32 +8030,197 @@ var rulesProcessorToolTargets = [
7760
8030
  "warp",
7761
8031
  "windsurf"
7762
8032
  ];
7763
- var RulesProcessorToolTargetSchema = z32.enum(rulesProcessorToolTargets);
7764
- var rulesProcessorToolTargetsGlobal = [
7765
- "claudecode",
7766
- "codexcli",
7767
- "geminicli"
7768
- ];
8033
+ var RulesProcessorToolTargetSchema = z33.enum(rulesProcessorToolTargets);
7769
8034
  var toolRuleFactories = /* @__PURE__ */ new Map([
7770
- ["agentsmd", { class: AgentsMdRule, meta: { extension: "md" } }],
7771
- ["amazonqcli", { class: AmazonQCliRule, meta: { extension: "md" } }],
7772
- ["antigravity", { class: AntigravityRule, meta: { extension: "md" } }],
7773
- ["augmentcode", { class: AugmentcodeRule, meta: { extension: "md" } }],
7774
- ["augmentcode-legacy", { class: AugmentcodeLegacyRule, meta: { extension: "md" } }],
7775
- ["claudecode", { class: ClaudecodeRule, meta: { extension: "md" } }],
7776
- ["cline", { class: ClineRule, meta: { extension: "md" } }],
7777
- ["codexcli", { class: CodexcliRule, meta: { extension: "md" } }],
7778
- ["copilot", { class: CopilotRule, meta: { extension: "md" } }],
7779
- ["cursor", { class: CursorRule, meta: { extension: "mdc" } }],
7780
- ["geminicli", { class: GeminiCliRule, meta: { extension: "md" } }],
7781
- ["junie", { class: JunieRule, meta: { extension: "md" } }],
7782
- ["kiro", { class: KiroRule, meta: { extension: "md" } }],
7783
- ["opencode", { class: OpenCodeRule, meta: { extension: "md" } }],
7784
- ["qwencode", { class: QwencodeRule, meta: { extension: "md" } }],
7785
- ["roo", { class: RooRule, meta: { extension: "md" } }],
7786
- ["warp", { class: WarpRule, meta: { extension: "md" } }],
7787
- ["windsurf", { class: WindsurfRule, meta: { extension: "md" } }]
8035
+ [
8036
+ "agentsmd",
8037
+ {
8038
+ class: AgentsMdRule,
8039
+ meta: {
8040
+ extension: "md",
8041
+ supportsGlobal: false,
8042
+ ruleDiscoveryMode: "toon",
8043
+ additionalConventions: {
8044
+ commands: { commandClass: AgentsmdCommand },
8045
+ subagents: { subagentClass: AgentsmdSubagent },
8046
+ skills: { skillClass: AgentsmdSkill }
8047
+ }
8048
+ }
8049
+ }
8050
+ ],
8051
+ [
8052
+ "amazonqcli",
8053
+ {
8054
+ class: AmazonQCliRule,
8055
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
8056
+ }
8057
+ ],
8058
+ [
8059
+ "antigravity",
8060
+ {
8061
+ class: AntigravityRule,
8062
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
8063
+ }
8064
+ ],
8065
+ [
8066
+ "augmentcode",
8067
+ {
8068
+ class: AugmentcodeRule,
8069
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
8070
+ }
8071
+ ],
8072
+ [
8073
+ "augmentcode-legacy",
8074
+ {
8075
+ class: AugmentcodeLegacyRule,
8076
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
8077
+ }
8078
+ ],
8079
+ [
8080
+ "claudecode",
8081
+ {
8082
+ class: ClaudecodeRule,
8083
+ meta: { extension: "md", supportsGlobal: true, ruleDiscoveryMode: "auto" }
8084
+ }
8085
+ ],
8086
+ [
8087
+ "claudecode-legacy",
8088
+ {
8089
+ class: ClaudecodeLegacyRule,
8090
+ meta: { extension: "md", supportsGlobal: true, ruleDiscoveryMode: "claudecode-legacy" }
8091
+ }
8092
+ ],
8093
+ [
8094
+ "cline",
8095
+ {
8096
+ class: ClineRule,
8097
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
8098
+ }
8099
+ ],
8100
+ [
8101
+ "codexcli",
8102
+ {
8103
+ class: CodexcliRule,
8104
+ meta: {
8105
+ extension: "md",
8106
+ supportsGlobal: true,
8107
+ ruleDiscoveryMode: "toon",
8108
+ additionalConventions: {
8109
+ subagents: { subagentClass: CodexCliSubagent },
8110
+ skills: { skillClass: CodexCliSkill, globalOnly: true }
8111
+ }
8112
+ }
8113
+ }
8114
+ ],
8115
+ [
8116
+ "copilot",
8117
+ {
8118
+ class: CopilotRule,
8119
+ meta: {
8120
+ extension: "md",
8121
+ supportsGlobal: false,
8122
+ ruleDiscoveryMode: "auto",
8123
+ additionalConventions: {
8124
+ commands: { commandClass: CopilotCommand },
8125
+ subagents: { subagentClass: CopilotSubagent },
8126
+ skills: { skillClass: CopilotSkill }
8127
+ }
8128
+ }
8129
+ }
8130
+ ],
8131
+ [
8132
+ "cursor",
8133
+ {
8134
+ class: CursorRule,
8135
+ meta: {
8136
+ extension: "mdc",
8137
+ supportsGlobal: false,
8138
+ ruleDiscoveryMode: "auto",
8139
+ additionalConventions: {
8140
+ commands: { commandClass: CursorCommand },
8141
+ subagents: { subagentClass: CursorSubagent },
8142
+ skills: { skillClass: CursorSkill }
8143
+ },
8144
+ createsSeparateConventionsRule: true
8145
+ }
8146
+ }
8147
+ ],
8148
+ [
8149
+ "geminicli",
8150
+ {
8151
+ class: GeminiCliRule,
8152
+ meta: {
8153
+ extension: "md",
8154
+ supportsGlobal: true,
8155
+ ruleDiscoveryMode: "toon",
8156
+ additionalConventions: {
8157
+ commands: { commandClass: GeminiCliCommand },
8158
+ subagents: { subagentClass: GeminiCliSubagent },
8159
+ skills: { skillClass: GeminiCliSkill }
8160
+ }
8161
+ }
8162
+ }
8163
+ ],
8164
+ [
8165
+ "junie",
8166
+ {
8167
+ class: JunieRule,
8168
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
8169
+ }
8170
+ ],
8171
+ [
8172
+ "kiro",
8173
+ {
8174
+ class: KiroRule,
8175
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
8176
+ }
8177
+ ],
8178
+ [
8179
+ "opencode",
8180
+ {
8181
+ class: OpenCodeRule,
8182
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
8183
+ }
8184
+ ],
8185
+ [
8186
+ "qwencode",
8187
+ {
8188
+ class: QwencodeRule,
8189
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
8190
+ }
8191
+ ],
8192
+ [
8193
+ "roo",
8194
+ {
8195
+ class: RooRule,
8196
+ meta: {
8197
+ extension: "md",
8198
+ supportsGlobal: false,
8199
+ ruleDiscoveryMode: "auto",
8200
+ additionalConventions: {
8201
+ commands: { commandClass: RooCommand },
8202
+ subagents: { subagentClass: RooSubagent }
8203
+ },
8204
+ createsSeparateConventionsRule: true
8205
+ }
8206
+ }
8207
+ ],
8208
+ [
8209
+ "warp",
8210
+ {
8211
+ class: WarpRule,
8212
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
8213
+ }
8214
+ ],
8215
+ [
8216
+ "windsurf",
8217
+ {
8218
+ class: WindsurfRule,
8219
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
8220
+ }
8221
+ ]
7788
8222
  ]);
8223
+ var rulesProcessorToolTargetsGlobal = Array.from(toolRuleFactories.entries()).filter(([_, factory]) => factory.meta.supportsGlobal).map(([target]) => target);
7789
8224
  var defaultGetFactory6 = (target) => {
7790
8225
  const factory = toolRuleFactories.get(target);
7791
8226
  if (!factory) {
@@ -7800,6 +8235,7 @@ var RulesProcessor = class extends FeatureProcessor {
7800
8235
  simulateSkills;
7801
8236
  global;
7802
8237
  getFactory;
8238
+ skills;
7803
8239
  constructor({
7804
8240
  baseDir = process.cwd(),
7805
8241
  toolTarget,
@@ -7807,7 +8243,8 @@ var RulesProcessor = class extends FeatureProcessor {
7807
8243
  simulateSubagents = false,
7808
8244
  simulateSkills = false,
7809
8245
  global = false,
7810
- getFactory = defaultGetFactory6
8246
+ getFactory = defaultGetFactory6,
8247
+ skills
7811
8248
  }) {
7812
8249
  super({ baseDir });
7813
8250
  const result = RulesProcessorToolTargetSchema.safeParse(toolTarget);
@@ -7822,12 +8259,14 @@ var RulesProcessor = class extends FeatureProcessor {
7822
8259
  this.simulateSubagents = simulateSubagents;
7823
8260
  this.simulateSkills = simulateSkills;
7824
8261
  this.getFactory = getFactory;
8262
+ this.skills = skills;
7825
8263
  }
7826
8264
  async convertRulesyncFilesToToolFiles(rulesyncFiles) {
7827
8265
  const rulesyncRules = rulesyncFiles.filter(
7828
8266
  (file) => file instanceof RulesyncRule
7829
8267
  );
7830
8268
  const factory = this.getFactory(this.toolTarget);
8269
+ const { meta } = factory;
7831
8270
  const toolRules = rulesyncRules.map((rulesyncRule) => {
7832
8271
  if (!factory.class.isTargetedByRulesyncRule(rulesyncRule)) {
7833
8272
  return null;
@@ -7840,150 +8279,105 @@ var RulesProcessor = class extends FeatureProcessor {
7840
8279
  });
7841
8280
  }).filter((rule) => rule !== null);
7842
8281
  const isSimulated = this.simulateCommands || this.simulateSubagents || this.simulateSkills;
7843
- if (isSimulated && this.toolTarget === "cursor") {
7844
- toolRules.push(
7845
- new CursorRule({
7846
- baseDir: this.baseDir,
7847
- frontmatter: {
7848
- alwaysApply: true
7849
- },
7850
- body: this.generateAdditionalConventionsSection({
7851
- commands: { relativeDirPath: CursorCommand.getSettablePaths().relativeDirPath },
7852
- subagents: {
7853
- relativeDirPath: CursorSubagent.getSettablePaths().relativeDirPath
7854
- },
7855
- skills: {
7856
- relativeDirPath: CursorSkill.getSettablePaths().relativeDirPath
7857
- }
7858
- }),
7859
- relativeDirPath: CursorRule.getSettablePaths().nonRoot.relativeDirPath,
7860
- relativeFilePath: "additional-conventions.mdc",
7861
- validate: true
7862
- })
7863
- );
7864
- }
7865
- if (isSimulated && this.toolTarget === "roo") {
7866
- toolRules.push(
7867
- new RooRule({
7868
- baseDir: this.baseDir,
7869
- relativeDirPath: RooRule.getSettablePaths().nonRoot.relativeDirPath,
7870
- relativeFilePath: "additional-conventions.md",
7871
- fileContent: this.generateAdditionalConventionsSection({
7872
- commands: { relativeDirPath: RooCommand.getSettablePaths().relativeDirPath },
7873
- subagents: {
7874
- relativeDirPath: RooSubagent.getSettablePaths().relativeDirPath
7875
- }
7876
- }),
7877
- validate: true
7878
- })
7879
- );
8282
+ if (isSimulated && meta.createsSeparateConventionsRule && meta.additionalConventions) {
8283
+ const conventionsContent = this.generateAdditionalConventionsSectionFromMeta(meta);
8284
+ const settablePaths = factory.class.getSettablePaths();
8285
+ const nonRootPath = "nonRoot" in settablePaths ? settablePaths.nonRoot : null;
8286
+ if (nonRootPath) {
8287
+ toolRules.push(
8288
+ factory.class.fromRulesyncRule({
8289
+ baseDir: this.baseDir,
8290
+ rulesyncRule: new RulesyncRule({
8291
+ baseDir: this.baseDir,
8292
+ relativeDirPath: nonRootPath.relativeDirPath,
8293
+ relativeFilePath: "additional-conventions.md",
8294
+ frontmatter: {
8295
+ root: false,
8296
+ targets: [this.toolTarget]
8297
+ },
8298
+ body: conventionsContent
8299
+ }),
8300
+ validate: true,
8301
+ global: this.global
8302
+ })
8303
+ );
8304
+ }
7880
8305
  }
7881
8306
  const rootRuleIndex = toolRules.findIndex((rule) => rule.isRoot());
7882
8307
  if (rootRuleIndex === -1) {
7883
8308
  return toolRules;
7884
8309
  }
7885
- switch (this.toolTarget) {
7886
- case "agentsmd": {
7887
- const rootRule = toolRules[rootRuleIndex];
7888
- rootRule?.setFileContent(
7889
- this.generateToonReferencesSection(toolRules) + this.generateAdditionalConventionsSection({
7890
- commands: { relativeDirPath: AgentsmdCommand.getSettablePaths().relativeDirPath },
7891
- subagents: {
7892
- relativeDirPath: AgentsmdSubagent.getSettablePaths().relativeDirPath
7893
- }
7894
- }) + rootRule.getFileContent()
7895
- );
7896
- return toolRules;
7897
- }
7898
- case "augmentcode-legacy": {
7899
- const rootRule = toolRules[rootRuleIndex];
7900
- rootRule?.setFileContent(
7901
- this.generateToonReferencesSection(toolRules) + rootRule.getFileContent()
7902
- );
7903
- return toolRules;
7904
- }
7905
- case "claudecode": {
7906
- const rootRule = toolRules[rootRuleIndex];
7907
- rootRule?.setFileContent(
7908
- this.generateReferencesSection(toolRules) + rootRule.getFileContent()
7909
- );
7910
- return toolRules;
7911
- }
7912
- case "codexcli": {
7913
- const rootRule = toolRules[rootRuleIndex];
7914
- rootRule?.setFileContent(
7915
- this.generateToonReferencesSection(toolRules) + this.generateAdditionalConventionsSection({
7916
- subagents: {
7917
- relativeDirPath: CodexCliSubagent.getSettablePaths().relativeDirPath
7918
- },
7919
- // Codex CLI skills are only supported in global mode
7920
- ...this.global && {
7921
- skills: {
7922
- relativeDirPath: CodexCliSkill.getSettablePaths({ global: this.global }).relativeDirPath
7923
- }
7924
- }
7925
- }) + rootRule.getFileContent()
7926
- );
7927
- return toolRules;
7928
- }
7929
- case "copilot": {
7930
- const rootRule = toolRules[rootRuleIndex];
7931
- rootRule?.setFileContent(
7932
- this.generateAdditionalConventionsSection({
7933
- commands: { relativeDirPath: CopilotCommand.getSettablePaths().relativeDirPath },
7934
- subagents: {
7935
- relativeDirPath: CopilotSubagent.getSettablePaths().relativeDirPath
7936
- },
7937
- skills: {
7938
- relativeDirPath: CopilotSkill.getSettablePaths().relativeDirPath
7939
- }
7940
- }) + rootRule.getFileContent()
7941
- );
7942
- return toolRules;
7943
- }
7944
- case "geminicli": {
7945
- const rootRule = toolRules[rootRuleIndex];
7946
- rootRule?.setFileContent(
7947
- this.generateToonReferencesSection(toolRules) + this.generateAdditionalConventionsSection({
7948
- commands: { relativeDirPath: GeminiCliCommand.getSettablePaths().relativeDirPath },
7949
- subagents: {
7950
- relativeDirPath: GeminiCliSubagent.getSettablePaths().relativeDirPath
7951
- }
7952
- }) + rootRule.getFileContent()
7953
- );
7954
- return toolRules;
7955
- }
7956
- case "kiro": {
7957
- const rootRule = toolRules[rootRuleIndex];
7958
- rootRule?.setFileContent(
7959
- this.generateToonReferencesSection(toolRules) + rootRule.getFileContent()
7960
- );
7961
- return toolRules;
7962
- }
7963
- case "opencode": {
7964
- const rootRule = toolRules[rootRuleIndex];
7965
- rootRule?.setFileContent(
7966
- this.generateToonReferencesSection(toolRules) + rootRule.getFileContent()
7967
- );
7968
- return toolRules;
7969
- }
7970
- case "qwencode": {
7971
- const rootRule = toolRules[rootRuleIndex];
7972
- rootRule?.setFileContent(
7973
- this.generateToonReferencesSection(toolRules) + rootRule.getFileContent()
7974
- );
7975
- return toolRules;
7976
- }
7977
- case "warp": {
7978
- const rootRule = toolRules[rootRuleIndex];
7979
- rootRule?.setFileContent(
7980
- this.generateToonReferencesSection(toolRules) + rootRule.getFileContent()
7981
- );
7982
- return toolRules;
7983
- }
8310
+ const rootRule = toolRules[rootRuleIndex];
8311
+ if (!rootRule) {
8312
+ return toolRules;
8313
+ }
8314
+ const referenceSection = this.generateReferenceSectionFromMeta(meta, toolRules);
8315
+ const conventionsSection = !meta.createsSeparateConventionsRule && meta.additionalConventions ? this.generateAdditionalConventionsSectionFromMeta(meta) : "";
8316
+ const newContent = referenceSection + conventionsSection + rootRule.getFileContent();
8317
+ rootRule.setFileContent(newContent);
8318
+ return toolRules;
8319
+ }
8320
+ buildSkillList(skillClass) {
8321
+ if (!this.skills) return [];
8322
+ const toolRelativeDirPath = skillClass.getSettablePaths({
8323
+ global: this.global
8324
+ }).relativeDirPath;
8325
+ return this.skills.filter((skill) => skillClass.isTargetedByRulesyncSkill(skill)).map((skill) => {
8326
+ const frontmatter = skill.getFrontmatter();
8327
+ const relativePath = join82(toolRelativeDirPath, skill.getDirName(), SKILL_FILE_NAME);
8328
+ return {
8329
+ name: frontmatter.name,
8330
+ description: frontmatter.description,
8331
+ path: relativePath
8332
+ };
8333
+ });
8334
+ }
8335
+ /**
8336
+ * Generate reference section based on meta configuration.
8337
+ */
8338
+ generateReferenceSectionFromMeta(meta, toolRules) {
8339
+ switch (meta.ruleDiscoveryMode) {
8340
+ case "toon":
8341
+ return this.generateToonReferencesSection(toolRules);
8342
+ case "claudecode-legacy":
8343
+ return this.generateReferencesSection(toolRules);
8344
+ case "auto":
7984
8345
  default:
7985
- return toolRules;
8346
+ return "";
8347
+ }
8348
+ }
8349
+ /**
8350
+ * Generate additional conventions section based on meta configuration.
8351
+ */
8352
+ generateAdditionalConventionsSectionFromMeta(meta) {
8353
+ const { additionalConventions } = meta;
8354
+ if (!additionalConventions) {
8355
+ return "";
8356
+ }
8357
+ const conventions = {};
8358
+ if (additionalConventions.commands) {
8359
+ const { commandClass } = additionalConventions.commands;
8360
+ const relativeDirPath = commandClass.getSettablePaths({
8361
+ global: this.global
8362
+ }).relativeDirPath;
8363
+ conventions.commands = { relativeDirPath };
8364
+ }
8365
+ if (additionalConventions.subagents) {
8366
+ const { subagentClass } = additionalConventions.subagents;
8367
+ const relativeDirPath = subagentClass.getSettablePaths({
8368
+ global: this.global
8369
+ }).relativeDirPath;
8370
+ conventions.subagents = { relativeDirPath };
7986
8371
  }
8372
+ if (additionalConventions.skills) {
8373
+ const { skillClass, globalOnly } = additionalConventions.skills;
8374
+ if (!globalOnly || this.global) {
8375
+ conventions.skills = {
8376
+ skillList: this.buildSkillList(skillClass)
8377
+ };
8378
+ }
8379
+ }
8380
+ return this.generateAdditionalConventionsSection(conventions);
7987
8381
  }
7988
8382
  async convertToolFilesToRulesyncFiles(toolFiles) {
7989
8383
  const toolRules = toolFiles.filter((file) => file instanceof ToolRule);
@@ -7997,7 +8391,7 @@ var RulesProcessor = class extends FeatureProcessor {
7997
8391
  * Load and parse rulesync rule files from .rulesync/rules/ directory
7998
8392
  */
7999
8393
  async loadRulesyncFiles() {
8000
- const files = await findFilesByGlobs(join81(RULESYNC_RULES_RELATIVE_DIR_PATH, "*.md"));
8394
+ const files = await findFilesByGlobs(join82(RULESYNC_RULES_RELATIVE_DIR_PATH, "*.md"));
8001
8395
  logger.debug(`Found ${files.length} rulesync files`);
8002
8396
  const rulesyncRules = await Promise.all(
8003
8397
  files.map((file) => RulesyncRule.fromFile({ relativeFilePath: basename21(file) }))
@@ -8018,7 +8412,7 @@ var RulesProcessor = class extends FeatureProcessor {
8018
8412
  return rulesyncRules;
8019
8413
  }
8020
8414
  async loadRulesyncFilesLegacy() {
8021
- const legacyFiles = await findFilesByGlobs(join81(RULESYNC_RELATIVE_DIR_PATH, "*.md"));
8415
+ const legacyFiles = await findFilesByGlobs(join82(RULESYNC_RELATIVE_DIR_PATH, "*.md"));
8022
8416
  logger.debug(`Found ${legacyFiles.length} legacy rulesync files`);
8023
8417
  return Promise.all(
8024
8418
  legacyFiles.map((file) => RulesyncRule.fromFileLegacy({ relativeFilePath: basename21(file) }))
@@ -8039,7 +8433,7 @@ var RulesProcessor = class extends FeatureProcessor {
8039
8433
  return [];
8040
8434
  }
8041
8435
  const rootFilePaths = await findFilesByGlobs(
8042
- join81(
8436
+ join82(
8043
8437
  this.baseDir,
8044
8438
  settablePaths.root.relativeDirPath ?? ".",
8045
8439
  settablePaths.root.relativeFilePath
@@ -8061,7 +8455,7 @@ var RulesProcessor = class extends FeatureProcessor {
8061
8455
  return [];
8062
8456
  }
8063
8457
  const nonRootFilePaths = await findFilesByGlobs(
8064
- join81(this.baseDir, settablePaths.nonRoot.relativeDirPath, `*.${factory.meta.extension}`)
8458
+ join82(this.baseDir, settablePaths.nonRoot.relativeDirPath, `*.${factory.meta.extension}`)
8065
8459
  );
8066
8460
  return await Promise.all(
8067
8461
  nonRootFilePaths.map(
@@ -8160,23 +8554,15 @@ s/<command> [arguments]
8160
8554
  This syntax employs a double slash (\`s/\`) to prevent conflicts with built-in slash commands.
8161
8555
  The \`s\` in \`s/\` stands for *simulate*. Because custom slash commands are not built-in, this syntax provides a pseudo way to invoke them.
8162
8556
 
8163
- When users call a custom slash command, you have to look for the markdown file, \`${join81(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "{command}.md")}\`, then execute the contents of that file as the block of operations.` : "";
8557
+ When users call a custom slash command, you have to look for the markdown file, \`${join82(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "{command}.md")}\`, then execute the contents of that file as the block of operations.` : "";
8164
8558
  const subagentsSection = subagents ? `## Simulated Subagents
8165
8559
 
8166
8560
  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.
8167
8561
 
8168
- When users call a simulated subagent, it will look for the corresponding markdown file, \`${join81(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "{subagent}.md")}\`, and execute its contents as the block of operations.
8169
-
8170
- For example, if the user instructs \`Call planner subagent to plan the refactoring\`, you have to look for the markdown file, \`${join81(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "planner.md")}\`, and execute its contents as the block of operations.` : "";
8171
- const skillsSection = skills ? `## Simulated Skills
8562
+ When users call a simulated subagent, it will look for the corresponding markdown file, \`${join82(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "{subagent}.md")}\`, and execute its contents as the block of operations.
8172
8563
 
8173
- Simulated skills are specialized capabilities that can be invoked to handle specific types of tasks.
8174
-
8175
- When users invoke a simulated skill, look for the corresponding SKILL.md file in \`${join81(RULESYNC_SKILLS_RELATIVE_DIR_PATH, "{skill}/SKILL.md")}\` and execute its contents as the block of operations.
8176
-
8177
- For example, if the user instructs \`Use the skill example-skill to achieve something\`, look for \`${join81(RULESYNC_SKILLS_RELATIVE_DIR_PATH, "example-skill/SKILL.md")}\` and execute its contents.
8178
-
8179
- Additionally, you should proactively consider using available skills when they would help accomplish a task more effectively, even if the user doesn't explicitly request them.` : "";
8564
+ For example, if the user instructs \`Call planner subagent to plan the refactoring\`, you have to look for the markdown file, \`${join82(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "planner.md")}\`, and execute its contents as the block of operations.` : "";
8565
+ const skillsSection = skills ? this.generateSkillsSection(skills) : "";
8180
8566
  const result = [
8181
8567
  overview,
8182
8568
  ...this.simulateCommands && CommandsProcessor.getToolTargetsSimulated().includes(this.toolTarget) ? [commandsSection] : [],
@@ -8185,6 +8571,21 @@ Additionally, you should proactively consider using available skills when they w
8185
8571
  ].join("\n\n") + "\n\n";
8186
8572
  return result;
8187
8573
  }
8574
+ generateSkillsSection(skills) {
8575
+ if (!skills.skillList || skills.skillList.length === 0) {
8576
+ return "";
8577
+ }
8578
+ const skillListWithAtPrefix = skills.skillList.map((skill) => ({
8579
+ ...skill,
8580
+ path: `@${skill.path}`
8581
+ }));
8582
+ const toonContent = encode({ skillList: skillListWithAtPrefix });
8583
+ return `## Simulated Skills
8584
+
8585
+ Simulated skills are specialized capabilities that can be invoked to handle specific types of tasks. When you determine that a skill would be helpful for the current task, read the corresponding SKILL.md file and execute its instructions.
8586
+
8587
+ ${toonContent}`;
8588
+ }
8188
8589
  };
8189
8590
 
8190
8591
  // src/cli/commands/generate.ts
@@ -8197,13 +8598,15 @@ async function generateCommand(options) {
8197
8598
  process.exit(1);
8198
8599
  }
8199
8600
  logger.info(`Base directories: ${config.getBaseDirs().join(", ")}`);
8200
- const totalRulesOutputs = await generateRules(config);
8201
8601
  const totalIgnoreOutputs = await generateIgnore(config);
8202
8602
  const totalMcpOutputs = await generateMcp(config);
8203
8603
  const totalCommandOutputs = await generateCommands(config);
8204
8604
  const totalSubagentOutputs = await generateSubagents(config);
8205
- const totalSkillOutputs = await generateSkills(config);
8206
- const totalGenerated = totalRulesOutputs + totalMcpOutputs + totalCommandOutputs + totalIgnoreOutputs + totalSubagentOutputs + totalSkillOutputs;
8605
+ const skillsResult = await generateSkills(config);
8606
+ const totalRulesOutputs = await generateRules(config, {
8607
+ skills: skillsResult.skills
8608
+ });
8609
+ const totalGenerated = totalRulesOutputs + totalMcpOutputs + totalCommandOutputs + totalIgnoreOutputs + totalSubagentOutputs + skillsResult.totalOutputs;
8207
8610
  if (totalGenerated === 0) {
8208
8611
  const enabledFeatures = config.getFeatures().join(", ");
8209
8612
  logger.warn(`\u26A0\uFE0F No files generated for enabled features: ${enabledFeatures}`);
@@ -8216,11 +8619,11 @@ async function generateCommand(options) {
8216
8619
  if (totalMcpOutputs > 0) parts.push(`${totalMcpOutputs} MCP files`);
8217
8620
  if (totalCommandOutputs > 0) parts.push(`${totalCommandOutputs} commands`);
8218
8621
  if (totalSubagentOutputs > 0) parts.push(`${totalSubagentOutputs} subagents`);
8219
- if (totalSkillOutputs > 0) parts.push(`${totalSkillOutputs} skills`);
8622
+ if (skillsResult.totalOutputs > 0) parts.push(`${skillsResult.totalOutputs} skills`);
8220
8623
  logger.success(`\u{1F389} All done! Generated ${totalGenerated} file(s) total (${parts.join(" + ")})`);
8221
8624
  }
8222
8625
  }
8223
- async function generateRules(config) {
8626
+ async function generateRules(config, options) {
8224
8627
  if (!config.getFeatures().includes("rules")) {
8225
8628
  logger.debug("Skipping rule generation (not in --features)");
8226
8629
  return 0;
@@ -8239,7 +8642,8 @@ async function generateRules(config) {
8239
8642
  global: config.getGlobal(),
8240
8643
  simulateCommands: config.getSimulateCommands(),
8241
8644
  simulateSubagents: config.getSimulateSubagents(),
8242
- simulateSkills: config.getSimulateSkills()
8645
+ simulateSkills: config.getSimulateSkills(),
8646
+ skills: options?.skills
8243
8647
  });
8244
8648
  if (config.getDelete()) {
8245
8649
  const oldToolFiles = await processor.loadToolFiles({ forDeletion: true });
@@ -8403,9 +8807,10 @@ async function generateSubagents(config) {
8403
8807
  async function generateSkills(config) {
8404
8808
  if (!config.getFeatures().includes("skills")) {
8405
8809
  logger.debug("Skipping skill generation (not in --features)");
8406
- return 0;
8810
+ return { totalOutputs: 0, skills: [] };
8407
8811
  }
8408
8812
  let totalSkillOutputs = 0;
8813
+ const allSkills = [];
8409
8814
  logger.info("Generating skill files...");
8410
8815
  const toolTargets = intersection(
8411
8816
  config.getTargets(),
@@ -8426,112 +8831,164 @@ async function generateSkills(config) {
8426
8831
  await processor.removeAiDirs(oldToolDirs);
8427
8832
  }
8428
8833
  const rulesyncDirs = await processor.loadRulesyncDirs();
8834
+ for (const rulesyncDir of rulesyncDirs) {
8835
+ if (rulesyncDir instanceof RulesyncSkill) {
8836
+ allSkills.push(rulesyncDir);
8837
+ }
8838
+ }
8429
8839
  const toolDirs = await processor.convertRulesyncDirsToToolDirs(rulesyncDirs);
8430
8840
  const writtenCount = await processor.writeAiDirs(toolDirs);
8431
8841
  totalSkillOutputs += writtenCount;
8432
8842
  logger.success(`Generated ${writtenCount} ${toolTarget} skill(s) in ${baseDir}`);
8433
8843
  }
8434
8844
  }
8435
- return totalSkillOutputs;
8845
+ return { totalOutputs: totalSkillOutputs, skills: allSkills };
8436
8846
  }
8437
8847
 
8438
8848
  // src/cli/commands/gitignore.ts
8439
- import { join as join82 } from "path";
8849
+ import { join as join83 } from "path";
8850
+ var RULESYNC_HEADER = "# Generated by Rulesync";
8851
+ var LEGACY_RULESYNC_HEADER = "# Generated by rulesync - AI tool configuration files";
8852
+ var RULESYNC_IGNORE_ENTRIES = [
8853
+ // AGENTS.md
8854
+ "**/AGENTS.md",
8855
+ "**/.agents/",
8856
+ // Amazon Q
8857
+ "**/.amazonq/",
8858
+ // Augment
8859
+ "**/.augmentignore",
8860
+ "**/.augment/rules/",
8861
+ "**/.augment-guidelines",
8862
+ // Claude Code
8863
+ "**/CLAUDE.md",
8864
+ "**/.claude/CLAUDE.md",
8865
+ "**/.claude/memories/",
8866
+ "**/.claude/rules/",
8867
+ "**/.claude/commands/",
8868
+ "**/.claude/agents/",
8869
+ "**/.claude/skills/",
8870
+ "**/.claude/settings.local.json",
8871
+ "**/.mcp.json",
8872
+ // Cline
8873
+ "**/.clinerules/",
8874
+ "**/.clineignore",
8875
+ "**/.cline/mcp.json",
8876
+ // Codex
8877
+ "**/.codexignore",
8878
+ "**/.codex/",
8879
+ "**/.codex/skills/",
8880
+ // Cursor
8881
+ "**/.cursor/",
8882
+ "**/.cursorignore",
8883
+ // Gemini
8884
+ "**/GEMINI.md",
8885
+ "**/.gemini/memories/",
8886
+ "**/.gemini/commands/",
8887
+ "**/.gemini/subagents/",
8888
+ "**/.gemini/skills/",
8889
+ "**/.geminiignore",
8890
+ // GitHub Copilot
8891
+ "**/.github/copilot-instructions.md",
8892
+ "**/.github/instructions/",
8893
+ "**/.github/prompts/",
8894
+ "**/.github/subagents/",
8895
+ "**/.github/skills/",
8896
+ "**/.vscode/mcp.json",
8897
+ // Junie
8898
+ "**/.junie/guidelines.md",
8899
+ "**/.junie/mcp.json",
8900
+ // Kiro
8901
+ "**/.kiro/steering/",
8902
+ "**/.aiignore",
8903
+ // OpenCode
8904
+ "**/.opencode/memories/",
8905
+ "**/.opencode/command/",
8906
+ "**/opencode.json",
8907
+ // Qwen
8908
+ "**/QWEN.md",
8909
+ "**/.qwen/memories/",
8910
+ // Roo
8911
+ "**/.roo/rules/",
8912
+ "**/.rooignore",
8913
+ "**/.roo/mcp.json",
8914
+ "**/.roo/subagents/",
8915
+ // Warp
8916
+ "**/.warp/",
8917
+ "**/WARP.md",
8918
+ // Others
8919
+ "**/modular-mcp.json",
8920
+ "!.rulesync/.aiignore"
8921
+ ];
8922
+ var isRulesyncHeader = (line) => {
8923
+ const trimmed = line.trim();
8924
+ return trimmed === RULESYNC_HEADER || trimmed === LEGACY_RULESYNC_HEADER;
8925
+ };
8926
+ var isRulesyncEntry = (line) => {
8927
+ const trimmed = line.trim();
8928
+ if (trimmed === "" || isRulesyncHeader(line)) {
8929
+ return false;
8930
+ }
8931
+ return RULESYNC_IGNORE_ENTRIES.includes(trimmed);
8932
+ };
8933
+ var removeExistingRulesyncEntries = (content) => {
8934
+ const lines = content.split("\n");
8935
+ const filteredLines = [];
8936
+ let inRulesyncBlock = false;
8937
+ let consecutiveEmptyLines = 0;
8938
+ for (const line of lines) {
8939
+ const trimmed = line.trim();
8940
+ if (isRulesyncHeader(line)) {
8941
+ inRulesyncBlock = true;
8942
+ continue;
8943
+ }
8944
+ if (inRulesyncBlock) {
8945
+ if (trimmed === "") {
8946
+ consecutiveEmptyLines++;
8947
+ if (consecutiveEmptyLines >= 2) {
8948
+ inRulesyncBlock = false;
8949
+ consecutiveEmptyLines = 0;
8950
+ }
8951
+ continue;
8952
+ }
8953
+ if (isRulesyncEntry(line)) {
8954
+ consecutiveEmptyLines = 0;
8955
+ continue;
8956
+ }
8957
+ inRulesyncBlock = false;
8958
+ consecutiveEmptyLines = 0;
8959
+ }
8960
+ if (isRulesyncEntry(line)) {
8961
+ continue;
8962
+ }
8963
+ filteredLines.push(line);
8964
+ }
8965
+ let result = filteredLines.join("\n");
8966
+ while (result.endsWith("\n\n")) {
8967
+ result = result.slice(0, -1);
8968
+ }
8969
+ return result;
8970
+ };
8440
8971
  var gitignoreCommand = async () => {
8441
- const gitignorePath = join82(process.cwd(), ".gitignore");
8442
- const rulesFilesToIgnore = [
8443
- "# Generated by rulesync - AI tool configuration files",
8444
- // AGENTS.md
8445
- "**/AGENTS.md",
8446
- "**/.agents/",
8447
- // Amazon Q
8448
- "**/.amazonq/",
8449
- // Augment
8450
- "**/.augmentignore",
8451
- "**/.augment/rules/",
8452
- "**/.augment-guidelines",
8453
- // Claude Code
8454
- "**/CLAUDE.md",
8455
- "**/.claude/memories/",
8456
- "**/.claude/commands/",
8457
- "**/.claude/agents/",
8458
- "**/.claude/skills/",
8459
- "**/.claude/settings.local.json",
8460
- "**/.mcp.json",
8461
- // Cline
8462
- "**/.clinerules/",
8463
- "**/.clineignore",
8464
- "**/.cline/mcp.json",
8465
- // Codex
8466
- "**/.codexignore",
8467
- "**/.codex/",
8468
- "**/.codex/skills/",
8469
- // Cursor
8470
- "**/.cursor/",
8471
- "**/.cursorignore",
8472
- // Gemini
8473
- "**/GEMINI.md",
8474
- "**/.gemini/memories/",
8475
- "**/.gemini/commands/",
8476
- "**/.gemini/subagents/",
8477
- "**/.gemini/skills/",
8478
- // GitHub Copilot
8479
- "**/.github/copilot-instructions.md",
8480
- "**/.github/instructions/",
8481
- "**/.github/prompts/",
8482
- "**/.github/subagents/",
8483
- "**/.github/skills/",
8484
- "**/.vscode/mcp.json",
8485
- // Junie
8486
- "**/.junie/guidelines.md",
8487
- "**/.junie/mcp.json",
8488
- // Kiro
8489
- "**/.kiro/steering/",
8490
- "**/.aiignore",
8491
- // OpenCode
8492
- "**/.opencode/memories/",
8493
- "**/.opencode/command/",
8494
- "**/opencode.json",
8495
- // Qwen
8496
- "**/QWEN.md",
8497
- "**/.qwen/memories/",
8498
- // Roo
8499
- "**/.roo/rules/",
8500
- "**/.rooignore",
8501
- "**/.roo/mcp.json",
8502
- "**/.roo/subagents/",
8503
- // Warp
8504
- "**/.warp/",
8505
- "**/WARP.md",
8506
- // Others
8507
- "**/modular-mcp.json",
8508
- "!.rulesync/.aiignore"
8509
- ];
8972
+ const gitignorePath = join83(process.cwd(), ".gitignore");
8510
8973
  let gitignoreContent = "";
8511
8974
  if (await fileExists(gitignorePath)) {
8512
8975
  gitignoreContent = await readFileContent(gitignorePath);
8513
8976
  }
8514
- const linesToAdd = [];
8515
- for (const rule of rulesFilesToIgnore) {
8516
- if (!gitignoreContent.includes(rule)) {
8517
- linesToAdd.push(rule);
8518
- }
8519
- }
8520
- if (linesToAdd.length === 0) {
8977
+ const cleanedContent = removeExistingRulesyncEntries(gitignoreContent);
8978
+ const rulesyncBlock = [RULESYNC_HEADER, ...RULESYNC_IGNORE_ENTRIES].join("\n");
8979
+ const newContent = cleanedContent.trim() ? `${cleanedContent.trimEnd()}
8980
+
8981
+ ${rulesyncBlock}
8982
+ ` : `${rulesyncBlock}
8983
+ `;
8984
+ if (gitignoreContent === newContent) {
8521
8985
  logger.success(".gitignore is already up to date");
8522
8986
  return;
8523
8987
  }
8524
- const newContent = gitignoreContent ? `${gitignoreContent.trimEnd()}
8525
-
8526
- ${linesToAdd.join("\n")}
8527
- ` : `${linesToAdd.join("\n")}
8528
- `;
8529
8988
  await writeFileContent(gitignorePath, newContent);
8530
- logger.success(`Added ${linesToAdd.length} rules to .gitignore:`);
8531
- for (const line of linesToAdd) {
8532
- if (!line.startsWith("#")) {
8533
- logger.info(` ${line}`);
8534
- }
8989
+ logger.success("Updated .gitignore with rulesync entries:");
8990
+ for (const entry of RULESYNC_IGNORE_ENTRIES) {
8991
+ logger.info(` ${entry}`);
8535
8992
  }
8536
8993
  };
8537
8994
 
@@ -8711,7 +9168,7 @@ async function importSkills(config, tool) {
8711
9168
  }
8712
9169
 
8713
9170
  // src/cli/commands/init.ts
8714
- import { join as join83 } from "path";
9171
+ import { join as join84 } from "path";
8715
9172
  async function initCommand() {
8716
9173
  logger.info("Initializing rulesync...");
8717
9174
  await ensureDir(RULESYNC_RELATIVE_DIR_PATH);
@@ -8874,14 +9331,14 @@ Attention, again, you are just the planner, so though you can read any files and
8874
9331
  await ensureDir(commandPaths.relativeDirPath);
8875
9332
  await ensureDir(subagentPaths.relativeDirPath);
8876
9333
  await ensureDir(ignorePaths.recommended.relativeDirPath);
8877
- const ruleFilepath = join83(rulePaths.recommended.relativeDirPath, sampleRuleFile.filename);
9334
+ const ruleFilepath = join84(rulePaths.recommended.relativeDirPath, sampleRuleFile.filename);
8878
9335
  if (!await fileExists(ruleFilepath)) {
8879
9336
  await writeFileContent(ruleFilepath, sampleRuleFile.content);
8880
9337
  logger.success(`Created ${ruleFilepath}`);
8881
9338
  } else {
8882
9339
  logger.info(`Skipped ${ruleFilepath} (already exists)`);
8883
9340
  }
8884
- const mcpFilepath = join83(
9341
+ const mcpFilepath = join84(
8885
9342
  mcpPaths.recommended.relativeDirPath,
8886
9343
  mcpPaths.recommended.relativeFilePath
8887
9344
  );
@@ -8891,21 +9348,21 @@ Attention, again, you are just the planner, so though you can read any files and
8891
9348
  } else {
8892
9349
  logger.info(`Skipped ${mcpFilepath} (already exists)`);
8893
9350
  }
8894
- const commandFilepath = join83(commandPaths.relativeDirPath, sampleCommandFile.filename);
9351
+ const commandFilepath = join84(commandPaths.relativeDirPath, sampleCommandFile.filename);
8895
9352
  if (!await fileExists(commandFilepath)) {
8896
9353
  await writeFileContent(commandFilepath, sampleCommandFile.content);
8897
9354
  logger.success(`Created ${commandFilepath}`);
8898
9355
  } else {
8899
9356
  logger.info(`Skipped ${commandFilepath} (already exists)`);
8900
9357
  }
8901
- const subagentFilepath = join83(subagentPaths.relativeDirPath, sampleSubagentFile.filename);
9358
+ const subagentFilepath = join84(subagentPaths.relativeDirPath, sampleSubagentFile.filename);
8902
9359
  if (!await fileExists(subagentFilepath)) {
8903
9360
  await writeFileContent(subagentFilepath, sampleSubagentFile.content);
8904
9361
  logger.success(`Created ${subagentFilepath}`);
8905
9362
  } else {
8906
9363
  logger.info(`Skipped ${subagentFilepath} (already exists)`);
8907
9364
  }
8908
- const ignoreFilepath = join83(
9365
+ const ignoreFilepath = join84(
8909
9366
  ignorePaths.recommended.relativeDirPath,
8910
9367
  ignorePaths.recommended.relativeFilePath
8911
9368
  );
@@ -8921,12 +9378,12 @@ Attention, again, you are just the planner, so though you can read any files and
8921
9378
  import { FastMCP } from "fastmcp";
8922
9379
 
8923
9380
  // src/mcp/commands.ts
8924
- import { basename as basename22, join as join84 } from "path";
8925
- import { z as z33 } from "zod/mini";
9381
+ import { basename as basename22, join as join85 } from "path";
9382
+ import { z as z34 } from "zod/mini";
8926
9383
  var maxCommandSizeBytes = 1024 * 1024;
8927
9384
  var maxCommandsCount = 1e3;
8928
9385
  async function listCommands() {
8929
- const commandsDir = join84(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
9386
+ const commandsDir = join85(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
8930
9387
  try {
8931
9388
  const files = await listDirectoryFiles(commandsDir);
8932
9389
  const mdFiles = files.filter((file) => file.endsWith(".md"));
@@ -8938,7 +9395,7 @@ async function listCommands() {
8938
9395
  });
8939
9396
  const frontmatter = command.getFrontmatter();
8940
9397
  return {
8941
- relativePathFromCwd: join84(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, file),
9398
+ relativePathFromCwd: join85(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, file),
8942
9399
  frontmatter
8943
9400
  };
8944
9401
  } catch (error) {
@@ -8964,7 +9421,7 @@ async function getCommand({ relativePathFromCwd }) {
8964
9421
  relativeFilePath: filename
8965
9422
  });
8966
9423
  return {
8967
- relativePathFromCwd: join84(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
9424
+ relativePathFromCwd: join85(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
8968
9425
  frontmatter: command.getFrontmatter(),
8969
9426
  body: command.getBody()
8970
9427
  };
@@ -8993,7 +9450,7 @@ async function putCommand({
8993
9450
  try {
8994
9451
  const existingCommands = await listCommands();
8995
9452
  const isUpdate = existingCommands.some(
8996
- (command2) => command2.relativePathFromCwd === join84(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
9453
+ (command2) => command2.relativePathFromCwd === join85(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
8997
9454
  );
8998
9455
  if (!isUpdate && existingCommands.length >= maxCommandsCount) {
8999
9456
  throw new Error(`Maximum number of commands (${maxCommandsCount}) reached`);
@@ -9008,11 +9465,11 @@ async function putCommand({
9008
9465
  fileContent,
9009
9466
  validate: true
9010
9467
  });
9011
- const commandsDir = join84(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
9468
+ const commandsDir = join85(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
9012
9469
  await ensureDir(commandsDir);
9013
9470
  await writeFileContent(command.getFilePath(), command.getFileContent());
9014
9471
  return {
9015
- relativePathFromCwd: join84(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
9472
+ relativePathFromCwd: join85(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
9016
9473
  frontmatter: command.getFrontmatter(),
9017
9474
  body: command.getBody()
9018
9475
  };
@@ -9028,11 +9485,11 @@ async function deleteCommand({ relativePathFromCwd }) {
9028
9485
  intendedRootDir: process.cwd()
9029
9486
  });
9030
9487
  const filename = basename22(relativePathFromCwd);
9031
- const fullPath = join84(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename);
9488
+ const fullPath = join85(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename);
9032
9489
  try {
9033
9490
  await removeFile(fullPath);
9034
9491
  return {
9035
- relativePathFromCwd: join84(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
9492
+ relativePathFromCwd: join85(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
9036
9493
  };
9037
9494
  } catch (error) {
9038
9495
  throw new Error(`Failed to delete command file ${relativePathFromCwd}: ${formatError(error)}`, {
@@ -9041,23 +9498,23 @@ async function deleteCommand({ relativePathFromCwd }) {
9041
9498
  }
9042
9499
  }
9043
9500
  var commandToolSchemas = {
9044
- listCommands: z33.object({}),
9045
- getCommand: z33.object({
9046
- relativePathFromCwd: z33.string()
9501
+ listCommands: z34.object({}),
9502
+ getCommand: z34.object({
9503
+ relativePathFromCwd: z34.string()
9047
9504
  }),
9048
- putCommand: z33.object({
9049
- relativePathFromCwd: z33.string(),
9505
+ putCommand: z34.object({
9506
+ relativePathFromCwd: z34.string(),
9050
9507
  frontmatter: RulesyncCommandFrontmatterSchema,
9051
- body: z33.string()
9508
+ body: z34.string()
9052
9509
  }),
9053
- deleteCommand: z33.object({
9054
- relativePathFromCwd: z33.string()
9510
+ deleteCommand: z34.object({
9511
+ relativePathFromCwd: z34.string()
9055
9512
  })
9056
9513
  };
9057
9514
  var commandTools = {
9058
9515
  listCommands: {
9059
9516
  name: "listCommands",
9060
- description: `List all commands from ${join84(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
9517
+ description: `List all commands from ${join85(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
9061
9518
  parameters: commandToolSchemas.listCommands,
9062
9519
  execute: async () => {
9063
9520
  const commands = await listCommands();
@@ -9099,11 +9556,11 @@ var commandTools = {
9099
9556
  };
9100
9557
 
9101
9558
  // src/mcp/ignore.ts
9102
- import { join as join85 } from "path";
9103
- import { z as z34 } from "zod/mini";
9559
+ import { join as join86 } from "path";
9560
+ import { z as z35 } from "zod/mini";
9104
9561
  var maxIgnoreFileSizeBytes = 100 * 1024;
9105
9562
  async function getIgnoreFile() {
9106
- const ignoreFilePath = join85(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
9563
+ const ignoreFilePath = join86(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
9107
9564
  try {
9108
9565
  const content = await readFileContent(ignoreFilePath);
9109
9566
  return {
@@ -9117,7 +9574,7 @@ async function getIgnoreFile() {
9117
9574
  }
9118
9575
  }
9119
9576
  async function putIgnoreFile({ content }) {
9120
- const ignoreFilePath = join85(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
9577
+ const ignoreFilePath = join86(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
9121
9578
  const contentSizeBytes = Buffer.byteLength(content, "utf8");
9122
9579
  if (contentSizeBytes > maxIgnoreFileSizeBytes) {
9123
9580
  throw new Error(
@@ -9138,8 +9595,8 @@ async function putIgnoreFile({ content }) {
9138
9595
  }
9139
9596
  }
9140
9597
  async function deleteIgnoreFile() {
9141
- const aiignorePath = join85(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
9142
- const legacyIgnorePath = join85(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
9598
+ const aiignorePath = join86(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
9599
+ const legacyIgnorePath = join86(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
9143
9600
  try {
9144
9601
  await Promise.all([removeFile(aiignorePath), removeFile(legacyIgnorePath)]);
9145
9602
  return {
@@ -9157,11 +9614,11 @@ async function deleteIgnoreFile() {
9157
9614
  }
9158
9615
  }
9159
9616
  var ignoreToolSchemas = {
9160
- getIgnoreFile: z34.object({}),
9161
- putIgnoreFile: z34.object({
9162
- content: z34.string()
9617
+ getIgnoreFile: z35.object({}),
9618
+ putIgnoreFile: z35.object({
9619
+ content: z35.string()
9163
9620
  }),
9164
- deleteIgnoreFile: z34.object({})
9621
+ deleteIgnoreFile: z35.object({})
9165
9622
  };
9166
9623
  var ignoreTools = {
9167
9624
  getIgnoreFile: {
@@ -9194,8 +9651,8 @@ var ignoreTools = {
9194
9651
  };
9195
9652
 
9196
9653
  // src/mcp/mcp.ts
9197
- import { join as join86 } from "path";
9198
- import { z as z35 } from "zod/mini";
9654
+ import { join as join87 } from "path";
9655
+ import { z as z36 } from "zod/mini";
9199
9656
  var maxMcpSizeBytes = 1024 * 1024;
9200
9657
  async function getMcpFile() {
9201
9658
  const config = await ConfigResolver.resolve({});
@@ -9204,7 +9661,7 @@ async function getMcpFile() {
9204
9661
  validate: true,
9205
9662
  modularMcp: config.getModularMcp()
9206
9663
  });
9207
- const relativePathFromCwd = join86(
9664
+ const relativePathFromCwd = join87(
9208
9665
  rulesyncMcp.getRelativeDirPath(),
9209
9666
  rulesyncMcp.getRelativeFilePath()
9210
9667
  );
@@ -9237,7 +9694,7 @@ async function putMcpFile({ content }) {
9237
9694
  const paths = RulesyncMcp.getSettablePaths();
9238
9695
  const relativeDirPath = paths.recommended.relativeDirPath;
9239
9696
  const relativeFilePath = paths.recommended.relativeFilePath;
9240
- const fullPath = join86(baseDir, relativeDirPath, relativeFilePath);
9697
+ const fullPath = join87(baseDir, relativeDirPath, relativeFilePath);
9241
9698
  const rulesyncMcp = new RulesyncMcp({
9242
9699
  baseDir,
9243
9700
  relativeDirPath,
@@ -9246,9 +9703,9 @@ async function putMcpFile({ content }) {
9246
9703
  validate: true,
9247
9704
  modularMcp: config.getModularMcp()
9248
9705
  });
9249
- await ensureDir(join86(baseDir, relativeDirPath));
9706
+ await ensureDir(join87(baseDir, relativeDirPath));
9250
9707
  await writeFileContent(fullPath, content);
9251
- const relativePathFromCwd = join86(relativeDirPath, relativeFilePath);
9708
+ const relativePathFromCwd = join87(relativeDirPath, relativeFilePath);
9252
9709
  return {
9253
9710
  relativePathFromCwd,
9254
9711
  content: rulesyncMcp.getFileContent()
@@ -9263,15 +9720,15 @@ async function deleteMcpFile() {
9263
9720
  try {
9264
9721
  const baseDir = process.cwd();
9265
9722
  const paths = RulesyncMcp.getSettablePaths();
9266
- const recommendedPath = join86(
9723
+ const recommendedPath = join87(
9267
9724
  baseDir,
9268
9725
  paths.recommended.relativeDirPath,
9269
9726
  paths.recommended.relativeFilePath
9270
9727
  );
9271
- const legacyPath = join86(baseDir, paths.legacy.relativeDirPath, paths.legacy.relativeFilePath);
9728
+ const legacyPath = join87(baseDir, paths.legacy.relativeDirPath, paths.legacy.relativeFilePath);
9272
9729
  await removeFile(recommendedPath);
9273
9730
  await removeFile(legacyPath);
9274
- const relativePathFromCwd = join86(
9731
+ const relativePathFromCwd = join87(
9275
9732
  paths.recommended.relativeDirPath,
9276
9733
  paths.recommended.relativeFilePath
9277
9734
  );
@@ -9285,11 +9742,11 @@ async function deleteMcpFile() {
9285
9742
  }
9286
9743
  }
9287
9744
  var mcpToolSchemas = {
9288
- getMcpFile: z35.object({}),
9289
- putMcpFile: z35.object({
9290
- content: z35.string()
9745
+ getMcpFile: z36.object({}),
9746
+ putMcpFile: z36.object({
9747
+ content: z36.string()
9291
9748
  }),
9292
- deleteMcpFile: z35.object({})
9749
+ deleteMcpFile: z36.object({})
9293
9750
  };
9294
9751
  var mcpTools = {
9295
9752
  getMcpFile: {
@@ -9322,12 +9779,12 @@ var mcpTools = {
9322
9779
  };
9323
9780
 
9324
9781
  // src/mcp/rules.ts
9325
- import { basename as basename23, join as join87 } from "path";
9326
- import { z as z36 } from "zod/mini";
9782
+ import { basename as basename23, join as join88 } from "path";
9783
+ import { z as z37 } from "zod/mini";
9327
9784
  var maxRuleSizeBytes = 1024 * 1024;
9328
9785
  var maxRulesCount = 1e3;
9329
9786
  async function listRules() {
9330
- const rulesDir = join87(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
9787
+ const rulesDir = join88(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
9331
9788
  try {
9332
9789
  const files = await listDirectoryFiles(rulesDir);
9333
9790
  const mdFiles = files.filter((file) => file.endsWith(".md"));
@@ -9340,7 +9797,7 @@ async function listRules() {
9340
9797
  });
9341
9798
  const frontmatter = rule.getFrontmatter();
9342
9799
  return {
9343
- relativePathFromCwd: join87(RULESYNC_RULES_RELATIVE_DIR_PATH, file),
9800
+ relativePathFromCwd: join88(RULESYNC_RULES_RELATIVE_DIR_PATH, file),
9344
9801
  frontmatter
9345
9802
  };
9346
9803
  } catch (error) {
@@ -9367,7 +9824,7 @@ async function getRule({ relativePathFromCwd }) {
9367
9824
  validate: true
9368
9825
  });
9369
9826
  return {
9370
- relativePathFromCwd: join87(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
9827
+ relativePathFromCwd: join88(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
9371
9828
  frontmatter: rule.getFrontmatter(),
9372
9829
  body: rule.getBody()
9373
9830
  };
@@ -9396,7 +9853,7 @@ async function putRule({
9396
9853
  try {
9397
9854
  const existingRules = await listRules();
9398
9855
  const isUpdate = existingRules.some(
9399
- (rule2) => rule2.relativePathFromCwd === join87(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
9856
+ (rule2) => rule2.relativePathFromCwd === join88(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
9400
9857
  );
9401
9858
  if (!isUpdate && existingRules.length >= maxRulesCount) {
9402
9859
  throw new Error(`Maximum number of rules (${maxRulesCount}) reached`);
@@ -9409,11 +9866,11 @@ async function putRule({
9409
9866
  body,
9410
9867
  validate: true
9411
9868
  });
9412
- const rulesDir = join87(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
9869
+ const rulesDir = join88(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
9413
9870
  await ensureDir(rulesDir);
9414
9871
  await writeFileContent(rule.getFilePath(), rule.getFileContent());
9415
9872
  return {
9416
- relativePathFromCwd: join87(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
9873
+ relativePathFromCwd: join88(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
9417
9874
  frontmatter: rule.getFrontmatter(),
9418
9875
  body: rule.getBody()
9419
9876
  };
@@ -9429,11 +9886,11 @@ async function deleteRule({ relativePathFromCwd }) {
9429
9886
  intendedRootDir: process.cwd()
9430
9887
  });
9431
9888
  const filename = basename23(relativePathFromCwd);
9432
- const fullPath = join87(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH, filename);
9889
+ const fullPath = join88(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH, filename);
9433
9890
  try {
9434
9891
  await removeFile(fullPath);
9435
9892
  return {
9436
- relativePathFromCwd: join87(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
9893
+ relativePathFromCwd: join88(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
9437
9894
  };
9438
9895
  } catch (error) {
9439
9896
  throw new Error(`Failed to delete rule file ${relativePathFromCwd}: ${formatError(error)}`, {
@@ -9442,23 +9899,23 @@ async function deleteRule({ relativePathFromCwd }) {
9442
9899
  }
9443
9900
  }
9444
9901
  var ruleToolSchemas = {
9445
- listRules: z36.object({}),
9446
- getRule: z36.object({
9447
- relativePathFromCwd: z36.string()
9902
+ listRules: z37.object({}),
9903
+ getRule: z37.object({
9904
+ relativePathFromCwd: z37.string()
9448
9905
  }),
9449
- putRule: z36.object({
9450
- relativePathFromCwd: z36.string(),
9906
+ putRule: z37.object({
9907
+ relativePathFromCwd: z37.string(),
9451
9908
  frontmatter: RulesyncRuleFrontmatterSchema,
9452
- body: z36.string()
9909
+ body: z37.string()
9453
9910
  }),
9454
- deleteRule: z36.object({
9455
- relativePathFromCwd: z36.string()
9911
+ deleteRule: z37.object({
9912
+ relativePathFromCwd: z37.string()
9456
9913
  })
9457
9914
  };
9458
9915
  var ruleTools = {
9459
9916
  listRules: {
9460
9917
  name: "listRules",
9461
- description: `List all rules from ${join87(RULESYNC_RULES_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
9918
+ description: `List all rules from ${join88(RULESYNC_RULES_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
9462
9919
  parameters: ruleToolSchemas.listRules,
9463
9920
  execute: async () => {
9464
9921
  const rules = await listRules();
@@ -9500,8 +9957,8 @@ var ruleTools = {
9500
9957
  };
9501
9958
 
9502
9959
  // src/mcp/skills.ts
9503
- import { basename as basename24, dirname as dirname2, join as join88 } from "path";
9504
- import { z as z37 } from "zod/mini";
9960
+ import { basename as basename24, dirname as dirname2, join as join89 } from "path";
9961
+ import { z as z38 } from "zod/mini";
9505
9962
  var maxSkillSizeBytes = 1024 * 1024;
9506
9963
  var maxSkillsCount = 1e3;
9507
9964
  function aiDirFileToMcpSkillFile(file) {
@@ -9524,9 +9981,9 @@ function extractDirName(relativeDirPathFromCwd) {
9524
9981
  return dirName;
9525
9982
  }
9526
9983
  async function listSkills() {
9527
- const skillsDir = join88(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH);
9984
+ const skillsDir = join89(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH);
9528
9985
  try {
9529
- const skillDirPaths = await findFilesByGlobs(join88(skillsDir, "*"), { type: "dir" });
9986
+ const skillDirPaths = await findFilesByGlobs(join89(skillsDir, "*"), { type: "dir" });
9530
9987
  const skills = await Promise.all(
9531
9988
  skillDirPaths.map(async (dirPath) => {
9532
9989
  const dirName = basename24(dirPath);
@@ -9537,7 +9994,7 @@ async function listSkills() {
9537
9994
  });
9538
9995
  const frontmatter = skill.getFrontmatter();
9539
9996
  return {
9540
- relativeDirPathFromCwd: join88(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
9997
+ relativeDirPathFromCwd: join89(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
9541
9998
  frontmatter
9542
9999
  };
9543
10000
  } catch (error) {
@@ -9563,7 +10020,7 @@ async function getSkill({ relativeDirPathFromCwd }) {
9563
10020
  dirName
9564
10021
  });
9565
10022
  return {
9566
- relativeDirPathFromCwd: join88(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
10023
+ relativeDirPathFromCwd: join89(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
9567
10024
  frontmatter: skill.getFrontmatter(),
9568
10025
  body: skill.getBody(),
9569
10026
  otherFiles: skill.getOtherFiles().map(aiDirFileToMcpSkillFile)
@@ -9597,7 +10054,7 @@ async function putSkill({
9597
10054
  try {
9598
10055
  const existingSkills = await listSkills();
9599
10056
  const isUpdate = existingSkills.some(
9600
- (skill2) => skill2.relativeDirPathFromCwd === join88(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName)
10057
+ (skill2) => skill2.relativeDirPathFromCwd === join89(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName)
9601
10058
  );
9602
10059
  if (!isUpdate && existingSkills.length >= maxSkillsCount) {
9603
10060
  throw new Error(`Maximum number of skills (${maxSkillsCount}) reached`);
@@ -9612,9 +10069,9 @@ async function putSkill({
9612
10069
  otherFiles: aiDirFiles,
9613
10070
  validate: true
9614
10071
  });
9615
- const skillDirPath = join88(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName);
10072
+ const skillDirPath = join89(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName);
9616
10073
  await ensureDir(skillDirPath);
9617
- const skillFilePath = join88(skillDirPath, SKILL_FILE_NAME);
10074
+ const skillFilePath = join89(skillDirPath, SKILL_FILE_NAME);
9618
10075
  const skillFileContent = stringifyFrontmatter(body, frontmatter);
9619
10076
  await writeFileContent(skillFilePath, skillFileContent);
9620
10077
  for (const file of otherFiles) {
@@ -9622,15 +10079,15 @@ async function putSkill({
9622
10079
  relativePath: file.name,
9623
10080
  intendedRootDir: skillDirPath
9624
10081
  });
9625
- const filePath = join88(skillDirPath, file.name);
9626
- const fileDir = join88(skillDirPath, dirname2(file.name));
10082
+ const filePath = join89(skillDirPath, file.name);
10083
+ const fileDir = join89(skillDirPath, dirname2(file.name));
9627
10084
  if (fileDir !== skillDirPath) {
9628
10085
  await ensureDir(fileDir);
9629
10086
  }
9630
10087
  await writeFileContent(filePath, file.body);
9631
10088
  }
9632
10089
  return {
9633
- relativeDirPathFromCwd: join88(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
10090
+ relativeDirPathFromCwd: join89(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
9634
10091
  frontmatter: skill.getFrontmatter(),
9635
10092
  body: skill.getBody(),
9636
10093
  otherFiles: skill.getOtherFiles().map(aiDirFileToMcpSkillFile)
@@ -9652,13 +10109,13 @@ async function deleteSkill({
9652
10109
  intendedRootDir: process.cwd()
9653
10110
  });
9654
10111
  const dirName = extractDirName(relativeDirPathFromCwd);
9655
- const skillDirPath = join88(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName);
10112
+ const skillDirPath = join89(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName);
9656
10113
  try {
9657
10114
  if (await directoryExists(skillDirPath)) {
9658
10115
  await removeDirectory(skillDirPath);
9659
10116
  }
9660
10117
  return {
9661
- relativeDirPathFromCwd: join88(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName)
10118
+ relativeDirPathFromCwd: join89(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName)
9662
10119
  };
9663
10120
  } catch (error) {
9664
10121
  throw new Error(
@@ -9669,29 +10126,29 @@ async function deleteSkill({
9669
10126
  );
9670
10127
  }
9671
10128
  }
9672
- var McpSkillFileSchema = z37.object({
9673
- name: z37.string(),
9674
- body: z37.string()
10129
+ var McpSkillFileSchema = z38.object({
10130
+ name: z38.string(),
10131
+ body: z38.string()
9675
10132
  });
9676
10133
  var skillToolSchemas = {
9677
- listSkills: z37.object({}),
9678
- getSkill: z37.object({
9679
- relativeDirPathFromCwd: z37.string()
10134
+ listSkills: z38.object({}),
10135
+ getSkill: z38.object({
10136
+ relativeDirPathFromCwd: z38.string()
9680
10137
  }),
9681
- putSkill: z37.object({
9682
- relativeDirPathFromCwd: z37.string(),
10138
+ putSkill: z38.object({
10139
+ relativeDirPathFromCwd: z38.string(),
9683
10140
  frontmatter: RulesyncSkillFrontmatterSchema,
9684
- body: z37.string(),
9685
- otherFiles: z37.optional(z37.array(McpSkillFileSchema))
10141
+ body: z38.string(),
10142
+ otherFiles: z38.optional(z38.array(McpSkillFileSchema))
9686
10143
  }),
9687
- deleteSkill: z37.object({
9688
- relativeDirPathFromCwd: z37.string()
10144
+ deleteSkill: z38.object({
10145
+ relativeDirPathFromCwd: z38.string()
9689
10146
  })
9690
10147
  };
9691
10148
  var skillTools = {
9692
10149
  listSkills: {
9693
10150
  name: "listSkills",
9694
- description: `List all skills from ${join88(RULESYNC_SKILLS_RELATIVE_DIR_PATH, "*", SKILL_FILE_NAME)} with their frontmatter.`,
10151
+ description: `List all skills from ${join89(RULESYNC_SKILLS_RELATIVE_DIR_PATH, "*", SKILL_FILE_NAME)} with their frontmatter.`,
9695
10152
  parameters: skillToolSchemas.listSkills,
9696
10153
  execute: async () => {
9697
10154
  const skills = await listSkills();
@@ -9734,12 +10191,12 @@ var skillTools = {
9734
10191
  };
9735
10192
 
9736
10193
  // src/mcp/subagents.ts
9737
- import { basename as basename25, join as join89 } from "path";
9738
- import { z as z38 } from "zod/mini";
10194
+ import { basename as basename25, join as join90 } from "path";
10195
+ import { z as z39 } from "zod/mini";
9739
10196
  var maxSubagentSizeBytes = 1024 * 1024;
9740
10197
  var maxSubagentsCount = 1e3;
9741
10198
  async function listSubagents() {
9742
- const subagentsDir = join89(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
10199
+ const subagentsDir = join90(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
9743
10200
  try {
9744
10201
  const files = await listDirectoryFiles(subagentsDir);
9745
10202
  const mdFiles = files.filter((file) => file.endsWith(".md"));
@@ -9752,7 +10209,7 @@ async function listSubagents() {
9752
10209
  });
9753
10210
  const frontmatter = subagent.getFrontmatter();
9754
10211
  return {
9755
- relativePathFromCwd: join89(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, file),
10212
+ relativePathFromCwd: join90(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, file),
9756
10213
  frontmatter
9757
10214
  };
9758
10215
  } catch (error) {
@@ -9781,7 +10238,7 @@ async function getSubagent({ relativePathFromCwd }) {
9781
10238
  validate: true
9782
10239
  });
9783
10240
  return {
9784
- relativePathFromCwd: join89(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
10241
+ relativePathFromCwd: join90(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
9785
10242
  frontmatter: subagent.getFrontmatter(),
9786
10243
  body: subagent.getBody()
9787
10244
  };
@@ -9810,7 +10267,7 @@ async function putSubagent({
9810
10267
  try {
9811
10268
  const existingSubagents = await listSubagents();
9812
10269
  const isUpdate = existingSubagents.some(
9813
- (subagent2) => subagent2.relativePathFromCwd === join89(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
10270
+ (subagent2) => subagent2.relativePathFromCwd === join90(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
9814
10271
  );
9815
10272
  if (!isUpdate && existingSubagents.length >= maxSubagentsCount) {
9816
10273
  throw new Error(`Maximum number of subagents (${maxSubagentsCount}) reached`);
@@ -9823,11 +10280,11 @@ async function putSubagent({
9823
10280
  body,
9824
10281
  validate: true
9825
10282
  });
9826
- const subagentsDir = join89(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
10283
+ const subagentsDir = join90(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
9827
10284
  await ensureDir(subagentsDir);
9828
10285
  await writeFileContent(subagent.getFilePath(), subagent.getFileContent());
9829
10286
  return {
9830
- relativePathFromCwd: join89(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
10287
+ relativePathFromCwd: join90(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
9831
10288
  frontmatter: subagent.getFrontmatter(),
9832
10289
  body: subagent.getBody()
9833
10290
  };
@@ -9843,11 +10300,11 @@ async function deleteSubagent({ relativePathFromCwd }) {
9843
10300
  intendedRootDir: process.cwd()
9844
10301
  });
9845
10302
  const filename = basename25(relativePathFromCwd);
9846
- const fullPath = join89(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename);
10303
+ const fullPath = join90(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename);
9847
10304
  try {
9848
10305
  await removeFile(fullPath);
9849
10306
  return {
9850
- relativePathFromCwd: join89(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
10307
+ relativePathFromCwd: join90(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
9851
10308
  };
9852
10309
  } catch (error) {
9853
10310
  throw new Error(
@@ -9859,23 +10316,23 @@ async function deleteSubagent({ relativePathFromCwd }) {
9859
10316
  }
9860
10317
  }
9861
10318
  var subagentToolSchemas = {
9862
- listSubagents: z38.object({}),
9863
- getSubagent: z38.object({
9864
- relativePathFromCwd: z38.string()
10319
+ listSubagents: z39.object({}),
10320
+ getSubagent: z39.object({
10321
+ relativePathFromCwd: z39.string()
9865
10322
  }),
9866
- putSubagent: z38.object({
9867
- relativePathFromCwd: z38.string(),
10323
+ putSubagent: z39.object({
10324
+ relativePathFromCwd: z39.string(),
9868
10325
  frontmatter: RulesyncSubagentFrontmatterSchema,
9869
- body: z38.string()
10326
+ body: z39.string()
9870
10327
  }),
9871
- deleteSubagent: z38.object({
9872
- relativePathFromCwd: z38.string()
10328
+ deleteSubagent: z39.object({
10329
+ relativePathFromCwd: z39.string()
9873
10330
  })
9874
10331
  };
9875
10332
  var subagentTools = {
9876
10333
  listSubagents: {
9877
10334
  name: "listSubagents",
9878
- description: `List all subagents from ${join89(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
10335
+ description: `List all subagents from ${join90(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
9879
10336
  parameters: subagentToolSchemas.listSubagents,
9880
10337
  execute: async () => {
9881
10338
  const subagents = await listSubagents();
@@ -9953,7 +10410,7 @@ async function mcpCommand({ version }) {
9953
10410
  }
9954
10411
 
9955
10412
  // src/cli/index.ts
9956
- var getVersion = () => "3.31.0";
10413
+ var getVersion = () => "3.33.0";
9957
10414
  var main = async () => {
9958
10415
  const program = new Command();
9959
10416
  const version = getVersion();