rulesync 3.32.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.
package/dist/index.cjs CHANGED
@@ -3536,6 +3536,12 @@ var CodexcliMcp = class _CodexcliMcp extends ToolMcp {
3536
3536
 
3537
3537
  // src/features/mcp/copilot-mcp.ts
3538
3538
  var import_node_path35 = require("path");
3539
+ function convertToCopilotFormat(mcpServers) {
3540
+ return { servers: mcpServers };
3541
+ }
3542
+ function convertFromCopilotFormat(copilotConfig) {
3543
+ return copilotConfig.servers ?? {};
3544
+ }
3539
3545
  var CopilotMcp = class _CopilotMcp extends ToolMcp {
3540
3546
  json;
3541
3547
  constructor(params) {
@@ -3575,16 +3581,20 @@ var CopilotMcp = class _CopilotMcp extends ToolMcp {
3575
3581
  rulesyncMcp,
3576
3582
  validate = true
3577
3583
  }) {
3584
+ const copilotConfig = convertToCopilotFormat(rulesyncMcp.getMcpServers());
3578
3585
  return new _CopilotMcp({
3579
3586
  baseDir,
3580
3587
  relativeDirPath: this.getSettablePaths().relativeDirPath,
3581
3588
  relativeFilePath: this.getSettablePaths().relativeFilePath,
3582
- fileContent: rulesyncMcp.getFileContent(),
3589
+ fileContent: JSON.stringify(copilotConfig, null, 2),
3583
3590
  validate
3584
3591
  });
3585
3592
  }
3586
3593
  toRulesyncMcp() {
3587
- return this.toRulesyncMcpDefault();
3594
+ const mcpServers = convertFromCopilotFormat(this.json);
3595
+ return this.toRulesyncMcpDefault({
3596
+ fileContent: JSON.stringify({ mcpServers }, null, 2)
3597
+ });
3588
3598
  }
3589
3599
  validate() {
3590
3600
  return { success: true, error: null };
@@ -3968,6 +3978,37 @@ var OpencodeMcp = class _OpencodeMcp extends ToolMcp {
3968
3978
 
3969
3979
  // src/features/mcp/roo-mcp.ts
3970
3980
  var import_node_path40 = require("path");
3981
+ function isRooMcpServers(value) {
3982
+ return value !== void 0 && value !== null && typeof value === "object";
3983
+ }
3984
+ function convertToRooFormat(mcpServers) {
3985
+ return Object.fromEntries(
3986
+ Object.entries(mcpServers).map(([serverName, serverConfig]) => {
3987
+ const converted = { ...serverConfig };
3988
+ if (serverConfig.type === "http") {
3989
+ converted.type = "streamable-http";
3990
+ }
3991
+ if (serverConfig.transport === "http") {
3992
+ converted.transport = "streamable-http";
3993
+ }
3994
+ return [serverName, converted];
3995
+ })
3996
+ );
3997
+ }
3998
+ function convertFromRooFormat(mcpServers) {
3999
+ return Object.fromEntries(
4000
+ Object.entries(mcpServers).map(([serverName, serverConfig]) => {
4001
+ const converted = { ...serverConfig };
4002
+ if (serverConfig.type === "streamable-http") {
4003
+ converted.type = "http";
4004
+ }
4005
+ if (serverConfig.transport === "streamable-http") {
4006
+ converted.transport = "http";
4007
+ }
4008
+ return [serverName, converted];
4009
+ })
4010
+ );
4011
+ }
3971
4012
  var RooMcp = class _RooMcp extends ToolMcp {
3972
4013
  json;
3973
4014
  constructor(params) {
@@ -4007,7 +4048,9 @@ var RooMcp = class _RooMcp extends ToolMcp {
4007
4048
  rulesyncMcp,
4008
4049
  validate = true
4009
4050
  }) {
4010
- const fileContent = rulesyncMcp.getFileContent();
4051
+ const mcpServers = rulesyncMcp.getMcpServers();
4052
+ const convertedMcpServers = convertToRooFormat(mcpServers);
4053
+ const fileContent = JSON.stringify({ mcpServers: convertedMcpServers }, null, 2);
4011
4054
  return new _RooMcp({
4012
4055
  baseDir,
4013
4056
  relativeDirPath: this.getSettablePaths().relativeDirPath,
@@ -4017,7 +4060,11 @@ var RooMcp = class _RooMcp extends ToolMcp {
4017
4060
  });
4018
4061
  }
4019
4062
  toRulesyncMcp() {
4020
- return this.toRulesyncMcpDefault();
4063
+ const rawMcpServers = isRooMcpServers(this.json.mcpServers) ? this.json.mcpServers : {};
4064
+ const convertedMcpServers = convertFromRooFormat(rawMcpServers);
4065
+ return this.toRulesyncMcpDefault({
4066
+ fileContent: JSON.stringify({ mcpServers: convertedMcpServers }, null, 2)
4067
+ });
4021
4068
  }
4022
4069
  validate() {
4023
4070
  return { success: true, error: null };
@@ -4262,17 +4309,19 @@ var import_node_path84 = require("path");
4262
4309
  var import_toon = require("@toon-format/toon");
4263
4310
  var import_mini33 = require("zod/mini");
4264
4311
 
4265
- // src/features/skills/codexcli-skill.ts
4266
- var import_node_path44 = require("path");
4267
- var import_mini20 = require("zod/mini");
4268
-
4269
4312
  // src/constants/general.ts
4270
4313
  var SKILL_FILE_NAME = "SKILL.md";
4271
4314
 
4272
- // src/features/skills/rulesync-skill.ts
4273
- var import_node_path42 = require("path");
4315
+ // src/features/skills/agentsmd-skill.ts
4316
+ var import_node_path44 = require("path");
4317
+
4318
+ // src/features/skills/simulated-skill.ts
4319
+ var import_node_path43 = require("path");
4274
4320
  var import_mini19 = require("zod/mini");
4275
4321
 
4322
+ // src/features/skills/tool-skill.ts
4323
+ var import_node_path42 = require("path");
4324
+
4276
4325
  // src/types/ai-dir.ts
4277
4326
  var import_node_path41 = __toESM(require("path"), 1);
4278
4327
  var AiDir = class {
@@ -4385,113 +4434,7 @@ var AiDir = class {
4385
4434
  }
4386
4435
  };
4387
4436
 
4388
- // src/features/skills/rulesync-skill.ts
4389
- var RulesyncSkillFrontmatterSchemaInternal = import_mini19.z.object({
4390
- name: import_mini19.z.string(),
4391
- description: import_mini19.z.string(),
4392
- targets: import_mini19.z._default(RulesyncTargetsSchema, ["*"]),
4393
- claudecode: import_mini19.z.optional(
4394
- import_mini19.z.object({
4395
- "allowed-tools": import_mini19.z.optional(import_mini19.z.array(import_mini19.z.string()))
4396
- })
4397
- )
4398
- });
4399
- var RulesyncSkillFrontmatterSchema = RulesyncSkillFrontmatterSchemaInternal;
4400
- var RulesyncSkill = class _RulesyncSkill extends AiDir {
4401
- constructor({
4402
- baseDir = process.cwd(),
4403
- relativeDirPath = RULESYNC_SKILLS_RELATIVE_DIR_PATH,
4404
- dirName,
4405
- frontmatter,
4406
- body,
4407
- otherFiles = [],
4408
- validate = true,
4409
- global = false
4410
- }) {
4411
- super({
4412
- baseDir,
4413
- relativeDirPath,
4414
- dirName,
4415
- mainFile: {
4416
- name: SKILL_FILE_NAME,
4417
- body,
4418
- frontmatter: { ...frontmatter }
4419
- },
4420
- otherFiles,
4421
- global
4422
- });
4423
- if (validate) {
4424
- const result = this.validate();
4425
- if (!result.success) {
4426
- throw result.error;
4427
- }
4428
- }
4429
- }
4430
- static getSettablePaths() {
4431
- return {
4432
- relativeDirPath: RULESYNC_SKILLS_RELATIVE_DIR_PATH
4433
- };
4434
- }
4435
- getFrontmatter() {
4436
- if (!this.mainFile?.frontmatter) {
4437
- throw new Error("Frontmatter is not defined");
4438
- }
4439
- const result = RulesyncSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
4440
- return result;
4441
- }
4442
- getBody() {
4443
- return this.mainFile?.body ?? "";
4444
- }
4445
- validate() {
4446
- const result = RulesyncSkillFrontmatterSchema.safeParse(this.mainFile?.frontmatter);
4447
- if (!result.success) {
4448
- return {
4449
- success: false,
4450
- error: new Error(
4451
- `Invalid frontmatter in ${this.getDirPath()}: ${formatError(result.error)}`
4452
- )
4453
- };
4454
- }
4455
- return { success: true, error: null };
4456
- }
4457
- static async fromDir({
4458
- baseDir = process.cwd(),
4459
- relativeDirPath = RULESYNC_SKILLS_RELATIVE_DIR_PATH,
4460
- dirName,
4461
- global = false
4462
- }) {
4463
- const skillDirPath = (0, import_node_path42.join)(baseDir, relativeDirPath, dirName);
4464
- const skillFilePath = (0, import_node_path42.join)(skillDirPath, SKILL_FILE_NAME);
4465
- if (!await fileExists(skillFilePath)) {
4466
- throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
4467
- }
4468
- const fileContent = await readFileContent(skillFilePath);
4469
- const { frontmatter, body: content } = parseFrontmatter(fileContent);
4470
- const result = RulesyncSkillFrontmatterSchema.safeParse(frontmatter);
4471
- if (!result.success) {
4472
- throw new Error(`Invalid frontmatter in ${skillFilePath}: ${formatError(result.error)}`);
4473
- }
4474
- const otherFiles = await this.collectOtherFiles(
4475
- baseDir,
4476
- relativeDirPath,
4477
- dirName,
4478
- SKILL_FILE_NAME
4479
- );
4480
- return new _RulesyncSkill({
4481
- baseDir,
4482
- relativeDirPath,
4483
- dirName,
4484
- frontmatter: result.data,
4485
- body: content.trim(),
4486
- otherFiles,
4487
- validate: true,
4488
- global
4489
- });
4490
- }
4491
- };
4492
-
4493
4437
  // src/features/skills/tool-skill.ts
4494
- var import_node_path43 = require("path");
4495
4438
  var ToolSkill = class extends AiDir {
4496
4439
  /**
4497
4440
  * Get the settable paths for this tool's skill directories.
@@ -4565,8 +4508,8 @@ var ToolSkill = class extends AiDir {
4565
4508
  }) {
4566
4509
  const settablePaths = getSettablePaths({ global });
4567
4510
  const actualRelativeDirPath = relativeDirPath ?? settablePaths.relativeDirPath;
4568
- const skillDirPath = (0, import_node_path43.join)(baseDir, actualRelativeDirPath, dirName);
4569
- const skillFilePath = (0, import_node_path43.join)(skillDirPath, SKILL_FILE_NAME);
4511
+ const skillDirPath = (0, import_node_path42.join)(baseDir, actualRelativeDirPath, dirName);
4512
+ const skillFilePath = (0, import_node_path42.join)(skillDirPath, SKILL_FILE_NAME);
4570
4513
  if (!await fileExists(skillFilePath)) {
4571
4514
  throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
4572
4515
  }
@@ -4590,21 +4533,22 @@ var ToolSkill = class extends AiDir {
4590
4533
  }
4591
4534
  };
4592
4535
 
4593
- // src/features/skills/codexcli-skill.ts
4594
- var CodexCliSkillFrontmatterSchema = import_mini20.z.object({
4595
- name: import_mini20.z.string(),
4596
- description: import_mini20.z.string()
4536
+ // src/features/skills/simulated-skill.ts
4537
+ var SimulatedSkillFrontmatterSchema = import_mini19.z.object({
4538
+ name: import_mini19.z.string(),
4539
+ description: import_mini19.z.string()
4597
4540
  });
4598
- var CodexCliSkill = class _CodexCliSkill extends ToolSkill {
4541
+ var SimulatedSkill = class extends ToolSkill {
4542
+ frontmatter;
4543
+ body;
4599
4544
  constructor({
4600
4545
  baseDir = process.cwd(),
4601
- relativeDirPath = (0, import_node_path44.join)(".codex", "skills"),
4546
+ relativeDirPath,
4602
4547
  dirName,
4603
4548
  frontmatter,
4604
4549
  body,
4605
4550
  otherFiles = [],
4606
- validate = true,
4607
- global = false
4551
+ validate = true
4608
4552
  }) {
4609
4553
  super({
4610
4554
  baseDir,
@@ -4616,42 +4560,37 @@ var CodexCliSkill = class _CodexCliSkill extends ToolSkill {
4616
4560
  frontmatter: { ...frontmatter }
4617
4561
  },
4618
4562
  otherFiles,
4619
- global
4563
+ global: false
4564
+ // Simulated skills are project mode only
4620
4565
  });
4621
4566
  if (validate) {
4622
- const result = this.validate();
4567
+ const result = SimulatedSkillFrontmatterSchema.safeParse(frontmatter);
4623
4568
  if (!result.success) {
4624
- throw result.error;
4569
+ throw new Error(
4570
+ `Invalid frontmatter in ${(0, import_node_path43.join)(relativeDirPath, dirName)}: ${formatError(result.error)}`
4571
+ );
4625
4572
  }
4626
4573
  }
4574
+ this.frontmatter = frontmatter;
4575
+ this.body = body;
4627
4576
  }
4628
- static getSettablePaths({ global = false } = {}) {
4629
- if (!global) {
4630
- throw new Error("CodexCliSkill only supports global mode. Please pass { global: true }.");
4631
- }
4632
- return {
4633
- relativeDirPath: (0, import_node_path44.join)(".codex", "skills")
4634
- };
4577
+ getBody() {
4578
+ return this.body;
4635
4579
  }
4636
4580
  getFrontmatter() {
4637
- if (!this.mainFile?.frontmatter) {
4638
- throw new Error("Frontmatter is not defined");
4639
- }
4640
- const result = CodexCliSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
4641
- return result;
4581
+ return this.frontmatter;
4642
4582
  }
4643
- getBody() {
4644
- return this.mainFile?.body ?? "";
4583
+ toRulesyncSkill() {
4584
+ throw new Error("Not implemented because it is a SIMULATED skill.");
4645
4585
  }
4646
4586
  validate() {
4647
- if (!this.mainFile) {
4648
- return {
4649
- success: false,
4650
- error: new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
4651
- };
4587
+ if (!this.frontmatter) {
4588
+ return { success: true, error: null };
4652
4589
  }
4653
- const result = CodexCliSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
4654
- if (!result.success) {
4590
+ const result = SimulatedSkillFrontmatterSchema.safeParse(this.frontmatter);
4591
+ if (result.success) {
4592
+ return { success: true, error: null };
4593
+ } else {
4655
4594
  return {
4656
4595
  success: false,
4657
4596
  error: new Error(
@@ -4659,98 +4598,141 @@ var CodexCliSkill = class _CodexCliSkill extends ToolSkill {
4659
4598
  )
4660
4599
  };
4661
4600
  }
4662
- return { success: true, error: null };
4663
- }
4664
- toRulesyncSkill() {
4665
- const frontmatter = this.getFrontmatter();
4666
- const rulesyncFrontmatter = {
4667
- name: frontmatter.name,
4668
- description: frontmatter.description,
4669
- targets: ["*"]
4670
- };
4671
- return new RulesyncSkill({
4672
- baseDir: this.baseDir,
4673
- relativeDirPath: this.relativeDirPath,
4674
- dirName: this.getDirName(),
4675
- frontmatter: rulesyncFrontmatter,
4676
- body: this.getBody(),
4677
- otherFiles: this.getOtherFiles(),
4678
- validate: true,
4679
- global: this.global
4680
- });
4681
4601
  }
4682
- static fromRulesyncSkill({
4602
+ static fromRulesyncSkillDefault({
4683
4603
  rulesyncSkill,
4684
- validate = true,
4685
- global = false
4604
+ validate = true
4686
4605
  }) {
4687
- const settablePaths = _CodexCliSkill.getSettablePaths({ global });
4688
4606
  const rulesyncFrontmatter = rulesyncSkill.getFrontmatter();
4689
- const codexFrontmatter = {
4607
+ const simulatedFrontmatter = {
4690
4608
  name: rulesyncFrontmatter.name,
4691
4609
  description: rulesyncFrontmatter.description
4692
4610
  };
4693
- return new _CodexCliSkill({
4611
+ return {
4694
4612
  baseDir: rulesyncSkill.getBaseDir(),
4695
- relativeDirPath: settablePaths.relativeDirPath,
4613
+ relativeDirPath: this.getSettablePaths().relativeDirPath,
4696
4614
  dirName: rulesyncSkill.getDirName(),
4697
- frontmatter: codexFrontmatter,
4615
+ frontmatter: simulatedFrontmatter,
4698
4616
  body: rulesyncSkill.getBody(),
4699
4617
  otherFiles: rulesyncSkill.getOtherFiles(),
4700
- validate,
4701
- global
4702
- });
4703
- }
4704
- static isTargetedByRulesyncSkill(rulesyncSkill) {
4705
- const targets = rulesyncSkill.getFrontmatter().targets;
4706
- return targets.includes("*") || targets.includes("codexcli");
4618
+ validate
4619
+ };
4707
4620
  }
4708
- static async fromDir(params) {
4709
- const loaded = await this.loadSkillDirContent({
4710
- ...params,
4711
- getSettablePaths: _CodexCliSkill.getSettablePaths
4712
- });
4713
- const result = CodexCliSkillFrontmatterSchema.safeParse(loaded.frontmatter);
4714
- if (!result.success) {
4715
- const skillDirPath = (0, import_node_path44.join)(loaded.baseDir, loaded.relativeDirPath, loaded.dirName);
4716
- throw new Error(
4717
- `Invalid frontmatter in ${(0, import_node_path44.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`
4718
- );
4621
+ static async fromDirDefault({
4622
+ baseDir = process.cwd(),
4623
+ relativeDirPath,
4624
+ dirName
4625
+ }) {
4626
+ const settablePaths = this.getSettablePaths();
4627
+ const actualRelativeDirPath = relativeDirPath ?? settablePaths.relativeDirPath;
4628
+ const skillDirPath = (0, import_node_path43.join)(baseDir, actualRelativeDirPath, dirName);
4629
+ const skillFilePath = (0, import_node_path43.join)(skillDirPath, SKILL_FILE_NAME);
4630
+ if (!await fileExists(skillFilePath)) {
4631
+ throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
4719
4632
  }
4720
- return new _CodexCliSkill({
4721
- baseDir: loaded.baseDir,
4722
- relativeDirPath: loaded.relativeDirPath,
4723
- dirName: loaded.dirName,
4633
+ const fileContent = await readFileContent(skillFilePath);
4634
+ const { frontmatter, body: content } = parseFrontmatter(fileContent);
4635
+ const result = SimulatedSkillFrontmatterSchema.safeParse(frontmatter);
4636
+ if (!result.success) {
4637
+ throw new Error(`Invalid frontmatter in ${skillFilePath}: ${formatError(result.error)}`);
4638
+ }
4639
+ const otherFiles = await this.collectOtherFiles(
4640
+ baseDir,
4641
+ actualRelativeDirPath,
4642
+ dirName,
4643
+ SKILL_FILE_NAME
4644
+ );
4645
+ return {
4646
+ baseDir,
4647
+ relativeDirPath: actualRelativeDirPath,
4648
+ dirName,
4724
4649
  frontmatter: result.data,
4725
- body: loaded.body,
4726
- otherFiles: loaded.otherFiles,
4727
- validate: true,
4728
- global: loaded.global
4650
+ body: content.trim(),
4651
+ otherFiles,
4652
+ validate: true
4653
+ };
4654
+ }
4655
+ /**
4656
+ * Check if a RulesyncSkill should be converted to this simulated skill type.
4657
+ * Uses the targets field in the RulesyncSkill frontmatter to determine targeting.
4658
+ */
4659
+ static isTargetedByRulesyncSkillDefault({
4660
+ rulesyncSkill,
4661
+ toolTarget
4662
+ }) {
4663
+ const frontmatter = rulesyncSkill.getFrontmatter();
4664
+ const targets = frontmatter.targets;
4665
+ if (targets.includes("*")) {
4666
+ return true;
4667
+ }
4668
+ return targets.includes(toolTarget);
4669
+ }
4670
+ /**
4671
+ * Get the settable paths for this tool's skill directories.
4672
+ * Must be implemented by concrete subclasses.
4673
+ */
4674
+ static getSettablePaths(_options) {
4675
+ throw new Error("Please implement this method in the subclass.");
4676
+ }
4677
+ };
4678
+
4679
+ // src/features/skills/agentsmd-skill.ts
4680
+ var AgentsmdSkill = class _AgentsmdSkill extends SimulatedSkill {
4681
+ static getSettablePaths(options) {
4682
+ if (options?.global) {
4683
+ throw new Error("AgentsmdSkill does not support global mode.");
4684
+ }
4685
+ return {
4686
+ relativeDirPath: (0, import_node_path44.join)(".agents", "skills")
4687
+ };
4688
+ }
4689
+ static async fromDir(params) {
4690
+ const baseParams = await this.fromDirDefault(params);
4691
+ return new _AgentsmdSkill(baseParams);
4692
+ }
4693
+ static fromRulesyncSkill(params) {
4694
+ const baseParams = {
4695
+ ...this.fromRulesyncSkillDefault(params),
4696
+ relativeDirPath: this.getSettablePaths().relativeDirPath
4697
+ };
4698
+ return new _AgentsmdSkill(baseParams);
4699
+ }
4700
+ static isTargetedByRulesyncSkill(rulesyncSkill) {
4701
+ return this.isTargetedByRulesyncSkillDefault({
4702
+ rulesyncSkill,
4703
+ toolTarget: "agentsmd"
4729
4704
  });
4730
4705
  }
4731
4706
  };
4732
4707
 
4733
- // src/features/skills/copilot-skill.ts
4708
+ // src/features/skills/codexcli-skill.ts
4734
4709
  var import_node_path46 = require("path");
4710
+ var import_mini21 = require("zod/mini");
4735
4711
 
4736
- // src/features/skills/simulated-skill.ts
4712
+ // src/features/skills/rulesync-skill.ts
4737
4713
  var import_node_path45 = require("path");
4738
- var import_mini21 = require("zod/mini");
4739
- var SimulatedSkillFrontmatterSchema = import_mini21.z.object({
4740
- name: import_mini21.z.string(),
4741
- description: import_mini21.z.string()
4714
+ var import_mini20 = require("zod/mini");
4715
+ var RulesyncSkillFrontmatterSchemaInternal = import_mini20.z.object({
4716
+ name: import_mini20.z.string(),
4717
+ description: import_mini20.z.string(),
4718
+ targets: import_mini20.z._default(RulesyncTargetsSchema, ["*"]),
4719
+ claudecode: import_mini20.z.optional(
4720
+ import_mini20.z.object({
4721
+ "allowed-tools": import_mini20.z.optional(import_mini20.z.array(import_mini20.z.string()))
4722
+ })
4723
+ )
4742
4724
  });
4743
- var SimulatedSkill = class extends ToolSkill {
4744
- frontmatter;
4745
- body;
4725
+ var RulesyncSkillFrontmatterSchema = RulesyncSkillFrontmatterSchemaInternal;
4726
+ var RulesyncSkill = class _RulesyncSkill extends AiDir {
4746
4727
  constructor({
4747
4728
  baseDir = process.cwd(),
4748
- relativeDirPath,
4729
+ relativeDirPath = RULESYNC_SKILLS_RELATIVE_DIR_PATH,
4749
4730
  dirName,
4750
4731
  frontmatter,
4751
4732
  body,
4752
4733
  otherFiles = [],
4753
- validate = true
4734
+ validate = true,
4735
+ global = false
4754
4736
  }) {
4755
4737
  super({
4756
4738
  baseDir,
@@ -4762,37 +4744,33 @@ var SimulatedSkill = class extends ToolSkill {
4762
4744
  frontmatter: { ...frontmatter }
4763
4745
  },
4764
4746
  otherFiles,
4765
- global: false
4766
- // Simulated skills are project mode only
4747
+ global
4767
4748
  });
4768
4749
  if (validate) {
4769
- const result = SimulatedSkillFrontmatterSchema.safeParse(frontmatter);
4750
+ const result = this.validate();
4770
4751
  if (!result.success) {
4771
- throw new Error(
4772
- `Invalid frontmatter in ${(0, import_node_path45.join)(relativeDirPath, dirName)}: ${formatError(result.error)}`
4773
- );
4752
+ throw result.error;
4774
4753
  }
4775
4754
  }
4776
- this.frontmatter = frontmatter;
4777
- this.body = body;
4778
4755
  }
4779
- getBody() {
4780
- return this.body;
4756
+ static getSettablePaths() {
4757
+ return {
4758
+ relativeDirPath: RULESYNC_SKILLS_RELATIVE_DIR_PATH
4759
+ };
4781
4760
  }
4782
4761
  getFrontmatter() {
4783
- return this.frontmatter;
4762
+ if (!this.mainFile?.frontmatter) {
4763
+ throw new Error("Frontmatter is not defined");
4764
+ }
4765
+ const result = RulesyncSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
4766
+ return result;
4784
4767
  }
4785
- toRulesyncSkill() {
4786
- throw new Error("Not implemented because it is a SIMULATED skill.");
4768
+ getBody() {
4769
+ return this.mainFile?.body ?? "";
4787
4770
  }
4788
4771
  validate() {
4789
- if (!this.frontmatter) {
4790
- return { success: true, error: null };
4791
- }
4792
- const result = SimulatedSkillFrontmatterSchema.safeParse(this.frontmatter);
4793
- if (result.success) {
4794
- return { success: true, error: null };
4795
- } else {
4772
+ const result = RulesyncSkillFrontmatterSchema.safeParse(this.mainFile?.frontmatter);
4773
+ if (!result.success) {
4796
4774
  return {
4797
4775
  success: false,
4798
4776
  error: new Error(
@@ -4800,92 +4778,193 @@ var SimulatedSkill = class extends ToolSkill {
4800
4778
  )
4801
4779
  };
4802
4780
  }
4781
+ return { success: true, error: null };
4803
4782
  }
4804
- static fromRulesyncSkillDefault({
4805
- rulesyncSkill,
4806
- validate = true
4807
- }) {
4808
- const rulesyncFrontmatter = rulesyncSkill.getFrontmatter();
4809
- const simulatedFrontmatter = {
4810
- name: rulesyncFrontmatter.name,
4811
- description: rulesyncFrontmatter.description
4812
- };
4813
- return {
4814
- baseDir: rulesyncSkill.getBaseDir(),
4815
- relativeDirPath: this.getSettablePaths().relativeDirPath,
4816
- dirName: rulesyncSkill.getDirName(),
4817
- frontmatter: simulatedFrontmatter,
4818
- body: rulesyncSkill.getBody(),
4819
- otherFiles: rulesyncSkill.getOtherFiles(),
4820
- validate
4821
- };
4822
- }
4823
- static async fromDirDefault({
4783
+ static async fromDir({
4824
4784
  baseDir = process.cwd(),
4825
- relativeDirPath,
4826
- dirName
4785
+ relativeDirPath = RULESYNC_SKILLS_RELATIVE_DIR_PATH,
4786
+ dirName,
4787
+ global = false
4827
4788
  }) {
4828
- const settablePaths = this.getSettablePaths();
4829
- const actualRelativeDirPath = relativeDirPath ?? settablePaths.relativeDirPath;
4830
- const skillDirPath = (0, import_node_path45.join)(baseDir, actualRelativeDirPath, dirName);
4789
+ const skillDirPath = (0, import_node_path45.join)(baseDir, relativeDirPath, dirName);
4831
4790
  const skillFilePath = (0, import_node_path45.join)(skillDirPath, SKILL_FILE_NAME);
4832
4791
  if (!await fileExists(skillFilePath)) {
4833
4792
  throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
4834
4793
  }
4835
4794
  const fileContent = await readFileContent(skillFilePath);
4836
4795
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
4837
- const result = SimulatedSkillFrontmatterSchema.safeParse(frontmatter);
4796
+ const result = RulesyncSkillFrontmatterSchema.safeParse(frontmatter);
4838
4797
  if (!result.success) {
4839
4798
  throw new Error(`Invalid frontmatter in ${skillFilePath}: ${formatError(result.error)}`);
4840
4799
  }
4841
4800
  const otherFiles = await this.collectOtherFiles(
4842
4801
  baseDir,
4843
- actualRelativeDirPath,
4802
+ relativeDirPath,
4844
4803
  dirName,
4845
4804
  SKILL_FILE_NAME
4846
4805
  );
4847
- return {
4806
+ return new _RulesyncSkill({
4848
4807
  baseDir,
4849
- relativeDirPath: actualRelativeDirPath,
4808
+ relativeDirPath,
4850
4809
  dirName,
4851
4810
  frontmatter: result.data,
4852
4811
  body: content.trim(),
4853
4812
  otherFiles,
4854
- validate: true
4813
+ validate: true,
4814
+ global
4815
+ });
4816
+ }
4817
+ };
4818
+
4819
+ // src/features/skills/codexcli-skill.ts
4820
+ var CodexCliSkillFrontmatterSchema = import_mini21.z.object({
4821
+ name: import_mini21.z.string(),
4822
+ description: import_mini21.z.string()
4823
+ });
4824
+ var CodexCliSkill = class _CodexCliSkill extends ToolSkill {
4825
+ constructor({
4826
+ baseDir = process.cwd(),
4827
+ relativeDirPath = (0, import_node_path46.join)(".codex", "skills"),
4828
+ dirName,
4829
+ frontmatter,
4830
+ body,
4831
+ otherFiles = [],
4832
+ validate = true,
4833
+ global = false
4834
+ }) {
4835
+ super({
4836
+ baseDir,
4837
+ relativeDirPath,
4838
+ dirName,
4839
+ mainFile: {
4840
+ name: SKILL_FILE_NAME,
4841
+ body,
4842
+ frontmatter: { ...frontmatter }
4843
+ },
4844
+ otherFiles,
4845
+ global
4846
+ });
4847
+ if (validate) {
4848
+ const result = this.validate();
4849
+ if (!result.success) {
4850
+ throw result.error;
4851
+ }
4852
+ }
4853
+ }
4854
+ static getSettablePaths({ global = false } = {}) {
4855
+ if (!global) {
4856
+ throw new Error("CodexCliSkill only supports global mode. Please pass { global: true }.");
4857
+ }
4858
+ return {
4859
+ relativeDirPath: (0, import_node_path46.join)(".codex", "skills")
4855
4860
  };
4856
4861
  }
4857
- /**
4858
- * Check if a RulesyncSkill should be converted to this simulated skill type.
4859
- * Uses the targets field in the RulesyncSkill frontmatter to determine targeting.
4860
- */
4861
- static isTargetedByRulesyncSkillDefault({
4862
+ getFrontmatter() {
4863
+ if (!this.mainFile?.frontmatter) {
4864
+ throw new Error("Frontmatter is not defined");
4865
+ }
4866
+ const result = CodexCliSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
4867
+ return result;
4868
+ }
4869
+ getBody() {
4870
+ return this.mainFile?.body ?? "";
4871
+ }
4872
+ validate() {
4873
+ if (!this.mainFile) {
4874
+ return {
4875
+ success: false,
4876
+ error: new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
4877
+ };
4878
+ }
4879
+ const result = CodexCliSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
4880
+ if (!result.success) {
4881
+ return {
4882
+ success: false,
4883
+ error: new Error(
4884
+ `Invalid frontmatter in ${this.getDirPath()}: ${formatError(result.error)}`
4885
+ )
4886
+ };
4887
+ }
4888
+ return { success: true, error: null };
4889
+ }
4890
+ toRulesyncSkill() {
4891
+ const frontmatter = this.getFrontmatter();
4892
+ const rulesyncFrontmatter = {
4893
+ name: frontmatter.name,
4894
+ description: frontmatter.description,
4895
+ targets: ["*"]
4896
+ };
4897
+ return new RulesyncSkill({
4898
+ baseDir: this.baseDir,
4899
+ relativeDirPath: this.relativeDirPath,
4900
+ dirName: this.getDirName(),
4901
+ frontmatter: rulesyncFrontmatter,
4902
+ body: this.getBody(),
4903
+ otherFiles: this.getOtherFiles(),
4904
+ validate: true,
4905
+ global: this.global
4906
+ });
4907
+ }
4908
+ static fromRulesyncSkill({
4862
4909
  rulesyncSkill,
4863
- toolTarget
4910
+ validate = true,
4911
+ global = false
4864
4912
  }) {
4865
- const frontmatter = rulesyncSkill.getFrontmatter();
4866
- const targets = frontmatter.targets;
4867
- if (targets.includes("*")) {
4868
- return true;
4869
- }
4870
- return targets.includes(toolTarget);
4913
+ const settablePaths = _CodexCliSkill.getSettablePaths({ global });
4914
+ const rulesyncFrontmatter = rulesyncSkill.getFrontmatter();
4915
+ const codexFrontmatter = {
4916
+ name: rulesyncFrontmatter.name,
4917
+ description: rulesyncFrontmatter.description
4918
+ };
4919
+ return new _CodexCliSkill({
4920
+ baseDir: rulesyncSkill.getBaseDir(),
4921
+ relativeDirPath: settablePaths.relativeDirPath,
4922
+ dirName: rulesyncSkill.getDirName(),
4923
+ frontmatter: codexFrontmatter,
4924
+ body: rulesyncSkill.getBody(),
4925
+ otherFiles: rulesyncSkill.getOtherFiles(),
4926
+ validate,
4927
+ global
4928
+ });
4871
4929
  }
4872
- /**
4873
- * Get the settable paths for this tool's skill directories.
4874
- * Must be implemented by concrete subclasses.
4875
- */
4876
- static getSettablePaths(_options) {
4877
- throw new Error("Please implement this method in the subclass.");
4930
+ static isTargetedByRulesyncSkill(rulesyncSkill) {
4931
+ const targets = rulesyncSkill.getFrontmatter().targets;
4932
+ return targets.includes("*") || targets.includes("codexcli");
4933
+ }
4934
+ static async fromDir(params) {
4935
+ const loaded = await this.loadSkillDirContent({
4936
+ ...params,
4937
+ getSettablePaths: _CodexCliSkill.getSettablePaths
4938
+ });
4939
+ const result = CodexCliSkillFrontmatterSchema.safeParse(loaded.frontmatter);
4940
+ if (!result.success) {
4941
+ const skillDirPath = (0, import_node_path46.join)(loaded.baseDir, loaded.relativeDirPath, loaded.dirName);
4942
+ throw new Error(
4943
+ `Invalid frontmatter in ${(0, import_node_path46.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`
4944
+ );
4945
+ }
4946
+ return new _CodexCliSkill({
4947
+ baseDir: loaded.baseDir,
4948
+ relativeDirPath: loaded.relativeDirPath,
4949
+ dirName: loaded.dirName,
4950
+ frontmatter: result.data,
4951
+ body: loaded.body,
4952
+ otherFiles: loaded.otherFiles,
4953
+ validate: true,
4954
+ global: loaded.global
4955
+ });
4878
4956
  }
4879
4957
  };
4880
4958
 
4881
4959
  // src/features/skills/copilot-skill.ts
4960
+ var import_node_path47 = require("path");
4882
4961
  var CopilotSkill = class _CopilotSkill extends SimulatedSkill {
4883
4962
  static getSettablePaths(options) {
4884
4963
  if (options?.global) {
4885
4964
  throw new Error("CopilotSkill does not support global mode.");
4886
4965
  }
4887
4966
  return {
4888
- relativeDirPath: (0, import_node_path46.join)(".github", "skills")
4967
+ relativeDirPath: (0, import_node_path47.join)(".github", "skills")
4889
4968
  };
4890
4969
  }
4891
4970
  static async fromDir(params) {
@@ -4908,31 +4987,61 @@ var CopilotSkill = class _CopilotSkill extends SimulatedSkill {
4908
4987
  };
4909
4988
 
4910
4989
  // src/features/skills/cursor-skill.ts
4911
- var import_node_path47 = require("path");
4990
+ var import_node_path48 = require("path");
4912
4991
  var CursorSkill = class _CursorSkill extends SimulatedSkill {
4913
4992
  static getSettablePaths(options) {
4914
4993
  if (options?.global) {
4915
- throw new Error("CursorSkill does not support global mode.");
4994
+ throw new Error("CursorSkill does not support global mode.");
4995
+ }
4996
+ return {
4997
+ relativeDirPath: (0, import_node_path48.join)(".cursor", "skills")
4998
+ };
4999
+ }
5000
+ static async fromDir(params) {
5001
+ const baseParams = await this.fromDirDefault(params);
5002
+ return new _CursorSkill(baseParams);
5003
+ }
5004
+ static fromRulesyncSkill(params) {
5005
+ const baseParams = {
5006
+ ...this.fromRulesyncSkillDefault(params),
5007
+ relativeDirPath: this.getSettablePaths().relativeDirPath
5008
+ };
5009
+ return new _CursorSkill(baseParams);
5010
+ }
5011
+ static isTargetedByRulesyncSkill(rulesyncSkill) {
5012
+ return this.isTargetedByRulesyncSkillDefault({
5013
+ rulesyncSkill,
5014
+ toolTarget: "cursor"
5015
+ });
5016
+ }
5017
+ };
5018
+
5019
+ // src/features/skills/geminicli-skill.ts
5020
+ var import_node_path49 = require("path");
5021
+ var GeminiCliSkill = class _GeminiCliSkill extends SimulatedSkill {
5022
+ static getSettablePaths(options) {
5023
+ if (options?.global) {
5024
+ throw new Error("GeminiCliSkill does not support global mode.");
4916
5025
  }
4917
5026
  return {
4918
- relativeDirPath: (0, import_node_path47.join)(".cursor", "skills")
5027
+ relativeDirPath: (0, import_node_path49.join)(".gemini", "skills")
4919
5028
  };
4920
5029
  }
4921
5030
  static async fromDir(params) {
4922
5031
  const baseParams = await this.fromDirDefault(params);
4923
- return new _CursorSkill(baseParams);
5032
+ return new _GeminiCliSkill(baseParams);
4924
5033
  }
4925
5034
  static fromRulesyncSkill(params) {
4926
5035
  const baseParams = {
4927
5036
  ...this.fromRulesyncSkillDefault(params),
4928
5037
  relativeDirPath: this.getSettablePaths().relativeDirPath
4929
5038
  };
4930
- return new _CursorSkill(baseParams);
5039
+ return new _GeminiCliSkill(baseParams);
4931
5040
  }
4932
5041
  static isTargetedByRulesyncSkill(rulesyncSkill) {
4933
5042
  return this.isTargetedByRulesyncSkillDefault({
4934
5043
  rulesyncSkill,
4935
- toolTarget: "cursor"
5044
+ toolTarget: "geminicli"
4936
5045
  });
4937
5046
  }
4938
5047
  };
@@ -4942,7 +5051,7 @@ var import_node_path52 = require("path");
4942
5051
  var import_mini23 = require("zod/mini");
4943
5052
 
4944
5053
  // src/types/dir-feature-processor.ts
4945
- var import_node_path48 = require("path");
5054
+ var import_node_path50 = require("path");
4946
5055
  var DirFeatureProcessor = class {
4947
5056
  baseDir;
4948
5057
  constructor({ baseDir = process.cwd() }) {
@@ -4964,14 +5073,14 @@ var DirFeatureProcessor = class {
4964
5073
  await ensureDir(dirPath);
4965
5074
  const mainFile = aiDir.getMainFile();
4966
5075
  if (mainFile) {
4967
- const mainFilePath = (0, import_node_path48.join)(dirPath, mainFile.name);
5076
+ const mainFilePath = (0, import_node_path50.join)(dirPath, mainFile.name);
4968
5077
  const content = stringifyFrontmatter(mainFile.body, mainFile.frontmatter);
4969
5078
  const contentWithNewline = addTrailingNewline(content);
4970
5079
  await writeFileContent(mainFilePath, contentWithNewline);
4971
5080
  }
4972
5081
  const otherFiles = aiDir.getOtherFiles();
4973
5082
  for (const file of otherFiles) {
4974
- const filePath = (0, import_node_path48.join)(dirPath, file.relativeFilePathToDirPath);
5083
+ const filePath = (0, import_node_path50.join)(dirPath, file.relativeFilePathToDirPath);
4975
5084
  const contentWithNewline = addTrailingNewline(file.fileBuffer.toString("utf-8"));
4976
5085
  await writeFileContent(filePath, contentWithNewline);
4977
5086
  }
@@ -4985,38 +5094,8 @@ var DirFeatureProcessor = class {
4985
5094
  }
4986
5095
  };
4987
5096
 
4988
- // src/features/skills/agentsmd-skill.ts
4989
- var import_node_path49 = require("path");
4990
- var AgentsmdSkill = class _AgentsmdSkill extends SimulatedSkill {
4991
- static getSettablePaths(options) {
4992
- if (options?.global) {
4993
- throw new Error("AgentsmdSkill does not support global mode.");
4994
- }
4995
- return {
4996
- relativeDirPath: (0, import_node_path49.join)(".agents", "skills")
4997
- };
4998
- }
4999
- static async fromDir(params) {
5000
- const baseParams = await this.fromDirDefault(params);
5001
- return new _AgentsmdSkill(baseParams);
5002
- }
5003
- static fromRulesyncSkill(params) {
5004
- const baseParams = {
5005
- ...this.fromRulesyncSkillDefault(params),
5006
- relativeDirPath: this.getSettablePaths().relativeDirPath
5007
- };
5008
- return new _AgentsmdSkill(baseParams);
5009
- }
5010
- static isTargetedByRulesyncSkill(rulesyncSkill) {
5011
- return this.isTargetedByRulesyncSkillDefault({
5012
- rulesyncSkill,
5013
- toolTarget: "agentsmd"
5014
- });
5015
- }
5016
- };
5017
-
5018
5097
  // src/features/skills/claudecode-skill.ts
5019
- var import_node_path50 = require("path");
5098
+ var import_node_path51 = require("path");
5020
5099
  var import_mini22 = require("zod/mini");
5021
5100
  var ClaudecodeSkillFrontmatterSchema = import_mini22.z.object({
5022
5101
  name: import_mini22.z.string(),
@@ -5026,7 +5105,7 @@ var ClaudecodeSkillFrontmatterSchema = import_mini22.z.object({
5026
5105
  var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
5027
5106
  constructor({
5028
5107
  baseDir = process.cwd(),
5029
- relativeDirPath = (0, import_node_path50.join)(".claude", "skills"),
5108
+ relativeDirPath = (0, import_node_path51.join)(".claude", "skills"),
5030
5109
  dirName,
5031
5110
  frontmatter,
5032
5111
  body,
@@ -5057,7 +5136,7 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
5057
5136
  global: _global = false
5058
5137
  } = {}) {
5059
5138
  return {
5060
- relativeDirPath: (0, import_node_path50.join)(".claude", "skills")
5139
+ relativeDirPath: (0, import_node_path51.join)(".claude", "skills")
5061
5140
  };
5062
5141
  }
5063
5142
  getFrontmatter() {
@@ -5144,9 +5223,9 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
5144
5223
  });
5145
5224
  const result = ClaudecodeSkillFrontmatterSchema.safeParse(loaded.frontmatter);
5146
5225
  if (!result.success) {
5147
- const skillDirPath = (0, import_node_path50.join)(loaded.baseDir, loaded.relativeDirPath, loaded.dirName);
5226
+ const skillDirPath = (0, import_node_path51.join)(loaded.baseDir, loaded.relativeDirPath, loaded.dirName);
5148
5227
  throw new Error(
5149
- `Invalid frontmatter in ${(0, import_node_path50.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`
5228
+ `Invalid frontmatter in ${(0, import_node_path51.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`
5150
5229
  );
5151
5230
  }
5152
5231
  return new _ClaudecodeSkill({
@@ -5162,36 +5241,6 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
5162
5241
  }
5163
5242
  };
5164
5243
 
5165
- // src/features/skills/geminicli-skill.ts
5166
- var import_node_path51 = require("path");
5167
- var GeminiCliSkill = class _GeminiCliSkill extends SimulatedSkill {
5168
- static getSettablePaths(options) {
5169
- if (options?.global) {
5170
- throw new Error("GeminiCliSkill does not support global mode.");
5171
- }
5172
- return {
5173
- relativeDirPath: (0, import_node_path51.join)(".gemini", "skills")
5174
- };
5175
- }
5176
- static async fromDir(params) {
5177
- const baseParams = await this.fromDirDefault(params);
5178
- return new _GeminiCliSkill(baseParams);
5179
- }
5180
- static fromRulesyncSkill(params) {
5181
- const baseParams = {
5182
- ...this.fromRulesyncSkillDefault(params),
5183
- relativeDirPath: this.getSettablePaths().relativeDirPath
5184
- };
5185
- return new _GeminiCliSkill(baseParams);
5186
- }
5187
- static isTargetedByRulesyncSkill(rulesyncSkill) {
5188
- return this.isTargetedByRulesyncSkillDefault({
5189
- rulesyncSkill,
5190
- toolTarget: "geminicli"
5191
- });
5192
- }
5193
- };
5194
-
5195
5244
  // src/features/skills/skills-processor.ts
5196
5245
  var skillsProcessorToolTargetTuple = [
5197
5246
  "agentsmd",
@@ -8005,33 +8054,196 @@ var rulesProcessorToolTargets = [
8005
8054
  "windsurf"
8006
8055
  ];
8007
8056
  var RulesProcessorToolTargetSchema = import_mini33.z.enum(rulesProcessorToolTargets);
8008
- var rulesProcessorToolTargetsGlobal = [
8009
- "claudecode",
8010
- "claudecode-legacy",
8011
- "codexcli",
8012
- "geminicli"
8013
- ];
8014
8057
  var toolRuleFactories = /* @__PURE__ */ new Map([
8015
- ["agentsmd", { class: AgentsMdRule, meta: { extension: "md" } }],
8016
- ["amazonqcli", { class: AmazonQCliRule, meta: { extension: "md" } }],
8017
- ["antigravity", { class: AntigravityRule, meta: { extension: "md" } }],
8018
- ["augmentcode", { class: AugmentcodeRule, meta: { extension: "md" } }],
8019
- ["augmentcode-legacy", { class: AugmentcodeLegacyRule, meta: { extension: "md" } }],
8020
- ["claudecode", { class: ClaudecodeRule, meta: { extension: "md" } }],
8021
- ["claudecode-legacy", { class: ClaudecodeLegacyRule, meta: { extension: "md" } }],
8022
- ["cline", { class: ClineRule, meta: { extension: "md" } }],
8023
- ["codexcli", { class: CodexcliRule, meta: { extension: "md" } }],
8024
- ["copilot", { class: CopilotRule, meta: { extension: "md" } }],
8025
- ["cursor", { class: CursorRule, meta: { extension: "mdc" } }],
8026
- ["geminicli", { class: GeminiCliRule, meta: { extension: "md" } }],
8027
- ["junie", { class: JunieRule, meta: { extension: "md" } }],
8028
- ["kiro", { class: KiroRule, meta: { extension: "md" } }],
8029
- ["opencode", { class: OpenCodeRule, meta: { extension: "md" } }],
8030
- ["qwencode", { class: QwencodeRule, meta: { extension: "md" } }],
8031
- ["roo", { class: RooRule, meta: { extension: "md" } }],
8032
- ["warp", { class: WarpRule, meta: { extension: "md" } }],
8033
- ["windsurf", { class: WindsurfRule, meta: { extension: "md" } }]
8058
+ [
8059
+ "agentsmd",
8060
+ {
8061
+ class: AgentsMdRule,
8062
+ meta: {
8063
+ extension: "md",
8064
+ supportsGlobal: false,
8065
+ ruleDiscoveryMode: "toon",
8066
+ additionalConventions: {
8067
+ commands: { commandClass: AgentsmdCommand },
8068
+ subagents: { subagentClass: AgentsmdSubagent },
8069
+ skills: { skillClass: AgentsmdSkill }
8070
+ }
8071
+ }
8072
+ }
8073
+ ],
8074
+ [
8075
+ "amazonqcli",
8076
+ {
8077
+ class: AmazonQCliRule,
8078
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
8079
+ }
8080
+ ],
8081
+ [
8082
+ "antigravity",
8083
+ {
8084
+ class: AntigravityRule,
8085
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
8086
+ }
8087
+ ],
8088
+ [
8089
+ "augmentcode",
8090
+ {
8091
+ class: AugmentcodeRule,
8092
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
8093
+ }
8094
+ ],
8095
+ [
8096
+ "augmentcode-legacy",
8097
+ {
8098
+ class: AugmentcodeLegacyRule,
8099
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
8100
+ }
8101
+ ],
8102
+ [
8103
+ "claudecode",
8104
+ {
8105
+ class: ClaudecodeRule,
8106
+ meta: { extension: "md", supportsGlobal: true, ruleDiscoveryMode: "auto" }
8107
+ }
8108
+ ],
8109
+ [
8110
+ "claudecode-legacy",
8111
+ {
8112
+ class: ClaudecodeLegacyRule,
8113
+ meta: { extension: "md", supportsGlobal: true, ruleDiscoveryMode: "claudecode-legacy" }
8114
+ }
8115
+ ],
8116
+ [
8117
+ "cline",
8118
+ {
8119
+ class: ClineRule,
8120
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
8121
+ }
8122
+ ],
8123
+ [
8124
+ "codexcli",
8125
+ {
8126
+ class: CodexcliRule,
8127
+ meta: {
8128
+ extension: "md",
8129
+ supportsGlobal: true,
8130
+ ruleDiscoveryMode: "toon",
8131
+ additionalConventions: {
8132
+ subagents: { subagentClass: CodexCliSubagent },
8133
+ skills: { skillClass: CodexCliSkill, globalOnly: true }
8134
+ }
8135
+ }
8136
+ }
8137
+ ],
8138
+ [
8139
+ "copilot",
8140
+ {
8141
+ class: CopilotRule,
8142
+ meta: {
8143
+ extension: "md",
8144
+ supportsGlobal: false,
8145
+ ruleDiscoveryMode: "auto",
8146
+ additionalConventions: {
8147
+ commands: { commandClass: CopilotCommand },
8148
+ subagents: { subagentClass: CopilotSubagent },
8149
+ skills: { skillClass: CopilotSkill }
8150
+ }
8151
+ }
8152
+ }
8153
+ ],
8154
+ [
8155
+ "cursor",
8156
+ {
8157
+ class: CursorRule,
8158
+ meta: {
8159
+ extension: "mdc",
8160
+ supportsGlobal: false,
8161
+ ruleDiscoveryMode: "auto",
8162
+ additionalConventions: {
8163
+ commands: { commandClass: CursorCommand },
8164
+ subagents: { subagentClass: CursorSubagent },
8165
+ skills: { skillClass: CursorSkill }
8166
+ },
8167
+ createsSeparateConventionsRule: true
8168
+ }
8169
+ }
8170
+ ],
8171
+ [
8172
+ "geminicli",
8173
+ {
8174
+ class: GeminiCliRule,
8175
+ meta: {
8176
+ extension: "md",
8177
+ supportsGlobal: true,
8178
+ ruleDiscoveryMode: "toon",
8179
+ additionalConventions: {
8180
+ commands: { commandClass: GeminiCliCommand },
8181
+ subagents: { subagentClass: GeminiCliSubagent },
8182
+ skills: { skillClass: GeminiCliSkill }
8183
+ }
8184
+ }
8185
+ }
8186
+ ],
8187
+ [
8188
+ "junie",
8189
+ {
8190
+ class: JunieRule,
8191
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
8192
+ }
8193
+ ],
8194
+ [
8195
+ "kiro",
8196
+ {
8197
+ class: KiroRule,
8198
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
8199
+ }
8200
+ ],
8201
+ [
8202
+ "opencode",
8203
+ {
8204
+ class: OpenCodeRule,
8205
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
8206
+ }
8207
+ ],
8208
+ [
8209
+ "qwencode",
8210
+ {
8211
+ class: QwencodeRule,
8212
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
8213
+ }
8214
+ ],
8215
+ [
8216
+ "roo",
8217
+ {
8218
+ class: RooRule,
8219
+ meta: {
8220
+ extension: "md",
8221
+ supportsGlobal: false,
8222
+ ruleDiscoveryMode: "auto",
8223
+ additionalConventions: {
8224
+ commands: { commandClass: RooCommand },
8225
+ subagents: { subagentClass: RooSubagent }
8226
+ },
8227
+ createsSeparateConventionsRule: true
8228
+ }
8229
+ }
8230
+ ],
8231
+ [
8232
+ "warp",
8233
+ {
8234
+ class: WarpRule,
8235
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
8236
+ }
8237
+ ],
8238
+ [
8239
+ "windsurf",
8240
+ {
8241
+ class: WindsurfRule,
8242
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
8243
+ }
8244
+ ]
8034
8245
  ]);
8246
+ var rulesProcessorToolTargetsGlobal = Array.from(toolRuleFactories.entries()).filter(([_, factory]) => factory.meta.supportsGlobal).map(([target]) => target);
8035
8247
  var defaultGetFactory6 = (target) => {
8036
8248
  const factory = toolRuleFactories.get(target);
8037
8249
  if (!factory) {
@@ -8046,6 +8258,7 @@ var RulesProcessor = class extends FeatureProcessor {
8046
8258
  simulateSkills;
8047
8259
  global;
8048
8260
  getFactory;
8261
+ skills;
8049
8262
  constructor({
8050
8263
  baseDir = process.cwd(),
8051
8264
  toolTarget,
@@ -8053,7 +8266,8 @@ var RulesProcessor = class extends FeatureProcessor {
8053
8266
  simulateSubagents = false,
8054
8267
  simulateSkills = false,
8055
8268
  global = false,
8056
- getFactory = defaultGetFactory6
8269
+ getFactory = defaultGetFactory6,
8270
+ skills
8057
8271
  }) {
8058
8272
  super({ baseDir });
8059
8273
  const result = RulesProcessorToolTargetSchema.safeParse(toolTarget);
@@ -8068,12 +8282,14 @@ var RulesProcessor = class extends FeatureProcessor {
8068
8282
  this.simulateSubagents = simulateSubagents;
8069
8283
  this.simulateSkills = simulateSkills;
8070
8284
  this.getFactory = getFactory;
8285
+ this.skills = skills;
8071
8286
  }
8072
8287
  async convertRulesyncFilesToToolFiles(rulesyncFiles) {
8073
8288
  const rulesyncRules = rulesyncFiles.filter(
8074
8289
  (file) => file instanceof RulesyncRule
8075
8290
  );
8076
8291
  const factory = this.getFactory(this.toolTarget);
8292
+ const { meta } = factory;
8077
8293
  const toolRules = rulesyncRules.map((rulesyncRule) => {
8078
8294
  if (!factory.class.isTargetedByRulesyncRule(rulesyncRule)) {
8079
8295
  return null;
@@ -8086,153 +8302,105 @@ var RulesProcessor = class extends FeatureProcessor {
8086
8302
  });
8087
8303
  }).filter((rule) => rule !== null);
8088
8304
  const isSimulated = this.simulateCommands || this.simulateSubagents || this.simulateSkills;
8089
- if (isSimulated && this.toolTarget === "cursor") {
8090
- toolRules.push(
8091
- new CursorRule({
8092
- baseDir: this.baseDir,
8093
- frontmatter: {
8094
- alwaysApply: true
8095
- },
8096
- body: this.generateAdditionalConventionsSection({
8097
- commands: { relativeDirPath: CursorCommand.getSettablePaths().relativeDirPath },
8098
- subagents: {
8099
- relativeDirPath: CursorSubagent.getSettablePaths().relativeDirPath
8100
- },
8101
- skills: {
8102
- relativeDirPath: CursorSkill.getSettablePaths().relativeDirPath
8103
- }
8104
- }),
8105
- relativeDirPath: CursorRule.getSettablePaths().nonRoot.relativeDirPath,
8106
- relativeFilePath: "additional-conventions.mdc",
8107
- validate: true
8108
- })
8109
- );
8110
- }
8111
- if (isSimulated && this.toolTarget === "roo") {
8112
- toolRules.push(
8113
- new RooRule({
8114
- baseDir: this.baseDir,
8115
- relativeDirPath: RooRule.getSettablePaths().nonRoot.relativeDirPath,
8116
- relativeFilePath: "additional-conventions.md",
8117
- fileContent: this.generateAdditionalConventionsSection({
8118
- commands: { relativeDirPath: RooCommand.getSettablePaths().relativeDirPath },
8119
- subagents: {
8120
- relativeDirPath: RooSubagent.getSettablePaths().relativeDirPath
8121
- }
8122
- }),
8123
- validate: true
8124
- })
8125
- );
8305
+ if (isSimulated && meta.createsSeparateConventionsRule && meta.additionalConventions) {
8306
+ const conventionsContent = this.generateAdditionalConventionsSectionFromMeta(meta);
8307
+ const settablePaths = factory.class.getSettablePaths();
8308
+ const nonRootPath = "nonRoot" in settablePaths ? settablePaths.nonRoot : null;
8309
+ if (nonRootPath) {
8310
+ toolRules.push(
8311
+ factory.class.fromRulesyncRule({
8312
+ baseDir: this.baseDir,
8313
+ rulesyncRule: new RulesyncRule({
8314
+ baseDir: this.baseDir,
8315
+ relativeDirPath: nonRootPath.relativeDirPath,
8316
+ relativeFilePath: "additional-conventions.md",
8317
+ frontmatter: {
8318
+ root: false,
8319
+ targets: [this.toolTarget]
8320
+ },
8321
+ body: conventionsContent
8322
+ }),
8323
+ validate: true,
8324
+ global: this.global
8325
+ })
8326
+ );
8327
+ }
8126
8328
  }
8127
8329
  const rootRuleIndex = toolRules.findIndex((rule) => rule.isRoot());
8128
8330
  if (rootRuleIndex === -1) {
8129
8331
  return toolRules;
8130
8332
  }
8131
- switch (this.toolTarget) {
8132
- case "agentsmd": {
8133
- const rootRule = toolRules[rootRuleIndex];
8134
- rootRule?.setFileContent(
8135
- this.generateToonReferencesSection(toolRules) + this.generateAdditionalConventionsSection({
8136
- commands: { relativeDirPath: AgentsmdCommand.getSettablePaths().relativeDirPath },
8137
- subagents: {
8138
- relativeDirPath: AgentsmdSubagent.getSettablePaths().relativeDirPath
8139
- }
8140
- }) + rootRule.getFileContent()
8141
- );
8142
- return toolRules;
8143
- }
8144
- case "augmentcode-legacy": {
8145
- const rootRule = toolRules[rootRuleIndex];
8146
- rootRule?.setFileContent(
8147
- this.generateToonReferencesSection(toolRules) + rootRule.getFileContent()
8148
- );
8149
- return toolRules;
8150
- }
8151
- case "claudecode": {
8152
- return toolRules;
8153
- }
8154
- case "claudecode-legacy": {
8155
- const rootRule = toolRules[rootRuleIndex];
8156
- rootRule?.setFileContent(
8157
- this.generateReferencesSection(toolRules) + rootRule.getFileContent()
8158
- );
8159
- return toolRules;
8160
- }
8161
- case "codexcli": {
8162
- const rootRule = toolRules[rootRuleIndex];
8163
- rootRule?.setFileContent(
8164
- this.generateToonReferencesSection(toolRules) + this.generateAdditionalConventionsSection({
8165
- subagents: {
8166
- relativeDirPath: CodexCliSubagent.getSettablePaths().relativeDirPath
8167
- },
8168
- // Codex CLI skills are only supported in global mode
8169
- ...this.global && {
8170
- skills: {
8171
- relativeDirPath: CodexCliSkill.getSettablePaths({ global: this.global }).relativeDirPath
8172
- }
8173
- }
8174
- }) + rootRule.getFileContent()
8175
- );
8176
- return toolRules;
8177
- }
8178
- case "copilot": {
8179
- const rootRule = toolRules[rootRuleIndex];
8180
- rootRule?.setFileContent(
8181
- this.generateAdditionalConventionsSection({
8182
- commands: { relativeDirPath: CopilotCommand.getSettablePaths().relativeDirPath },
8183
- subagents: {
8184
- relativeDirPath: CopilotSubagent.getSettablePaths().relativeDirPath
8185
- },
8186
- skills: {
8187
- relativeDirPath: CopilotSkill.getSettablePaths().relativeDirPath
8188
- }
8189
- }) + rootRule.getFileContent()
8190
- );
8191
- return toolRules;
8192
- }
8193
- case "geminicli": {
8194
- const rootRule = toolRules[rootRuleIndex];
8195
- rootRule?.setFileContent(
8196
- this.generateToonReferencesSection(toolRules) + this.generateAdditionalConventionsSection({
8197
- commands: { relativeDirPath: GeminiCliCommand.getSettablePaths().relativeDirPath },
8198
- subagents: {
8199
- relativeDirPath: GeminiCliSubagent.getSettablePaths().relativeDirPath
8200
- }
8201
- }) + rootRule.getFileContent()
8202
- );
8203
- return toolRules;
8204
- }
8205
- case "kiro": {
8206
- const rootRule = toolRules[rootRuleIndex];
8207
- rootRule?.setFileContent(
8208
- this.generateToonReferencesSection(toolRules) + rootRule.getFileContent()
8209
- );
8210
- return toolRules;
8211
- }
8212
- case "opencode": {
8213
- const rootRule = toolRules[rootRuleIndex];
8214
- rootRule?.setFileContent(
8215
- this.generateToonReferencesSection(toolRules) + rootRule.getFileContent()
8216
- );
8217
- return toolRules;
8218
- }
8219
- case "qwencode": {
8220
- const rootRule = toolRules[rootRuleIndex];
8221
- rootRule?.setFileContent(
8222
- this.generateToonReferencesSection(toolRules) + rootRule.getFileContent()
8223
- );
8224
- return toolRules;
8225
- }
8226
- case "warp": {
8227
- const rootRule = toolRules[rootRuleIndex];
8228
- rootRule?.setFileContent(
8229
- this.generateToonReferencesSection(toolRules) + rootRule.getFileContent()
8230
- );
8231
- return toolRules;
8232
- }
8333
+ const rootRule = toolRules[rootRuleIndex];
8334
+ if (!rootRule) {
8335
+ return toolRules;
8336
+ }
8337
+ const referenceSection = this.generateReferenceSectionFromMeta(meta, toolRules);
8338
+ const conventionsSection = !meta.createsSeparateConventionsRule && meta.additionalConventions ? this.generateAdditionalConventionsSectionFromMeta(meta) : "";
8339
+ const newContent = referenceSection + conventionsSection + rootRule.getFileContent();
8340
+ rootRule.setFileContent(newContent);
8341
+ return toolRules;
8342
+ }
8343
+ buildSkillList(skillClass) {
8344
+ if (!this.skills) return [];
8345
+ const toolRelativeDirPath = skillClass.getSettablePaths({
8346
+ global: this.global
8347
+ }).relativeDirPath;
8348
+ return this.skills.filter((skill) => skillClass.isTargetedByRulesyncSkill(skill)).map((skill) => {
8349
+ const frontmatter = skill.getFrontmatter();
8350
+ const relativePath = (0, import_node_path84.join)(toolRelativeDirPath, skill.getDirName(), SKILL_FILE_NAME);
8351
+ return {
8352
+ name: frontmatter.name,
8353
+ description: frontmatter.description,
8354
+ path: relativePath
8355
+ };
8356
+ });
8357
+ }
8358
+ /**
8359
+ * Generate reference section based on meta configuration.
8360
+ */
8361
+ generateReferenceSectionFromMeta(meta, toolRules) {
8362
+ switch (meta.ruleDiscoveryMode) {
8363
+ case "toon":
8364
+ return this.generateToonReferencesSection(toolRules);
8365
+ case "claudecode-legacy":
8366
+ return this.generateReferencesSection(toolRules);
8367
+ case "auto":
8233
8368
  default:
8234
- return toolRules;
8369
+ return "";
8370
+ }
8371
+ }
8372
+ /**
8373
+ * Generate additional conventions section based on meta configuration.
8374
+ */
8375
+ generateAdditionalConventionsSectionFromMeta(meta) {
8376
+ const { additionalConventions } = meta;
8377
+ if (!additionalConventions) {
8378
+ return "";
8379
+ }
8380
+ const conventions = {};
8381
+ if (additionalConventions.commands) {
8382
+ const { commandClass } = additionalConventions.commands;
8383
+ const relativeDirPath = commandClass.getSettablePaths({
8384
+ global: this.global
8385
+ }).relativeDirPath;
8386
+ conventions.commands = { relativeDirPath };
8387
+ }
8388
+ if (additionalConventions.subagents) {
8389
+ const { subagentClass } = additionalConventions.subagents;
8390
+ const relativeDirPath = subagentClass.getSettablePaths({
8391
+ global: this.global
8392
+ }).relativeDirPath;
8393
+ conventions.subagents = { relativeDirPath };
8235
8394
  }
8395
+ if (additionalConventions.skills) {
8396
+ const { skillClass, globalOnly } = additionalConventions.skills;
8397
+ if (!globalOnly || this.global) {
8398
+ conventions.skills = {
8399
+ skillList: this.buildSkillList(skillClass)
8400
+ };
8401
+ }
8402
+ }
8403
+ return this.generateAdditionalConventionsSection(conventions);
8236
8404
  }
8237
8405
  async convertToolFilesToRulesyncFiles(toolFiles) {
8238
8406
  const toolRules = toolFiles.filter((file) => file instanceof ToolRule);
@@ -8417,15 +8585,7 @@ Simulated subagents are specialized AI assistants that can be invoked to handle
8417
8585
  When users call a simulated subagent, it will look for the corresponding markdown file, \`${(0, import_node_path84.join)(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "{subagent}.md")}\`, and execute its contents as the block of operations.
8418
8586
 
8419
8587
  For example, if the user instructs \`Call planner subagent to plan the refactoring\`, you have to look for the markdown file, \`${(0, import_node_path84.join)(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "planner.md")}\`, and execute its contents as the block of operations.` : "";
8420
- const skillsSection = skills ? `## Simulated Skills
8421
-
8422
- Simulated skills are specialized capabilities that can be invoked to handle specific types of tasks.
8423
-
8424
- When users invoke a simulated skill, look for the corresponding SKILL.md file in \`${(0, import_node_path84.join)(RULESYNC_SKILLS_RELATIVE_DIR_PATH, "{skill}/SKILL.md")}\` and execute its contents as the block of operations.
8425
-
8426
- For example, if the user instructs \`Use the skill example-skill to achieve something\`, look for \`${(0, import_node_path84.join)(RULESYNC_SKILLS_RELATIVE_DIR_PATH, "example-skill/SKILL.md")}\` and execute its contents.
8427
-
8428
- 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.` : "";
8588
+ const skillsSection = skills ? this.generateSkillsSection(skills) : "";
8429
8589
  const result = [
8430
8590
  overview,
8431
8591
  ...this.simulateCommands && CommandsProcessor.getToolTargetsSimulated().includes(this.toolTarget) ? [commandsSection] : [],
@@ -8434,6 +8594,21 @@ Additionally, you should proactively consider using available skills when they w
8434
8594
  ].join("\n\n") + "\n\n";
8435
8595
  return result;
8436
8596
  }
8597
+ generateSkillsSection(skills) {
8598
+ if (!skills.skillList || skills.skillList.length === 0) {
8599
+ return "";
8600
+ }
8601
+ const skillListWithAtPrefix = skills.skillList.map((skill) => ({
8602
+ ...skill,
8603
+ path: `@${skill.path}`
8604
+ }));
8605
+ const toonContent = (0, import_toon.encode)({ skillList: skillListWithAtPrefix });
8606
+ return `## Simulated Skills
8607
+
8608
+ 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.
8609
+
8610
+ ${toonContent}`;
8611
+ }
8437
8612
  };
8438
8613
 
8439
8614
  // src/cli/commands/generate.ts
@@ -8446,13 +8621,15 @@ async function generateCommand(options) {
8446
8621
  process.exit(1);
8447
8622
  }
8448
8623
  logger.info(`Base directories: ${config.getBaseDirs().join(", ")}`);
8449
- const totalRulesOutputs = await generateRules(config);
8450
8624
  const totalIgnoreOutputs = await generateIgnore(config);
8451
8625
  const totalMcpOutputs = await generateMcp(config);
8452
8626
  const totalCommandOutputs = await generateCommands(config);
8453
8627
  const totalSubagentOutputs = await generateSubagents(config);
8454
- const totalSkillOutputs = await generateSkills(config);
8455
- const totalGenerated = totalRulesOutputs + totalMcpOutputs + totalCommandOutputs + totalIgnoreOutputs + totalSubagentOutputs + totalSkillOutputs;
8628
+ const skillsResult = await generateSkills(config);
8629
+ const totalRulesOutputs = await generateRules(config, {
8630
+ skills: skillsResult.skills
8631
+ });
8632
+ const totalGenerated = totalRulesOutputs + totalMcpOutputs + totalCommandOutputs + totalIgnoreOutputs + totalSubagentOutputs + skillsResult.totalOutputs;
8456
8633
  if (totalGenerated === 0) {
8457
8634
  const enabledFeatures = config.getFeatures().join(", ");
8458
8635
  logger.warn(`\u26A0\uFE0F No files generated for enabled features: ${enabledFeatures}`);
@@ -8465,11 +8642,11 @@ async function generateCommand(options) {
8465
8642
  if (totalMcpOutputs > 0) parts.push(`${totalMcpOutputs} MCP files`);
8466
8643
  if (totalCommandOutputs > 0) parts.push(`${totalCommandOutputs} commands`);
8467
8644
  if (totalSubagentOutputs > 0) parts.push(`${totalSubagentOutputs} subagents`);
8468
- if (totalSkillOutputs > 0) parts.push(`${totalSkillOutputs} skills`);
8645
+ if (skillsResult.totalOutputs > 0) parts.push(`${skillsResult.totalOutputs} skills`);
8469
8646
  logger.success(`\u{1F389} All done! Generated ${totalGenerated} file(s) total (${parts.join(" + ")})`);
8470
8647
  }
8471
8648
  }
8472
- async function generateRules(config) {
8649
+ async function generateRules(config, options) {
8473
8650
  if (!config.getFeatures().includes("rules")) {
8474
8651
  logger.debug("Skipping rule generation (not in --features)");
8475
8652
  return 0;
@@ -8488,7 +8665,8 @@ async function generateRules(config) {
8488
8665
  global: config.getGlobal(),
8489
8666
  simulateCommands: config.getSimulateCommands(),
8490
8667
  simulateSubagents: config.getSimulateSubagents(),
8491
- simulateSkills: config.getSimulateSkills()
8668
+ simulateSkills: config.getSimulateSkills(),
8669
+ skills: options?.skills
8492
8670
  });
8493
8671
  if (config.getDelete()) {
8494
8672
  const oldToolFiles = await processor.loadToolFiles({ forDeletion: true });
@@ -8652,9 +8830,10 @@ async function generateSubagents(config) {
8652
8830
  async function generateSkills(config) {
8653
8831
  if (!config.getFeatures().includes("skills")) {
8654
8832
  logger.debug("Skipping skill generation (not in --features)");
8655
- return 0;
8833
+ return { totalOutputs: 0, skills: [] };
8656
8834
  }
8657
8835
  let totalSkillOutputs = 0;
8836
+ const allSkills = [];
8658
8837
  logger.info("Generating skill files...");
8659
8838
  const toolTargets = (0, import_es_toolkit2.intersection)(
8660
8839
  config.getTargets(),
@@ -8675,13 +8854,18 @@ async function generateSkills(config) {
8675
8854
  await processor.removeAiDirs(oldToolDirs);
8676
8855
  }
8677
8856
  const rulesyncDirs = await processor.loadRulesyncDirs();
8857
+ for (const rulesyncDir of rulesyncDirs) {
8858
+ if (rulesyncDir instanceof RulesyncSkill) {
8859
+ allSkills.push(rulesyncDir);
8860
+ }
8861
+ }
8678
8862
  const toolDirs = await processor.convertRulesyncDirsToToolDirs(rulesyncDirs);
8679
8863
  const writtenCount = await processor.writeAiDirs(toolDirs);
8680
8864
  totalSkillOutputs += writtenCount;
8681
8865
  logger.success(`Generated ${writtenCount} ${toolTarget} skill(s) in ${baseDir}`);
8682
8866
  }
8683
8867
  }
8684
- return totalSkillOutputs;
8868
+ return { totalOutputs: totalSkillOutputs, skills: allSkills };
8685
8869
  }
8686
8870
 
8687
8871
  // src/cli/commands/gitignore.ts
@@ -10249,7 +10433,7 @@ async function mcpCommand({ version }) {
10249
10433
  }
10250
10434
 
10251
10435
  // src/cli/index.ts
10252
- var getVersion = () => "3.32.0";
10436
+ var getVersion = () => "3.33.0";
10253
10437
  var main = async () => {
10254
10438
  const program = new import_commander.Command();
10255
10439
  const version = getVersion();