rulesync 3.32.0 → 3.34.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 +5 -0
  2. package/dist/index.cjs +1087 -627
  3. package/dist/index.js +1079 -619
  4. package/package.json +11 -11
package/dist/index.cjs CHANGED
@@ -102,7 +102,7 @@ var Logger = class {
102
102
  var logger = new Logger();
103
103
 
104
104
  // src/cli/commands/generate.ts
105
- var import_es_toolkit2 = require("es-toolkit");
105
+ var import_es_toolkit3 = require("es-toolkit");
106
106
 
107
107
  // src/config/config-resolver.ts
108
108
  var import_node_path2 = require("path");
@@ -113,6 +113,7 @@ var import_node_fs = require("fs");
113
113
  var import_promises = require("fs/promises");
114
114
  var import_node_os = __toESM(require("os"), 1);
115
115
  var import_node_path = require("path");
116
+ var import_es_toolkit = require("es-toolkit");
116
117
  async function ensureDir(dirPath) {
117
118
  try {
118
119
  await (0, import_promises.stat)(dirPath);
@@ -240,6 +241,13 @@ function validateBaseDir(baseDir) {
240
241
  }
241
242
  checkPathTraversal({ relativePath: baseDir, intendedRootDir: process.cwd() });
242
243
  }
244
+ function toKebabCaseFilename(filename) {
245
+ const lastDotIndex = filename.lastIndexOf(".");
246
+ const extension = lastDotIndex > 0 ? filename.slice(lastDotIndex) : "";
247
+ const nameWithoutExt = lastDotIndex > 0 ? filename.slice(0, lastDotIndex) : filename;
248
+ const kebabName = (0, import_es_toolkit.kebabCase)(nameWithoutExt);
249
+ return kebabName + extension;
250
+ }
243
251
 
244
252
  // src/config/config.ts
245
253
  var import_mini3 = require("zod/mini");
@@ -2347,7 +2355,7 @@ var AugmentcodeIgnore = class _AugmentcodeIgnore extends ToolIgnore {
2347
2355
 
2348
2356
  // src/features/ignore/claudecode-ignore.ts
2349
2357
  var import_node_path20 = require("path");
2350
- var import_es_toolkit = require("es-toolkit");
2358
+ var import_es_toolkit2 = require("es-toolkit");
2351
2359
  var ClaudecodeIgnore = class _ClaudecodeIgnore extends ToolIgnore {
2352
2360
  constructor(params) {
2353
2361
  super(params);
@@ -2397,11 +2405,19 @@ var ClaudecodeIgnore = class _ClaudecodeIgnore extends ToolIgnore {
2397
2405
  const exists = await fileExists(filePath);
2398
2406
  const existingFileContent = exists ? await readFileContent(filePath) : "{}";
2399
2407
  const existingJsonValue = JSON.parse(existingFileContent);
2408
+ const existingDenies = existingJsonValue.permissions?.deny ?? [];
2409
+ const preservedDenies = existingDenies.filter((deny) => {
2410
+ const isReadPattern = deny.startsWith("Read(") && deny.endsWith(")");
2411
+ if (isReadPattern) {
2412
+ return deniedValues.includes(deny);
2413
+ }
2414
+ return true;
2415
+ });
2400
2416
  const jsonValue = {
2401
2417
  ...existingJsonValue,
2402
2418
  permissions: {
2403
2419
  ...existingJsonValue.permissions,
2404
- deny: (0, import_es_toolkit.uniq)([...existingJsonValue.permissions?.deny ?? [], ...deniedValues].toSorted())
2420
+ deny: (0, import_es_toolkit2.uniq)([...preservedDenies, ...deniedValues].toSorted())
2405
2421
  }
2406
2422
  };
2407
2423
  return new _ClaudecodeIgnore({
@@ -3536,6 +3552,12 @@ var CodexcliMcp = class _CodexcliMcp extends ToolMcp {
3536
3552
 
3537
3553
  // src/features/mcp/copilot-mcp.ts
3538
3554
  var import_node_path35 = require("path");
3555
+ function convertToCopilotFormat(mcpServers) {
3556
+ return { servers: mcpServers };
3557
+ }
3558
+ function convertFromCopilotFormat(copilotConfig) {
3559
+ return copilotConfig.servers ?? {};
3560
+ }
3539
3561
  var CopilotMcp = class _CopilotMcp extends ToolMcp {
3540
3562
  json;
3541
3563
  constructor(params) {
@@ -3575,16 +3597,20 @@ var CopilotMcp = class _CopilotMcp extends ToolMcp {
3575
3597
  rulesyncMcp,
3576
3598
  validate = true
3577
3599
  }) {
3600
+ const copilotConfig = convertToCopilotFormat(rulesyncMcp.getMcpServers());
3578
3601
  return new _CopilotMcp({
3579
3602
  baseDir,
3580
3603
  relativeDirPath: this.getSettablePaths().relativeDirPath,
3581
3604
  relativeFilePath: this.getSettablePaths().relativeFilePath,
3582
- fileContent: rulesyncMcp.getFileContent(),
3605
+ fileContent: JSON.stringify(copilotConfig, null, 2),
3583
3606
  validate
3584
3607
  });
3585
3608
  }
3586
3609
  toRulesyncMcp() {
3587
- return this.toRulesyncMcpDefault();
3610
+ const mcpServers = convertFromCopilotFormat(this.json);
3611
+ return this.toRulesyncMcpDefault({
3612
+ fileContent: JSON.stringify({ mcpServers }, null, 2)
3613
+ });
3588
3614
  }
3589
3615
  validate() {
3590
3616
  return { success: true, error: null };
@@ -3968,6 +3994,37 @@ var OpencodeMcp = class _OpencodeMcp extends ToolMcp {
3968
3994
 
3969
3995
  // src/features/mcp/roo-mcp.ts
3970
3996
  var import_node_path40 = require("path");
3997
+ function isRooMcpServers(value) {
3998
+ return value !== void 0 && value !== null && typeof value === "object";
3999
+ }
4000
+ function convertToRooFormat(mcpServers) {
4001
+ return Object.fromEntries(
4002
+ Object.entries(mcpServers).map(([serverName, serverConfig]) => {
4003
+ const converted = { ...serverConfig };
4004
+ if (serverConfig.type === "http") {
4005
+ converted.type = "streamable-http";
4006
+ }
4007
+ if (serverConfig.transport === "http") {
4008
+ converted.transport = "streamable-http";
4009
+ }
4010
+ return [serverName, converted];
4011
+ })
4012
+ );
4013
+ }
4014
+ function convertFromRooFormat(mcpServers) {
4015
+ return Object.fromEntries(
4016
+ Object.entries(mcpServers).map(([serverName, serverConfig]) => {
4017
+ const converted = { ...serverConfig };
4018
+ if (serverConfig.type === "streamable-http") {
4019
+ converted.type = "http";
4020
+ }
4021
+ if (serverConfig.transport === "streamable-http") {
4022
+ converted.transport = "http";
4023
+ }
4024
+ return [serverName, converted];
4025
+ })
4026
+ );
4027
+ }
3971
4028
  var RooMcp = class _RooMcp extends ToolMcp {
3972
4029
  json;
3973
4030
  constructor(params) {
@@ -4007,7 +4064,9 @@ var RooMcp = class _RooMcp extends ToolMcp {
4007
4064
  rulesyncMcp,
4008
4065
  validate = true
4009
4066
  }) {
4010
- const fileContent = rulesyncMcp.getFileContent();
4067
+ const mcpServers = rulesyncMcp.getMcpServers();
4068
+ const convertedMcpServers = convertToRooFormat(mcpServers);
4069
+ const fileContent = JSON.stringify({ mcpServers: convertedMcpServers }, null, 2);
4011
4070
  return new _RooMcp({
4012
4071
  baseDir,
4013
4072
  relativeDirPath: this.getSettablePaths().relativeDirPath,
@@ -4017,7 +4076,11 @@ var RooMcp = class _RooMcp extends ToolMcp {
4017
4076
  });
4018
4077
  }
4019
4078
  toRulesyncMcp() {
4020
- return this.toRulesyncMcpDefault();
4079
+ const rawMcpServers = isRooMcpServers(this.json.mcpServers) ? this.json.mcpServers : {};
4080
+ const convertedMcpServers = convertFromRooFormat(rawMcpServers);
4081
+ return this.toRulesyncMcpDefault({
4082
+ fileContent: JSON.stringify({ mcpServers: convertedMcpServers }, null, 2)
4083
+ });
4021
4084
  }
4022
4085
  validate() {
4023
4086
  return { success: true, error: null };
@@ -4260,19 +4323,21 @@ var McpProcessor = class extends FeatureProcessor {
4260
4323
  // src/features/rules/rules-processor.ts
4261
4324
  var import_node_path84 = require("path");
4262
4325
  var import_toon = require("@toon-format/toon");
4263
- var import_mini33 = require("zod/mini");
4264
-
4265
- // src/features/skills/codexcli-skill.ts
4266
- var import_node_path44 = require("path");
4267
- var import_mini20 = require("zod/mini");
4326
+ var import_mini34 = require("zod/mini");
4268
4327
 
4269
4328
  // src/constants/general.ts
4270
4329
  var SKILL_FILE_NAME = "SKILL.md";
4271
4330
 
4272
- // src/features/skills/rulesync-skill.ts
4273
- var import_node_path42 = require("path");
4331
+ // src/features/skills/agentsmd-skill.ts
4332
+ var import_node_path44 = require("path");
4333
+
4334
+ // src/features/skills/simulated-skill.ts
4335
+ var import_node_path43 = require("path");
4274
4336
  var import_mini19 = require("zod/mini");
4275
4337
 
4338
+ // src/features/skills/tool-skill.ts
4339
+ var import_node_path42 = require("path");
4340
+
4276
4341
  // src/types/ai-dir.ts
4277
4342
  var import_node_path41 = __toESM(require("path"), 1);
4278
4343
  var AiDir = class {
@@ -4385,113 +4450,7 @@ var AiDir = class {
4385
4450
  }
4386
4451
  };
4387
4452
 
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
4453
  // src/features/skills/tool-skill.ts
4494
- var import_node_path43 = require("path");
4495
4454
  var ToolSkill = class extends AiDir {
4496
4455
  /**
4497
4456
  * Get the settable paths for this tool's skill directories.
@@ -4565,8 +4524,8 @@ var ToolSkill = class extends AiDir {
4565
4524
  }) {
4566
4525
  const settablePaths = getSettablePaths({ global });
4567
4526
  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);
4527
+ const skillDirPath = (0, import_node_path42.join)(baseDir, actualRelativeDirPath, dirName);
4528
+ const skillFilePath = (0, import_node_path42.join)(skillDirPath, SKILL_FILE_NAME);
4570
4529
  if (!await fileExists(skillFilePath)) {
4571
4530
  throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
4572
4531
  }
@@ -4590,21 +4549,22 @@ var ToolSkill = class extends AiDir {
4590
4549
  }
4591
4550
  };
4592
4551
 
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()
4552
+ // src/features/skills/simulated-skill.ts
4553
+ var SimulatedSkillFrontmatterSchema = import_mini19.z.object({
4554
+ name: import_mini19.z.string(),
4555
+ description: import_mini19.z.string()
4597
4556
  });
4598
- var CodexCliSkill = class _CodexCliSkill extends ToolSkill {
4557
+ var SimulatedSkill = class extends ToolSkill {
4558
+ frontmatter;
4559
+ body;
4599
4560
  constructor({
4600
4561
  baseDir = process.cwd(),
4601
- relativeDirPath = (0, import_node_path44.join)(".codex", "skills"),
4562
+ relativeDirPath,
4602
4563
  dirName,
4603
4564
  frontmatter,
4604
4565
  body,
4605
4566
  otherFiles = [],
4606
- validate = true,
4607
- global = false
4567
+ validate = true
4608
4568
  }) {
4609
4569
  super({
4610
4570
  baseDir,
@@ -4616,42 +4576,37 @@ var CodexCliSkill = class _CodexCliSkill extends ToolSkill {
4616
4576
  frontmatter: { ...frontmatter }
4617
4577
  },
4618
4578
  otherFiles,
4619
- global
4579
+ global: false
4580
+ // Simulated skills are project mode only
4620
4581
  });
4621
4582
  if (validate) {
4622
- const result = this.validate();
4583
+ const result = SimulatedSkillFrontmatterSchema.safeParse(frontmatter);
4623
4584
  if (!result.success) {
4624
- throw result.error;
4585
+ throw new Error(
4586
+ `Invalid frontmatter in ${(0, import_node_path43.join)(relativeDirPath, dirName)}: ${formatError(result.error)}`
4587
+ );
4625
4588
  }
4626
4589
  }
4590
+ this.frontmatter = frontmatter;
4591
+ this.body = body;
4627
4592
  }
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
- };
4593
+ getBody() {
4594
+ return this.body;
4635
4595
  }
4636
4596
  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;
4597
+ return this.frontmatter;
4642
4598
  }
4643
- getBody() {
4644
- return this.mainFile?.body ?? "";
4599
+ toRulesyncSkill() {
4600
+ throw new Error("Not implemented because it is a SIMULATED skill.");
4645
4601
  }
4646
4602
  validate() {
4647
- if (!this.mainFile) {
4648
- return {
4649
- success: false,
4650
- error: new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
4651
- };
4603
+ if (!this.frontmatter) {
4604
+ return { success: true, error: null };
4652
4605
  }
4653
- const result = CodexCliSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
4654
- if (!result.success) {
4606
+ const result = SimulatedSkillFrontmatterSchema.safeParse(this.frontmatter);
4607
+ if (result.success) {
4608
+ return { success: true, error: null };
4609
+ } else {
4655
4610
  return {
4656
4611
  success: false,
4657
4612
  error: new Error(
@@ -4659,98 +4614,141 @@ var CodexCliSkill = class _CodexCliSkill extends ToolSkill {
4659
4614
  )
4660
4615
  };
4661
4616
  }
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
4617
  }
4682
- static fromRulesyncSkill({
4618
+ static fromRulesyncSkillDefault({
4683
4619
  rulesyncSkill,
4684
- validate = true,
4685
- global = false
4620
+ validate = true
4686
4621
  }) {
4687
- const settablePaths = _CodexCliSkill.getSettablePaths({ global });
4688
4622
  const rulesyncFrontmatter = rulesyncSkill.getFrontmatter();
4689
- const codexFrontmatter = {
4623
+ const simulatedFrontmatter = {
4690
4624
  name: rulesyncFrontmatter.name,
4691
4625
  description: rulesyncFrontmatter.description
4692
4626
  };
4693
- return new _CodexCliSkill({
4627
+ return {
4694
4628
  baseDir: rulesyncSkill.getBaseDir(),
4695
- relativeDirPath: settablePaths.relativeDirPath,
4629
+ relativeDirPath: this.getSettablePaths().relativeDirPath,
4696
4630
  dirName: rulesyncSkill.getDirName(),
4697
- frontmatter: codexFrontmatter,
4631
+ frontmatter: simulatedFrontmatter,
4698
4632
  body: rulesyncSkill.getBody(),
4699
4633
  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");
4634
+ validate
4635
+ };
4707
4636
  }
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
- );
4719
- }
4720
- return new _CodexCliSkill({
4721
- baseDir: loaded.baseDir,
4722
- relativeDirPath: loaded.relativeDirPath,
4723
- dirName: loaded.dirName,
4637
+ static async fromDirDefault({
4638
+ baseDir = process.cwd(),
4639
+ relativeDirPath,
4640
+ dirName
4641
+ }) {
4642
+ const settablePaths = this.getSettablePaths();
4643
+ const actualRelativeDirPath = relativeDirPath ?? settablePaths.relativeDirPath;
4644
+ const skillDirPath = (0, import_node_path43.join)(baseDir, actualRelativeDirPath, dirName);
4645
+ const skillFilePath = (0, import_node_path43.join)(skillDirPath, SKILL_FILE_NAME);
4646
+ if (!await fileExists(skillFilePath)) {
4647
+ throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
4648
+ }
4649
+ const fileContent = await readFileContent(skillFilePath);
4650
+ const { frontmatter, body: content } = parseFrontmatter(fileContent);
4651
+ const result = SimulatedSkillFrontmatterSchema.safeParse(frontmatter);
4652
+ if (!result.success) {
4653
+ throw new Error(`Invalid frontmatter in ${skillFilePath}: ${formatError(result.error)}`);
4654
+ }
4655
+ const otherFiles = await this.collectOtherFiles(
4656
+ baseDir,
4657
+ actualRelativeDirPath,
4658
+ dirName,
4659
+ SKILL_FILE_NAME
4660
+ );
4661
+ return {
4662
+ baseDir,
4663
+ relativeDirPath: actualRelativeDirPath,
4664
+ dirName,
4724
4665
  frontmatter: result.data,
4725
- body: loaded.body,
4726
- otherFiles: loaded.otherFiles,
4727
- validate: true,
4728
- global: loaded.global
4666
+ body: content.trim(),
4667
+ otherFiles,
4668
+ validate: true
4669
+ };
4670
+ }
4671
+ /**
4672
+ * Check if a RulesyncSkill should be converted to this simulated skill type.
4673
+ * Uses the targets field in the RulesyncSkill frontmatter to determine targeting.
4674
+ */
4675
+ static isTargetedByRulesyncSkillDefault({
4676
+ rulesyncSkill,
4677
+ toolTarget
4678
+ }) {
4679
+ const frontmatter = rulesyncSkill.getFrontmatter();
4680
+ const targets = frontmatter.targets;
4681
+ if (targets.includes("*")) {
4682
+ return true;
4683
+ }
4684
+ return targets.includes(toolTarget);
4685
+ }
4686
+ /**
4687
+ * Get the settable paths for this tool's skill directories.
4688
+ * Must be implemented by concrete subclasses.
4689
+ */
4690
+ static getSettablePaths(_options) {
4691
+ throw new Error("Please implement this method in the subclass.");
4692
+ }
4693
+ };
4694
+
4695
+ // src/features/skills/agentsmd-skill.ts
4696
+ var AgentsmdSkill = class _AgentsmdSkill extends SimulatedSkill {
4697
+ static getSettablePaths(options) {
4698
+ if (options?.global) {
4699
+ throw new Error("AgentsmdSkill does not support global mode.");
4700
+ }
4701
+ return {
4702
+ relativeDirPath: (0, import_node_path44.join)(".agents", "skills")
4703
+ };
4704
+ }
4705
+ static async fromDir(params) {
4706
+ const baseParams = await this.fromDirDefault(params);
4707
+ return new _AgentsmdSkill(baseParams);
4708
+ }
4709
+ static fromRulesyncSkill(params) {
4710
+ const baseParams = {
4711
+ ...this.fromRulesyncSkillDefault(params),
4712
+ relativeDirPath: this.getSettablePaths().relativeDirPath
4713
+ };
4714
+ return new _AgentsmdSkill(baseParams);
4715
+ }
4716
+ static isTargetedByRulesyncSkill(rulesyncSkill) {
4717
+ return this.isTargetedByRulesyncSkillDefault({
4718
+ rulesyncSkill,
4719
+ toolTarget: "agentsmd"
4729
4720
  });
4730
4721
  }
4731
4722
  };
4732
4723
 
4733
- // src/features/skills/copilot-skill.ts
4724
+ // src/features/skills/codexcli-skill.ts
4734
4725
  var import_node_path46 = require("path");
4726
+ var import_mini21 = require("zod/mini");
4735
4727
 
4736
- // src/features/skills/simulated-skill.ts
4728
+ // src/features/skills/rulesync-skill.ts
4737
4729
  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()
4730
+ var import_mini20 = require("zod/mini");
4731
+ var RulesyncSkillFrontmatterSchemaInternal = import_mini20.z.object({
4732
+ name: import_mini20.z.string(),
4733
+ description: import_mini20.z.string(),
4734
+ targets: import_mini20.z._default(RulesyncTargetsSchema, ["*"]),
4735
+ claudecode: import_mini20.z.optional(
4736
+ import_mini20.z.object({
4737
+ "allowed-tools": import_mini20.z.optional(import_mini20.z.array(import_mini20.z.string()))
4738
+ })
4739
+ )
4742
4740
  });
4743
- var SimulatedSkill = class extends ToolSkill {
4744
- frontmatter;
4745
- body;
4741
+ var RulesyncSkillFrontmatterSchema = RulesyncSkillFrontmatterSchemaInternal;
4742
+ var RulesyncSkill = class _RulesyncSkill extends AiDir {
4746
4743
  constructor({
4747
4744
  baseDir = process.cwd(),
4748
- relativeDirPath,
4745
+ relativeDirPath = RULESYNC_SKILLS_RELATIVE_DIR_PATH,
4749
4746
  dirName,
4750
4747
  frontmatter,
4751
4748
  body,
4752
4749
  otherFiles = [],
4753
- validate = true
4750
+ validate = true,
4751
+ global = false
4754
4752
  }) {
4755
4753
  super({
4756
4754
  baseDir,
@@ -4762,37 +4760,33 @@ var SimulatedSkill = class extends ToolSkill {
4762
4760
  frontmatter: { ...frontmatter }
4763
4761
  },
4764
4762
  otherFiles,
4765
- global: false
4766
- // Simulated skills are project mode only
4763
+ global
4767
4764
  });
4768
4765
  if (validate) {
4769
- const result = SimulatedSkillFrontmatterSchema.safeParse(frontmatter);
4766
+ const result = this.validate();
4770
4767
  if (!result.success) {
4771
- throw new Error(
4772
- `Invalid frontmatter in ${(0, import_node_path45.join)(relativeDirPath, dirName)}: ${formatError(result.error)}`
4773
- );
4768
+ throw result.error;
4774
4769
  }
4775
4770
  }
4776
- this.frontmatter = frontmatter;
4777
- this.body = body;
4778
4771
  }
4779
- getBody() {
4780
- return this.body;
4772
+ static getSettablePaths() {
4773
+ return {
4774
+ relativeDirPath: RULESYNC_SKILLS_RELATIVE_DIR_PATH
4775
+ };
4781
4776
  }
4782
4777
  getFrontmatter() {
4783
- return this.frontmatter;
4778
+ if (!this.mainFile?.frontmatter) {
4779
+ throw new Error("Frontmatter is not defined");
4780
+ }
4781
+ const result = RulesyncSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
4782
+ return result;
4784
4783
  }
4785
- toRulesyncSkill() {
4786
- throw new Error("Not implemented because it is a SIMULATED skill.");
4784
+ getBody() {
4785
+ return this.mainFile?.body ?? "";
4787
4786
  }
4788
4787
  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 {
4788
+ const result = RulesyncSkillFrontmatterSchema.safeParse(this.mainFile?.frontmatter);
4789
+ if (!result.success) {
4796
4790
  return {
4797
4791
  success: false,
4798
4792
  error: new Error(
@@ -4800,92 +4794,193 @@ var SimulatedSkill = class extends ToolSkill {
4800
4794
  )
4801
4795
  };
4802
4796
  }
4797
+ return { success: true, error: null };
4803
4798
  }
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({
4799
+ static async fromDir({
4824
4800
  baseDir = process.cwd(),
4825
- relativeDirPath,
4826
- dirName
4801
+ relativeDirPath = RULESYNC_SKILLS_RELATIVE_DIR_PATH,
4802
+ dirName,
4803
+ global = false
4827
4804
  }) {
4828
- const settablePaths = this.getSettablePaths();
4829
- const actualRelativeDirPath = relativeDirPath ?? settablePaths.relativeDirPath;
4830
- const skillDirPath = (0, import_node_path45.join)(baseDir, actualRelativeDirPath, dirName);
4805
+ const skillDirPath = (0, import_node_path45.join)(baseDir, relativeDirPath, dirName);
4831
4806
  const skillFilePath = (0, import_node_path45.join)(skillDirPath, SKILL_FILE_NAME);
4832
4807
  if (!await fileExists(skillFilePath)) {
4833
4808
  throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
4834
4809
  }
4835
4810
  const fileContent = await readFileContent(skillFilePath);
4836
4811
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
4837
- const result = SimulatedSkillFrontmatterSchema.safeParse(frontmatter);
4812
+ const result = RulesyncSkillFrontmatterSchema.safeParse(frontmatter);
4838
4813
  if (!result.success) {
4839
4814
  throw new Error(`Invalid frontmatter in ${skillFilePath}: ${formatError(result.error)}`);
4840
4815
  }
4841
4816
  const otherFiles = await this.collectOtherFiles(
4842
4817
  baseDir,
4843
- actualRelativeDirPath,
4818
+ relativeDirPath,
4844
4819
  dirName,
4845
4820
  SKILL_FILE_NAME
4846
4821
  );
4847
- return {
4822
+ return new _RulesyncSkill({
4848
4823
  baseDir,
4849
- relativeDirPath: actualRelativeDirPath,
4824
+ relativeDirPath,
4850
4825
  dirName,
4851
4826
  frontmatter: result.data,
4852
4827
  body: content.trim(),
4853
4828
  otherFiles,
4854
- validate: true
4829
+ validate: true,
4830
+ global
4831
+ });
4832
+ }
4833
+ };
4834
+
4835
+ // src/features/skills/codexcli-skill.ts
4836
+ var CodexCliSkillFrontmatterSchema = import_mini21.z.object({
4837
+ name: import_mini21.z.string(),
4838
+ description: import_mini21.z.string()
4839
+ });
4840
+ var CodexCliSkill = class _CodexCliSkill extends ToolSkill {
4841
+ constructor({
4842
+ baseDir = process.cwd(),
4843
+ relativeDirPath = (0, import_node_path46.join)(".codex", "skills"),
4844
+ dirName,
4845
+ frontmatter,
4846
+ body,
4847
+ otherFiles = [],
4848
+ validate = true,
4849
+ global = false
4850
+ }) {
4851
+ super({
4852
+ baseDir,
4853
+ relativeDirPath,
4854
+ dirName,
4855
+ mainFile: {
4856
+ name: SKILL_FILE_NAME,
4857
+ body,
4858
+ frontmatter: { ...frontmatter }
4859
+ },
4860
+ otherFiles,
4861
+ global
4862
+ });
4863
+ if (validate) {
4864
+ const result = this.validate();
4865
+ if (!result.success) {
4866
+ throw result.error;
4867
+ }
4868
+ }
4869
+ }
4870
+ static getSettablePaths({ global = false } = {}) {
4871
+ if (!global) {
4872
+ throw new Error("CodexCliSkill only supports global mode. Please pass { global: true }.");
4873
+ }
4874
+ return {
4875
+ relativeDirPath: (0, import_node_path46.join)(".codex", "skills")
4855
4876
  };
4856
4877
  }
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({
4878
+ getFrontmatter() {
4879
+ if (!this.mainFile?.frontmatter) {
4880
+ throw new Error("Frontmatter is not defined");
4881
+ }
4882
+ const result = CodexCliSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
4883
+ return result;
4884
+ }
4885
+ getBody() {
4886
+ return this.mainFile?.body ?? "";
4887
+ }
4888
+ validate() {
4889
+ if (!this.mainFile) {
4890
+ return {
4891
+ success: false,
4892
+ error: new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
4893
+ };
4894
+ }
4895
+ const result = CodexCliSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
4896
+ if (!result.success) {
4897
+ return {
4898
+ success: false,
4899
+ error: new Error(
4900
+ `Invalid frontmatter in ${this.getDirPath()}: ${formatError(result.error)}`
4901
+ )
4902
+ };
4903
+ }
4904
+ return { success: true, error: null };
4905
+ }
4906
+ toRulesyncSkill() {
4907
+ const frontmatter = this.getFrontmatter();
4908
+ const rulesyncFrontmatter = {
4909
+ name: frontmatter.name,
4910
+ description: frontmatter.description,
4911
+ targets: ["*"]
4912
+ };
4913
+ return new RulesyncSkill({
4914
+ baseDir: this.baseDir,
4915
+ relativeDirPath: this.relativeDirPath,
4916
+ dirName: this.getDirName(),
4917
+ frontmatter: rulesyncFrontmatter,
4918
+ body: this.getBody(),
4919
+ otherFiles: this.getOtherFiles(),
4920
+ validate: true,
4921
+ global: this.global
4922
+ });
4923
+ }
4924
+ static fromRulesyncSkill({
4862
4925
  rulesyncSkill,
4863
- toolTarget
4926
+ validate = true,
4927
+ global = false
4864
4928
  }) {
4865
- const frontmatter = rulesyncSkill.getFrontmatter();
4866
- const targets = frontmatter.targets;
4867
- if (targets.includes("*")) {
4868
- return true;
4869
- }
4870
- return targets.includes(toolTarget);
4929
+ const settablePaths = _CodexCliSkill.getSettablePaths({ global });
4930
+ const rulesyncFrontmatter = rulesyncSkill.getFrontmatter();
4931
+ const codexFrontmatter = {
4932
+ name: rulesyncFrontmatter.name,
4933
+ description: rulesyncFrontmatter.description
4934
+ };
4935
+ return new _CodexCliSkill({
4936
+ baseDir: rulesyncSkill.getBaseDir(),
4937
+ relativeDirPath: settablePaths.relativeDirPath,
4938
+ dirName: rulesyncSkill.getDirName(),
4939
+ frontmatter: codexFrontmatter,
4940
+ body: rulesyncSkill.getBody(),
4941
+ otherFiles: rulesyncSkill.getOtherFiles(),
4942
+ validate,
4943
+ global
4944
+ });
4871
4945
  }
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.");
4946
+ static isTargetedByRulesyncSkill(rulesyncSkill) {
4947
+ const targets = rulesyncSkill.getFrontmatter().targets;
4948
+ return targets.includes("*") || targets.includes("codexcli");
4949
+ }
4950
+ static async fromDir(params) {
4951
+ const loaded = await this.loadSkillDirContent({
4952
+ ...params,
4953
+ getSettablePaths: _CodexCliSkill.getSettablePaths
4954
+ });
4955
+ const result = CodexCliSkillFrontmatterSchema.safeParse(loaded.frontmatter);
4956
+ if (!result.success) {
4957
+ const skillDirPath = (0, import_node_path46.join)(loaded.baseDir, loaded.relativeDirPath, loaded.dirName);
4958
+ throw new Error(
4959
+ `Invalid frontmatter in ${(0, import_node_path46.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`
4960
+ );
4961
+ }
4962
+ return new _CodexCliSkill({
4963
+ baseDir: loaded.baseDir,
4964
+ relativeDirPath: loaded.relativeDirPath,
4965
+ dirName: loaded.dirName,
4966
+ frontmatter: result.data,
4967
+ body: loaded.body,
4968
+ otherFiles: loaded.otherFiles,
4969
+ validate: true,
4970
+ global: loaded.global
4971
+ });
4878
4972
  }
4879
4973
  };
4880
4974
 
4881
4975
  // src/features/skills/copilot-skill.ts
4976
+ var import_node_path47 = require("path");
4882
4977
  var CopilotSkill = class _CopilotSkill extends SimulatedSkill {
4883
4978
  static getSettablePaths(options) {
4884
4979
  if (options?.global) {
4885
4980
  throw new Error("CopilotSkill does not support global mode.");
4886
4981
  }
4887
4982
  return {
4888
- relativeDirPath: (0, import_node_path46.join)(".github", "skills")
4983
+ relativeDirPath: (0, import_node_path47.join)(".github", "skills")
4889
4984
  };
4890
4985
  }
4891
4986
  static async fromDir(params) {
@@ -4908,14 +5003,14 @@ var CopilotSkill = class _CopilotSkill extends SimulatedSkill {
4908
5003
  };
4909
5004
 
4910
5005
  // src/features/skills/cursor-skill.ts
4911
- var import_node_path47 = require("path");
5006
+ var import_node_path48 = require("path");
4912
5007
  var CursorSkill = class _CursorSkill extends SimulatedSkill {
4913
5008
  static getSettablePaths(options) {
4914
5009
  if (options?.global) {
4915
5010
  throw new Error("CursorSkill does not support global mode.");
4916
5011
  }
4917
5012
  return {
4918
- relativeDirPath: (0, import_node_path47.join)(".cursor", "skills")
5013
+ relativeDirPath: (0, import_node_path48.join)(".cursor", "skills")
4919
5014
  };
4920
5015
  }
4921
5016
  static async fromDir(params) {
@@ -4937,12 +5032,42 @@ var CursorSkill = class _CursorSkill extends SimulatedSkill {
4937
5032
  }
4938
5033
  };
4939
5034
 
5035
+ // src/features/skills/geminicli-skill.ts
5036
+ var import_node_path49 = require("path");
5037
+ var GeminiCliSkill = class _GeminiCliSkill extends SimulatedSkill {
5038
+ static getSettablePaths(options) {
5039
+ if (options?.global) {
5040
+ throw new Error("GeminiCliSkill does not support global mode.");
5041
+ }
5042
+ return {
5043
+ relativeDirPath: (0, import_node_path49.join)(".gemini", "skills")
5044
+ };
5045
+ }
5046
+ static async fromDir(params) {
5047
+ const baseParams = await this.fromDirDefault(params);
5048
+ return new _GeminiCliSkill(baseParams);
5049
+ }
5050
+ static fromRulesyncSkill(params) {
5051
+ const baseParams = {
5052
+ ...this.fromRulesyncSkillDefault(params),
5053
+ relativeDirPath: this.getSettablePaths().relativeDirPath
5054
+ };
5055
+ return new _GeminiCliSkill(baseParams);
5056
+ }
5057
+ static isTargetedByRulesyncSkill(rulesyncSkill) {
5058
+ return this.isTargetedByRulesyncSkillDefault({
5059
+ rulesyncSkill,
5060
+ toolTarget: "geminicli"
5061
+ });
5062
+ }
5063
+ };
5064
+
4940
5065
  // src/features/skills/skills-processor.ts
4941
5066
  var import_node_path52 = require("path");
4942
5067
  var import_mini23 = require("zod/mini");
4943
5068
 
4944
5069
  // src/types/dir-feature-processor.ts
4945
- var import_node_path48 = require("path");
5070
+ var import_node_path50 = require("path");
4946
5071
  var DirFeatureProcessor = class {
4947
5072
  baseDir;
4948
5073
  constructor({ baseDir = process.cwd() }) {
@@ -4964,14 +5089,14 @@ var DirFeatureProcessor = class {
4964
5089
  await ensureDir(dirPath);
4965
5090
  const mainFile = aiDir.getMainFile();
4966
5091
  if (mainFile) {
4967
- const mainFilePath = (0, import_node_path48.join)(dirPath, mainFile.name);
5092
+ const mainFilePath = (0, import_node_path50.join)(dirPath, mainFile.name);
4968
5093
  const content = stringifyFrontmatter(mainFile.body, mainFile.frontmatter);
4969
5094
  const contentWithNewline = addTrailingNewline(content);
4970
5095
  await writeFileContent(mainFilePath, contentWithNewline);
4971
5096
  }
4972
5097
  const otherFiles = aiDir.getOtherFiles();
4973
5098
  for (const file of otherFiles) {
4974
- const filePath = (0, import_node_path48.join)(dirPath, file.relativeFilePathToDirPath);
5099
+ const filePath = (0, import_node_path50.join)(dirPath, file.relativeFilePathToDirPath);
4975
5100
  const contentWithNewline = addTrailingNewline(file.fileBuffer.toString("utf-8"));
4976
5101
  await writeFileContent(filePath, contentWithNewline);
4977
5102
  }
@@ -4985,38 +5110,8 @@ var DirFeatureProcessor = class {
4985
5110
  }
4986
5111
  };
4987
5112
 
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
5113
  // src/features/skills/claudecode-skill.ts
5019
- var import_node_path50 = require("path");
5114
+ var import_node_path51 = require("path");
5020
5115
  var import_mini22 = require("zod/mini");
5021
5116
  var ClaudecodeSkillFrontmatterSchema = import_mini22.z.object({
5022
5117
  name: import_mini22.z.string(),
@@ -5026,7 +5121,7 @@ var ClaudecodeSkillFrontmatterSchema = import_mini22.z.object({
5026
5121
  var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
5027
5122
  constructor({
5028
5123
  baseDir = process.cwd(),
5029
- relativeDirPath = (0, import_node_path50.join)(".claude", "skills"),
5124
+ relativeDirPath = (0, import_node_path51.join)(".claude", "skills"),
5030
5125
  dirName,
5031
5126
  frontmatter,
5032
5127
  body,
@@ -5057,7 +5152,7 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
5057
5152
  global: _global = false
5058
5153
  } = {}) {
5059
5154
  return {
5060
- relativeDirPath: (0, import_node_path50.join)(".claude", "skills")
5155
+ relativeDirPath: (0, import_node_path51.join)(".claude", "skills")
5061
5156
  };
5062
5157
  }
5063
5158
  getFrontmatter() {
@@ -5144,9 +5239,9 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
5144
5239
  });
5145
5240
  const result = ClaudecodeSkillFrontmatterSchema.safeParse(loaded.frontmatter);
5146
5241
  if (!result.success) {
5147
- const skillDirPath = (0, import_node_path50.join)(loaded.baseDir, loaded.relativeDirPath, loaded.dirName);
5242
+ const skillDirPath = (0, import_node_path51.join)(loaded.baseDir, loaded.relativeDirPath, loaded.dirName);
5148
5243
  throw new Error(
5149
- `Invalid frontmatter in ${(0, import_node_path50.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`
5244
+ `Invalid frontmatter in ${(0, import_node_path51.join)(skillDirPath, SKILL_FILE_NAME)}: ${formatError(result.error)}`
5150
5245
  );
5151
5246
  }
5152
5247
  return new _ClaudecodeSkill({
@@ -5162,36 +5257,6 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
5162
5257
  }
5163
5258
  };
5164
5259
 
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
5260
  // src/features/skills/skills-processor.ts
5196
5261
  var skillsProcessorToolTargetTuple = [
5197
5262
  "agentsmd",
@@ -6124,6 +6189,12 @@ var RulesyncRuleFrontmatterSchema = import_mini28.z.object({
6124
6189
  import_mini28.z.object({
6125
6190
  excludeAgent: import_mini28.z.optional(import_mini28.z.union([import_mini28.z.literal("code-review"), import_mini28.z.literal("coding-agent")]))
6126
6191
  })
6192
+ ),
6193
+ antigravity: import_mini28.z.optional(
6194
+ import_mini28.z.looseObject({
6195
+ trigger: import_mini28.z.optional(import_mini28.z.string()),
6196
+ globs: import_mini28.z.optional(import_mini28.z.array(import_mini28.z.string()))
6197
+ })
6127
6198
  )
6128
6199
  });
6129
6200
  var RulesyncRule = class _RulesyncRule extends RulesyncFile {
@@ -6493,7 +6564,176 @@ var AmazonQCliRule = class _AmazonQCliRule extends ToolRule {
6493
6564
 
6494
6565
  // src/features/rules/antigravity-rule.ts
6495
6566
  var import_node_path67 = require("path");
6567
+ var import_mini29 = require("zod/mini");
6568
+ var AntigravityRuleFrontmatterSchema = import_mini29.z.looseObject({
6569
+ trigger: import_mini29.z.optional(
6570
+ import_mini29.z.union([
6571
+ import_mini29.z.literal("always_on"),
6572
+ import_mini29.z.literal("glob"),
6573
+ import_mini29.z.literal("manual"),
6574
+ import_mini29.z.literal("model_decision"),
6575
+ import_mini29.z.string()
6576
+ // accepts any string for forward compatibility
6577
+ ])
6578
+ ),
6579
+ globs: import_mini29.z.optional(import_mini29.z.string()),
6580
+ description: import_mini29.z.optional(import_mini29.z.string())
6581
+ });
6582
+ function parseGlobsString(globs) {
6583
+ if (!globs) {
6584
+ return [];
6585
+ }
6586
+ if (Array.isArray(globs)) {
6587
+ return globs;
6588
+ }
6589
+ if (globs.trim() === "") {
6590
+ return [];
6591
+ }
6592
+ return globs.split(",").map((g) => g.trim());
6593
+ }
6594
+ function stringifyGlobs(globs) {
6595
+ if (!globs || globs.length === 0) {
6596
+ return void 0;
6597
+ }
6598
+ return globs.join(",");
6599
+ }
6600
+ function normalizeStoredAntigravity(stored) {
6601
+ if (!stored) {
6602
+ return void 0;
6603
+ }
6604
+ const { globs, ...rest } = stored;
6605
+ return {
6606
+ ...rest,
6607
+ globs: Array.isArray(globs) ? stringifyGlobs(globs) : globs
6608
+ };
6609
+ }
6610
+ var globStrategy = {
6611
+ canHandle: (trigger) => trigger === "glob",
6612
+ generateFrontmatter: (normalized, rulesyncFrontmatter) => {
6613
+ const effectiveGlobsArray = normalized?.globs ? parseGlobsString(normalized.globs) : rulesyncFrontmatter.globs ?? [];
6614
+ return {
6615
+ ...normalized,
6616
+ trigger: "glob",
6617
+ globs: stringifyGlobs(effectiveGlobsArray)
6618
+ };
6619
+ },
6620
+ exportRulesyncData: ({ description, ...frontmatter }) => ({
6621
+ globs: parseGlobsString(frontmatter.globs),
6622
+ description: description || "",
6623
+ antigravity: frontmatter
6624
+ })
6625
+ };
6626
+ var manualStrategy = {
6627
+ canHandle: (trigger) => trigger === "manual",
6628
+ generateFrontmatter: (normalized) => ({
6629
+ ...normalized,
6630
+ trigger: "manual"
6631
+ }),
6632
+ exportRulesyncData: ({ description, ...frontmatter }) => ({
6633
+ globs: [],
6634
+ description: description || "",
6635
+ antigravity: frontmatter
6636
+ })
6637
+ };
6638
+ var alwaysOnStrategy = {
6639
+ canHandle: (trigger) => trigger === "always_on",
6640
+ generateFrontmatter: (normalized) => ({
6641
+ ...normalized,
6642
+ trigger: "always_on"
6643
+ }),
6644
+ exportRulesyncData: ({ description, ...frontmatter }) => ({
6645
+ globs: ["**/*"],
6646
+ description: description || "",
6647
+ antigravity: frontmatter
6648
+ })
6649
+ };
6650
+ var modelDecisionStrategy = {
6651
+ canHandle: (trigger) => trigger === "model_decision",
6652
+ generateFrontmatter: (normalized, rulesyncFrontmatter) => ({
6653
+ ...normalized,
6654
+ trigger: "model_decision",
6655
+ description: rulesyncFrontmatter.description
6656
+ }),
6657
+ exportRulesyncData: ({ description, ...frontmatter }) => ({
6658
+ globs: [],
6659
+ description: description || "",
6660
+ antigravity: frontmatter
6661
+ })
6662
+ };
6663
+ var unknownStrategy = {
6664
+ canHandle: (trigger) => trigger !== void 0,
6665
+ generateFrontmatter: (normalized) => {
6666
+ const trigger = typeof normalized?.trigger === "string" ? normalized.trigger : "manual";
6667
+ return {
6668
+ ...normalized,
6669
+ trigger
6670
+ };
6671
+ },
6672
+ exportRulesyncData: ({ description, ...frontmatter }) => ({
6673
+ globs: frontmatter.globs ? parseGlobsString(frontmatter.globs) : ["**/*"],
6674
+ description: description || "",
6675
+ antigravity: frontmatter
6676
+ })
6677
+ };
6678
+ var inferenceStrategy = {
6679
+ canHandle: (trigger) => trigger === void 0,
6680
+ generateFrontmatter: (normalized, rulesyncFrontmatter) => {
6681
+ const effectiveGlobsArray = normalized?.globs ? parseGlobsString(normalized.globs) : rulesyncFrontmatter.globs ?? [];
6682
+ if (effectiveGlobsArray.length > 0 && !effectiveGlobsArray.includes("**/*") && !effectiveGlobsArray.includes("*")) {
6683
+ return {
6684
+ ...normalized,
6685
+ trigger: "glob",
6686
+ globs: stringifyGlobs(effectiveGlobsArray)
6687
+ };
6688
+ }
6689
+ return {
6690
+ ...normalized,
6691
+ trigger: "always_on"
6692
+ };
6693
+ },
6694
+ exportRulesyncData: ({ description, ...frontmatter }) => ({
6695
+ globs: frontmatter.globs ? parseGlobsString(frontmatter.globs) : ["**/*"],
6696
+ description: description || "",
6697
+ antigravity: frontmatter
6698
+ })
6699
+ };
6700
+ var STRATEGIES = [
6701
+ globStrategy,
6702
+ manualStrategy,
6703
+ alwaysOnStrategy,
6704
+ modelDecisionStrategy,
6705
+ unknownStrategy,
6706
+ inferenceStrategy
6707
+ ];
6496
6708
  var AntigravityRule = class _AntigravityRule extends ToolRule {
6709
+ frontmatter;
6710
+ body;
6711
+ /**
6712
+ * Creates an AntigravityRule instance.
6713
+ *
6714
+ * @param params - Rule parameters including frontmatter and body
6715
+ * @param params.frontmatter - Antigravity-specific frontmatter configuration
6716
+ * @param params.body - The markdown body content (without frontmatter)
6717
+ *
6718
+ * Note: Files without frontmatter will default to always_on trigger during fromFile().
6719
+ */
6720
+ constructor({ frontmatter, body, ...rest }) {
6721
+ if (rest.validate !== false) {
6722
+ const result = AntigravityRuleFrontmatterSchema.safeParse(frontmatter);
6723
+ if (!result.success) {
6724
+ throw new Error(
6725
+ `Invalid frontmatter in ${(0, import_node_path67.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
6726
+ );
6727
+ }
6728
+ }
6729
+ super({
6730
+ ...rest,
6731
+ // Ensure fileContent includes frontmatter when constructed directly
6732
+ fileContent: stringifyFrontmatter(body, frontmatter)
6733
+ });
6734
+ this.frontmatter = frontmatter;
6735
+ this.body = body;
6736
+ }
6497
6737
  static getSettablePaths() {
6498
6738
  return {
6499
6739
  nonRoot: {
@@ -6506,36 +6746,121 @@ var AntigravityRule = class _AntigravityRule extends ToolRule {
6506
6746
  relativeFilePath,
6507
6747
  validate = true
6508
6748
  }) {
6509
- const fileContent = await readFileContent(
6510
- (0, import_node_path67.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
6749
+ const filePath = (0, import_node_path67.join)(
6750
+ baseDir,
6751
+ this.getSettablePaths().nonRoot.relativeDirPath,
6752
+ relativeFilePath
6511
6753
  );
6754
+ const fileContent = await readFileContent(filePath);
6755
+ const { frontmatter, body } = parseFrontmatter(fileContent);
6756
+ let parsedFrontmatter;
6757
+ if (validate) {
6758
+ const result = AntigravityRuleFrontmatterSchema.safeParse(frontmatter);
6759
+ if (result.success) {
6760
+ parsedFrontmatter = result.data;
6761
+ } else {
6762
+ throw new Error(`Invalid frontmatter in ${filePath}: ${formatError(result.error)}`);
6763
+ }
6764
+ } else {
6765
+ parsedFrontmatter = frontmatter;
6766
+ }
6512
6767
  return new _AntigravityRule({
6513
6768
  baseDir,
6514
6769
  relativeDirPath: this.getSettablePaths().nonRoot.relativeDirPath,
6515
6770
  relativeFilePath,
6516
- fileContent,
6771
+ body,
6772
+ frontmatter: parsedFrontmatter,
6517
6773
  validate,
6518
6774
  root: false
6519
6775
  });
6520
6776
  }
6777
+ /**
6778
+ * Converts a RulesyncRule to an AntigravityRule.
6779
+ *
6780
+ * Trigger inference:
6781
+ * - If antigravity.trigger is set, it's preserved
6782
+ * - If specific globs are set, infers "glob" trigger
6783
+ * - Otherwise, infers "always_on" trigger
6784
+ */
6521
6785
  static fromRulesyncRule({
6522
6786
  baseDir = process.cwd(),
6523
6787
  rulesyncRule,
6524
6788
  validate = true
6525
6789
  }) {
6526
- return new _AntigravityRule(
6527
- this.buildToolRuleParamsDefault({
6528
- baseDir,
6529
- rulesyncRule,
6530
- validate,
6531
- nonRootPath: this.getSettablePaths().nonRoot
6532
- })
6533
- );
6790
+ const rulesyncFrontmatter = rulesyncRule.getFrontmatter();
6791
+ const storedAntigravity = rulesyncFrontmatter.antigravity;
6792
+ const normalized = normalizeStoredAntigravity(storedAntigravity);
6793
+ const storedTrigger = storedAntigravity?.trigger;
6794
+ const strategy = STRATEGIES.find((s) => s.canHandle(storedTrigger));
6795
+ if (!strategy) {
6796
+ throw new Error(`No strategy found for trigger: ${storedTrigger}`);
6797
+ }
6798
+ const frontmatter = strategy.generateFrontmatter(normalized, rulesyncFrontmatter);
6799
+ const paths = this.getSettablePaths();
6800
+ const kebabCaseFilename = toKebabCaseFilename(rulesyncRule.getRelativeFilePath());
6801
+ return new _AntigravityRule({
6802
+ baseDir,
6803
+ relativeDirPath: paths.nonRoot.relativeDirPath,
6804
+ relativeFilePath: kebabCaseFilename,
6805
+ frontmatter,
6806
+ body: rulesyncRule.getBody(),
6807
+ validate,
6808
+ root: false
6809
+ });
6534
6810
  }
6811
+ /**
6812
+ * Converts this AntigravityRule to a RulesyncRule.
6813
+ *
6814
+ * The Antigravity configuration is preserved in the RulesyncRule's
6815
+ * frontmatter.antigravity field for round-trip compatibility.
6816
+ *
6817
+ * Note: All Antigravity rules are treated as non-root (root: false),
6818
+ * as they are all placed in the .agent/rules directory.
6819
+ *
6820
+ * @returns RulesyncRule instance with Antigravity config preserved
6821
+ */
6535
6822
  toRulesyncRule() {
6536
- return this.toRulesyncRuleDefault();
6823
+ const strategy = STRATEGIES.find((s) => s.canHandle(this.frontmatter.trigger));
6824
+ let rulesyncData = {
6825
+ globs: [],
6826
+ description: "",
6827
+ antigravity: this.frontmatter
6828
+ };
6829
+ if (strategy) {
6830
+ rulesyncData = strategy.exportRulesyncData(this.frontmatter);
6831
+ }
6832
+ const antigravityForRulesync = {
6833
+ ...rulesyncData.antigravity,
6834
+ globs: this.frontmatter.globs ? parseGlobsString(this.frontmatter.globs) : void 0
6835
+ };
6836
+ return new RulesyncRule({
6837
+ baseDir: process.cwd(),
6838
+ relativeDirPath: RulesyncRule.getSettablePaths().recommended.relativeDirPath,
6839
+ relativeFilePath: this.getRelativeFilePath(),
6840
+ frontmatter: {
6841
+ root: false,
6842
+ targets: ["*"],
6843
+ ...rulesyncData,
6844
+ antigravity: antigravityForRulesync
6845
+ },
6846
+ // When converting back, we only want the body content
6847
+ body: this.body
6848
+ });
6849
+ }
6850
+ getBody() {
6851
+ return this.body;
6852
+ }
6853
+ // Helper to access raw file content including frontmatter is `this.fileContent` (from ToolFile)
6854
+ // But we might want `body` only for some operations?
6855
+ // ToolFile.getFileContent() returns the whole string.
6856
+ getFrontmatter() {
6857
+ return this.frontmatter;
6537
6858
  }
6538
6859
  validate() {
6860
+ const result = AntigravityRuleFrontmatterSchema.safeParse(this.frontmatter);
6861
+ if (!result.success) {
6862
+ return { success: false, error: new Error(formatError(result.error)) };
6863
+ }
6539
6864
  return { success: true, error: null };
6540
6865
  }
6541
6866
  static isTargetedByRulesyncRule(rulesyncRule) {
@@ -6769,9 +7094,9 @@ var ClaudecodeLegacyRule = class _ClaudecodeLegacyRule extends ToolRule {
6769
7094
 
6770
7095
  // src/features/rules/claudecode-rule.ts
6771
7096
  var import_node_path71 = require("path");
6772
- var import_mini29 = require("zod/mini");
6773
- var ClaudecodeRuleFrontmatterSchema = import_mini29.z.object({
6774
- paths: import_mini29.z.optional(import_mini29.z.string())
7097
+ var import_mini30 = require("zod/mini");
7098
+ var ClaudecodeRuleFrontmatterSchema = import_mini30.z.object({
7099
+ paths: import_mini30.z.optional(import_mini30.z.string())
6775
7100
  });
6776
7101
  var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
6777
7102
  frontmatter;
@@ -6961,9 +7286,9 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
6961
7286
 
6962
7287
  // src/features/rules/cline-rule.ts
6963
7288
  var import_node_path72 = require("path");
6964
- var import_mini30 = require("zod/mini");
6965
- var ClineRuleFrontmatterSchema = import_mini30.z.object({
6966
- description: import_mini30.z.string()
7289
+ var import_mini31 = require("zod/mini");
7290
+ var ClineRuleFrontmatterSchema = import_mini31.z.object({
7291
+ description: import_mini31.z.string()
6967
7292
  });
6968
7293
  var ClineRule = class _ClineRule extends ToolRule {
6969
7294
  static getSettablePaths() {
@@ -7110,11 +7435,11 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
7110
7435
 
7111
7436
  // src/features/rules/copilot-rule.ts
7112
7437
  var import_node_path74 = require("path");
7113
- var import_mini31 = require("zod/mini");
7114
- var CopilotRuleFrontmatterSchema = import_mini31.z.object({
7115
- description: import_mini31.z.optional(import_mini31.z.string()),
7116
- applyTo: import_mini31.z.optional(import_mini31.z.string()),
7117
- excludeAgent: import_mini31.z.optional(import_mini31.z.union([import_mini31.z.literal("code-review"), import_mini31.z.literal("coding-agent")]))
7438
+ var import_mini32 = require("zod/mini");
7439
+ var CopilotRuleFrontmatterSchema = import_mini32.z.object({
7440
+ description: import_mini32.z.optional(import_mini32.z.string()),
7441
+ applyTo: import_mini32.z.optional(import_mini32.z.string()),
7442
+ excludeAgent: import_mini32.z.optional(import_mini32.z.union([import_mini32.z.literal("code-review"), import_mini32.z.literal("coding-agent")]))
7118
7443
  });
7119
7444
  var CopilotRule = class _CopilotRule extends ToolRule {
7120
7445
  frontmatter;
@@ -7282,11 +7607,11 @@ var CopilotRule = class _CopilotRule extends ToolRule {
7282
7607
 
7283
7608
  // src/features/rules/cursor-rule.ts
7284
7609
  var import_node_path75 = require("path");
7285
- var import_mini32 = require("zod/mini");
7286
- var CursorRuleFrontmatterSchema = import_mini32.z.object({
7287
- description: import_mini32.z.optional(import_mini32.z.string()),
7288
- globs: import_mini32.z.optional(import_mini32.z.string()),
7289
- alwaysApply: import_mini32.z.optional(import_mini32.z.boolean())
7610
+ var import_mini33 = require("zod/mini");
7611
+ var CursorRuleFrontmatterSchema = import_mini33.z.object({
7612
+ description: import_mini33.z.optional(import_mini33.z.string()),
7613
+ globs: import_mini33.z.optional(import_mini33.z.string()),
7614
+ alwaysApply: import_mini33.z.optional(import_mini33.z.boolean())
7290
7615
  });
7291
7616
  var CursorRule = class _CursorRule extends ToolRule {
7292
7617
  frontmatter;
@@ -8004,34 +8329,197 @@ var rulesProcessorToolTargets = [
8004
8329
  "warp",
8005
8330
  "windsurf"
8006
8331
  ];
8007
- var RulesProcessorToolTargetSchema = import_mini33.z.enum(rulesProcessorToolTargets);
8008
- var rulesProcessorToolTargetsGlobal = [
8009
- "claudecode",
8010
- "claudecode-legacy",
8011
- "codexcli",
8012
- "geminicli"
8013
- ];
8332
+ var RulesProcessorToolTargetSchema = import_mini34.z.enum(rulesProcessorToolTargets);
8014
8333
  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" } }]
8334
+ [
8335
+ "agentsmd",
8336
+ {
8337
+ class: AgentsMdRule,
8338
+ meta: {
8339
+ extension: "md",
8340
+ supportsGlobal: false,
8341
+ ruleDiscoveryMode: "toon",
8342
+ additionalConventions: {
8343
+ commands: { commandClass: AgentsmdCommand },
8344
+ subagents: { subagentClass: AgentsmdSubagent },
8345
+ skills: { skillClass: AgentsmdSkill }
8346
+ }
8347
+ }
8348
+ }
8349
+ ],
8350
+ [
8351
+ "amazonqcli",
8352
+ {
8353
+ class: AmazonQCliRule,
8354
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
8355
+ }
8356
+ ],
8357
+ [
8358
+ "antigravity",
8359
+ {
8360
+ class: AntigravityRule,
8361
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
8362
+ }
8363
+ ],
8364
+ [
8365
+ "augmentcode",
8366
+ {
8367
+ class: AugmentcodeRule,
8368
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
8369
+ }
8370
+ ],
8371
+ [
8372
+ "augmentcode-legacy",
8373
+ {
8374
+ class: AugmentcodeLegacyRule,
8375
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
8376
+ }
8377
+ ],
8378
+ [
8379
+ "claudecode",
8380
+ {
8381
+ class: ClaudecodeRule,
8382
+ meta: { extension: "md", supportsGlobal: true, ruleDiscoveryMode: "auto" }
8383
+ }
8384
+ ],
8385
+ [
8386
+ "claudecode-legacy",
8387
+ {
8388
+ class: ClaudecodeLegacyRule,
8389
+ meta: { extension: "md", supportsGlobal: true, ruleDiscoveryMode: "claudecode-legacy" }
8390
+ }
8391
+ ],
8392
+ [
8393
+ "cline",
8394
+ {
8395
+ class: ClineRule,
8396
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
8397
+ }
8398
+ ],
8399
+ [
8400
+ "codexcli",
8401
+ {
8402
+ class: CodexcliRule,
8403
+ meta: {
8404
+ extension: "md",
8405
+ supportsGlobal: true,
8406
+ ruleDiscoveryMode: "toon",
8407
+ additionalConventions: {
8408
+ subagents: { subagentClass: CodexCliSubagent },
8409
+ skills: { skillClass: CodexCliSkill, globalOnly: true }
8410
+ }
8411
+ }
8412
+ }
8413
+ ],
8414
+ [
8415
+ "copilot",
8416
+ {
8417
+ class: CopilotRule,
8418
+ meta: {
8419
+ extension: "md",
8420
+ supportsGlobal: false,
8421
+ ruleDiscoveryMode: "auto",
8422
+ additionalConventions: {
8423
+ commands: { commandClass: CopilotCommand },
8424
+ subagents: { subagentClass: CopilotSubagent },
8425
+ skills: { skillClass: CopilotSkill }
8426
+ }
8427
+ }
8428
+ }
8429
+ ],
8430
+ [
8431
+ "cursor",
8432
+ {
8433
+ class: CursorRule,
8434
+ meta: {
8435
+ extension: "mdc",
8436
+ supportsGlobal: false,
8437
+ ruleDiscoveryMode: "auto",
8438
+ additionalConventions: {
8439
+ commands: { commandClass: CursorCommand },
8440
+ subagents: { subagentClass: CursorSubagent },
8441
+ skills: { skillClass: CursorSkill }
8442
+ },
8443
+ createsSeparateConventionsRule: true
8444
+ }
8445
+ }
8446
+ ],
8447
+ [
8448
+ "geminicli",
8449
+ {
8450
+ class: GeminiCliRule,
8451
+ meta: {
8452
+ extension: "md",
8453
+ supportsGlobal: true,
8454
+ ruleDiscoveryMode: "toon",
8455
+ additionalConventions: {
8456
+ commands: { commandClass: GeminiCliCommand },
8457
+ subagents: { subagentClass: GeminiCliSubagent },
8458
+ skills: { skillClass: GeminiCliSkill }
8459
+ }
8460
+ }
8461
+ }
8462
+ ],
8463
+ [
8464
+ "junie",
8465
+ {
8466
+ class: JunieRule,
8467
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
8468
+ }
8469
+ ],
8470
+ [
8471
+ "kiro",
8472
+ {
8473
+ class: KiroRule,
8474
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
8475
+ }
8476
+ ],
8477
+ [
8478
+ "opencode",
8479
+ {
8480
+ class: OpenCodeRule,
8481
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
8482
+ }
8483
+ ],
8484
+ [
8485
+ "qwencode",
8486
+ {
8487
+ class: QwencodeRule,
8488
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
8489
+ }
8490
+ ],
8491
+ [
8492
+ "roo",
8493
+ {
8494
+ class: RooRule,
8495
+ meta: {
8496
+ extension: "md",
8497
+ supportsGlobal: false,
8498
+ ruleDiscoveryMode: "auto",
8499
+ additionalConventions: {
8500
+ commands: { commandClass: RooCommand },
8501
+ subagents: { subagentClass: RooSubagent }
8502
+ },
8503
+ createsSeparateConventionsRule: true
8504
+ }
8505
+ }
8506
+ ],
8507
+ [
8508
+ "warp",
8509
+ {
8510
+ class: WarpRule,
8511
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "toon" }
8512
+ }
8513
+ ],
8514
+ [
8515
+ "windsurf",
8516
+ {
8517
+ class: WindsurfRule,
8518
+ meta: { extension: "md", supportsGlobal: false, ruleDiscoveryMode: "auto" }
8519
+ }
8520
+ ]
8034
8521
  ]);
8522
+ var rulesProcessorToolTargetsGlobal = Array.from(toolRuleFactories.entries()).filter(([_, factory]) => factory.meta.supportsGlobal).map(([target]) => target);
8035
8523
  var defaultGetFactory6 = (target) => {
8036
8524
  const factory = toolRuleFactories.get(target);
8037
8525
  if (!factory) {
@@ -8046,6 +8534,7 @@ var RulesProcessor = class extends FeatureProcessor {
8046
8534
  simulateSkills;
8047
8535
  global;
8048
8536
  getFactory;
8537
+ skills;
8049
8538
  constructor({
8050
8539
  baseDir = process.cwd(),
8051
8540
  toolTarget,
@@ -8053,7 +8542,8 @@ var RulesProcessor = class extends FeatureProcessor {
8053
8542
  simulateSubagents = false,
8054
8543
  simulateSkills = false,
8055
8544
  global = false,
8056
- getFactory = defaultGetFactory6
8545
+ getFactory = defaultGetFactory6,
8546
+ skills
8057
8547
  }) {
8058
8548
  super({ baseDir });
8059
8549
  const result = RulesProcessorToolTargetSchema.safeParse(toolTarget);
@@ -8068,12 +8558,14 @@ var RulesProcessor = class extends FeatureProcessor {
8068
8558
  this.simulateSubagents = simulateSubagents;
8069
8559
  this.simulateSkills = simulateSkills;
8070
8560
  this.getFactory = getFactory;
8561
+ this.skills = skills;
8071
8562
  }
8072
8563
  async convertRulesyncFilesToToolFiles(rulesyncFiles) {
8073
8564
  const rulesyncRules = rulesyncFiles.filter(
8074
8565
  (file) => file instanceof RulesyncRule
8075
8566
  );
8076
8567
  const factory = this.getFactory(this.toolTarget);
8568
+ const { meta } = factory;
8077
8569
  const toolRules = rulesyncRules.map((rulesyncRule) => {
8078
8570
  if (!factory.class.isTargetedByRulesyncRule(rulesyncRule)) {
8079
8571
  return null;
@@ -8086,153 +8578,105 @@ var RulesProcessor = class extends FeatureProcessor {
8086
8578
  });
8087
8579
  }).filter((rule) => rule !== null);
8088
8580
  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
- );
8581
+ if (isSimulated && meta.createsSeparateConventionsRule && meta.additionalConventions) {
8582
+ const conventionsContent = this.generateAdditionalConventionsSectionFromMeta(meta);
8583
+ const settablePaths = factory.class.getSettablePaths();
8584
+ const nonRootPath = "nonRoot" in settablePaths ? settablePaths.nonRoot : null;
8585
+ if (nonRootPath) {
8586
+ toolRules.push(
8587
+ factory.class.fromRulesyncRule({
8588
+ baseDir: this.baseDir,
8589
+ rulesyncRule: new RulesyncRule({
8590
+ baseDir: this.baseDir,
8591
+ relativeDirPath: nonRootPath.relativeDirPath,
8592
+ relativeFilePath: "additional-conventions.md",
8593
+ frontmatter: {
8594
+ root: false,
8595
+ targets: [this.toolTarget]
8596
+ },
8597
+ body: conventionsContent
8598
+ }),
8599
+ validate: true,
8600
+ global: this.global
8601
+ })
8602
+ );
8603
+ }
8126
8604
  }
8127
8605
  const rootRuleIndex = toolRules.findIndex((rule) => rule.isRoot());
8128
8606
  if (rootRuleIndex === -1) {
8129
8607
  return toolRules;
8130
8608
  }
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
- }
8609
+ const rootRule = toolRules[rootRuleIndex];
8610
+ if (!rootRule) {
8611
+ return toolRules;
8612
+ }
8613
+ const referenceSection = this.generateReferenceSectionFromMeta(meta, toolRules);
8614
+ const conventionsSection = !meta.createsSeparateConventionsRule && meta.additionalConventions ? this.generateAdditionalConventionsSectionFromMeta(meta) : "";
8615
+ const newContent = referenceSection + conventionsSection + rootRule.getFileContent();
8616
+ rootRule.setFileContent(newContent);
8617
+ return toolRules;
8618
+ }
8619
+ buildSkillList(skillClass) {
8620
+ if (!this.skills) return [];
8621
+ const toolRelativeDirPath = skillClass.getSettablePaths({
8622
+ global: this.global
8623
+ }).relativeDirPath;
8624
+ return this.skills.filter((skill) => skillClass.isTargetedByRulesyncSkill(skill)).map((skill) => {
8625
+ const frontmatter = skill.getFrontmatter();
8626
+ const relativePath = (0, import_node_path84.join)(toolRelativeDirPath, skill.getDirName(), SKILL_FILE_NAME);
8627
+ return {
8628
+ name: frontmatter.name,
8629
+ description: frontmatter.description,
8630
+ path: relativePath
8631
+ };
8632
+ });
8633
+ }
8634
+ /**
8635
+ * Generate reference section based on meta configuration.
8636
+ */
8637
+ generateReferenceSectionFromMeta(meta, toolRules) {
8638
+ switch (meta.ruleDiscoveryMode) {
8639
+ case "toon":
8640
+ return this.generateToonReferencesSection(toolRules);
8641
+ case "claudecode-legacy":
8642
+ return this.generateReferencesSection(toolRules);
8643
+ case "auto":
8233
8644
  default:
8234
- return toolRules;
8645
+ return "";
8646
+ }
8647
+ }
8648
+ /**
8649
+ * Generate additional conventions section based on meta configuration.
8650
+ */
8651
+ generateAdditionalConventionsSectionFromMeta(meta) {
8652
+ const { additionalConventions } = meta;
8653
+ if (!additionalConventions) {
8654
+ return "";
8655
+ }
8656
+ const conventions = {};
8657
+ if (additionalConventions.commands) {
8658
+ const { commandClass } = additionalConventions.commands;
8659
+ const relativeDirPath = commandClass.getSettablePaths({
8660
+ global: this.global
8661
+ }).relativeDirPath;
8662
+ conventions.commands = { relativeDirPath };
8235
8663
  }
8664
+ if (additionalConventions.subagents) {
8665
+ const { subagentClass } = additionalConventions.subagents;
8666
+ const relativeDirPath = subagentClass.getSettablePaths({
8667
+ global: this.global
8668
+ }).relativeDirPath;
8669
+ conventions.subagents = { relativeDirPath };
8670
+ }
8671
+ if (additionalConventions.skills) {
8672
+ const { skillClass, globalOnly } = additionalConventions.skills;
8673
+ if (!globalOnly || this.global) {
8674
+ conventions.skills = {
8675
+ skillList: this.buildSkillList(skillClass)
8676
+ };
8677
+ }
8678
+ }
8679
+ return this.generateAdditionalConventionsSection(conventions);
8236
8680
  }
8237
8681
  async convertToolFilesToRulesyncFiles(toolFiles) {
8238
8682
  const toolRules = toolFiles.filter((file) => file instanceof ToolRule);
@@ -8417,15 +8861,7 @@ Simulated subagents are specialized AI assistants that can be invoked to handle
8417
8861
  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
8862
 
8419
8863
  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.` : "";
8864
+ const skillsSection = skills ? this.generateSkillsSection(skills) : "";
8429
8865
  const result = [
8430
8866
  overview,
8431
8867
  ...this.simulateCommands && CommandsProcessor.getToolTargetsSimulated().includes(this.toolTarget) ? [commandsSection] : [],
@@ -8434,6 +8870,21 @@ Additionally, you should proactively consider using available skills when they w
8434
8870
  ].join("\n\n") + "\n\n";
8435
8871
  return result;
8436
8872
  }
8873
+ generateSkillsSection(skills) {
8874
+ if (!skills.skillList || skills.skillList.length === 0) {
8875
+ return "";
8876
+ }
8877
+ const skillListWithAtPrefix = skills.skillList.map((skill) => ({
8878
+ ...skill,
8879
+ path: `@${skill.path}`
8880
+ }));
8881
+ const toonContent = (0, import_toon.encode)({ skillList: skillListWithAtPrefix });
8882
+ return `## Simulated Skills
8883
+
8884
+ 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.
8885
+
8886
+ ${toonContent}`;
8887
+ }
8437
8888
  };
8438
8889
 
8439
8890
  // src/cli/commands/generate.ts
@@ -8446,13 +8897,15 @@ async function generateCommand(options) {
8446
8897
  process.exit(1);
8447
8898
  }
8448
8899
  logger.info(`Base directories: ${config.getBaseDirs().join(", ")}`);
8449
- const totalRulesOutputs = await generateRules(config);
8450
8900
  const totalIgnoreOutputs = await generateIgnore(config);
8451
8901
  const totalMcpOutputs = await generateMcp(config);
8452
8902
  const totalCommandOutputs = await generateCommands(config);
8453
8903
  const totalSubagentOutputs = await generateSubagents(config);
8454
- const totalSkillOutputs = await generateSkills(config);
8455
- const totalGenerated = totalRulesOutputs + totalMcpOutputs + totalCommandOutputs + totalIgnoreOutputs + totalSubagentOutputs + totalSkillOutputs;
8904
+ const skillsResult = await generateSkills(config);
8905
+ const totalRulesOutputs = await generateRules(config, {
8906
+ skills: skillsResult.skills
8907
+ });
8908
+ const totalGenerated = totalRulesOutputs + totalMcpOutputs + totalCommandOutputs + totalIgnoreOutputs + totalSubagentOutputs + skillsResult.totalOutputs;
8456
8909
  if (totalGenerated === 0) {
8457
8910
  const enabledFeatures = config.getFeatures().join(", ");
8458
8911
  logger.warn(`\u26A0\uFE0F No files generated for enabled features: ${enabledFeatures}`);
@@ -8465,18 +8918,18 @@ async function generateCommand(options) {
8465
8918
  if (totalMcpOutputs > 0) parts.push(`${totalMcpOutputs} MCP files`);
8466
8919
  if (totalCommandOutputs > 0) parts.push(`${totalCommandOutputs} commands`);
8467
8920
  if (totalSubagentOutputs > 0) parts.push(`${totalSubagentOutputs} subagents`);
8468
- if (totalSkillOutputs > 0) parts.push(`${totalSkillOutputs} skills`);
8921
+ if (skillsResult.totalOutputs > 0) parts.push(`${skillsResult.totalOutputs} skills`);
8469
8922
  logger.success(`\u{1F389} All done! Generated ${totalGenerated} file(s) total (${parts.join(" + ")})`);
8470
8923
  }
8471
8924
  }
8472
- async function generateRules(config) {
8925
+ async function generateRules(config, options) {
8473
8926
  if (!config.getFeatures().includes("rules")) {
8474
8927
  logger.debug("Skipping rule generation (not in --features)");
8475
8928
  return 0;
8476
8929
  }
8477
8930
  let totalRulesOutputs = 0;
8478
8931
  logger.info("Generating rule files...");
8479
- const toolTargets = (0, import_es_toolkit2.intersection)(
8932
+ const toolTargets = (0, import_es_toolkit3.intersection)(
8480
8933
  config.getTargets(),
8481
8934
  RulesProcessor.getToolTargets({ global: config.getGlobal() })
8482
8935
  );
@@ -8488,7 +8941,8 @@ async function generateRules(config) {
8488
8941
  global: config.getGlobal(),
8489
8942
  simulateCommands: config.getSimulateCommands(),
8490
8943
  simulateSubagents: config.getSimulateSubagents(),
8491
- simulateSkills: config.getSimulateSkills()
8944
+ simulateSkills: config.getSimulateSkills(),
8945
+ skills: options?.skills
8492
8946
  });
8493
8947
  if (config.getDelete()) {
8494
8948
  const oldToolFiles = await processor.loadToolFiles({ forDeletion: true });
@@ -8517,7 +8971,7 @@ async function generateIgnore(config) {
8517
8971
  }
8518
8972
  let totalIgnoreOutputs = 0;
8519
8973
  logger.info("Generating ignore files...");
8520
- for (const toolTarget of (0, import_es_toolkit2.intersection)(config.getTargets(), IgnoreProcessor.getToolTargets())) {
8974
+ for (const toolTarget of (0, import_es_toolkit3.intersection)(config.getTargets(), IgnoreProcessor.getToolTargets())) {
8521
8975
  for (const baseDir of config.getBaseDirs()) {
8522
8976
  try {
8523
8977
  const processor = new IgnoreProcessor({
@@ -8556,7 +9010,7 @@ async function generateMcp(config) {
8556
9010
  if (config.getModularMcp()) {
8557
9011
  logger.info("\u2139\uFE0F Modular MCP support is experimental.");
8558
9012
  }
8559
- const toolTargets = (0, import_es_toolkit2.intersection)(
9013
+ const toolTargets = (0, import_es_toolkit3.intersection)(
8560
9014
  config.getTargets(),
8561
9015
  McpProcessor.getToolTargets({ global: config.getGlobal() })
8562
9016
  );
@@ -8588,7 +9042,7 @@ async function generateCommands(config) {
8588
9042
  }
8589
9043
  let totalCommandOutputs = 0;
8590
9044
  logger.info("Generating command files...");
8591
- const toolTargets = (0, import_es_toolkit2.intersection)(
9045
+ const toolTargets = (0, import_es_toolkit3.intersection)(
8592
9046
  config.getTargets(),
8593
9047
  CommandsProcessor.getToolTargets({
8594
9048
  global: config.getGlobal(),
@@ -8622,7 +9076,7 @@ async function generateSubagents(config) {
8622
9076
  }
8623
9077
  let totalSubagentOutputs = 0;
8624
9078
  logger.info("Generating subagent files...");
8625
- const toolTargets = (0, import_es_toolkit2.intersection)(
9079
+ const toolTargets = (0, import_es_toolkit3.intersection)(
8626
9080
  config.getTargets(),
8627
9081
  SubagentsProcessor.getToolTargets({
8628
9082
  global: config.getGlobal(),
@@ -8652,11 +9106,12 @@ async function generateSubagents(config) {
8652
9106
  async function generateSkills(config) {
8653
9107
  if (!config.getFeatures().includes("skills")) {
8654
9108
  logger.debug("Skipping skill generation (not in --features)");
8655
- return 0;
9109
+ return { totalOutputs: 0, skills: [] };
8656
9110
  }
8657
9111
  let totalSkillOutputs = 0;
9112
+ const allSkills = [];
8658
9113
  logger.info("Generating skill files...");
8659
- const toolTargets = (0, import_es_toolkit2.intersection)(
9114
+ const toolTargets = (0, import_es_toolkit3.intersection)(
8660
9115
  config.getTargets(),
8661
9116
  SkillsProcessor.getToolTargets({
8662
9117
  global: config.getGlobal(),
@@ -8675,13 +9130,18 @@ async function generateSkills(config) {
8675
9130
  await processor.removeAiDirs(oldToolDirs);
8676
9131
  }
8677
9132
  const rulesyncDirs = await processor.loadRulesyncDirs();
9133
+ for (const rulesyncDir of rulesyncDirs) {
9134
+ if (rulesyncDir instanceof RulesyncSkill) {
9135
+ allSkills.push(rulesyncDir);
9136
+ }
9137
+ }
8678
9138
  const toolDirs = await processor.convertRulesyncDirsToToolDirs(rulesyncDirs);
8679
9139
  const writtenCount = await processor.writeAiDirs(toolDirs);
8680
9140
  totalSkillOutputs += writtenCount;
8681
9141
  logger.success(`Generated ${writtenCount} ${toolTarget} skill(s) in ${baseDir}`);
8682
9142
  }
8683
9143
  }
8684
- return totalSkillOutputs;
9144
+ return { totalOutputs: totalSkillOutputs, skills: allSkills };
8685
9145
  }
8686
9146
 
8687
9147
  // src/cli/commands/gitignore.ts
@@ -9218,7 +9678,7 @@ var import_fastmcp = require("fastmcp");
9218
9678
 
9219
9679
  // src/mcp/commands.ts
9220
9680
  var import_node_path87 = require("path");
9221
- var import_mini34 = require("zod/mini");
9681
+ var import_mini35 = require("zod/mini");
9222
9682
  var maxCommandSizeBytes = 1024 * 1024;
9223
9683
  var maxCommandsCount = 1e3;
9224
9684
  async function listCommands() {
@@ -9337,17 +9797,17 @@ async function deleteCommand({ relativePathFromCwd }) {
9337
9797
  }
9338
9798
  }
9339
9799
  var commandToolSchemas = {
9340
- listCommands: import_mini34.z.object({}),
9341
- getCommand: import_mini34.z.object({
9342
- relativePathFromCwd: import_mini34.z.string()
9800
+ listCommands: import_mini35.z.object({}),
9801
+ getCommand: import_mini35.z.object({
9802
+ relativePathFromCwd: import_mini35.z.string()
9343
9803
  }),
9344
- putCommand: import_mini34.z.object({
9345
- relativePathFromCwd: import_mini34.z.string(),
9804
+ putCommand: import_mini35.z.object({
9805
+ relativePathFromCwd: import_mini35.z.string(),
9346
9806
  frontmatter: RulesyncCommandFrontmatterSchema,
9347
- body: import_mini34.z.string()
9807
+ body: import_mini35.z.string()
9348
9808
  }),
9349
- deleteCommand: import_mini34.z.object({
9350
- relativePathFromCwd: import_mini34.z.string()
9809
+ deleteCommand: import_mini35.z.object({
9810
+ relativePathFromCwd: import_mini35.z.string()
9351
9811
  })
9352
9812
  };
9353
9813
  var commandTools = {
@@ -9396,7 +9856,7 @@ var commandTools = {
9396
9856
 
9397
9857
  // src/mcp/ignore.ts
9398
9858
  var import_node_path88 = require("path");
9399
- var import_mini35 = require("zod/mini");
9859
+ var import_mini36 = require("zod/mini");
9400
9860
  var maxIgnoreFileSizeBytes = 100 * 1024;
9401
9861
  async function getIgnoreFile() {
9402
9862
  const ignoreFilePath = (0, import_node_path88.join)(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
@@ -9453,11 +9913,11 @@ async function deleteIgnoreFile() {
9453
9913
  }
9454
9914
  }
9455
9915
  var ignoreToolSchemas = {
9456
- getIgnoreFile: import_mini35.z.object({}),
9457
- putIgnoreFile: import_mini35.z.object({
9458
- content: import_mini35.z.string()
9916
+ getIgnoreFile: import_mini36.z.object({}),
9917
+ putIgnoreFile: import_mini36.z.object({
9918
+ content: import_mini36.z.string()
9459
9919
  }),
9460
- deleteIgnoreFile: import_mini35.z.object({})
9920
+ deleteIgnoreFile: import_mini36.z.object({})
9461
9921
  };
9462
9922
  var ignoreTools = {
9463
9923
  getIgnoreFile: {
@@ -9491,7 +9951,7 @@ var ignoreTools = {
9491
9951
 
9492
9952
  // src/mcp/mcp.ts
9493
9953
  var import_node_path89 = require("path");
9494
- var import_mini36 = require("zod/mini");
9954
+ var import_mini37 = require("zod/mini");
9495
9955
  var maxMcpSizeBytes = 1024 * 1024;
9496
9956
  async function getMcpFile() {
9497
9957
  const config = await ConfigResolver.resolve({});
@@ -9581,11 +10041,11 @@ async function deleteMcpFile() {
9581
10041
  }
9582
10042
  }
9583
10043
  var mcpToolSchemas = {
9584
- getMcpFile: import_mini36.z.object({}),
9585
- putMcpFile: import_mini36.z.object({
9586
- content: import_mini36.z.string()
10044
+ getMcpFile: import_mini37.z.object({}),
10045
+ putMcpFile: import_mini37.z.object({
10046
+ content: import_mini37.z.string()
9587
10047
  }),
9588
- deleteMcpFile: import_mini36.z.object({})
10048
+ deleteMcpFile: import_mini37.z.object({})
9589
10049
  };
9590
10050
  var mcpTools = {
9591
10051
  getMcpFile: {
@@ -9619,7 +10079,7 @@ var mcpTools = {
9619
10079
 
9620
10080
  // src/mcp/rules.ts
9621
10081
  var import_node_path90 = require("path");
9622
- var import_mini37 = require("zod/mini");
10082
+ var import_mini38 = require("zod/mini");
9623
10083
  var maxRuleSizeBytes = 1024 * 1024;
9624
10084
  var maxRulesCount = 1e3;
9625
10085
  async function listRules() {
@@ -9738,17 +10198,17 @@ async function deleteRule({ relativePathFromCwd }) {
9738
10198
  }
9739
10199
  }
9740
10200
  var ruleToolSchemas = {
9741
- listRules: import_mini37.z.object({}),
9742
- getRule: import_mini37.z.object({
9743
- relativePathFromCwd: import_mini37.z.string()
10201
+ listRules: import_mini38.z.object({}),
10202
+ getRule: import_mini38.z.object({
10203
+ relativePathFromCwd: import_mini38.z.string()
9744
10204
  }),
9745
- putRule: import_mini37.z.object({
9746
- relativePathFromCwd: import_mini37.z.string(),
10205
+ putRule: import_mini38.z.object({
10206
+ relativePathFromCwd: import_mini38.z.string(),
9747
10207
  frontmatter: RulesyncRuleFrontmatterSchema,
9748
- body: import_mini37.z.string()
10208
+ body: import_mini38.z.string()
9749
10209
  }),
9750
- deleteRule: import_mini37.z.object({
9751
- relativePathFromCwd: import_mini37.z.string()
10210
+ deleteRule: import_mini38.z.object({
10211
+ relativePathFromCwd: import_mini38.z.string()
9752
10212
  })
9753
10213
  };
9754
10214
  var ruleTools = {
@@ -9797,7 +10257,7 @@ var ruleTools = {
9797
10257
 
9798
10258
  // src/mcp/skills.ts
9799
10259
  var import_node_path91 = require("path");
9800
- var import_mini38 = require("zod/mini");
10260
+ var import_mini39 = require("zod/mini");
9801
10261
  var maxSkillSizeBytes = 1024 * 1024;
9802
10262
  var maxSkillsCount = 1e3;
9803
10263
  function aiDirFileToMcpSkillFile(file) {
@@ -9965,23 +10425,23 @@ async function deleteSkill({
9965
10425
  );
9966
10426
  }
9967
10427
  }
9968
- var McpSkillFileSchema = import_mini38.z.object({
9969
- name: import_mini38.z.string(),
9970
- body: import_mini38.z.string()
10428
+ var McpSkillFileSchema = import_mini39.z.object({
10429
+ name: import_mini39.z.string(),
10430
+ body: import_mini39.z.string()
9971
10431
  });
9972
10432
  var skillToolSchemas = {
9973
- listSkills: import_mini38.z.object({}),
9974
- getSkill: import_mini38.z.object({
9975
- relativeDirPathFromCwd: import_mini38.z.string()
10433
+ listSkills: import_mini39.z.object({}),
10434
+ getSkill: import_mini39.z.object({
10435
+ relativeDirPathFromCwd: import_mini39.z.string()
9976
10436
  }),
9977
- putSkill: import_mini38.z.object({
9978
- relativeDirPathFromCwd: import_mini38.z.string(),
10437
+ putSkill: import_mini39.z.object({
10438
+ relativeDirPathFromCwd: import_mini39.z.string(),
9979
10439
  frontmatter: RulesyncSkillFrontmatterSchema,
9980
- body: import_mini38.z.string(),
9981
- otherFiles: import_mini38.z.optional(import_mini38.z.array(McpSkillFileSchema))
10440
+ body: import_mini39.z.string(),
10441
+ otherFiles: import_mini39.z.optional(import_mini39.z.array(McpSkillFileSchema))
9982
10442
  }),
9983
- deleteSkill: import_mini38.z.object({
9984
- relativeDirPathFromCwd: import_mini38.z.string()
10443
+ deleteSkill: import_mini39.z.object({
10444
+ relativeDirPathFromCwd: import_mini39.z.string()
9985
10445
  })
9986
10446
  };
9987
10447
  var skillTools = {
@@ -10031,7 +10491,7 @@ var skillTools = {
10031
10491
 
10032
10492
  // src/mcp/subagents.ts
10033
10493
  var import_node_path92 = require("path");
10034
- var import_mini39 = require("zod/mini");
10494
+ var import_mini40 = require("zod/mini");
10035
10495
  var maxSubagentSizeBytes = 1024 * 1024;
10036
10496
  var maxSubagentsCount = 1e3;
10037
10497
  async function listSubagents() {
@@ -10155,17 +10615,17 @@ async function deleteSubagent({ relativePathFromCwd }) {
10155
10615
  }
10156
10616
  }
10157
10617
  var subagentToolSchemas = {
10158
- listSubagents: import_mini39.z.object({}),
10159
- getSubagent: import_mini39.z.object({
10160
- relativePathFromCwd: import_mini39.z.string()
10618
+ listSubagents: import_mini40.z.object({}),
10619
+ getSubagent: import_mini40.z.object({
10620
+ relativePathFromCwd: import_mini40.z.string()
10161
10621
  }),
10162
- putSubagent: import_mini39.z.object({
10163
- relativePathFromCwd: import_mini39.z.string(),
10622
+ putSubagent: import_mini40.z.object({
10623
+ relativePathFromCwd: import_mini40.z.string(),
10164
10624
  frontmatter: RulesyncSubagentFrontmatterSchema,
10165
- body: import_mini39.z.string()
10625
+ body: import_mini40.z.string()
10166
10626
  }),
10167
- deleteSubagent: import_mini39.z.object({
10168
- relativePathFromCwd: import_mini39.z.string()
10627
+ deleteSubagent: import_mini40.z.object({
10628
+ relativePathFromCwd: import_mini40.z.string()
10169
10629
  })
10170
10630
  };
10171
10631
  var subagentTools = {
@@ -10249,7 +10709,7 @@ async function mcpCommand({ version }) {
10249
10709
  }
10250
10710
 
10251
10711
  // src/cli/index.ts
10252
- var getVersion = () => "3.32.0";
10712
+ var getVersion = () => "3.34.0";
10253
10713
  var main = async () => {
10254
10714
  const program = new import_commander.Command();
10255
10715
  const version = getVersion();