rulesync 3.23.6 → 3.25.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 +89 -33
  2. package/dist/index.cjs +1923 -485
  3. package/dist/index.js +1923 -485
  4. package/package.json +18 -18
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ var ANNOUNCEMENT = "".trim();
8
8
 
9
9
  // src/types/features.ts
10
10
  import { z } from "zod/mini";
11
- var ALL_FEATURES = ["rules", "ignore", "mcp", "subagents", "commands"];
11
+ var ALL_FEATURES = ["rules", "ignore", "mcp", "subagents", "commands", "skills"];
12
12
  var ALL_FEATURES_WITH_WILDCARD = [...ALL_FEATURES, "*"];
13
13
  var FeatureSchema = z.enum(ALL_FEATURES);
14
14
  var FeaturesSchema = z.array(FeatureSchema);
@@ -137,6 +137,10 @@ async function readFileContent(filepath) {
137
137
  logger.debug(`Reading file: ${filepath}`);
138
138
  return readFile(filepath, "utf-8");
139
139
  }
140
+ async function readFileBuffer(filepath) {
141
+ logger.debug(`Reading file buffer: ${filepath}`);
142
+ return readFile(filepath);
143
+ }
140
144
  function addTrailingNewline(content) {
141
145
  if (!content) {
142
146
  return "\n";
@@ -164,11 +168,32 @@ async function listDirectoryFiles(dir) {
164
168
  }
165
169
  }
166
170
  async function findFilesByGlobs(globs, options = {}) {
171
+ const { type = "all" } = options;
167
172
  const items = globSync(globs, { withFileTypes: true });
168
- if (!options.fileOnly) {
169
- return items.map((item) => join(item.parentPath, item.name));
173
+ switch (type) {
174
+ case "file":
175
+ return items.filter((item) => item.isFile()).map((item) => join(item.parentPath, item.name));
176
+ case "dir":
177
+ return items.filter((item) => item.isDirectory()).map((item) => join(item.parentPath, item.name));
178
+ case "all":
179
+ return items.map((item) => join(item.parentPath, item.name));
180
+ default:
181
+ throw new Error(`Invalid type: ${type}`);
182
+ }
183
+ }
184
+ async function removeDirectory(dirPath) {
185
+ const dangerousPaths = [".", "/", "~", "src", "node_modules"];
186
+ if (dangerousPaths.includes(dirPath) || dirPath === "") {
187
+ logger.warn(`Skipping deletion of dangerous path: ${dirPath}`);
188
+ return;
189
+ }
190
+ try {
191
+ if (await fileExists(dirPath)) {
192
+ await rm(dirPath, { recursive: true, force: true });
193
+ }
194
+ } catch (error) {
195
+ logger.warn(`Failed to remove directory ${dirPath}:`, error);
170
196
  }
171
- return items.filter((item) => item.isFile()).map((item) => join(item.parentPath, item.name));
172
197
  }
173
198
  async function removeFile(filepath) {
174
199
  logger.debug(`Removing file: ${filepath}`);
@@ -231,8 +256,9 @@ var ConfigParamsSchema = z3.object({
231
256
  delete: z3.boolean(),
232
257
  // New non-experimental options
233
258
  global: optional(z3.boolean()),
234
- simulatedCommands: optional(z3.boolean()),
235
- simulatedSubagents: optional(z3.boolean()),
259
+ simulateCommands: optional(z3.boolean()),
260
+ simulateSubagents: optional(z3.boolean()),
261
+ simulateSkills: optional(z3.boolean()),
236
262
  modularMcp: optional(z3.boolean()),
237
263
  // Deprecated experimental options (for backward compatibility)
238
264
  experimentalGlobal: optional(z3.boolean()),
@@ -248,8 +274,9 @@ var Config = class {
248
274
  verbose;
249
275
  delete;
250
276
  global;
251
- simulatedCommands;
252
- simulatedSubagents;
277
+ simulateCommands;
278
+ simulateSubagents;
279
+ simulateSkills;
253
280
  modularMcp;
254
281
  constructor({
255
282
  baseDirs,
@@ -258,8 +285,9 @@ var Config = class {
258
285
  verbose,
259
286
  delete: isDelete,
260
287
  global,
261
- simulatedCommands,
262
- simulatedSubagents,
288
+ simulateCommands,
289
+ simulateSubagents,
290
+ simulateSkills,
263
291
  modularMcp,
264
292
  experimentalGlobal,
265
293
  experimentalSimulateCommands,
@@ -271,8 +299,9 @@ var Config = class {
271
299
  this.verbose = verbose;
272
300
  this.delete = isDelete;
273
301
  this.global = global ?? experimentalGlobal ?? false;
274
- this.simulatedCommands = simulatedCommands ?? experimentalSimulateCommands ?? false;
275
- this.simulatedSubagents = simulatedSubagents ?? experimentalSimulateSubagents ?? false;
302
+ this.simulateCommands = simulateCommands ?? experimentalSimulateCommands ?? false;
303
+ this.simulateSubagents = simulateSubagents ?? experimentalSimulateSubagents ?? false;
304
+ this.simulateSkills = simulateSkills ?? false;
276
305
  this.modularMcp = modularMcp ?? false;
277
306
  }
278
307
  getBaseDirs() {
@@ -299,11 +328,14 @@ var Config = class {
299
328
  getGlobal() {
300
329
  return this.global;
301
330
  }
302
- getSimulatedCommands() {
303
- return this.simulatedCommands;
331
+ getSimulateCommands() {
332
+ return this.simulateCommands;
304
333
  }
305
- getSimulatedSubagents() {
306
- return this.simulatedSubagents;
334
+ getSimulateSubagents() {
335
+ return this.simulateSubagents;
336
+ }
337
+ getSimulateSkills() {
338
+ return this.simulateSkills;
307
339
  }
308
340
  getModularMcp() {
309
341
  return this.modularMcp;
@@ -313,13 +345,13 @@ var Config = class {
313
345
  getExperimentalGlobal() {
314
346
  return this.global;
315
347
  }
316
- /** @deprecated Use getSimulatedCommands() instead */
348
+ /** @deprecated Use getSimulateCommands() instead */
317
349
  getExperimentalSimulateCommands() {
318
- return this.simulatedCommands;
350
+ return this.simulateCommands;
319
351
  }
320
- /** @deprecated Use getSimulatedSubagents() instead */
352
+ /** @deprecated Use getSimulateSubagents() instead */
321
353
  getExperimentalSimulateSubagents() {
322
- return this.simulatedSubagents;
354
+ return this.simulateSubagents;
323
355
  }
324
356
  };
325
357
 
@@ -332,8 +364,9 @@ var getDefaults = () => ({
332
364
  baseDirs: [process.cwd()],
333
365
  configPath: "rulesync.jsonc",
334
366
  global: false,
335
- simulatedCommands: false,
336
- simulatedSubagents: false,
367
+ simulateCommands: false,
368
+ simulateSubagents: false,
369
+ simulateSkills: false,
337
370
  modularMcp: false,
338
371
  experimentalGlobal: false,
339
372
  experimentalSimulateCommands: false,
@@ -348,8 +381,9 @@ var ConfigResolver = class {
348
381
  baseDirs,
349
382
  configPath = getDefaults().configPath,
350
383
  global,
351
- simulatedCommands,
352
- simulatedSubagents,
384
+ simulateCommands,
385
+ simulateSubagents,
386
+ simulateSkills,
353
387
  modularMcp,
354
388
  experimentalGlobal,
355
389
  experimentalSimulateCommands,
@@ -380,8 +414,9 @@ var ConfigResolver = class {
380
414
  warnDeprecatedOptions({ experimentalSimulateSubagents: deprecatedSubagents });
381
415
  }
382
416
  const resolvedGlobal = global ?? configByFile.global ?? experimentalGlobal ?? configByFile.experimentalGlobal ?? getDefaults().global;
383
- const resolvedSimulatedCommands = simulatedCommands ?? configByFile.simulatedCommands ?? experimentalSimulateCommands ?? configByFile.experimentalSimulateCommands ?? getDefaults().simulatedCommands;
384
- const resolvedSimulatedSubagents = simulatedSubagents ?? configByFile.simulatedSubagents ?? experimentalSimulateSubagents ?? configByFile.experimentalSimulateSubagents ?? getDefaults().simulatedSubagents;
417
+ const resolvedSimulateCommands = simulateCommands ?? configByFile.simulateCommands ?? experimentalSimulateCommands ?? configByFile.experimentalSimulateCommands ?? getDefaults().simulateCommands;
418
+ const resolvedSimulateSubagents = simulateSubagents ?? configByFile.simulateSubagents ?? experimentalSimulateSubagents ?? configByFile.experimentalSimulateSubagents ?? getDefaults().simulateSubagents;
419
+ const resolvedSimulateSkills = simulateSkills ?? configByFile.simulateSkills ?? getDefaults().simulateSkills;
385
420
  const configParams = {
386
421
  targets: targets ?? configByFile.targets ?? getDefaults().targets,
387
422
  features: features ?? configByFile.features ?? getDefaults().features,
@@ -392,8 +427,9 @@ var ConfigResolver = class {
392
427
  global: resolvedGlobal
393
428
  }),
394
429
  global: resolvedGlobal,
395
- simulatedCommands: resolvedSimulatedCommands,
396
- simulatedSubagents: resolvedSimulatedSubagents,
430
+ simulateCommands: resolvedSimulateCommands,
431
+ simulateSubagents: resolvedSimulateSubagents,
432
+ simulateSkills: resolvedSimulateSkills,
397
433
  modularMcp: modularMcp ?? configByFile.modularMcp ?? getDefaults().modularMcp
398
434
  };
399
435
  return new Config(configParams);
@@ -409,12 +445,12 @@ function warnDeprecatedOptions({
409
445
  }
410
446
  if (experimentalSimulateCommands !== void 0) {
411
447
  logger.warn(
412
- "'experimentalSimulateCommands' option is deprecated. Please use 'simulatedCommands' instead."
448
+ "'experimentalSimulateCommands' option is deprecated. Please use 'simulateCommands' instead."
413
449
  );
414
450
  }
415
451
  if (experimentalSimulateSubagents !== void 0) {
416
452
  logger.warn(
417
- "'experimentalSimulateSubagents' option is deprecated. Please use 'simulatedSubagents' instead."
453
+ "'experimentalSimulateSubagents' option is deprecated. Please use 'simulateSubagents' instead."
418
454
  );
419
455
  }
420
456
  }
@@ -1674,7 +1710,7 @@ var CommandsProcessor = class extends FeatureProcessor {
1674
1710
  );
1675
1711
  const rulesyncCommands = (await Promise.allSettled(
1676
1712
  rulesyncCommandPaths.map(
1677
- (path2) => RulesyncCommand.fromFile({ relativeFilePath: basename11(path2) })
1713
+ (path3) => RulesyncCommand.fromFile({ relativeFilePath: basename11(path3) })
1678
1714
  )
1679
1715
  )).filter((result) => result.status === "fulfilled").map((result) => result.value);
1680
1716
  logger.info(`Successfully loaded ${rulesyncCommands.length} rulesync commands`);
@@ -1684,7 +1720,9 @@ var CommandsProcessor = class extends FeatureProcessor {
1684
1720
  * Implementation of abstract method from FeatureProcessor
1685
1721
  * Load tool-specific command configurations and parse them into ToolCommand instances
1686
1722
  */
1687
- async loadToolFiles() {
1723
+ async loadToolFiles({
1724
+ forDeletion: _forDeletion = false
1725
+ } = {}) {
1688
1726
  switch (this.toolTarget) {
1689
1727
  case "agentsmd":
1690
1728
  return await this.loadAgentsmdCommands();
@@ -1704,9 +1742,6 @@ var CommandsProcessor = class extends FeatureProcessor {
1704
1742
  throw new Error(`Unsupported tool target: ${this.toolTarget}`);
1705
1743
  }
1706
1744
  }
1707
- async loadToolFilesToDelete() {
1708
- return this.loadToolFiles();
1709
- }
1710
1745
  async loadToolCommandDefault({
1711
1746
  toolTarget,
1712
1747
  relativeDirPath,
@@ -1716,45 +1751,45 @@ var CommandsProcessor = class extends FeatureProcessor {
1716
1751
  join12(this.baseDir, relativeDirPath, `*.${extension}`)
1717
1752
  );
1718
1753
  const toolCommands = (await Promise.allSettled(
1719
- commandFilePaths.map((path2) => {
1754
+ commandFilePaths.map((path3) => {
1720
1755
  switch (toolTarget) {
1721
1756
  case "agentsmd":
1722
1757
  return AgentsmdCommand.fromFile({
1723
1758
  baseDir: this.baseDir,
1724
- relativeFilePath: basename11(path2)
1759
+ relativeFilePath: basename11(path3)
1725
1760
  });
1726
1761
  case "claudecode":
1727
1762
  return ClaudecodeCommand.fromFile({
1728
1763
  baseDir: this.baseDir,
1729
- relativeFilePath: basename11(path2),
1764
+ relativeFilePath: basename11(path3),
1730
1765
  global: this.global
1731
1766
  });
1732
1767
  case "geminicli":
1733
1768
  return GeminiCliCommand.fromFile({
1734
1769
  baseDir: this.baseDir,
1735
- relativeFilePath: basename11(path2),
1770
+ relativeFilePath: basename11(path3),
1736
1771
  global: this.global
1737
1772
  });
1738
1773
  case "roo":
1739
1774
  return RooCommand.fromFile({
1740
1775
  baseDir: this.baseDir,
1741
- relativeFilePath: basename11(path2)
1776
+ relativeFilePath: basename11(path3)
1742
1777
  });
1743
1778
  case "copilot":
1744
1779
  return CopilotCommand.fromFile({
1745
1780
  baseDir: this.baseDir,
1746
- relativeFilePath: basename11(path2)
1781
+ relativeFilePath: basename11(path3)
1747
1782
  });
1748
1783
  case "cursor":
1749
1784
  return CursorCommand.fromFile({
1750
1785
  baseDir: this.baseDir,
1751
- relativeFilePath: basename11(path2),
1786
+ relativeFilePath: basename11(path3),
1752
1787
  global: this.global
1753
1788
  });
1754
1789
  case "codexcli":
1755
1790
  return CodexcliCommand.fromFile({
1756
1791
  baseDir: this.baseDir,
1757
- relativeFilePath: basename11(path2),
1792
+ relativeFilePath: basename11(path3),
1758
1793
  global: this.global
1759
1794
  });
1760
1795
  default:
@@ -1844,8 +1879,12 @@ var CommandsProcessor = class extends FeatureProcessor {
1844
1879
  * Return the tool targets that this processor supports
1845
1880
  */
1846
1881
  static getToolTargets({
1882
+ global = false,
1847
1883
  includeSimulated = false
1848
1884
  } = {}) {
1885
+ if (global) {
1886
+ return commandsProcessorToolTargetsGlobal;
1887
+ }
1849
1888
  if (!includeSimulated) {
1850
1889
  return commandsProcessorToolTargets.filter(
1851
1890
  (target) => !commandsProcessorToolTargetsSimulated.includes(target)
@@ -1856,9 +1895,6 @@ var CommandsProcessor = class extends FeatureProcessor {
1856
1895
  static getToolTargetsSimulated() {
1857
1896
  return commandsProcessorToolTargetsSimulated;
1858
1897
  }
1859
- static getToolTargetsGlobal() {
1860
- return commandsProcessorToolTargetsGlobal;
1861
- }
1862
1898
  };
1863
1899
 
1864
1900
  // src/features/ignore/ignore-processor.ts
@@ -2282,7 +2318,7 @@ var JunieIgnore = class _JunieIgnore extends ToolIgnore {
2282
2318
  static getSettablePaths() {
2283
2319
  return {
2284
2320
  relativeDirPath: ".",
2285
- relativeFilePath: ".junieignore"
2321
+ relativeFilePath: ".aiignore"
2286
2322
  };
2287
2323
  }
2288
2324
  toRulesyncIgnore() {
@@ -2546,9 +2582,14 @@ var IgnoreProcessor = class extends FeatureProcessor {
2546
2582
  * Implementation of abstract method from FeatureProcessor
2547
2583
  * Load tool-specific ignore configurations and parse them into ToolIgnore instances
2548
2584
  */
2549
- async loadToolFiles() {
2585
+ async loadToolFiles({
2586
+ forDeletion = false
2587
+ } = {}) {
2550
2588
  try {
2551
2589
  const toolIgnores = await this.loadToolIgnores();
2590
+ if (forDeletion) {
2591
+ return toolIgnores.filter((toolFile) => !(toolFile instanceof ClaudecodeIgnore));
2592
+ }
2552
2593
  return toolIgnores;
2553
2594
  } catch (error) {
2554
2595
  const errorMessage = `Failed to load tool files: ${formatError(error)}`;
@@ -2588,11 +2629,6 @@ var IgnoreProcessor = class extends FeatureProcessor {
2588
2629
  throw new Error(`Unsupported tool target: ${this.toolTarget}`);
2589
2630
  }
2590
2631
  }
2591
- async loadToolFilesToDelete() {
2592
- return (await this.loadToolFiles()).filter(
2593
- (toolFile) => !(toolFile instanceof ClaudecodeIgnore)
2594
- );
2595
- }
2596
2632
  /**
2597
2633
  * Implementation of abstract method from FeatureProcessor
2598
2634
  * Convert RulesyncFile[] to ToolFile[]
@@ -2684,13 +2720,16 @@ var IgnoreProcessor = class extends FeatureProcessor {
2684
2720
  * Implementation of abstract method from FeatureProcessor
2685
2721
  * Return the tool targets that this processor supports
2686
2722
  */
2687
- static getToolTargets() {
2723
+ static getToolTargets({ global = false } = {}) {
2724
+ if (global) {
2725
+ throw new Error("IgnoreProcessor does not support global mode");
2726
+ }
2688
2727
  return ignoreProcessorToolTargets;
2689
2728
  }
2690
2729
  };
2691
2730
 
2692
2731
  // src/features/mcp/mcp-processor.ts
2693
- import { z as z15 } from "zod/mini";
2732
+ import { z as z16 } from "zod/mini";
2694
2733
 
2695
2734
  // src/features/mcp/amazonqcli-mcp.ts
2696
2735
  import { join as join26 } from "path";
@@ -2819,21 +2858,23 @@ var RulesyncMcp = class _RulesyncMcp extends RulesyncFile {
2819
2858
  modularMcp
2820
2859
  });
2821
2860
  }
2822
- getExposedMcpServers() {
2823
- return Object.fromEntries(
2824
- Object.entries(this.json.mcpServers).filter(([, serverConfig]) => !this.modularMcp || serverConfig.exposed).map(([serverName, serverConfig]) => [
2825
- serverName,
2826
- omit(serverConfig, ["targets", "description", "exposed"])
2827
- ])
2828
- );
2829
- }
2830
- getModularizedMcpServers() {
2861
+ getMcpServers({ type = "all" } = {}) {
2862
+ const entries = Object.entries(this.json.mcpServers);
2863
+ const filteredEntries = entries.filter(([, serverConfig]) => {
2864
+ switch (type) {
2865
+ case "all":
2866
+ return true;
2867
+ case "exposed":
2868
+ return !this.modularMcp || serverConfig.exposed;
2869
+ case "modularized":
2870
+ return this.modularMcp && !serverConfig.exposed;
2871
+ }
2872
+ });
2831
2873
  return Object.fromEntries(
2832
- Object.entries(this.json.mcpServers).filter(([, serverConfig]) => this.modularMcp && !serverConfig.exposed).map(([serverName, serverConfig]) => [
2833
- serverName,
2834
- // description is required for modular-mcp servers
2835
- omit(serverConfig, ["targets", "exposed"])
2836
- ])
2874
+ filteredEntries.map(([serverName, serverConfig]) => {
2875
+ const fieldsToOmit = type === "modularized" ? ["targets", "exposed"] : ["targets", "description", "exposed"];
2876
+ return [serverName, omit(serverConfig, fieldsToOmit)];
2877
+ })
2837
2878
  );
2838
2879
  }
2839
2880
  getJson() {
@@ -3020,7 +3061,7 @@ var ModularMcp = class _ModularMcp extends AiFile {
3020
3061
  global && relativeDirPath ? { global: true, relativeDirPath } : { global: false, relativeDirPath: void 0 }
3021
3062
  );
3022
3063
  const modularMcpJson = {
3023
- mcpServers: rulesyncMcp.getModularizedMcpServers()
3064
+ mcpServers: rulesyncMcp.getMcpServers({ type: "modularized" })
3024
3065
  };
3025
3066
  return new _ModularMcp({
3026
3067
  baseDir,
@@ -3103,9 +3144,9 @@ var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
3103
3144
  relativeDirPath: this.getSettablePaths({ global: true }).relativeDirPath
3104
3145
  }) : ModularMcp.getMcpServers({ baseDir, global: false }),
3105
3146
  // Merge exposed servers
3106
- ...rulesyncMcp.getExposedMcpServers()
3147
+ ...rulesyncMcp.getMcpServers({ type: "exposed" })
3107
3148
  }
3108
- } : { ...json, mcpServers: rulesyncMcp.getExposedMcpServers() };
3149
+ } : { ...json, mcpServers: rulesyncMcp.getMcpServers({ type: "exposed" }) };
3109
3150
  return new _ClaudecodeMcp({
3110
3151
  baseDir,
3111
3152
  relativeDirPath: paths.relativeDirPath,
@@ -3474,8 +3515,235 @@ var GeminiCliMcp = class _GeminiCliMcp extends ToolMcp {
3474
3515
  }
3475
3516
  };
3476
3517
 
3477
- // src/features/mcp/roo-mcp.ts
3518
+ // src/features/mcp/junie-mcp.ts
3478
3519
  import { join as join34 } from "path";
3520
+ var JunieMcp = class _JunieMcp extends ToolMcp {
3521
+ json;
3522
+ constructor(params) {
3523
+ super(params);
3524
+ this.json = this.fileContent !== void 0 ? JSON.parse(this.fileContent) : {};
3525
+ }
3526
+ getJson() {
3527
+ return this.json;
3528
+ }
3529
+ static getSettablePaths() {
3530
+ return {
3531
+ relativeDirPath: join34(".junie", "mcp"),
3532
+ relativeFilePath: "mcp.json"
3533
+ };
3534
+ }
3535
+ static async fromFile({
3536
+ baseDir = process.cwd(),
3537
+ validate = true
3538
+ }) {
3539
+ const fileContent = await readFileContent(
3540
+ join34(
3541
+ baseDir,
3542
+ this.getSettablePaths().relativeDirPath,
3543
+ this.getSettablePaths().relativeFilePath
3544
+ )
3545
+ );
3546
+ return new _JunieMcp({
3547
+ baseDir,
3548
+ relativeDirPath: this.getSettablePaths().relativeDirPath,
3549
+ relativeFilePath: this.getSettablePaths().relativeFilePath,
3550
+ fileContent,
3551
+ validate
3552
+ });
3553
+ }
3554
+ static fromRulesyncMcp({
3555
+ baseDir = process.cwd(),
3556
+ rulesyncMcp,
3557
+ validate = true
3558
+ }) {
3559
+ return new _JunieMcp({
3560
+ baseDir,
3561
+ relativeDirPath: this.getSettablePaths().relativeDirPath,
3562
+ relativeFilePath: this.getSettablePaths().relativeFilePath,
3563
+ fileContent: rulesyncMcp.getFileContent(),
3564
+ validate
3565
+ });
3566
+ }
3567
+ toRulesyncMcp() {
3568
+ return this.toRulesyncMcpDefault();
3569
+ }
3570
+ validate() {
3571
+ return { success: true, error: null };
3572
+ }
3573
+ };
3574
+
3575
+ // src/features/mcp/opencode-mcp.ts
3576
+ import { join as join35 } from "path";
3577
+ import { z as z15 } from "zod/mini";
3578
+ var OpencodeMcpLocalServerSchema = z15.object({
3579
+ type: z15.literal("local"),
3580
+ command: z15.array(z15.string()),
3581
+ environment: z15.optional(z15.record(z15.string(), z15.string())),
3582
+ enabled: z15._default(z15.boolean(), true),
3583
+ cwd: z15.optional(z15.string())
3584
+ });
3585
+ var OpencodeMcpRemoteServerSchema = z15.object({
3586
+ type: z15.literal("remote"),
3587
+ url: z15.string(),
3588
+ headers: z15.optional(z15.record(z15.string(), z15.string())),
3589
+ enabled: z15._default(z15.boolean(), true)
3590
+ });
3591
+ var OpencodeMcpServerSchema = z15.union([
3592
+ OpencodeMcpLocalServerSchema,
3593
+ OpencodeMcpRemoteServerSchema
3594
+ ]);
3595
+ var OpencodeConfigSchema = z15.looseObject({
3596
+ $schema: z15.optional(z15.string()),
3597
+ mcp: z15.optional(z15.record(z15.string(), OpencodeMcpServerSchema))
3598
+ });
3599
+ function convertFromOpencodeFormat(opencodeMcp) {
3600
+ return Object.fromEntries(
3601
+ Object.entries(opencodeMcp).map(([serverName, serverConfig]) => {
3602
+ if (serverConfig.type === "remote") {
3603
+ return [
3604
+ serverName,
3605
+ {
3606
+ type: "sse",
3607
+ url: serverConfig.url,
3608
+ ...serverConfig.enabled === false && { disabled: true },
3609
+ ...serverConfig.headers && { headers: serverConfig.headers }
3610
+ }
3611
+ ];
3612
+ }
3613
+ const [command, ...args] = serverConfig.command;
3614
+ if (!command) {
3615
+ throw new Error(`Server "${serverName}" has an empty command array`);
3616
+ }
3617
+ return [
3618
+ serverName,
3619
+ {
3620
+ type: "stdio",
3621
+ command,
3622
+ ...args.length > 0 && { args },
3623
+ ...serverConfig.enabled === false && { disabled: true },
3624
+ ...serverConfig.environment && { env: serverConfig.environment },
3625
+ ...serverConfig.cwd && { cwd: serverConfig.cwd }
3626
+ }
3627
+ ];
3628
+ })
3629
+ );
3630
+ }
3631
+ function convertToOpencodeFormat(mcpServers) {
3632
+ return Object.fromEntries(
3633
+ Object.entries(mcpServers).map(([serverName, serverConfig]) => {
3634
+ const isRemote = serverConfig.type === "sse" || serverConfig.type === "http" || serverConfig.url;
3635
+ if (isRemote) {
3636
+ const remoteServer = {
3637
+ type: "remote",
3638
+ url: serverConfig.url ?? serverConfig.httpUrl ?? "",
3639
+ enabled: serverConfig.disabled !== void 0 ? !serverConfig.disabled : true,
3640
+ ...serverConfig.headers && { headers: serverConfig.headers }
3641
+ };
3642
+ return [serverName, remoteServer];
3643
+ }
3644
+ const commandArray = [];
3645
+ if (serverConfig.command) {
3646
+ if (Array.isArray(serverConfig.command)) {
3647
+ commandArray.push(...serverConfig.command);
3648
+ } else {
3649
+ commandArray.push(serverConfig.command);
3650
+ }
3651
+ }
3652
+ if (serverConfig.args) {
3653
+ commandArray.push(...serverConfig.args);
3654
+ }
3655
+ const localServer = {
3656
+ type: "local",
3657
+ command: commandArray,
3658
+ enabled: serverConfig.disabled !== void 0 ? !serverConfig.disabled : true,
3659
+ ...serverConfig.env && { environment: serverConfig.env },
3660
+ ...serverConfig.cwd && { cwd: serverConfig.cwd }
3661
+ };
3662
+ return [serverName, localServer];
3663
+ })
3664
+ );
3665
+ }
3666
+ var OpencodeMcp = class _OpencodeMcp extends ToolMcp {
3667
+ json;
3668
+ constructor(params) {
3669
+ super(params);
3670
+ this.json = OpencodeConfigSchema.parse(JSON.parse(this.fileContent || "{}"));
3671
+ }
3672
+ getJson() {
3673
+ return this.json;
3674
+ }
3675
+ static getSettablePaths({ global } = {}) {
3676
+ if (global) {
3677
+ return {
3678
+ relativeDirPath: ".",
3679
+ relativeFilePath: "opencode.json"
3680
+ };
3681
+ }
3682
+ return {
3683
+ relativeDirPath: ".",
3684
+ relativeFilePath: "opencode.json"
3685
+ };
3686
+ }
3687
+ static async fromFile({
3688
+ baseDir = process.cwd(),
3689
+ validate = true,
3690
+ global = false
3691
+ }) {
3692
+ const paths = this.getSettablePaths({ global });
3693
+ const fileContent = await readOrInitializeFileContent(
3694
+ join35(baseDir, paths.relativeDirPath, paths.relativeFilePath),
3695
+ JSON.stringify({ mcp: {} }, null, 2)
3696
+ );
3697
+ const json = JSON.parse(fileContent);
3698
+ const newJson = { ...json, mcp: json.mcp ?? {} };
3699
+ return new _OpencodeMcp({
3700
+ baseDir,
3701
+ relativeDirPath: paths.relativeDirPath,
3702
+ relativeFilePath: paths.relativeFilePath,
3703
+ fileContent: JSON.stringify(newJson, null, 2),
3704
+ validate
3705
+ });
3706
+ }
3707
+ static async fromRulesyncMcp({
3708
+ baseDir = process.cwd(),
3709
+ rulesyncMcp,
3710
+ validate = true,
3711
+ global = false
3712
+ }) {
3713
+ const paths = this.getSettablePaths({ global });
3714
+ const fileContent = await readOrInitializeFileContent(
3715
+ join35(baseDir, paths.relativeDirPath, paths.relativeFilePath),
3716
+ JSON.stringify({ mcp: {} }, null, 2)
3717
+ );
3718
+ const json = JSON.parse(fileContent);
3719
+ const convertedMcp = convertToOpencodeFormat(rulesyncMcp.getMcpServers());
3720
+ const newJson = { ...json, mcp: convertedMcp };
3721
+ return new _OpencodeMcp({
3722
+ baseDir,
3723
+ relativeDirPath: paths.relativeDirPath,
3724
+ relativeFilePath: paths.relativeFilePath,
3725
+ fileContent: JSON.stringify(newJson, null, 2),
3726
+ validate
3727
+ });
3728
+ }
3729
+ toRulesyncMcp() {
3730
+ const convertedMcpServers = convertFromOpencodeFormat(this.json.mcp ?? {});
3731
+ return this.toRulesyncMcpDefault({
3732
+ fileContent: JSON.stringify({ mcpServers: convertedMcpServers }, null, 2)
3733
+ });
3734
+ }
3735
+ validate() {
3736
+ const json = JSON.parse(this.fileContent || "{}");
3737
+ const result = OpencodeConfigSchema.safeParse(json);
3738
+ if (!result.success) {
3739
+ return { success: false, error: result.error };
3740
+ }
3741
+ return { success: true, error: null };
3742
+ }
3743
+ };
3744
+
3745
+ // src/features/mcp/roo-mcp.ts
3746
+ import { join as join36 } from "path";
3479
3747
  var RooMcp = class _RooMcp extends ToolMcp {
3480
3748
  json;
3481
3749
  constructor(params) {
@@ -3496,7 +3764,7 @@ var RooMcp = class _RooMcp extends ToolMcp {
3496
3764
  validate = true
3497
3765
  }) {
3498
3766
  const fileContent = await readFileContent(
3499
- join34(
3767
+ join36(
3500
3768
  baseDir,
3501
3769
  this.getSettablePaths().relativeDirPath,
3502
3770
  this.getSettablePaths().relativeFilePath
@@ -3537,16 +3805,23 @@ var mcpProcessorToolTargets = [
3537
3805
  "amazonqcli",
3538
3806
  "claudecode",
3539
3807
  "cline",
3808
+ "junie",
3540
3809
  "copilot",
3541
3810
  "cursor",
3542
3811
  "geminicli",
3812
+ "opencode",
3543
3813
  "roo"
3544
3814
  ];
3545
- var McpProcessorToolTargetSchema = z15.enum(
3815
+ var McpProcessorToolTargetSchema = z16.enum(
3546
3816
  // codexcli is not in the list of tool targets but we add it here because it is a valid tool target for global mode generation
3547
3817
  mcpProcessorToolTargets.concat("codexcli")
3548
3818
  );
3549
- var mcpProcessorToolTargetsGlobal = ["claudecode", "codexcli", "geminicli"];
3819
+ var mcpProcessorToolTargetsGlobal = [
3820
+ "claudecode",
3821
+ "codexcli",
3822
+ "geminicli",
3823
+ "opencode"
3824
+ ];
3550
3825
  var mcpProcessorToolTargetsModular = ["claudecode"];
3551
3826
  var McpProcessor = class extends FeatureProcessor {
3552
3827
  toolTarget;
@@ -3581,19 +3856,13 @@ var McpProcessor = class extends FeatureProcessor {
3581
3856
  return [];
3582
3857
  }
3583
3858
  }
3584
- async loadToolFilesToDelete() {
3585
- if (this.global) {
3586
- return (await this.loadToolFiles()).filter(
3587
- (toolFile) => !(toolFile instanceof ClaudecodeMcp)
3588
- );
3589
- }
3590
- return this.loadToolFiles();
3591
- }
3592
3859
  /**
3593
3860
  * Implementation of abstract method from FeatureProcessor
3594
3861
  * Load tool-specific MCP configurations and parse them into ToolMcp instances
3595
3862
  */
3596
- async loadToolFiles() {
3863
+ async loadToolFiles({
3864
+ forDeletion = false
3865
+ } = {}) {
3597
3866
  try {
3598
3867
  const toolMcps = await (async () => {
3599
3868
  switch (this.toolTarget) {
@@ -3622,6 +3891,14 @@ var McpProcessor = class extends FeatureProcessor {
3622
3891
  })
3623
3892
  ];
3624
3893
  }
3894
+ case "junie": {
3895
+ return [
3896
+ await JunieMcp.fromFile({
3897
+ baseDir: this.baseDir,
3898
+ validate: true
3899
+ })
3900
+ ];
3901
+ }
3625
3902
  case "codexcli": {
3626
3903
  return [
3627
3904
  await CodexcliMcp.fromFile({
@@ -3656,6 +3933,15 @@ var McpProcessor = class extends FeatureProcessor {
3656
3933
  })
3657
3934
  ];
3658
3935
  }
3936
+ case "opencode": {
3937
+ return [
3938
+ await OpencodeMcp.fromFile({
3939
+ baseDir: this.baseDir,
3940
+ validate: true,
3941
+ global: this.global
3942
+ })
3943
+ ];
3944
+ }
3659
3945
  case "roo": {
3660
3946
  return [
3661
3947
  await RooMcp.fromFile({
@@ -3669,6 +3955,13 @@ var McpProcessor = class extends FeatureProcessor {
3669
3955
  }
3670
3956
  })();
3671
3957
  logger.info(`Successfully loaded ${toolMcps.length} ${this.toolTarget} MCP files`);
3958
+ if (forDeletion) {
3959
+ let filteredMcps = toolMcps.filter((toolFile) => !(toolFile instanceof OpencodeMcp));
3960
+ if (this.global) {
3961
+ filteredMcps = filteredMcps.filter((toolFile) => !(toolFile instanceof ClaudecodeMcp));
3962
+ }
3963
+ return filteredMcps;
3964
+ }
3672
3965
  return toolMcps;
3673
3966
  } catch (error) {
3674
3967
  const errorMessage = `Failed to load MCP files for tool target: ${this.toolTarget}: ${formatError(error)}`;
@@ -3677,119 +3970,1159 @@ var McpProcessor = class extends FeatureProcessor {
3677
3970
  } else {
3678
3971
  logger.error(errorMessage);
3679
3972
  }
3680
- return [];
3973
+ return [];
3974
+ }
3975
+ }
3976
+ /**
3977
+ * Implementation of abstract method from FeatureProcessor
3978
+ * Convert RulesyncFile[] to ToolFile[]
3979
+ */
3980
+ async convertRulesyncFilesToToolFiles(rulesyncFiles) {
3981
+ const rulesyncMcp = rulesyncFiles.find(
3982
+ (file) => file instanceof RulesyncMcp
3983
+ );
3984
+ if (!rulesyncMcp) {
3985
+ throw new Error(`No ${RULESYNC_MCP_RELATIVE_FILE_PATH} found.`);
3986
+ }
3987
+ const toolMcps = await Promise.all(
3988
+ [rulesyncMcp].map(async (rulesyncMcp2) => {
3989
+ switch (this.toolTarget) {
3990
+ case "amazonqcli":
3991
+ return AmazonqcliMcp.fromRulesyncMcp({
3992
+ baseDir: this.baseDir,
3993
+ rulesyncMcp: rulesyncMcp2
3994
+ });
3995
+ case "claudecode":
3996
+ return await ClaudecodeMcp.fromRulesyncMcp({
3997
+ baseDir: this.baseDir,
3998
+ rulesyncMcp: rulesyncMcp2,
3999
+ global: this.global,
4000
+ modularMcp: this.modularMcp
4001
+ });
4002
+ case "cline":
4003
+ return ClineMcp.fromRulesyncMcp({
4004
+ baseDir: this.baseDir,
4005
+ rulesyncMcp: rulesyncMcp2
4006
+ });
4007
+ case "junie":
4008
+ return JunieMcp.fromRulesyncMcp({
4009
+ baseDir: this.baseDir,
4010
+ rulesyncMcp: rulesyncMcp2
4011
+ });
4012
+ case "copilot":
4013
+ return CopilotMcp.fromRulesyncMcp({
4014
+ baseDir: this.baseDir,
4015
+ rulesyncMcp: rulesyncMcp2
4016
+ });
4017
+ case "cursor":
4018
+ return CursorMcp.fromRulesyncMcp({
4019
+ baseDir: this.baseDir,
4020
+ rulesyncMcp: rulesyncMcp2
4021
+ });
4022
+ case "codexcli":
4023
+ return await CodexcliMcp.fromRulesyncMcp({
4024
+ baseDir: this.baseDir,
4025
+ rulesyncMcp: rulesyncMcp2,
4026
+ global: this.global
4027
+ });
4028
+ case "geminicli":
4029
+ return GeminiCliMcp.fromRulesyncMcp({
4030
+ baseDir: this.baseDir,
4031
+ rulesyncMcp: rulesyncMcp2,
4032
+ global: this.global
4033
+ });
4034
+ case "opencode":
4035
+ return OpencodeMcp.fromRulesyncMcp({
4036
+ baseDir: this.baseDir,
4037
+ rulesyncMcp: rulesyncMcp2,
4038
+ global: this.global
4039
+ });
4040
+ case "roo":
4041
+ return RooMcp.fromRulesyncMcp({
4042
+ baseDir: this.baseDir,
4043
+ rulesyncMcp: rulesyncMcp2
4044
+ });
4045
+ default:
4046
+ throw new Error(`Unsupported tool target: ${this.toolTarget}`);
4047
+ }
4048
+ })
4049
+ );
4050
+ const toolFiles = toolMcps;
4051
+ if (this.modularMcp && mcpProcessorToolTargetsModular.includes(this.toolTarget)) {
4052
+ const relativeDirPath = this.toolTarget === "claudecode" ? ClaudecodeMcp.getSettablePaths({ global: this.global }).relativeDirPath : void 0;
4053
+ toolFiles.push(
4054
+ ModularMcp.fromRulesyncMcp({
4055
+ baseDir: this.baseDir,
4056
+ rulesyncMcp,
4057
+ ...this.global && relativeDirPath ? { global: true, relativeDirPath } : { global: false }
4058
+ })
4059
+ );
4060
+ }
4061
+ return toolFiles;
4062
+ }
4063
+ /**
4064
+ * Implementation of abstract method from FeatureProcessor
4065
+ * Convert ToolFile[] to RulesyncFile[]
4066
+ */
4067
+ async convertToolFilesToRulesyncFiles(toolFiles) {
4068
+ const toolMcps = toolFiles.filter((file) => file instanceof ToolMcp);
4069
+ const rulesyncMcps = toolMcps.map((toolMcp) => {
4070
+ return toolMcp.toRulesyncMcp();
4071
+ });
4072
+ return rulesyncMcps;
4073
+ }
4074
+ /**
4075
+ * Implementation of abstract method from FeatureProcessor
4076
+ * Return the tool targets that this processor supports
4077
+ */
4078
+ static getToolTargets({ global = false } = {}) {
4079
+ if (global) {
4080
+ return mcpProcessorToolTargetsGlobal;
4081
+ }
4082
+ return mcpProcessorToolTargets;
4083
+ }
4084
+ };
4085
+
4086
+ // src/features/rules/rules-processor.ts
4087
+ import { basename as basename19, join as join77 } from "path";
4088
+ import { XMLBuilder } from "fast-xml-parser";
4089
+ import { z as z29 } from "zod/mini";
4090
+
4091
+ // src/features/skills/codexcli-skill.ts
4092
+ import { join as join39 } from "path";
4093
+
4094
+ // src/features/skills/simulated-skill.ts
4095
+ import { join as join38 } from "path";
4096
+ import { z as z17 } from "zod/mini";
4097
+
4098
+ // src/constants/general.ts
4099
+ var SKILL_FILE_NAME = "SKILL.md";
4100
+
4101
+ // src/types/ai-dir.ts
4102
+ import path2, { basename as basename12, join as join37, relative as relative3, resolve as resolve4 } from "path";
4103
+ var AiDir = class {
4104
+ /**
4105
+ * @example "."
4106
+ */
4107
+ baseDir;
4108
+ /**
4109
+ * @example ".rulesync/skills"
4110
+ */
4111
+ relativeDirPath;
4112
+ /**
4113
+ * @example "my-skill"
4114
+ */
4115
+ dirName;
4116
+ /**
4117
+ * Optional main file with frontmatter support
4118
+ */
4119
+ mainFile;
4120
+ /**
4121
+ * Additional files in the directory
4122
+ */
4123
+ otherFiles;
4124
+ /**
4125
+ * @example false
4126
+ */
4127
+ global;
4128
+ constructor({
4129
+ baseDir = process.cwd(),
4130
+ relativeDirPath,
4131
+ dirName,
4132
+ mainFile,
4133
+ otherFiles = [],
4134
+ global = false
4135
+ }) {
4136
+ if (dirName.includes(path2.sep) || dirName.includes("/") || dirName.includes("\\")) {
4137
+ throw new Error(`Directory name cannot contain path separators: dirName="${dirName}"`);
4138
+ }
4139
+ this.baseDir = baseDir;
4140
+ this.relativeDirPath = relativeDirPath;
4141
+ this.dirName = dirName;
4142
+ this.mainFile = mainFile;
4143
+ this.otherFiles = otherFiles;
4144
+ this.global = global;
4145
+ }
4146
+ static async fromDir(_params) {
4147
+ throw new Error("Please implement this method in the subclass.");
4148
+ }
4149
+ getBaseDir() {
4150
+ return this.baseDir;
4151
+ }
4152
+ getRelativeDirPath() {
4153
+ return this.relativeDirPath;
4154
+ }
4155
+ getDirName() {
4156
+ return this.dirName;
4157
+ }
4158
+ getDirPath() {
4159
+ const fullPath = path2.join(this.baseDir, this.relativeDirPath, this.dirName);
4160
+ const resolvedFull = resolve4(fullPath);
4161
+ const resolvedBase = resolve4(this.baseDir);
4162
+ const rel = relative3(resolvedBase, resolvedFull);
4163
+ if (rel.startsWith("..") || path2.isAbsolute(rel)) {
4164
+ throw new Error(
4165
+ `Path traversal detected: Final path escapes baseDir. baseDir="${this.baseDir}", relativeDirPath="${this.relativeDirPath}", dirName="${this.dirName}"`
4166
+ );
4167
+ }
4168
+ return fullPath;
4169
+ }
4170
+ getMainFile() {
4171
+ return this.mainFile;
4172
+ }
4173
+ getOtherFiles() {
4174
+ return this.otherFiles;
4175
+ }
4176
+ getRelativePathFromCwd() {
4177
+ return path2.join(this.relativeDirPath, this.dirName);
4178
+ }
4179
+ getGlobal() {
4180
+ return this.global;
4181
+ }
4182
+ setMainFile(name, body, frontmatter) {
4183
+ this.mainFile = { name, body, frontmatter };
4184
+ }
4185
+ /**
4186
+ * Recursively collects all files from a directory, excluding the specified main file.
4187
+ * This is a common utility for loading additional files alongside the main file.
4188
+ *
4189
+ * @param baseDir - The base directory path
4190
+ * @param relativeDirPath - The relative path to the directory containing the skill
4191
+ * @param dirName - The name of the directory
4192
+ * @param excludeFileName - The name of the file to exclude (typically the main file)
4193
+ * @returns Array of files with their relative paths and buffers
4194
+ */
4195
+ static async collectOtherFiles(baseDir, relativeDirPath, dirName, excludeFileName) {
4196
+ const dirPath = join37(baseDir, relativeDirPath, dirName);
4197
+ const glob = join37(dirPath, "**", "*");
4198
+ const filePaths = await findFilesByGlobs(glob, { type: "file" });
4199
+ const filteredPaths = filePaths.filter((filePath) => basename12(filePath) !== excludeFileName);
4200
+ const files = await Promise.all(
4201
+ filteredPaths.map(async (filePath) => {
4202
+ const fileBuffer = await readFileBuffer(filePath);
4203
+ return {
4204
+ relativeFilePathToDirPath: relative3(dirPath, filePath),
4205
+ fileBuffer
4206
+ };
4207
+ })
4208
+ );
4209
+ return files;
4210
+ }
4211
+ };
4212
+
4213
+ // src/features/skills/tool-skill.ts
4214
+ var ToolSkill = class extends AiDir {
4215
+ /**
4216
+ * Get the settable paths for this tool's skill directories.
4217
+ *
4218
+ * @param options - Optional configuration including global mode
4219
+ * @returns Object containing the relative directory path
4220
+ */
4221
+ static getSettablePaths(_options) {
4222
+ throw new Error("Please implement this method in the subclass.");
4223
+ }
4224
+ /**
4225
+ * Load a skill from a tool-specific directory.
4226
+ *
4227
+ * This method should:
4228
+ * 1. Read the SKILL.md file content
4229
+ * 2. Parse tool-specific frontmatter format
4230
+ * 3. Validate the parsed data
4231
+ * 4. Collect other skill files in the directory
4232
+ * 5. Return a concrete ToolSkill instance
4233
+ *
4234
+ * @param params - Parameters including the skill directory name
4235
+ * @returns Promise resolving to a concrete ToolSkill instance
4236
+ */
4237
+ static async fromDir(_params) {
4238
+ throw new Error("Please implement this method in the subclass.");
4239
+ }
4240
+ /**
4241
+ * Convert a RulesyncSkill to the tool-specific skill format.
4242
+ *
4243
+ * This method should:
4244
+ * 1. Extract relevant data from the RulesyncSkill
4245
+ * 2. Transform frontmatter to tool-specific format
4246
+ * 3. Transform body content if needed
4247
+ * 4. Preserve other skill files
4248
+ * 5. Return a concrete ToolSkill instance
4249
+ *
4250
+ * @param params - Parameters including the RulesyncSkill to convert
4251
+ * @returns A concrete ToolSkill instance
4252
+ */
4253
+ static fromRulesyncSkill(_params) {
4254
+ throw new Error("Please implement this method in the subclass.");
4255
+ }
4256
+ /**
4257
+ * Check if this tool is targeted by a RulesyncSkill.
4258
+ * Since skills don't have targets field like commands/subagents,
4259
+ * the default behavior may vary by tool.
4260
+ *
4261
+ * @param rulesyncSkill - The RulesyncSkill to check
4262
+ * @returns True if this tool should use the skill
4263
+ */
4264
+ static isTargetedByRulesyncSkill(_rulesyncSkill) {
4265
+ throw new Error("Please implement this method in the subclass.");
4266
+ }
4267
+ };
4268
+
4269
+ // src/features/skills/simulated-skill.ts
4270
+ var SimulatedSkillFrontmatterSchema = z17.object({
4271
+ name: z17.string(),
4272
+ description: z17.string()
4273
+ });
4274
+ var SimulatedSkill = class extends ToolSkill {
4275
+ frontmatter;
4276
+ body;
4277
+ constructor({
4278
+ baseDir = process.cwd(),
4279
+ relativeDirPath,
4280
+ dirName,
4281
+ frontmatter,
4282
+ body,
4283
+ otherFiles = [],
4284
+ validate = true
4285
+ }) {
4286
+ super({
4287
+ baseDir,
4288
+ relativeDirPath,
4289
+ dirName,
4290
+ mainFile: {
4291
+ name: SKILL_FILE_NAME,
4292
+ body,
4293
+ frontmatter: { ...frontmatter }
4294
+ },
4295
+ otherFiles,
4296
+ global: false
4297
+ // Simulated skills are project mode only
4298
+ });
4299
+ if (validate) {
4300
+ const result = SimulatedSkillFrontmatterSchema.safeParse(frontmatter);
4301
+ if (!result.success) {
4302
+ throw new Error(
4303
+ `Invalid frontmatter in ${join38(relativeDirPath, dirName)}: ${formatError(result.error)}`
4304
+ );
4305
+ }
4306
+ }
4307
+ this.frontmatter = frontmatter;
4308
+ this.body = body;
4309
+ }
4310
+ getBody() {
4311
+ return this.body;
4312
+ }
4313
+ getFrontmatter() {
4314
+ return this.frontmatter;
4315
+ }
4316
+ toRulesyncSkill() {
4317
+ throw new Error("Not implemented because it is a SIMULATED skill.");
4318
+ }
4319
+ validate() {
4320
+ if (!this.frontmatter) {
4321
+ return { success: true, error: null };
4322
+ }
4323
+ const result = SimulatedSkillFrontmatterSchema.safeParse(this.frontmatter);
4324
+ if (result.success) {
4325
+ return { success: true, error: null };
4326
+ } else {
4327
+ return {
4328
+ success: false,
4329
+ error: new Error(
4330
+ `Invalid frontmatter in ${this.getDirPath()}: ${formatError(result.error)}`
4331
+ )
4332
+ };
4333
+ }
4334
+ }
4335
+ static fromRulesyncSkillDefault({
4336
+ rulesyncSkill,
4337
+ validate = true
4338
+ }) {
4339
+ const rulesyncFrontmatter = rulesyncSkill.getFrontmatter();
4340
+ const simulatedFrontmatter = {
4341
+ name: rulesyncFrontmatter.name,
4342
+ description: rulesyncFrontmatter.description
4343
+ };
4344
+ const otherFiles = rulesyncSkill.getOtherFiles();
4345
+ if (otherFiles.length > 0) {
4346
+ logger.warn(
4347
+ `Skill "${rulesyncFrontmatter.name}" has ${otherFiles.length} additional file(s) that will be ignored for simulated skill generation.`
4348
+ );
4349
+ }
4350
+ return {
4351
+ baseDir: rulesyncSkill.getBaseDir(),
4352
+ relativeDirPath: this.getSettablePaths().relativeDirPath,
4353
+ dirName: rulesyncSkill.getDirName(),
4354
+ frontmatter: simulatedFrontmatter,
4355
+ body: rulesyncSkill.getBody(),
4356
+ otherFiles: [],
4357
+ // Simulated skills ignore otherFiles
4358
+ validate
4359
+ };
4360
+ }
4361
+ static async fromDirDefault({
4362
+ baseDir = process.cwd(),
4363
+ relativeDirPath,
4364
+ dirName
4365
+ }) {
4366
+ const settablePaths = this.getSettablePaths();
4367
+ const actualRelativeDirPath = relativeDirPath ?? settablePaths.relativeDirPath;
4368
+ const skillDirPath = join38(baseDir, actualRelativeDirPath, dirName);
4369
+ const skillFilePath = join38(skillDirPath, SKILL_FILE_NAME);
4370
+ if (!await fileExists(skillFilePath)) {
4371
+ throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
4372
+ }
4373
+ const fileContent = await readFileContent(skillFilePath);
4374
+ const { frontmatter, body: content } = parseFrontmatter(fileContent);
4375
+ const result = SimulatedSkillFrontmatterSchema.safeParse(frontmatter);
4376
+ if (!result.success) {
4377
+ throw new Error(`Invalid frontmatter in ${skillFilePath}: ${formatError(result.error)}`);
4378
+ }
4379
+ return {
4380
+ baseDir,
4381
+ relativeDirPath: actualRelativeDirPath,
4382
+ dirName,
4383
+ frontmatter: result.data,
4384
+ body: content.trim(),
4385
+ otherFiles: [],
4386
+ // Simulated skills ignore otherFiles
4387
+ validate: true
4388
+ };
4389
+ }
4390
+ /**
4391
+ * Check if a RulesyncSkill should be converted to this simulated skill type.
4392
+ * Uses the targets field in the RulesyncSkill frontmatter to determine targeting.
4393
+ */
4394
+ static isTargetedByRulesyncSkillDefault({
4395
+ rulesyncSkill,
4396
+ toolTarget
4397
+ }) {
4398
+ const frontmatter = rulesyncSkill.getFrontmatter();
4399
+ const targets = frontmatter.targets;
4400
+ if (targets.includes("*")) {
4401
+ return true;
4402
+ }
4403
+ return targets.includes(toolTarget);
4404
+ }
4405
+ /**
4406
+ * Get the settable paths for this tool's skill directories.
4407
+ * Must be implemented by concrete subclasses.
4408
+ */
4409
+ static getSettablePaths(_options) {
4410
+ throw new Error("Please implement this method in the subclass.");
4411
+ }
4412
+ };
4413
+
4414
+ // src/features/skills/codexcli-skill.ts
4415
+ var CodexCliSkill = class _CodexCliSkill extends SimulatedSkill {
4416
+ static getSettablePaths(options) {
4417
+ if (options?.global) {
4418
+ throw new Error("CodexCliSkill does not support global mode.");
4419
+ }
4420
+ return {
4421
+ relativeDirPath: join39(".codex", "skills")
4422
+ };
4423
+ }
4424
+ static async fromDir(params) {
4425
+ const baseParams = await this.fromDirDefault(params);
4426
+ return new _CodexCliSkill(baseParams);
4427
+ }
4428
+ static fromRulesyncSkill(params) {
4429
+ const baseParams = {
4430
+ ...this.fromRulesyncSkillDefault(params),
4431
+ relativeDirPath: this.getSettablePaths().relativeDirPath
4432
+ };
4433
+ return new _CodexCliSkill(baseParams);
4434
+ }
4435
+ static isTargetedByRulesyncSkill(rulesyncSkill) {
4436
+ return this.isTargetedByRulesyncSkillDefault({
4437
+ rulesyncSkill,
4438
+ toolTarget: "codexcli"
4439
+ });
4440
+ }
4441
+ };
4442
+
4443
+ // src/features/skills/copilot-skill.ts
4444
+ import { join as join40 } from "path";
4445
+ var CopilotSkill = class _CopilotSkill extends SimulatedSkill {
4446
+ static getSettablePaths(options) {
4447
+ if (options?.global) {
4448
+ throw new Error("CopilotSkill does not support global mode.");
4449
+ }
4450
+ return {
4451
+ relativeDirPath: join40(".github", "skills")
4452
+ };
4453
+ }
4454
+ static async fromDir(params) {
4455
+ const baseParams = await this.fromDirDefault(params);
4456
+ return new _CopilotSkill(baseParams);
4457
+ }
4458
+ static fromRulesyncSkill(params) {
4459
+ const baseParams = {
4460
+ ...this.fromRulesyncSkillDefault(params),
4461
+ relativeDirPath: this.getSettablePaths().relativeDirPath
4462
+ };
4463
+ return new _CopilotSkill(baseParams);
4464
+ }
4465
+ static isTargetedByRulesyncSkill(rulesyncSkill) {
4466
+ return this.isTargetedByRulesyncSkillDefault({
4467
+ rulesyncSkill,
4468
+ toolTarget: "copilot"
4469
+ });
4470
+ }
4471
+ };
4472
+
4473
+ // src/features/skills/cursor-skill.ts
4474
+ import { join as join41 } from "path";
4475
+ var CursorSkill = class _CursorSkill extends SimulatedSkill {
4476
+ static getSettablePaths(options) {
4477
+ if (options?.global) {
4478
+ throw new Error("CursorSkill does not support global mode.");
4479
+ }
4480
+ return {
4481
+ relativeDirPath: join41(".cursor", "skills")
4482
+ };
4483
+ }
4484
+ static async fromDir(params) {
4485
+ const baseParams = await this.fromDirDefault(params);
4486
+ return new _CursorSkill(baseParams);
4487
+ }
4488
+ static fromRulesyncSkill(params) {
4489
+ const baseParams = {
4490
+ ...this.fromRulesyncSkillDefault(params),
4491
+ relativeDirPath: this.getSettablePaths().relativeDirPath
4492
+ };
4493
+ return new _CursorSkill(baseParams);
4494
+ }
4495
+ static isTargetedByRulesyncSkill(rulesyncSkill) {
4496
+ return this.isTargetedByRulesyncSkillDefault({
4497
+ rulesyncSkill,
4498
+ toolTarget: "cursor"
4499
+ });
4500
+ }
4501
+ };
4502
+
4503
+ // src/features/skills/skills-processor.ts
4504
+ import { basename as basename13, join as join47 } from "path";
4505
+ import { z as z20 } from "zod/mini";
4506
+
4507
+ // src/types/dir-feature-processor.ts
4508
+ import { join as join42 } from "path";
4509
+ var DirFeatureProcessor = class {
4510
+ baseDir;
4511
+ constructor({ baseDir = process.cwd() }) {
4512
+ this.baseDir = baseDir;
4513
+ }
4514
+ /**
4515
+ * Return tool targets that this feature supports.
4516
+ */
4517
+ static getToolTargets(_params = {}) {
4518
+ throw new Error("Not implemented");
4519
+ }
4520
+ /**
4521
+ * Once converted to rulesync/tool dirs, write them to the filesystem.
4522
+ * Returns the number of directories written.
4523
+ */
4524
+ async writeAiDirs(aiDirs) {
4525
+ for (const aiDir of aiDirs) {
4526
+ const dirPath = aiDir.getDirPath();
4527
+ await ensureDir(dirPath);
4528
+ const mainFile = aiDir.getMainFile();
4529
+ if (mainFile) {
4530
+ const mainFilePath = join42(dirPath, mainFile.name);
4531
+ const contentWithNewline = addTrailingNewline(mainFile.body);
4532
+ await writeFileContent(mainFilePath, contentWithNewline);
4533
+ }
4534
+ const otherFiles = aiDir.getOtherFiles();
4535
+ for (const file of otherFiles) {
4536
+ const filePath = join42(dirPath, file.relativeFilePathToDirPath);
4537
+ const contentWithNewline = addTrailingNewline(file.fileBuffer.toString("utf-8"));
4538
+ await writeFileContent(filePath, contentWithNewline);
4539
+ }
4540
+ }
4541
+ return aiDirs.length;
4542
+ }
4543
+ async removeAiDirs(aiDirs) {
4544
+ for (const aiDir of aiDirs) {
4545
+ await removeDirectory(aiDir.getDirPath());
4546
+ }
4547
+ }
4548
+ };
4549
+
4550
+ // src/features/skills/agentsmd-skill.ts
4551
+ import { join as join43 } from "path";
4552
+ var AgentsmdSkill = class _AgentsmdSkill extends SimulatedSkill {
4553
+ static getSettablePaths(options) {
4554
+ if (options?.global) {
4555
+ throw new Error("AgentsmdSkill does not support global mode.");
4556
+ }
4557
+ return {
4558
+ relativeDirPath: join43(".agents", "skills")
4559
+ };
4560
+ }
4561
+ static async fromDir(params) {
4562
+ const baseParams = await this.fromDirDefault(params);
4563
+ return new _AgentsmdSkill(baseParams);
4564
+ }
4565
+ static fromRulesyncSkill(params) {
4566
+ const baseParams = {
4567
+ ...this.fromRulesyncSkillDefault(params),
4568
+ relativeDirPath: this.getSettablePaths().relativeDirPath
4569
+ };
4570
+ return new _AgentsmdSkill(baseParams);
4571
+ }
4572
+ static isTargetedByRulesyncSkill(rulesyncSkill) {
4573
+ return this.isTargetedByRulesyncSkillDefault({
4574
+ rulesyncSkill,
4575
+ toolTarget: "agentsmd"
4576
+ });
4577
+ }
4578
+ };
4579
+
4580
+ // src/features/skills/claudecode-skill.ts
4581
+ import { join as join45 } from "path";
4582
+ import { z as z19 } from "zod/mini";
4583
+
4584
+ // src/features/skills/rulesync-skill.ts
4585
+ import { join as join44 } from "path";
4586
+ import { z as z18 } from "zod/mini";
4587
+ var RulesyncSkillFrontmatterSchemaInternal = z18.object({
4588
+ name: z18.string(),
4589
+ description: z18.string(),
4590
+ targets: z18._default(RulesyncTargetsSchema, ["*"]),
4591
+ claudecode: z18.optional(
4592
+ z18.object({
4593
+ "allowed-tools": z18.optional(z18.array(z18.string()))
4594
+ })
4595
+ )
4596
+ });
4597
+ var RulesyncSkillFrontmatterSchema = RulesyncSkillFrontmatterSchemaInternal;
4598
+ var RulesyncSkill = class _RulesyncSkill extends AiDir {
4599
+ constructor({
4600
+ baseDir = process.cwd(),
4601
+ relativeDirPath = RULESYNC_SKILLS_RELATIVE_DIR_PATH,
4602
+ dirName,
4603
+ frontmatter,
4604
+ body,
4605
+ otherFiles = [],
4606
+ validate = true,
4607
+ global = false
4608
+ }) {
4609
+ super({
4610
+ baseDir,
4611
+ relativeDirPath,
4612
+ dirName,
4613
+ mainFile: {
4614
+ name: SKILL_FILE_NAME,
4615
+ body,
4616
+ frontmatter: { ...frontmatter }
4617
+ },
4618
+ otherFiles,
4619
+ global
4620
+ });
4621
+ if (validate) {
4622
+ const result = this.validate();
4623
+ if (!result.success) {
4624
+ throw result.error;
4625
+ }
4626
+ }
4627
+ }
4628
+ static getSettablePaths() {
4629
+ return {
4630
+ relativeDirPath: RULESYNC_SKILLS_RELATIVE_DIR_PATH
4631
+ };
4632
+ }
4633
+ getFrontmatter() {
4634
+ if (!this.mainFile?.frontmatter) {
4635
+ throw new Error("Frontmatter is not defined");
4636
+ }
4637
+ const result = RulesyncSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
4638
+ return result;
4639
+ }
4640
+ getBody() {
4641
+ return this.mainFile?.body ?? "";
4642
+ }
4643
+ validate() {
4644
+ const result = RulesyncSkillFrontmatterSchema.safeParse(this.mainFile?.frontmatter);
4645
+ if (!result.success) {
4646
+ return {
4647
+ success: false,
4648
+ error: new Error(
4649
+ `Invalid frontmatter in ${this.getDirPath()}: ${formatError(result.error)}`
4650
+ )
4651
+ };
4652
+ }
4653
+ return { success: true, error: null };
4654
+ }
4655
+ static async fromDir({
4656
+ baseDir = process.cwd(),
4657
+ relativeDirPath = RULESYNC_SKILLS_RELATIVE_DIR_PATH,
4658
+ dirName,
4659
+ global = false
4660
+ }) {
4661
+ const skillDirPath = join44(baseDir, relativeDirPath, dirName);
4662
+ const skillFilePath = join44(skillDirPath, SKILL_FILE_NAME);
4663
+ if (!await fileExists(skillFilePath)) {
4664
+ throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
4665
+ }
4666
+ const fileContent = await readFileContent(skillFilePath);
4667
+ const { frontmatter, body: content } = parseFrontmatter(fileContent);
4668
+ const result = RulesyncSkillFrontmatterSchema.safeParse(frontmatter);
4669
+ if (!result.success) {
4670
+ throw new Error(`Invalid frontmatter in ${skillFilePath}: ${formatError(result.error)}`);
4671
+ }
4672
+ const otherFiles = await this.collectOtherFiles(
4673
+ baseDir,
4674
+ relativeDirPath,
4675
+ dirName,
4676
+ SKILL_FILE_NAME
4677
+ );
4678
+ return new _RulesyncSkill({
4679
+ baseDir,
4680
+ relativeDirPath,
4681
+ dirName,
4682
+ frontmatter: result.data,
4683
+ body: content.trim(),
4684
+ otherFiles,
4685
+ validate: true,
4686
+ global
4687
+ });
4688
+ }
4689
+ };
4690
+
4691
+ // src/features/skills/claudecode-skill.ts
4692
+ var ClaudecodeSkillFrontmatterSchema = z19.object({
4693
+ name: z19.string(),
4694
+ description: z19.string(),
4695
+ "allowed-tools": z19.optional(z19.array(z19.string()))
4696
+ });
4697
+ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
4698
+ constructor({
4699
+ baseDir = process.cwd(),
4700
+ relativeDirPath = join45(".claude", "skills"),
4701
+ dirName,
4702
+ frontmatter,
4703
+ body,
4704
+ otherFiles = [],
4705
+ validate = true,
4706
+ global = false
4707
+ }) {
4708
+ super({
4709
+ baseDir,
4710
+ relativeDirPath,
4711
+ dirName,
4712
+ mainFile: {
4713
+ name: SKILL_FILE_NAME,
4714
+ body,
4715
+ frontmatter: { ...frontmatter }
4716
+ },
4717
+ otherFiles,
4718
+ global
4719
+ });
4720
+ if (validate) {
4721
+ const result = this.validate();
4722
+ if (!result.success) {
4723
+ throw result.error;
4724
+ }
4725
+ }
4726
+ }
4727
+ static getSettablePaths({
4728
+ global: _global = false
4729
+ } = {}) {
4730
+ return {
4731
+ relativeDirPath: join45(".claude", "skills")
4732
+ };
4733
+ }
4734
+ getFrontmatter() {
4735
+ if (!this.mainFile?.frontmatter) {
4736
+ throw new Error("Frontmatter is not defined");
4737
+ }
4738
+ const result = ClaudecodeSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
4739
+ return result;
4740
+ }
4741
+ getBody() {
4742
+ return this.mainFile?.body ?? "";
4743
+ }
4744
+ validate() {
4745
+ if (this.mainFile === void 0) {
4746
+ return {
4747
+ success: false,
4748
+ error: new Error(`${this.getDirPath()}: ${SKILL_FILE_NAME} file does not exist`)
4749
+ };
4750
+ }
4751
+ const result = ClaudecodeSkillFrontmatterSchema.safeParse(this.mainFile.frontmatter);
4752
+ if (!result.success) {
4753
+ return {
4754
+ success: false,
4755
+ error: new Error(
4756
+ `Invalid frontmatter in ${this.getDirPath()}: ${formatError(result.error)}`
4757
+ )
4758
+ };
4759
+ }
4760
+ return { success: true, error: null };
4761
+ }
4762
+ toRulesyncSkill() {
4763
+ const frontmatter = this.getFrontmatter();
4764
+ const rulesyncFrontmatter = {
4765
+ name: frontmatter.name,
4766
+ description: frontmatter.description,
4767
+ targets: ["*"],
4768
+ ...frontmatter["allowed-tools"] && {
4769
+ claudecode: {
4770
+ "allowed-tools": frontmatter["allowed-tools"]
4771
+ }
4772
+ }
4773
+ };
4774
+ return new RulesyncSkill({
4775
+ baseDir: this.baseDir,
4776
+ relativeDirPath: this.relativeDirPath,
4777
+ dirName: this.getDirName(),
4778
+ frontmatter: rulesyncFrontmatter,
4779
+ body: this.getBody(),
4780
+ otherFiles: this.getOtherFiles(),
4781
+ validate: true,
4782
+ global: this.global
4783
+ });
4784
+ }
4785
+ static fromRulesyncSkill({
4786
+ rulesyncSkill,
4787
+ validate = true,
4788
+ global = false
4789
+ }) {
4790
+ const rulesyncFrontmatter = rulesyncSkill.getFrontmatter();
4791
+ const claudecodeFrontmatter = {
4792
+ name: rulesyncFrontmatter.name,
4793
+ description: rulesyncFrontmatter.description,
4794
+ "allowed-tools": rulesyncFrontmatter.claudecode?.["allowed-tools"]
4795
+ };
4796
+ const settablePaths = _ClaudecodeSkill.getSettablePaths({ global });
4797
+ return new _ClaudecodeSkill({
4798
+ baseDir: rulesyncSkill.getBaseDir(),
4799
+ relativeDirPath: settablePaths.relativeDirPath,
4800
+ dirName: rulesyncSkill.getDirName(),
4801
+ frontmatter: claudecodeFrontmatter,
4802
+ body: rulesyncSkill.getBody(),
4803
+ otherFiles: rulesyncSkill.getOtherFiles(),
4804
+ validate,
4805
+ global
4806
+ });
4807
+ }
4808
+ static isTargetedByRulesyncSkill(_rulesyncSkill) {
4809
+ return true;
4810
+ }
4811
+ static async fromDir({
4812
+ baseDir = process.cwd(),
4813
+ relativeDirPath,
4814
+ dirName,
4815
+ global = false
4816
+ }) {
4817
+ const settablePaths = this.getSettablePaths({ global });
4818
+ const actualRelativeDirPath = relativeDirPath ?? settablePaths.relativeDirPath;
4819
+ const skillDirPath = join45(baseDir, actualRelativeDirPath, dirName);
4820
+ const skillFilePath = join45(skillDirPath, SKILL_FILE_NAME);
4821
+ if (!await fileExists(skillFilePath)) {
4822
+ throw new Error(`${SKILL_FILE_NAME} not found in ${skillDirPath}`);
4823
+ }
4824
+ const fileContent = await readFileContent(skillFilePath);
4825
+ const { frontmatter, body: content } = parseFrontmatter(fileContent);
4826
+ const result = ClaudecodeSkillFrontmatterSchema.safeParse(frontmatter);
4827
+ if (!result.success) {
4828
+ throw new Error(`Invalid frontmatter in ${skillFilePath}: ${formatError(result.error)}`);
4829
+ }
4830
+ const otherFiles = await this.collectOtherFiles(
4831
+ baseDir,
4832
+ actualRelativeDirPath,
4833
+ dirName,
4834
+ SKILL_FILE_NAME
4835
+ );
4836
+ return new _ClaudecodeSkill({
4837
+ baseDir,
4838
+ relativeDirPath: actualRelativeDirPath,
4839
+ dirName,
4840
+ frontmatter: result.data,
4841
+ body: content.trim(),
4842
+ otherFiles,
4843
+ validate: true,
4844
+ global
4845
+ });
4846
+ }
4847
+ };
4848
+
4849
+ // src/features/skills/geminicli-skill.ts
4850
+ import { join as join46 } from "path";
4851
+ var GeminiCliSkill = class _GeminiCliSkill extends SimulatedSkill {
4852
+ static getSettablePaths(options) {
4853
+ if (options?.global) {
4854
+ throw new Error("GeminiCliSkill does not support global mode.");
4855
+ }
4856
+ return {
4857
+ relativeDirPath: join46(".gemini", "skills")
4858
+ };
4859
+ }
4860
+ static async fromDir(params) {
4861
+ const baseParams = await this.fromDirDefault(params);
4862
+ return new _GeminiCliSkill(baseParams);
4863
+ }
4864
+ static fromRulesyncSkill(params) {
4865
+ const baseParams = {
4866
+ ...this.fromRulesyncSkillDefault(params),
4867
+ relativeDirPath: this.getSettablePaths().relativeDirPath
4868
+ };
4869
+ return new _GeminiCliSkill(baseParams);
4870
+ }
4871
+ static isTargetedByRulesyncSkill(rulesyncSkill) {
4872
+ return this.isTargetedByRulesyncSkillDefault({
4873
+ rulesyncSkill,
4874
+ toolTarget: "geminicli"
4875
+ });
4876
+ }
4877
+ };
4878
+
4879
+ // src/features/skills/skills-processor.ts
4880
+ var skillsProcessorToolTargets = [
4881
+ "claudecode",
4882
+ "copilot",
4883
+ "cursor",
4884
+ "codexcli",
4885
+ "geminicli",
4886
+ "agentsmd"
4887
+ ];
4888
+ var skillsProcessorToolTargetsSimulated = [
4889
+ "copilot",
4890
+ "cursor",
4891
+ "codexcli",
4892
+ "geminicli",
4893
+ "agentsmd"
4894
+ ];
4895
+ var skillsProcessorToolTargetsGlobal = ["claudecode"];
4896
+ var SkillsProcessorToolTargetSchema = z20.enum(skillsProcessorToolTargets);
4897
+ var SkillsProcessor = class extends DirFeatureProcessor {
4898
+ toolTarget;
4899
+ global;
4900
+ constructor({
4901
+ baseDir = process.cwd(),
4902
+ toolTarget,
4903
+ global = false
4904
+ }) {
4905
+ super({ baseDir });
4906
+ const result = SkillsProcessorToolTargetSchema.safeParse(toolTarget);
4907
+ if (!result.success) {
4908
+ throw new Error(
4909
+ `Invalid tool target for SkillsProcessor: ${toolTarget}. ${formatError(result.error)}`
4910
+ );
4911
+ }
4912
+ this.toolTarget = result.data;
4913
+ this.global = global;
4914
+ }
4915
+ async convertRulesyncDirsToToolDirs(rulesyncDirs) {
4916
+ const rulesyncSkills = rulesyncDirs.filter(
4917
+ (dir) => dir instanceof RulesyncSkill
4918
+ );
4919
+ const toolSkills = [];
4920
+ for (const rulesyncSkill of rulesyncSkills) {
4921
+ switch (this.toolTarget) {
4922
+ case "claudecode":
4923
+ if (!ClaudecodeSkill.isTargetedByRulesyncSkill(rulesyncSkill)) {
4924
+ continue;
4925
+ }
4926
+ toolSkills.push(
4927
+ ClaudecodeSkill.fromRulesyncSkill({
4928
+ rulesyncSkill,
4929
+ global: this.global
4930
+ })
4931
+ );
4932
+ break;
4933
+ case "copilot":
4934
+ if (!CopilotSkill.isTargetedByRulesyncSkill(rulesyncSkill)) {
4935
+ continue;
4936
+ }
4937
+ toolSkills.push(
4938
+ CopilotSkill.fromRulesyncSkill({
4939
+ rulesyncSkill
4940
+ })
4941
+ );
4942
+ break;
4943
+ case "cursor":
4944
+ if (!CursorSkill.isTargetedByRulesyncSkill(rulesyncSkill)) {
4945
+ continue;
4946
+ }
4947
+ toolSkills.push(
4948
+ CursorSkill.fromRulesyncSkill({
4949
+ rulesyncSkill
4950
+ })
4951
+ );
4952
+ break;
4953
+ case "codexcli":
4954
+ if (!CodexCliSkill.isTargetedByRulesyncSkill(rulesyncSkill)) {
4955
+ continue;
4956
+ }
4957
+ toolSkills.push(
4958
+ CodexCliSkill.fromRulesyncSkill({
4959
+ rulesyncSkill
4960
+ })
4961
+ );
4962
+ break;
4963
+ case "geminicli":
4964
+ if (!GeminiCliSkill.isTargetedByRulesyncSkill(rulesyncSkill)) {
4965
+ continue;
4966
+ }
4967
+ toolSkills.push(
4968
+ GeminiCliSkill.fromRulesyncSkill({
4969
+ rulesyncSkill
4970
+ })
4971
+ );
4972
+ break;
4973
+ case "agentsmd":
4974
+ if (!AgentsmdSkill.isTargetedByRulesyncSkill(rulesyncSkill)) {
4975
+ continue;
4976
+ }
4977
+ toolSkills.push(
4978
+ AgentsmdSkill.fromRulesyncSkill({
4979
+ rulesyncSkill
4980
+ })
4981
+ );
4982
+ break;
4983
+ default:
4984
+ throw new Error(`Unsupported tool target: ${this.toolTarget}`);
4985
+ }
4986
+ }
4987
+ return toolSkills;
4988
+ }
4989
+ async convertToolDirsToRulesyncDirs(toolDirs) {
4990
+ const toolSkills = toolDirs.filter((dir) => dir instanceof ToolSkill);
4991
+ const rulesyncSkills = [];
4992
+ for (const toolSkill of toolSkills) {
4993
+ if (toolSkill instanceof SimulatedSkill) {
4994
+ logger.debug(`Skipping simulated skill conversion: ${toolSkill.getDirPath()}`);
4995
+ continue;
4996
+ }
4997
+ rulesyncSkills.push(toolSkill.toRulesyncSkill());
4998
+ }
4999
+ return rulesyncSkills;
5000
+ }
5001
+ /**
5002
+ * Implementation of abstract method from DirFeatureProcessor
5003
+ * Load and parse rulesync skill directories from .rulesync/skills/ directory
5004
+ */
5005
+ async loadRulesyncDirs() {
5006
+ const paths = RulesyncSkill.getSettablePaths();
5007
+ const rulesyncSkillsDirPath = join47(this.baseDir, paths.relativeDirPath);
5008
+ const dirPaths = await findFilesByGlobs(join47(rulesyncSkillsDirPath, "*"), { type: "dir" });
5009
+ const dirNames = dirPaths.map((path3) => basename13(path3));
5010
+ const results = await Promise.allSettled(
5011
+ dirNames.map(
5012
+ (dirName) => RulesyncSkill.fromDir({ baseDir: this.baseDir, dirName, global: this.global })
5013
+ )
5014
+ );
5015
+ const rulesyncSkills = [];
5016
+ for (const result of results) {
5017
+ if (result.status === "fulfilled") {
5018
+ rulesyncSkills.push(result.value);
5019
+ }
3681
5020
  }
5021
+ logger.info(`Successfully loaded ${rulesyncSkills.length} rulesync skills`);
5022
+ return rulesyncSkills;
3682
5023
  }
3683
5024
  /**
3684
- * Implementation of abstract method from FeatureProcessor
3685
- * Convert RulesyncFile[] to ToolFile[]
5025
+ * Implementation of abstract method from DirFeatureProcessor
5026
+ * Load tool-specific skill configurations and parse them into ToolSkill instances
3686
5027
  */
3687
- async convertRulesyncFilesToToolFiles(rulesyncFiles) {
3688
- const rulesyncMcp = rulesyncFiles.find(
3689
- (file) => file instanceof RulesyncMcp
3690
- );
3691
- if (!rulesyncMcp) {
3692
- throw new Error(`No ${RULESYNC_MCP_RELATIVE_FILE_PATH} found.`);
5028
+ async loadToolDirs() {
5029
+ switch (this.toolTarget) {
5030
+ case "claudecode":
5031
+ return await this.loadClaudecodeSkills();
5032
+ case "copilot":
5033
+ return await this.loadSimulatedSkills(CopilotSkill);
5034
+ case "cursor":
5035
+ return await this.loadSimulatedSkills(CursorSkill);
5036
+ case "codexcli":
5037
+ return await this.loadSimulatedSkills(CodexCliSkill);
5038
+ case "geminicli":
5039
+ return await this.loadSimulatedSkills(GeminiCliSkill);
5040
+ case "agentsmd":
5041
+ return await this.loadSimulatedSkills(AgentsmdSkill);
5042
+ default:
5043
+ throw new Error(`Unsupported tool target: ${this.toolTarget}`);
3693
5044
  }
3694
- const toolMcps = await Promise.all(
3695
- [rulesyncMcp].map(async (rulesyncMcp2) => {
3696
- switch (this.toolTarget) {
3697
- case "amazonqcli":
3698
- return AmazonqcliMcp.fromRulesyncMcp({
3699
- baseDir: this.baseDir,
3700
- rulesyncMcp: rulesyncMcp2
3701
- });
3702
- case "claudecode":
3703
- return await ClaudecodeMcp.fromRulesyncMcp({
3704
- baseDir: this.baseDir,
3705
- rulesyncMcp: rulesyncMcp2,
3706
- global: this.global,
3707
- modularMcp: this.modularMcp
3708
- });
3709
- case "cline":
3710
- return ClineMcp.fromRulesyncMcp({
3711
- baseDir: this.baseDir,
3712
- rulesyncMcp: rulesyncMcp2
3713
- });
3714
- case "copilot":
3715
- return CopilotMcp.fromRulesyncMcp({
3716
- baseDir: this.baseDir,
3717
- rulesyncMcp: rulesyncMcp2
3718
- });
3719
- case "cursor":
3720
- return CursorMcp.fromRulesyncMcp({
3721
- baseDir: this.baseDir,
3722
- rulesyncMcp: rulesyncMcp2
3723
- });
3724
- case "codexcli":
3725
- return await CodexcliMcp.fromRulesyncMcp({
3726
- baseDir: this.baseDir,
3727
- rulesyncMcp: rulesyncMcp2,
3728
- global: this.global
3729
- });
3730
- case "geminicli":
3731
- return GeminiCliMcp.fromRulesyncMcp({
3732
- baseDir: this.baseDir,
3733
- rulesyncMcp: rulesyncMcp2,
3734
- global: this.global
3735
- });
3736
- case "roo":
3737
- return RooMcp.fromRulesyncMcp({
3738
- baseDir: this.baseDir,
3739
- rulesyncMcp: rulesyncMcp2
3740
- });
3741
- default:
3742
- throw new Error(`Unsupported tool target: ${this.toolTarget}`);
3743
- }
3744
- })
3745
- );
3746
- const toolFiles = toolMcps;
3747
- if (this.modularMcp && mcpProcessorToolTargetsModular.includes(this.toolTarget)) {
3748
- const relativeDirPath = this.toolTarget === "claudecode" ? ClaudecodeMcp.getSettablePaths({ global: this.global }).relativeDirPath : void 0;
3749
- toolFiles.push(
3750
- ModularMcp.fromRulesyncMcp({
5045
+ }
5046
+ async loadToolDirsToDelete() {
5047
+ return this.loadToolDirs();
5048
+ }
5049
+ /**
5050
+ * Load Claude Code skill configurations from .claude/skills/ directory
5051
+ */
5052
+ async loadClaudecodeSkills() {
5053
+ const paths = ClaudecodeSkill.getSettablePaths({ global: this.global });
5054
+ const skillsDirPath = join47(this.baseDir, paths.relativeDirPath);
5055
+ const dirPaths = await findFilesByGlobs(join47(skillsDirPath, "*"), { type: "dir" });
5056
+ const dirNames = dirPaths.map((path3) => basename13(path3));
5057
+ const toolSkills = (await Promise.allSettled(
5058
+ dirNames.map(
5059
+ (dirName) => ClaudecodeSkill.fromDir({
3751
5060
  baseDir: this.baseDir,
3752
- rulesyncMcp,
3753
- ...this.global && relativeDirPath ? { global: true, relativeDirPath } : { global: false }
5061
+ dirName,
5062
+ global: this.global
3754
5063
  })
3755
- );
3756
- }
3757
- return toolFiles;
5064
+ )
5065
+ )).filter((result) => result.status === "fulfilled").map((result) => result.value);
5066
+ logger.info(`Successfully loaded ${toolSkills.length} ${paths.relativeDirPath} skills`);
5067
+ return toolSkills;
3758
5068
  }
3759
5069
  /**
3760
- * Implementation of abstract method from FeatureProcessor
3761
- * Convert ToolFile[] to RulesyncFile[]
5070
+ * Load simulated skill configurations from tool-specific directories
3762
5071
  */
3763
- async convertToolFilesToRulesyncFiles(toolFiles) {
3764
- const toolMcps = toolFiles.filter((file) => file instanceof ToolMcp);
3765
- const rulesyncMcps = toolMcps.map((toolMcp) => {
3766
- return toolMcp.toRulesyncMcp();
3767
- });
3768
- return rulesyncMcps;
5072
+ async loadSimulatedSkills(SkillClass) {
5073
+ const paths = SkillClass.getSettablePaths();
5074
+ const skillsDirPath = join47(this.baseDir, paths.relativeDirPath);
5075
+ const dirPaths = await findFilesByGlobs(join47(skillsDirPath, "*"), { type: "dir" });
5076
+ const dirNames = dirPaths.map((path3) => basename13(path3));
5077
+ const toolSkills = (await Promise.allSettled(
5078
+ dirNames.map(
5079
+ (dirName) => SkillClass.fromDir({
5080
+ baseDir: this.baseDir,
5081
+ dirName
5082
+ })
5083
+ )
5084
+ )).filter((result) => result.status === "fulfilled").map((result) => result.value);
5085
+ logger.info(`Successfully loaded ${toolSkills.length} ${paths.relativeDirPath} skills`);
5086
+ return toolSkills;
3769
5087
  }
3770
5088
  /**
3771
- * Implementation of abstract method from FeatureProcessor
5089
+ * Implementation of abstract method from DirFeatureProcessor
3772
5090
  * Return the tool targets that this processor supports
3773
5091
  */
3774
- static getToolTargets() {
3775
- return mcpProcessorToolTargets;
5092
+ static getToolTargets({
5093
+ global = false,
5094
+ includeSimulated = false
5095
+ } = {}) {
5096
+ if (global) {
5097
+ return skillsProcessorToolTargetsGlobal;
5098
+ }
5099
+ if (!includeSimulated) {
5100
+ return skillsProcessorToolTargets.filter(
5101
+ (target) => !skillsProcessorToolTargetsSimulated.includes(target)
5102
+ );
5103
+ }
5104
+ return skillsProcessorToolTargets;
5105
+ }
5106
+ /**
5107
+ * Return the simulated tool targets
5108
+ */
5109
+ static getToolTargetsSimulated() {
5110
+ return skillsProcessorToolTargetsSimulated;
3776
5111
  }
5112
+ /**
5113
+ * Return the tool targets that this processor supports in global mode
5114
+ */
3777
5115
  static getToolTargetsGlobal() {
3778
- return mcpProcessorToolTargetsGlobal;
5116
+ return skillsProcessorToolTargetsGlobal;
3779
5117
  }
3780
5118
  };
3781
5119
 
3782
- // src/features/rules/rules-processor.ts
3783
- import { basename as basename17, join as join64 } from "path";
3784
- import { XMLBuilder } from "fast-xml-parser";
3785
- import { z as z24 } from "zod/mini";
3786
-
3787
5120
  // src/features/subagents/agentsmd-subagent.ts
3788
- import { join as join36 } from "path";
5121
+ import { join as join49 } from "path";
3789
5122
 
3790
5123
  // src/features/subagents/simulated-subagent.ts
3791
- import { basename as basename12, join as join35 } from "path";
3792
- import { z as z16 } from "zod/mini";
5124
+ import { basename as basename14, join as join48 } from "path";
5125
+ import { z as z21 } from "zod/mini";
3793
5126
 
3794
5127
  // src/features/subagents/tool-subagent.ts
3795
5128
  var ToolSubagent = class extends ToolFile {
@@ -3824,9 +5157,9 @@ var ToolSubagent = class extends ToolFile {
3824
5157
  };
3825
5158
 
3826
5159
  // src/features/subagents/simulated-subagent.ts
3827
- var SimulatedSubagentFrontmatterSchema = z16.object({
3828
- name: z16.string(),
3829
- description: z16.string()
5160
+ var SimulatedSubagentFrontmatterSchema = z21.object({
5161
+ name: z21.string(),
5162
+ description: z21.string()
3830
5163
  });
3831
5164
  var SimulatedSubagent = class extends ToolSubagent {
3832
5165
  frontmatter;
@@ -3836,7 +5169,7 @@ var SimulatedSubagent = class extends ToolSubagent {
3836
5169
  const result = SimulatedSubagentFrontmatterSchema.safeParse(frontmatter);
3837
5170
  if (!result.success) {
3838
5171
  throw new Error(
3839
- `Invalid frontmatter in ${join35(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
5172
+ `Invalid frontmatter in ${join48(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
3840
5173
  );
3841
5174
  }
3842
5175
  }
@@ -3887,7 +5220,7 @@ var SimulatedSubagent = class extends ToolSubagent {
3887
5220
  return {
3888
5221
  success: false,
3889
5222
  error: new Error(
3890
- `Invalid frontmatter in ${join35(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
5223
+ `Invalid frontmatter in ${join48(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
3891
5224
  )
3892
5225
  };
3893
5226
  }
@@ -3897,7 +5230,7 @@ var SimulatedSubagent = class extends ToolSubagent {
3897
5230
  relativeFilePath,
3898
5231
  validate = true
3899
5232
  }) {
3900
- const filePath = join35(baseDir, this.getSettablePaths().relativeDirPath, relativeFilePath);
5233
+ const filePath = join48(baseDir, this.getSettablePaths().relativeDirPath, relativeFilePath);
3901
5234
  const fileContent = await readFileContent(filePath);
3902
5235
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
3903
5236
  const result = SimulatedSubagentFrontmatterSchema.safeParse(frontmatter);
@@ -3907,7 +5240,7 @@ var SimulatedSubagent = class extends ToolSubagent {
3907
5240
  return {
3908
5241
  baseDir,
3909
5242
  relativeDirPath: this.getSettablePaths().relativeDirPath,
3910
- relativeFilePath: basename12(relativeFilePath),
5243
+ relativeFilePath: basename14(relativeFilePath),
3911
5244
  frontmatter: result.data,
3912
5245
  body: content.trim(),
3913
5246
  validate
@@ -3919,7 +5252,7 @@ var SimulatedSubagent = class extends ToolSubagent {
3919
5252
  var AgentsmdSubagent = class _AgentsmdSubagent extends SimulatedSubagent {
3920
5253
  static getSettablePaths() {
3921
5254
  return {
3922
- relativeDirPath: join36(".agents", "subagents")
5255
+ relativeDirPath: join49(".agents", "subagents")
3923
5256
  };
3924
5257
  }
3925
5258
  static async fromFile(params) {
@@ -3939,11 +5272,11 @@ var AgentsmdSubagent = class _AgentsmdSubagent extends SimulatedSubagent {
3939
5272
  };
3940
5273
 
3941
5274
  // src/features/subagents/codexcli-subagent.ts
3942
- import { join as join37 } from "path";
5275
+ import { join as join50 } from "path";
3943
5276
  var CodexCliSubagent = class _CodexCliSubagent extends SimulatedSubagent {
3944
5277
  static getSettablePaths() {
3945
5278
  return {
3946
- relativeDirPath: join37(".codex", "subagents")
5279
+ relativeDirPath: join50(".codex", "subagents")
3947
5280
  };
3948
5281
  }
3949
5282
  static async fromFile(params) {
@@ -3963,11 +5296,11 @@ var CodexCliSubagent = class _CodexCliSubagent extends SimulatedSubagent {
3963
5296
  };
3964
5297
 
3965
5298
  // src/features/subagents/copilot-subagent.ts
3966
- import { join as join38 } from "path";
5299
+ import { join as join51 } from "path";
3967
5300
  var CopilotSubagent = class _CopilotSubagent extends SimulatedSubagent {
3968
5301
  static getSettablePaths() {
3969
5302
  return {
3970
- relativeDirPath: join38(".github", "subagents")
5303
+ relativeDirPath: join51(".github", "subagents")
3971
5304
  };
3972
5305
  }
3973
5306
  static async fromFile(params) {
@@ -3987,11 +5320,11 @@ var CopilotSubagent = class _CopilotSubagent extends SimulatedSubagent {
3987
5320
  };
3988
5321
 
3989
5322
  // src/features/subagents/cursor-subagent.ts
3990
- import { join as join39 } from "path";
5323
+ import { join as join52 } from "path";
3991
5324
  var CursorSubagent = class _CursorSubagent extends SimulatedSubagent {
3992
5325
  static getSettablePaths() {
3993
5326
  return {
3994
- relativeDirPath: join39(".cursor", "subagents")
5327
+ relativeDirPath: join52(".cursor", "subagents")
3995
5328
  };
3996
5329
  }
3997
5330
  static async fromFile(params) {
@@ -4011,11 +5344,11 @@ var CursorSubagent = class _CursorSubagent extends SimulatedSubagent {
4011
5344
  };
4012
5345
 
4013
5346
  // src/features/subagents/geminicli-subagent.ts
4014
- import { join as join40 } from "path";
5347
+ import { join as join53 } from "path";
4015
5348
  var GeminiCliSubagent = class _GeminiCliSubagent extends SimulatedSubagent {
4016
5349
  static getSettablePaths() {
4017
5350
  return {
4018
- relativeDirPath: join40(".gemini", "subagents")
5351
+ relativeDirPath: join53(".gemini", "subagents")
4019
5352
  };
4020
5353
  }
4021
5354
  static async fromFile(params) {
@@ -4035,11 +5368,11 @@ var GeminiCliSubagent = class _GeminiCliSubagent extends SimulatedSubagent {
4035
5368
  };
4036
5369
 
4037
5370
  // src/features/subagents/roo-subagent.ts
4038
- import { join as join41 } from "path";
5371
+ import { join as join54 } from "path";
4039
5372
  var RooSubagent = class _RooSubagent extends SimulatedSubagent {
4040
5373
  static getSettablePaths() {
4041
5374
  return {
4042
- relativeDirPath: join41(".roo", "subagents")
5375
+ relativeDirPath: join54(".roo", "subagents")
4043
5376
  };
4044
5377
  }
4045
5378
  static async fromFile(params) {
@@ -4059,23 +5392,23 @@ var RooSubagent = class _RooSubagent extends SimulatedSubagent {
4059
5392
  };
4060
5393
 
4061
5394
  // src/features/subagents/subagents-processor.ts
4062
- import { basename as basename14, join as join44 } from "path";
4063
- import { z as z19 } from "zod/mini";
5395
+ import { basename as basename16, join as join57 } from "path";
5396
+ import { z as z24 } from "zod/mini";
4064
5397
 
4065
5398
  // src/features/subagents/claudecode-subagent.ts
4066
- import { join as join43 } from "path";
4067
- import { z as z18 } from "zod/mini";
5399
+ import { join as join56 } from "path";
5400
+ import { z as z23 } from "zod/mini";
4068
5401
 
4069
5402
  // src/features/subagents/rulesync-subagent.ts
4070
- import { basename as basename13, join as join42 } from "path";
4071
- import { z as z17 } from "zod/mini";
4072
- var RulesyncSubagentModelSchema = z17.enum(["opus", "sonnet", "haiku", "inherit"]);
4073
- var RulesyncSubagentFrontmatterSchema = z17.object({
5403
+ import { basename as basename15, join as join55 } from "path";
5404
+ import { z as z22 } from "zod/mini";
5405
+ var RulesyncSubagentModelSchema = z22.enum(["opus", "sonnet", "haiku", "inherit"]);
5406
+ var RulesyncSubagentFrontmatterSchema = z22.object({
4074
5407
  targets: RulesyncTargetsSchema,
4075
- name: z17.string(),
4076
- description: z17.string(),
4077
- claudecode: z17.optional(
4078
- z17.object({
5408
+ name: z22.string(),
5409
+ description: z22.string(),
5410
+ claudecode: z22.optional(
5411
+ z22.object({
4079
5412
  model: RulesyncSubagentModelSchema
4080
5413
  })
4081
5414
  )
@@ -4088,7 +5421,7 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
4088
5421
  const result = RulesyncSubagentFrontmatterSchema.safeParse(frontmatter);
4089
5422
  if (!result.success) {
4090
5423
  throw new Error(
4091
- `Invalid frontmatter in ${join42(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
5424
+ `Invalid frontmatter in ${join55(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
4092
5425
  );
4093
5426
  }
4094
5427
  }
@@ -4121,7 +5454,7 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
4121
5454
  return {
4122
5455
  success: false,
4123
5456
  error: new Error(
4124
- `Invalid frontmatter in ${join42(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
5457
+ `Invalid frontmatter in ${join55(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
4125
5458
  )
4126
5459
  };
4127
5460
  }
@@ -4130,14 +5463,14 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
4130
5463
  relativeFilePath
4131
5464
  }) {
4132
5465
  const fileContent = await readFileContent(
4133
- join42(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, relativeFilePath)
5466
+ join55(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, relativeFilePath)
4134
5467
  );
4135
5468
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
4136
5469
  const result = RulesyncSubagentFrontmatterSchema.safeParse(frontmatter);
4137
5470
  if (!result.success) {
4138
5471
  throw new Error(`Invalid frontmatter in ${relativeFilePath}: ${formatError(result.error)}`);
4139
5472
  }
4140
- const filename = basename13(relativeFilePath);
5473
+ const filename = basename15(relativeFilePath);
4141
5474
  return new _RulesyncSubagent({
4142
5475
  baseDir: process.cwd(),
4143
5476
  relativeDirPath: this.getSettablePaths().relativeDirPath,
@@ -4149,10 +5482,10 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
4149
5482
  };
4150
5483
 
4151
5484
  // src/features/subagents/claudecode-subagent.ts
4152
- var ClaudecodeSubagentFrontmatterSchema = z18.object({
4153
- name: z18.string(),
4154
- description: z18.string(),
4155
- model: z18.optional(z18.enum(["opus", "sonnet", "haiku", "inherit"]))
5485
+ var ClaudecodeSubagentFrontmatterSchema = z23.object({
5486
+ name: z23.string(),
5487
+ description: z23.string(),
5488
+ model: z23.optional(z23.enum(["opus", "sonnet", "haiku", "inherit"]))
4156
5489
  });
4157
5490
  var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4158
5491
  frontmatter;
@@ -4162,7 +5495,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4162
5495
  const result = ClaudecodeSubagentFrontmatterSchema.safeParse(frontmatter);
4163
5496
  if (!result.success) {
4164
5497
  throw new Error(
4165
- `Invalid frontmatter in ${join43(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
5498
+ `Invalid frontmatter in ${join56(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
4166
5499
  );
4167
5500
  }
4168
5501
  }
@@ -4174,7 +5507,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4174
5507
  }
4175
5508
  static getSettablePaths(_options = {}) {
4176
5509
  return {
4177
- relativeDirPath: join43(".claude", "agents")
5510
+ relativeDirPath: join56(".claude", "agents")
4178
5511
  };
4179
5512
  }
4180
5513
  getFrontmatter() {
@@ -4240,7 +5573,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4240
5573
  return {
4241
5574
  success: false,
4242
5575
  error: new Error(
4243
- `Invalid frontmatter in ${join43(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
5576
+ `Invalid frontmatter in ${join56(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
4244
5577
  )
4245
5578
  };
4246
5579
  }
@@ -4258,7 +5591,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4258
5591
  global = false
4259
5592
  }) {
4260
5593
  const paths = this.getSettablePaths({ global });
4261
- const filePath = join43(baseDir, paths.relativeDirPath, relativeFilePath);
5594
+ const filePath = join56(baseDir, paths.relativeDirPath, relativeFilePath);
4262
5595
  const fileContent = await readFileContent(filePath);
4263
5596
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
4264
5597
  const result = ClaudecodeSubagentFrontmatterSchema.safeParse(frontmatter);
@@ -4296,7 +5629,7 @@ var subagentsProcessorToolTargetsSimulated = [
4296
5629
  "roo"
4297
5630
  ];
4298
5631
  var subagentsProcessorToolTargetsGlobal = ["claudecode"];
4299
- var SubagentsProcessorToolTargetSchema = z19.enum(subagentsProcessorToolTargets);
5632
+ var SubagentsProcessorToolTargetSchema = z24.enum(subagentsProcessorToolTargets);
4300
5633
  var SubagentsProcessor = class extends FeatureProcessor {
4301
5634
  toolTarget;
4302
5635
  global;
@@ -4412,7 +5745,7 @@ var SubagentsProcessor = class extends FeatureProcessor {
4412
5745
  * Load and parse rulesync subagent files from .rulesync/subagents/ directory
4413
5746
  */
4414
5747
  async loadRulesyncFiles() {
4415
- const subagentsDir = join44(this.baseDir, RulesyncSubagent.getSettablePaths().relativeDirPath);
5748
+ const subagentsDir = join57(this.baseDir, RulesyncSubagent.getSettablePaths().relativeDirPath);
4416
5749
  const dirExists = await directoryExists(subagentsDir);
4417
5750
  if (!dirExists) {
4418
5751
  logger.debug(`Rulesync subagents directory not found: ${subagentsDir}`);
@@ -4427,7 +5760,7 @@ var SubagentsProcessor = class extends FeatureProcessor {
4427
5760
  logger.info(`Found ${mdFiles.length} subagent files in ${subagentsDir}`);
4428
5761
  const rulesyncSubagents = [];
4429
5762
  for (const mdFile of mdFiles) {
4430
- const filepath = join44(subagentsDir, mdFile);
5763
+ const filepath = join57(subagentsDir, mdFile);
4431
5764
  try {
4432
5765
  const rulesyncSubagent = await RulesyncSubagent.fromFile({
4433
5766
  relativeFilePath: mdFile,
@@ -4451,7 +5784,9 @@ var SubagentsProcessor = class extends FeatureProcessor {
4451
5784
  * Implementation of abstract method from Processor
4452
5785
  * Load tool-specific subagent configurations and parse them into ToolSubagent instances
4453
5786
  */
4454
- async loadToolFiles() {
5787
+ async loadToolFiles({
5788
+ forDeletion: _forDeletion = false
5789
+ } = {}) {
4455
5790
  switch (this.toolTarget) {
4456
5791
  case "agentsmd":
4457
5792
  return await this.loadAgentsmdSubagents();
@@ -4471,9 +5806,6 @@ var SubagentsProcessor = class extends FeatureProcessor {
4471
5806
  throw new Error(`Unsupported tool target: ${this.toolTarget}`);
4472
5807
  }
4473
5808
  }
4474
- async loadToolFilesToDelete() {
4475
- return this.loadToolFiles();
4476
- }
4477
5809
  /**
4478
5810
  * Load Agents.md subagent configurations from .agents/subagents/ directory
4479
5811
  */
@@ -4546,8 +5878,8 @@ var SubagentsProcessor = class extends FeatureProcessor {
4546
5878
  relativeDirPath,
4547
5879
  fromFile
4548
5880
  }) {
4549
- const paths = await findFilesByGlobs(join44(this.baseDir, relativeDirPath, "*.md"));
4550
- const subagents = (await Promise.allSettled(paths.map((path2) => fromFile(basename14(path2))))).filter((r) => r.status === "fulfilled").map((r) => r.value);
5881
+ const paths = await findFilesByGlobs(join57(this.baseDir, relativeDirPath, "*.md"));
5882
+ const subagents = (await Promise.allSettled(paths.map((path3) => fromFile(basename16(path3))))).filter((r) => r.status === "fulfilled").map((r) => r.value);
4551
5883
  logger.info(`Successfully loaded ${subagents.length} ${relativeDirPath} subagents`);
4552
5884
  return subagents;
4553
5885
  }
@@ -4556,8 +5888,12 @@ var SubagentsProcessor = class extends FeatureProcessor {
4556
5888
  * Return the tool targets that this processor supports
4557
5889
  */
4558
5890
  static getToolTargets({
5891
+ global = false,
4559
5892
  includeSimulated = false
4560
5893
  } = {}) {
5894
+ if (global) {
5895
+ return subagentsProcessorToolTargetsGlobal;
5896
+ }
4561
5897
  if (!includeSimulated) {
4562
5898
  return subagentsProcessorToolTargets.filter(
4563
5899
  (target) => !subagentsProcessorToolTargetsSimulated.includes(target)
@@ -4568,36 +5904,33 @@ var SubagentsProcessor = class extends FeatureProcessor {
4568
5904
  static getToolTargetsSimulated() {
4569
5905
  return subagentsProcessorToolTargetsSimulated;
4570
5906
  }
4571
- static getToolTargetsGlobal() {
4572
- return subagentsProcessorToolTargetsGlobal;
4573
- }
4574
5907
  };
4575
5908
 
4576
5909
  // src/features/rules/agentsmd-rule.ts
4577
- import { join as join47 } from "path";
5910
+ import { join as join60 } from "path";
4578
5911
 
4579
5912
  // src/features/rules/tool-rule.ts
4580
- import { join as join46 } from "path";
5913
+ import { join as join59 } from "path";
4581
5914
 
4582
5915
  // src/features/rules/rulesync-rule.ts
4583
- import { basename as basename15, join as join45 } from "path";
4584
- import { z as z20 } from "zod/mini";
4585
- var RulesyncRuleFrontmatterSchema = z20.object({
4586
- root: z20.optional(z20.optional(z20.boolean())),
4587
- targets: z20.optional(RulesyncTargetsSchema),
4588
- description: z20.optional(z20.string()),
4589
- globs: z20.optional(z20.array(z20.string())),
4590
- agentsmd: z20.optional(
4591
- z20.object({
5916
+ import { basename as basename17, join as join58 } from "path";
5917
+ import { z as z25 } from "zod/mini";
5918
+ var RulesyncRuleFrontmatterSchema = z25.object({
5919
+ root: z25.optional(z25.optional(z25.boolean())),
5920
+ targets: z25.optional(RulesyncTargetsSchema),
5921
+ description: z25.optional(z25.string()),
5922
+ globs: z25.optional(z25.array(z25.string())),
5923
+ agentsmd: z25.optional(
5924
+ z25.object({
4592
5925
  // @example "path/to/subproject"
4593
- subprojectPath: z20.optional(z20.string())
5926
+ subprojectPath: z25.optional(z25.string())
4594
5927
  })
4595
5928
  ),
4596
- cursor: z20.optional(
4597
- z20.object({
4598
- alwaysApply: z20.optional(z20.boolean()),
4599
- description: z20.optional(z20.string()),
4600
- globs: z20.optional(z20.array(z20.string()))
5929
+ cursor: z25.optional(
5930
+ z25.object({
5931
+ alwaysApply: z25.optional(z25.boolean()),
5932
+ description: z25.optional(z25.string()),
5933
+ globs: z25.optional(z25.array(z25.string()))
4601
5934
  })
4602
5935
  )
4603
5936
  });
@@ -4609,7 +5942,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
4609
5942
  const result = RulesyncRuleFrontmatterSchema.safeParse(frontmatter);
4610
5943
  if (!result.success) {
4611
5944
  throw new Error(
4612
- `Invalid frontmatter in ${join45(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
5945
+ `Invalid frontmatter in ${join58(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
4613
5946
  );
4614
5947
  }
4615
5948
  }
@@ -4644,7 +5977,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
4644
5977
  return {
4645
5978
  success: false,
4646
5979
  error: new Error(
4647
- `Invalid frontmatter in ${join45(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
5980
+ `Invalid frontmatter in ${join58(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
4648
5981
  )
4649
5982
  };
4650
5983
  }
@@ -4653,12 +5986,12 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
4653
5986
  relativeFilePath,
4654
5987
  validate = true
4655
5988
  }) {
4656
- const legacyPath = join45(
5989
+ const legacyPath = join58(
4657
5990
  process.cwd(),
4658
5991
  this.getSettablePaths().legacy.relativeDirPath,
4659
5992
  relativeFilePath
4660
5993
  );
4661
- const recommendedPath = join45(
5994
+ const recommendedPath = join58(
4662
5995
  this.getSettablePaths().recommended.relativeDirPath,
4663
5996
  relativeFilePath
4664
5997
  );
@@ -4677,7 +6010,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
4677
6010
  agentsmd: result.data.agentsmd,
4678
6011
  cursor: result.data.cursor
4679
6012
  };
4680
- const filename = basename15(legacyPath);
6013
+ const filename = basename17(legacyPath);
4681
6014
  return new _RulesyncRule({
4682
6015
  baseDir: process.cwd(),
4683
6016
  relativeDirPath: this.getSettablePaths().recommended.relativeDirPath,
@@ -4691,7 +6024,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
4691
6024
  relativeFilePath,
4692
6025
  validate = true
4693
6026
  }) {
4694
- const filePath = join45(
6027
+ const filePath = join58(
4695
6028
  process.cwd(),
4696
6029
  this.getSettablePaths().recommended.relativeDirPath,
4697
6030
  relativeFilePath
@@ -4710,7 +6043,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
4710
6043
  agentsmd: result.data.agentsmd,
4711
6044
  cursor: result.data.cursor
4712
6045
  };
4713
- const filename = basename15(filePath);
6046
+ const filename = basename17(filePath);
4714
6047
  return new _RulesyncRule({
4715
6048
  baseDir: process.cwd(),
4716
6049
  relativeDirPath: this.getSettablePaths().recommended.relativeDirPath,
@@ -4785,7 +6118,7 @@ var ToolRule = class extends ToolFile {
4785
6118
  rulesyncRule,
4786
6119
  validate = true,
4787
6120
  rootPath = { relativeDirPath: ".", relativeFilePath: "AGENTS.md" },
4788
- nonRootPath = { relativeDirPath: join46(".agents", "memories") }
6121
+ nonRootPath = { relativeDirPath: join59(".agents", "memories") }
4789
6122
  }) {
4790
6123
  const params = this.buildToolRuleParamsDefault({
4791
6124
  baseDir,
@@ -4796,7 +6129,7 @@ var ToolRule = class extends ToolFile {
4796
6129
  });
4797
6130
  const rulesyncFrontmatter = rulesyncRule.getFrontmatter();
4798
6131
  if (!rulesyncFrontmatter.root && rulesyncFrontmatter.agentsmd?.subprojectPath) {
4799
- params.relativeDirPath = join46(rulesyncFrontmatter.agentsmd.subprojectPath);
6132
+ params.relativeDirPath = join59(rulesyncFrontmatter.agentsmd.subprojectPath);
4800
6133
  params.relativeFilePath = "AGENTS.md";
4801
6134
  }
4802
6135
  return params;
@@ -4861,7 +6194,7 @@ var AgentsMdRule = class _AgentsMdRule extends ToolRule {
4861
6194
  relativeFilePath: "AGENTS.md"
4862
6195
  },
4863
6196
  nonRoot: {
4864
- relativeDirPath: join47(".agents", "memories")
6197
+ relativeDirPath: join60(".agents", "memories")
4865
6198
  }
4866
6199
  };
4867
6200
  }
@@ -4871,8 +6204,8 @@ var AgentsMdRule = class _AgentsMdRule extends ToolRule {
4871
6204
  validate = true
4872
6205
  }) {
4873
6206
  const isRoot = relativeFilePath === "AGENTS.md";
4874
- const relativePath = isRoot ? "AGENTS.md" : join47(".agents", "memories", relativeFilePath);
4875
- const fileContent = await readFileContent(join47(baseDir, relativePath));
6207
+ const relativePath = isRoot ? "AGENTS.md" : join60(".agents", "memories", relativeFilePath);
6208
+ const fileContent = await readFileContent(join60(baseDir, relativePath));
4876
6209
  return new _AgentsMdRule({
4877
6210
  baseDir,
4878
6211
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -4912,12 +6245,12 @@ var AgentsMdRule = class _AgentsMdRule extends ToolRule {
4912
6245
  };
4913
6246
 
4914
6247
  // src/features/rules/amazonqcli-rule.ts
4915
- import { join as join48 } from "path";
6248
+ import { join as join61 } from "path";
4916
6249
  var AmazonQCliRule = class _AmazonQCliRule extends ToolRule {
4917
6250
  static getSettablePaths() {
4918
6251
  return {
4919
6252
  nonRoot: {
4920
- relativeDirPath: join48(".amazonq", "rules")
6253
+ relativeDirPath: join61(".amazonq", "rules")
4921
6254
  }
4922
6255
  };
4923
6256
  }
@@ -4927,7 +6260,7 @@ var AmazonQCliRule = class _AmazonQCliRule extends ToolRule {
4927
6260
  validate = true
4928
6261
  }) {
4929
6262
  const fileContent = await readFileContent(
4930
- join48(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
6263
+ join61(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
4931
6264
  );
4932
6265
  return new _AmazonQCliRule({
4933
6266
  baseDir,
@@ -4967,7 +6300,7 @@ var AmazonQCliRule = class _AmazonQCliRule extends ToolRule {
4967
6300
  };
4968
6301
 
4969
6302
  // src/features/rules/augmentcode-legacy-rule.ts
4970
- import { join as join49 } from "path";
6303
+ import { join as join62 } from "path";
4971
6304
  var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
4972
6305
  toRulesyncRule() {
4973
6306
  const rulesyncFrontmatter = {
@@ -4993,7 +6326,7 @@ var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
4993
6326
  relativeFilePath: ".augment-guidelines"
4994
6327
  },
4995
6328
  nonRoot: {
4996
- relativeDirPath: join49(".augment", "rules")
6329
+ relativeDirPath: join62(".augment", "rules")
4997
6330
  }
4998
6331
  };
4999
6332
  }
@@ -5028,8 +6361,8 @@ var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
5028
6361
  }) {
5029
6362
  const settablePaths = this.getSettablePaths();
5030
6363
  const isRoot = relativeFilePath === settablePaths.root.relativeFilePath;
5031
- const relativePath = isRoot ? settablePaths.root.relativeFilePath : join49(settablePaths.nonRoot.relativeDirPath, relativeFilePath);
5032
- const fileContent = await readFileContent(join49(baseDir, relativePath));
6364
+ const relativePath = isRoot ? settablePaths.root.relativeFilePath : join62(settablePaths.nonRoot.relativeDirPath, relativeFilePath);
6365
+ const fileContent = await readFileContent(join62(baseDir, relativePath));
5033
6366
  return new _AugmentcodeLegacyRule({
5034
6367
  baseDir,
5035
6368
  relativeDirPath: isRoot ? settablePaths.root.relativeDirPath : settablePaths.nonRoot.relativeDirPath,
@@ -5042,7 +6375,7 @@ var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
5042
6375
  };
5043
6376
 
5044
6377
  // src/features/rules/augmentcode-rule.ts
5045
- import { join as join50 } from "path";
6378
+ import { join as join63 } from "path";
5046
6379
  var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
5047
6380
  toRulesyncRule() {
5048
6381
  return this.toRulesyncRuleDefault();
@@ -5050,7 +6383,7 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
5050
6383
  static getSettablePaths() {
5051
6384
  return {
5052
6385
  nonRoot: {
5053
- relativeDirPath: join50(".augment", "rules")
6386
+ relativeDirPath: join63(".augment", "rules")
5054
6387
  }
5055
6388
  };
5056
6389
  }
@@ -5074,7 +6407,7 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
5074
6407
  validate = true
5075
6408
  }) {
5076
6409
  const fileContent = await readFileContent(
5077
- join50(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
6410
+ join63(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5078
6411
  );
5079
6412
  const { body: content } = parseFrontmatter(fileContent);
5080
6413
  return new _AugmentcodeRule({
@@ -5097,7 +6430,7 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
5097
6430
  };
5098
6431
 
5099
6432
  // src/features/rules/claudecode-rule.ts
5100
- import { join as join51 } from "path";
6433
+ import { join as join64 } from "path";
5101
6434
  var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
5102
6435
  static getSettablePaths({
5103
6436
  global
@@ -5116,7 +6449,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
5116
6449
  relativeFilePath: "CLAUDE.md"
5117
6450
  },
5118
6451
  nonRoot: {
5119
- relativeDirPath: join51(".claude", "memories")
6452
+ relativeDirPath: join64(".claude", "memories")
5120
6453
  }
5121
6454
  };
5122
6455
  }
@@ -5131,7 +6464,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
5131
6464
  if (isRoot) {
5132
6465
  const relativePath2 = paths.root.relativeFilePath;
5133
6466
  const fileContent2 = await readFileContent(
5134
- join51(baseDir, paths.root.relativeDirPath, relativePath2)
6467
+ join64(baseDir, paths.root.relativeDirPath, relativePath2)
5135
6468
  );
5136
6469
  return new _ClaudecodeRule({
5137
6470
  baseDir,
@@ -5145,8 +6478,8 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
5145
6478
  if (!paths.nonRoot) {
5146
6479
  throw new Error("nonRoot path is not set");
5147
6480
  }
5148
- const relativePath = join51(paths.nonRoot.relativeDirPath, relativeFilePath);
5149
- const fileContent = await readFileContent(join51(baseDir, relativePath));
6481
+ const relativePath = join64(paths.nonRoot.relativeDirPath, relativeFilePath);
6482
+ const fileContent = await readFileContent(join64(baseDir, relativePath));
5150
6483
  return new _ClaudecodeRule({
5151
6484
  baseDir,
5152
6485
  relativeDirPath: paths.nonRoot.relativeDirPath,
@@ -5188,10 +6521,10 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
5188
6521
  };
5189
6522
 
5190
6523
  // src/features/rules/cline-rule.ts
5191
- import { join as join52 } from "path";
5192
- import { z as z21 } from "zod/mini";
5193
- var ClineRuleFrontmatterSchema = z21.object({
5194
- description: z21.string()
6524
+ import { join as join65 } from "path";
6525
+ import { z as z26 } from "zod/mini";
6526
+ var ClineRuleFrontmatterSchema = z26.object({
6527
+ description: z26.string()
5195
6528
  });
5196
6529
  var ClineRule = class _ClineRule extends ToolRule {
5197
6530
  static getSettablePaths() {
@@ -5233,7 +6566,7 @@ var ClineRule = class _ClineRule extends ToolRule {
5233
6566
  validate = true
5234
6567
  }) {
5235
6568
  const fileContent = await readFileContent(
5236
- join52(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
6569
+ join65(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5237
6570
  );
5238
6571
  return new _ClineRule({
5239
6572
  baseDir,
@@ -5246,7 +6579,7 @@ var ClineRule = class _ClineRule extends ToolRule {
5246
6579
  };
5247
6580
 
5248
6581
  // src/features/rules/codexcli-rule.ts
5249
- import { join as join53 } from "path";
6582
+ import { join as join66 } from "path";
5250
6583
  var CodexcliRule = class _CodexcliRule extends ToolRule {
5251
6584
  static getSettablePaths({
5252
6585
  global
@@ -5265,7 +6598,7 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
5265
6598
  relativeFilePath: "AGENTS.md"
5266
6599
  },
5267
6600
  nonRoot: {
5268
- relativeDirPath: join53(".codex", "memories")
6601
+ relativeDirPath: join66(".codex", "memories")
5269
6602
  }
5270
6603
  };
5271
6604
  }
@@ -5280,7 +6613,7 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
5280
6613
  if (isRoot) {
5281
6614
  const relativePath2 = paths.root.relativeFilePath;
5282
6615
  const fileContent2 = await readFileContent(
5283
- join53(baseDir, paths.root.relativeDirPath, relativePath2)
6616
+ join66(baseDir, paths.root.relativeDirPath, relativePath2)
5284
6617
  );
5285
6618
  return new _CodexcliRule({
5286
6619
  baseDir,
@@ -5294,8 +6627,8 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
5294
6627
  if (!paths.nonRoot) {
5295
6628
  throw new Error("nonRoot path is not set");
5296
6629
  }
5297
- const relativePath = join53(paths.nonRoot.relativeDirPath, relativeFilePath);
5298
- const fileContent = await readFileContent(join53(baseDir, relativePath));
6630
+ const relativePath = join66(paths.nonRoot.relativeDirPath, relativeFilePath);
6631
+ const fileContent = await readFileContent(join66(baseDir, relativePath));
5299
6632
  return new _CodexcliRule({
5300
6633
  baseDir,
5301
6634
  relativeDirPath: paths.nonRoot.relativeDirPath,
@@ -5337,11 +6670,11 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
5337
6670
  };
5338
6671
 
5339
6672
  // src/features/rules/copilot-rule.ts
5340
- import { join as join54 } from "path";
5341
- import { z as z22 } from "zod/mini";
5342
- var CopilotRuleFrontmatterSchema = z22.object({
5343
- description: z22.optional(z22.string()),
5344
- applyTo: z22.optional(z22.string())
6673
+ import { join as join67 } from "path";
6674
+ import { z as z27 } from "zod/mini";
6675
+ var CopilotRuleFrontmatterSchema = z27.object({
6676
+ description: z27.optional(z27.string()),
6677
+ applyTo: z27.optional(z27.string())
5345
6678
  });
5346
6679
  var CopilotRule = class _CopilotRule extends ToolRule {
5347
6680
  frontmatter;
@@ -5353,7 +6686,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
5353
6686
  relativeFilePath: "copilot-instructions.md"
5354
6687
  },
5355
6688
  nonRoot: {
5356
- relativeDirPath: join54(".github", "instructions")
6689
+ relativeDirPath: join67(".github", "instructions")
5357
6690
  }
5358
6691
  };
5359
6692
  }
@@ -5362,7 +6695,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
5362
6695
  const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
5363
6696
  if (!result.success) {
5364
6697
  throw new Error(
5365
- `Invalid frontmatter in ${join54(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
6698
+ `Invalid frontmatter in ${join67(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
5366
6699
  );
5367
6700
  }
5368
6701
  }
@@ -5440,11 +6773,11 @@ var CopilotRule = class _CopilotRule extends ToolRule {
5440
6773
  validate = true
5441
6774
  }) {
5442
6775
  const isRoot = relativeFilePath === "copilot-instructions.md";
5443
- const relativePath = isRoot ? join54(
6776
+ const relativePath = isRoot ? join67(
5444
6777
  this.getSettablePaths().root.relativeDirPath,
5445
6778
  this.getSettablePaths().root.relativeFilePath
5446
- ) : join54(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
5447
- const fileContent = await readFileContent(join54(baseDir, relativePath));
6779
+ ) : join67(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
6780
+ const fileContent = await readFileContent(join67(baseDir, relativePath));
5448
6781
  if (isRoot) {
5449
6782
  return new _CopilotRule({
5450
6783
  baseDir,
@@ -5463,7 +6796,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
5463
6796
  const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
5464
6797
  if (!result.success) {
5465
6798
  throw new Error(
5466
- `Invalid frontmatter in ${join54(baseDir, relativeFilePath)}: ${formatError(result.error)}`
6799
+ `Invalid frontmatter in ${join67(baseDir, relativeFilePath)}: ${formatError(result.error)}`
5467
6800
  );
5468
6801
  }
5469
6802
  return new _CopilotRule({
@@ -5487,7 +6820,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
5487
6820
  return {
5488
6821
  success: false,
5489
6822
  error: new Error(
5490
- `Invalid frontmatter in ${join54(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
6823
+ `Invalid frontmatter in ${join67(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
5491
6824
  )
5492
6825
  };
5493
6826
  }
@@ -5507,12 +6840,12 @@ var CopilotRule = class _CopilotRule extends ToolRule {
5507
6840
  };
5508
6841
 
5509
6842
  // src/features/rules/cursor-rule.ts
5510
- import { basename as basename16, join as join55 } from "path";
5511
- import { z as z23 } from "zod/mini";
5512
- var CursorRuleFrontmatterSchema = z23.object({
5513
- description: z23.optional(z23.string()),
5514
- globs: z23.optional(z23.string()),
5515
- alwaysApply: z23.optional(z23.boolean())
6843
+ import { basename as basename18, join as join68 } from "path";
6844
+ import { z as z28 } from "zod/mini";
6845
+ var CursorRuleFrontmatterSchema = z28.object({
6846
+ description: z28.optional(z28.string()),
6847
+ globs: z28.optional(z28.string()),
6848
+ alwaysApply: z28.optional(z28.boolean())
5516
6849
  });
5517
6850
  var CursorRule = class _CursorRule extends ToolRule {
5518
6851
  frontmatter;
@@ -5520,7 +6853,7 @@ var CursorRule = class _CursorRule extends ToolRule {
5520
6853
  static getSettablePaths() {
5521
6854
  return {
5522
6855
  nonRoot: {
5523
- relativeDirPath: join55(".cursor", "rules")
6856
+ relativeDirPath: join68(".cursor", "rules")
5524
6857
  }
5525
6858
  };
5526
6859
  }
@@ -5529,7 +6862,7 @@ var CursorRule = class _CursorRule extends ToolRule {
5529
6862
  const result = CursorRuleFrontmatterSchema.safeParse(frontmatter);
5530
6863
  if (!result.success) {
5531
6864
  throw new Error(
5532
- `Invalid frontmatter in ${join55(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
6865
+ `Invalid frontmatter in ${join68(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
5533
6866
  );
5534
6867
  }
5535
6868
  }
@@ -5646,19 +6979,19 @@ var CursorRule = class _CursorRule extends ToolRule {
5646
6979
  validate = true
5647
6980
  }) {
5648
6981
  const fileContent = await readFileContent(
5649
- join55(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
6982
+ join68(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5650
6983
  );
5651
6984
  const { frontmatter, body: content } = _CursorRule.parseCursorFrontmatter(fileContent);
5652
6985
  const result = CursorRuleFrontmatterSchema.safeParse(frontmatter);
5653
6986
  if (!result.success) {
5654
6987
  throw new Error(
5655
- `Invalid frontmatter in ${join55(baseDir, relativeFilePath)}: ${formatError(result.error)}`
6988
+ `Invalid frontmatter in ${join68(baseDir, relativeFilePath)}: ${formatError(result.error)}`
5656
6989
  );
5657
6990
  }
5658
6991
  return new _CursorRule({
5659
6992
  baseDir,
5660
6993
  relativeDirPath: this.getSettablePaths().nonRoot.relativeDirPath,
5661
- relativeFilePath: basename16(relativeFilePath),
6994
+ relativeFilePath: basename18(relativeFilePath),
5662
6995
  frontmatter: result.data,
5663
6996
  body: content.trim(),
5664
6997
  validate
@@ -5675,7 +7008,7 @@ var CursorRule = class _CursorRule extends ToolRule {
5675
7008
  return {
5676
7009
  success: false,
5677
7010
  error: new Error(
5678
- `Invalid frontmatter in ${join55(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
7011
+ `Invalid frontmatter in ${join68(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
5679
7012
  )
5680
7013
  };
5681
7014
  }
@@ -5695,7 +7028,7 @@ var CursorRule = class _CursorRule extends ToolRule {
5695
7028
  };
5696
7029
 
5697
7030
  // src/features/rules/geminicli-rule.ts
5698
- import { join as join56 } from "path";
7031
+ import { join as join69 } from "path";
5699
7032
  var GeminiCliRule = class _GeminiCliRule extends ToolRule {
5700
7033
  static getSettablePaths({
5701
7034
  global
@@ -5714,7 +7047,7 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
5714
7047
  relativeFilePath: "GEMINI.md"
5715
7048
  },
5716
7049
  nonRoot: {
5717
- relativeDirPath: join56(".gemini", "memories")
7050
+ relativeDirPath: join69(".gemini", "memories")
5718
7051
  }
5719
7052
  };
5720
7053
  }
@@ -5729,7 +7062,7 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
5729
7062
  if (isRoot) {
5730
7063
  const relativePath2 = paths.root.relativeFilePath;
5731
7064
  const fileContent2 = await readFileContent(
5732
- join56(baseDir, paths.root.relativeDirPath, relativePath2)
7065
+ join69(baseDir, paths.root.relativeDirPath, relativePath2)
5733
7066
  );
5734
7067
  return new _GeminiCliRule({
5735
7068
  baseDir,
@@ -5743,8 +7076,8 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
5743
7076
  if (!paths.nonRoot) {
5744
7077
  throw new Error("nonRoot path is not set");
5745
7078
  }
5746
- const relativePath = join56(paths.nonRoot.relativeDirPath, relativeFilePath);
5747
- const fileContent = await readFileContent(join56(baseDir, relativePath));
7079
+ const relativePath = join69(paths.nonRoot.relativeDirPath, relativeFilePath);
7080
+ const fileContent = await readFileContent(join69(baseDir, relativePath));
5748
7081
  return new _GeminiCliRule({
5749
7082
  baseDir,
5750
7083
  relativeDirPath: paths.nonRoot.relativeDirPath,
@@ -5786,7 +7119,7 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
5786
7119
  };
5787
7120
 
5788
7121
  // src/features/rules/junie-rule.ts
5789
- import { join as join57 } from "path";
7122
+ import { join as join70 } from "path";
5790
7123
  var JunieRule = class _JunieRule extends ToolRule {
5791
7124
  static getSettablePaths() {
5792
7125
  return {
@@ -5795,7 +7128,7 @@ var JunieRule = class _JunieRule extends ToolRule {
5795
7128
  relativeFilePath: "guidelines.md"
5796
7129
  },
5797
7130
  nonRoot: {
5798
- relativeDirPath: join57(".junie", "memories")
7131
+ relativeDirPath: join70(".junie", "memories")
5799
7132
  }
5800
7133
  };
5801
7134
  }
@@ -5805,8 +7138,8 @@ var JunieRule = class _JunieRule extends ToolRule {
5805
7138
  validate = true
5806
7139
  }) {
5807
7140
  const isRoot = relativeFilePath === "guidelines.md";
5808
- const relativePath = isRoot ? "guidelines.md" : join57(".junie", "memories", relativeFilePath);
5809
- const fileContent = await readFileContent(join57(baseDir, relativePath));
7141
+ const relativePath = isRoot ? "guidelines.md" : join70(".junie", "memories", relativeFilePath);
7142
+ const fileContent = await readFileContent(join70(baseDir, relativePath));
5810
7143
  return new _JunieRule({
5811
7144
  baseDir,
5812
7145
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -5846,12 +7179,12 @@ var JunieRule = class _JunieRule extends ToolRule {
5846
7179
  };
5847
7180
 
5848
7181
  // src/features/rules/kiro-rule.ts
5849
- import { join as join58 } from "path";
7182
+ import { join as join71 } from "path";
5850
7183
  var KiroRule = class _KiroRule extends ToolRule {
5851
7184
  static getSettablePaths() {
5852
7185
  return {
5853
7186
  nonRoot: {
5854
- relativeDirPath: join58(".kiro", "steering")
7187
+ relativeDirPath: join71(".kiro", "steering")
5855
7188
  }
5856
7189
  };
5857
7190
  }
@@ -5861,7 +7194,7 @@ var KiroRule = class _KiroRule extends ToolRule {
5861
7194
  validate = true
5862
7195
  }) {
5863
7196
  const fileContent = await readFileContent(
5864
- join58(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7197
+ join71(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
5865
7198
  );
5866
7199
  return new _KiroRule({
5867
7200
  baseDir,
@@ -5901,7 +7234,7 @@ var KiroRule = class _KiroRule extends ToolRule {
5901
7234
  };
5902
7235
 
5903
7236
  // src/features/rules/opencode-rule.ts
5904
- import { join as join59 } from "path";
7237
+ import { join as join72 } from "path";
5905
7238
  var OpenCodeRule = class _OpenCodeRule extends ToolRule {
5906
7239
  static getSettablePaths() {
5907
7240
  return {
@@ -5910,7 +7243,7 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
5910
7243
  relativeFilePath: "AGENTS.md"
5911
7244
  },
5912
7245
  nonRoot: {
5913
- relativeDirPath: join59(".opencode", "memories")
7246
+ relativeDirPath: join72(".opencode", "memories")
5914
7247
  }
5915
7248
  };
5916
7249
  }
@@ -5920,8 +7253,8 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
5920
7253
  validate = true
5921
7254
  }) {
5922
7255
  const isRoot = relativeFilePath === "AGENTS.md";
5923
- const relativePath = isRoot ? "AGENTS.md" : join59(".opencode", "memories", relativeFilePath);
5924
- const fileContent = await readFileContent(join59(baseDir, relativePath));
7256
+ const relativePath = isRoot ? "AGENTS.md" : join72(".opencode", "memories", relativeFilePath);
7257
+ const fileContent = await readFileContent(join72(baseDir, relativePath));
5925
7258
  return new _OpenCodeRule({
5926
7259
  baseDir,
5927
7260
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -5961,7 +7294,7 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
5961
7294
  };
5962
7295
 
5963
7296
  // src/features/rules/qwencode-rule.ts
5964
- import { join as join60 } from "path";
7297
+ import { join as join73 } from "path";
5965
7298
  var QwencodeRule = class _QwencodeRule extends ToolRule {
5966
7299
  static getSettablePaths() {
5967
7300
  return {
@@ -5970,7 +7303,7 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
5970
7303
  relativeFilePath: "QWEN.md"
5971
7304
  },
5972
7305
  nonRoot: {
5973
- relativeDirPath: join60(".qwen", "memories")
7306
+ relativeDirPath: join73(".qwen", "memories")
5974
7307
  }
5975
7308
  };
5976
7309
  }
@@ -5980,8 +7313,8 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
5980
7313
  validate = true
5981
7314
  }) {
5982
7315
  const isRoot = relativeFilePath === "QWEN.md";
5983
- const relativePath = isRoot ? "QWEN.md" : join60(".qwen", "memories", relativeFilePath);
5984
- const fileContent = await readFileContent(join60(baseDir, relativePath));
7316
+ const relativePath = isRoot ? "QWEN.md" : join73(".qwen", "memories", relativeFilePath);
7317
+ const fileContent = await readFileContent(join73(baseDir, relativePath));
5985
7318
  return new _QwencodeRule({
5986
7319
  baseDir,
5987
7320
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -6018,12 +7351,12 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
6018
7351
  };
6019
7352
 
6020
7353
  // src/features/rules/roo-rule.ts
6021
- import { join as join61 } from "path";
7354
+ import { join as join74 } from "path";
6022
7355
  var RooRule = class _RooRule extends ToolRule {
6023
7356
  static getSettablePaths() {
6024
7357
  return {
6025
7358
  nonRoot: {
6026
- relativeDirPath: join61(".roo", "rules")
7359
+ relativeDirPath: join74(".roo", "rules")
6027
7360
  }
6028
7361
  };
6029
7362
  }
@@ -6033,7 +7366,7 @@ var RooRule = class _RooRule extends ToolRule {
6033
7366
  validate = true
6034
7367
  }) {
6035
7368
  const fileContent = await readFileContent(
6036
- join61(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7369
+ join74(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
6037
7370
  );
6038
7371
  return new _RooRule({
6039
7372
  baseDir,
@@ -6088,7 +7421,7 @@ var RooRule = class _RooRule extends ToolRule {
6088
7421
  };
6089
7422
 
6090
7423
  // src/features/rules/warp-rule.ts
6091
- import { join as join62 } from "path";
7424
+ import { join as join75 } from "path";
6092
7425
  var WarpRule = class _WarpRule extends ToolRule {
6093
7426
  constructor({ fileContent, root, ...rest }) {
6094
7427
  super({
@@ -6104,7 +7437,7 @@ var WarpRule = class _WarpRule extends ToolRule {
6104
7437
  relativeFilePath: "WARP.md"
6105
7438
  },
6106
7439
  nonRoot: {
6107
- relativeDirPath: join62(".warp", "memories")
7440
+ relativeDirPath: join75(".warp", "memories")
6108
7441
  }
6109
7442
  };
6110
7443
  }
@@ -6114,8 +7447,8 @@ var WarpRule = class _WarpRule extends ToolRule {
6114
7447
  validate = true
6115
7448
  }) {
6116
7449
  const isRoot = relativeFilePath === this.getSettablePaths().root.relativeFilePath;
6117
- const relativePath = isRoot ? this.getSettablePaths().root.relativeFilePath : join62(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
6118
- const fileContent = await readFileContent(join62(baseDir, relativePath));
7450
+ const relativePath = isRoot ? this.getSettablePaths().root.relativeFilePath : join75(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
7451
+ const fileContent = await readFileContent(join75(baseDir, relativePath));
6119
7452
  return new _WarpRule({
6120
7453
  baseDir,
6121
7454
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : ".warp",
@@ -6155,12 +7488,12 @@ var WarpRule = class _WarpRule extends ToolRule {
6155
7488
  };
6156
7489
 
6157
7490
  // src/features/rules/windsurf-rule.ts
6158
- import { join as join63 } from "path";
7491
+ import { join as join76 } from "path";
6159
7492
  var WindsurfRule = class _WindsurfRule extends ToolRule {
6160
7493
  static getSettablePaths() {
6161
7494
  return {
6162
7495
  nonRoot: {
6163
- relativeDirPath: join63(".windsurf", "rules")
7496
+ relativeDirPath: join76(".windsurf", "rules")
6164
7497
  }
6165
7498
  };
6166
7499
  }
@@ -6170,7 +7503,7 @@ var WindsurfRule = class _WindsurfRule extends ToolRule {
6170
7503
  validate = true
6171
7504
  }) {
6172
7505
  const fileContent = await readFileContent(
6173
- join63(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7506
+ join76(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
6174
7507
  );
6175
7508
  return new _WindsurfRule({
6176
7509
  baseDir,
@@ -6228,7 +7561,7 @@ var rulesProcessorToolTargets = [
6228
7561
  "warp",
6229
7562
  "windsurf"
6230
7563
  ];
6231
- var RulesProcessorToolTargetSchema = z24.enum(rulesProcessorToolTargets);
7564
+ var RulesProcessorToolTargetSchema = z29.enum(rulesProcessorToolTargets);
6232
7565
  var rulesProcessorToolTargetsGlobal = [
6233
7566
  "claudecode",
6234
7567
  "codexcli",
@@ -6238,12 +7571,14 @@ var RulesProcessor = class extends FeatureProcessor {
6238
7571
  toolTarget;
6239
7572
  simulateCommands;
6240
7573
  simulateSubagents;
7574
+ simulateSkills;
6241
7575
  global;
6242
7576
  constructor({
6243
7577
  baseDir = process.cwd(),
6244
7578
  toolTarget,
6245
7579
  simulateCommands = false,
6246
7580
  simulateSubagents = false,
7581
+ simulateSkills = false,
6247
7582
  global = false
6248
7583
  }) {
6249
7584
  super({ baseDir });
@@ -6257,6 +7592,7 @@ var RulesProcessor = class extends FeatureProcessor {
6257
7592
  this.global = global;
6258
7593
  this.simulateCommands = simulateCommands;
6259
7594
  this.simulateSubagents = simulateSubagents;
7595
+ this.simulateSkills = simulateSkills;
6260
7596
  }
6261
7597
  async convertRulesyncFilesToToolFiles(rulesyncFiles) {
6262
7598
  const rulesyncRules = rulesyncFiles.filter(
@@ -6424,7 +7760,7 @@ var RulesProcessor = class extends FeatureProcessor {
6424
7760
  throw new Error(`Unsupported tool target: ${this.toolTarget}`);
6425
7761
  }
6426
7762
  }).filter((rule) => rule !== null);
6427
- const isSimulated = this.simulateCommands || this.simulateSubagents;
7763
+ const isSimulated = this.simulateCommands || this.simulateSubagents || this.simulateSkills;
6428
7764
  if (isSimulated && this.toolTarget === "cursor") {
6429
7765
  toolRules.push(
6430
7766
  new CursorRule({
@@ -6436,6 +7772,9 @@ var RulesProcessor = class extends FeatureProcessor {
6436
7772
  commands: { relativeDirPath: CursorCommand.getSettablePaths().relativeDirPath },
6437
7773
  subagents: {
6438
7774
  relativeDirPath: CursorSubagent.getSettablePaths().relativeDirPath
7775
+ },
7776
+ skills: {
7777
+ relativeDirPath: CursorSkill.getSettablePaths().relativeDirPath
6439
7778
  }
6440
7779
  }),
6441
7780
  relativeDirPath: CursorRule.getSettablePaths().nonRoot.relativeDirPath,
@@ -6497,6 +7836,9 @@ var RulesProcessor = class extends FeatureProcessor {
6497
7836
  this.generateXmlReferencesSection(toolRules) + this.generateAdditionalConventionsSection({
6498
7837
  subagents: {
6499
7838
  relativeDirPath: CodexCliSubagent.getSettablePaths().relativeDirPath
7839
+ },
7840
+ skills: {
7841
+ relativeDirPath: CodexCliSkill.getSettablePaths().relativeDirPath
6500
7842
  }
6501
7843
  }) + rootRule.getFileContent()
6502
7844
  );
@@ -6509,6 +7851,9 @@ var RulesProcessor = class extends FeatureProcessor {
6509
7851
  commands: { relativeDirPath: CopilotCommand.getSettablePaths().relativeDirPath },
6510
7852
  subagents: {
6511
7853
  relativeDirPath: CopilotSubagent.getSettablePaths().relativeDirPath
7854
+ },
7855
+ skills: {
7856
+ relativeDirPath: CopilotSkill.getSettablePaths().relativeDirPath
6512
7857
  }
6513
7858
  }) + rootRule.getFileContent()
6514
7859
  );
@@ -6570,10 +7915,10 @@ var RulesProcessor = class extends FeatureProcessor {
6570
7915
  * Load and parse rulesync rule files from .rulesync/rules/ directory
6571
7916
  */
6572
7917
  async loadRulesyncFiles() {
6573
- const files = await findFilesByGlobs(join64(RULESYNC_RULES_RELATIVE_DIR_PATH, "*.md"));
7918
+ const files = await findFilesByGlobs(join77(RULESYNC_RULES_RELATIVE_DIR_PATH, "*.md"));
6574
7919
  logger.debug(`Found ${files.length} rulesync files`);
6575
7920
  const rulesyncRules = await Promise.all(
6576
- files.map((file) => RulesyncRule.fromFile({ relativeFilePath: basename17(file) }))
7921
+ files.map((file) => RulesyncRule.fromFile({ relativeFilePath: basename19(file) }))
6577
7922
  );
6578
7923
  const rootRules = rulesyncRules.filter((rule) => rule.getFrontmatter().root);
6579
7924
  if (rootRules.length > 1) {
@@ -6591,17 +7936,19 @@ var RulesProcessor = class extends FeatureProcessor {
6591
7936
  return rulesyncRules;
6592
7937
  }
6593
7938
  async loadRulesyncFilesLegacy() {
6594
- const legacyFiles = await findFilesByGlobs(join64(RULESYNC_RELATIVE_DIR_PATH, "*.md"));
7939
+ const legacyFiles = await findFilesByGlobs(join77(RULESYNC_RELATIVE_DIR_PATH, "*.md"));
6595
7940
  logger.debug(`Found ${legacyFiles.length} legacy rulesync files`);
6596
7941
  return Promise.all(
6597
- legacyFiles.map((file) => RulesyncRule.fromFileLegacy({ relativeFilePath: basename17(file) }))
7942
+ legacyFiles.map((file) => RulesyncRule.fromFileLegacy({ relativeFilePath: basename19(file) }))
6598
7943
  );
6599
7944
  }
6600
7945
  /**
6601
7946
  * Implementation of abstract method from FeatureProcessor
6602
7947
  * Load tool-specific rule configurations and parse them into ToolRule instances
6603
7948
  */
6604
- async loadToolFiles() {
7949
+ async loadToolFiles({
7950
+ forDeletion: _forDeletion = false
7951
+ } = {}) {
6605
7952
  try {
6606
7953
  switch (this.toolTarget) {
6607
7954
  case "agentsmd":
@@ -6646,9 +7993,6 @@ var RulesProcessor = class extends FeatureProcessor {
6646
7993
  return [];
6647
7994
  }
6648
7995
  }
6649
- async loadToolFilesToDelete() {
6650
- return this.loadToolFiles();
6651
- }
6652
7996
  async loadToolRulesDefault({
6653
7997
  root,
6654
7998
  nonRoot
@@ -6658,13 +8002,13 @@ var RulesProcessor = class extends FeatureProcessor {
6658
8002
  return [];
6659
8003
  }
6660
8004
  const rootFilePaths = await findFilesByGlobs(
6661
- join64(this.baseDir, root.relativeDirPath ?? ".", root.relativeFilePath)
8005
+ join77(this.baseDir, root.relativeDirPath ?? ".", root.relativeFilePath)
6662
8006
  );
6663
8007
  return await Promise.all(
6664
8008
  rootFilePaths.map(
6665
8009
  (filePath) => root.fromFile({
6666
8010
  baseDir: this.baseDir,
6667
- relativeFilePath: basename17(filePath),
8011
+ relativeFilePath: basename19(filePath),
6668
8012
  global: this.global
6669
8013
  })
6670
8014
  )
@@ -6676,13 +8020,13 @@ var RulesProcessor = class extends FeatureProcessor {
6676
8020
  return [];
6677
8021
  }
6678
8022
  const nonRootFilePaths = await findFilesByGlobs(
6679
- join64(this.baseDir, nonRoot.relativeDirPath, `*.${nonRoot.extension}`)
8023
+ join77(this.baseDir, nonRoot.relativeDirPath, `*.${nonRoot.extension}`)
6680
8024
  );
6681
8025
  return await Promise.all(
6682
8026
  nonRootFilePaths.map(
6683
8027
  (filePath) => nonRoot.fromFile({
6684
8028
  baseDir: this.baseDir,
6685
- relativeFilePath: basename17(filePath),
8029
+ relativeFilePath: basename19(filePath),
6686
8030
  global: this.global
6687
8031
  })
6688
8032
  )
@@ -6969,12 +8313,12 @@ var RulesProcessor = class extends FeatureProcessor {
6969
8313
  * Implementation of abstract method from FeatureProcessor
6970
8314
  * Return the tool targets that this processor supports
6971
8315
  */
6972
- static getToolTargets() {
8316
+ static getToolTargets({ global = false } = {}) {
8317
+ if (global) {
8318
+ return rulesProcessorToolTargetsGlobal;
8319
+ }
6973
8320
  return rulesProcessorToolTargets;
6974
8321
  }
6975
- static getToolTargetsGlobal() {
6976
- return rulesProcessorToolTargetsGlobal;
6977
- }
6978
8322
  generateXmlReferencesSection(toolRules) {
6979
8323
  const toolRulesWithoutRoot = toolRules.filter((rule) => !rule.isRoot());
6980
8324
  if (toolRulesWithoutRoot.length === 0) {
@@ -7032,7 +8376,8 @@ var RulesProcessor = class extends FeatureProcessor {
7032
8376
  }
7033
8377
  generateAdditionalConventionsSection({
7034
8378
  commands,
7035
- subagents
8379
+ subagents,
8380
+ skills
7036
8381
  }) {
7037
8382
  const overview = `# Additional Conventions Beyond the Built-in Functions
7038
8383
 
@@ -7049,21 +8394,31 @@ Users can use following syntax to invoke a custom command.
7049
8394
  s/<command> [arguments]
7050
8395
  \`\`\`
7051
8396
 
7052
- This syntax employs a double slash (\`s/\`) to prevent conflicts with built-in slash commands.
8397
+ This syntax employs a double slash (\`s/\`) to prevent conflicts with built-in slash commands.
7053
8398
  The \`s\` in \`s/\` stands for *simulate*. Because custom slash commands are not built-in, this syntax provides a pseudo way to invoke them.
7054
8399
 
7055
- When users call a custom slash command, you have to look for the markdown file, \`${join64(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "{command}.md")}\`, then execute the contents of that file as the block of operations.` : "";
8400
+ When users call a custom slash command, you have to look for the markdown file, \`${join77(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "{command}.md")}\`, then execute the contents of that file as the block of operations.` : "";
7056
8401
  const subagentsSection = subagents ? `## Simulated Subagents
7057
8402
 
7058
8403
  Simulated subagents are specialized AI assistants that can be invoked to handle specific types of tasks. In this case, it can be appear something like custom slash commands simply. Simulated subagents can be called by custom slash commands.
7059
8404
 
7060
- When users call a simulated subagent, it will look for the corresponding markdown file, \`${join64(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "{subagent}.md")}\`, and execute its contents as the block of operations.
8405
+ When users call a simulated subagent, it will look for the corresponding markdown file, \`${join77(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "{subagent}.md")}\`, and execute its contents as the block of operations.
7061
8406
 
7062
- For example, if the user instructs \`Call planner subagent to plan the refactoring\`, you have to look for the markdown file, \`${join64(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "planner.md")}\`, and execute its contents as the block of operations.` : "";
8407
+ For example, if the user instructs \`Call planner subagent to plan the refactoring\`, you have to look for the markdown file, \`${join77(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "planner.md")}\`, and execute its contents as the block of operations.` : "";
8408
+ const skillsSection = skills ? `## Simulated Skills
8409
+
8410
+ Simulated skills are specialized capabilities that can be invoked to handle specific types of tasks.
8411
+
8412
+ When users invoke a simulated skill, look for the corresponding SKILL.md file in \`${join77(RULESYNC_SKILLS_RELATIVE_DIR_PATH, "{skill}/SKILL.md")}\` and execute its contents as the block of operations.
8413
+
8414
+ For example, if the user instructs \`Use the skill example-skill to achieve something\`, look for \`${join77(RULESYNC_SKILLS_RELATIVE_DIR_PATH, "example-skill/SKILL.md")}\` and execute its contents.
8415
+
8416
+ 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.` : "";
7063
8417
  const result = [
7064
8418
  overview,
7065
8419
  ...this.simulateCommands && CommandsProcessor.getToolTargetsSimulated().includes(this.toolTarget) ? [commandsSection] : [],
7066
- ...this.simulateSubagents && SubagentsProcessor.getToolTargetsSimulated().includes(this.toolTarget) ? [subagentsSection] : []
8420
+ ...this.simulateSubagents && SubagentsProcessor.getToolTargetsSimulated().includes(this.toolTarget) ? [subagentsSection] : [],
8421
+ ...this.simulateSkills && SkillsProcessor.getToolTargetsSimulated().includes(this.toolTarget) ? [skillsSection] : []
7067
8422
  ].join("\n\n") + "\n\n";
7068
8423
  return result;
7069
8424
  }
@@ -7084,7 +8439,8 @@ async function generateCommand(options) {
7084
8439
  const totalMcpOutputs = await generateMcp(config);
7085
8440
  const totalCommandOutputs = await generateCommands(config);
7086
8441
  const totalSubagentOutputs = await generateSubagents(config);
7087
- const totalGenerated = totalRulesOutputs + totalMcpOutputs + totalCommandOutputs + totalIgnoreOutputs + totalSubagentOutputs;
8442
+ const totalSkillOutputs = await generateSkills(config);
8443
+ const totalGenerated = totalRulesOutputs + totalMcpOutputs + totalCommandOutputs + totalIgnoreOutputs + totalSubagentOutputs + totalSkillOutputs;
7088
8444
  if (totalGenerated === 0) {
7089
8445
  const enabledFeatures = config.getFeatures().join(", ");
7090
8446
  logger.warn(`\u26A0\uFE0F No files generated for enabled features: ${enabledFeatures}`);
@@ -7097,6 +8453,7 @@ async function generateCommand(options) {
7097
8453
  if (totalMcpOutputs > 0) parts.push(`${totalMcpOutputs} MCP files`);
7098
8454
  if (totalCommandOutputs > 0) parts.push(`${totalCommandOutputs} commands`);
7099
8455
  if (totalSubagentOutputs > 0) parts.push(`${totalSubagentOutputs} subagents`);
8456
+ if (totalSkillOutputs > 0) parts.push(`${totalSkillOutputs} skills`);
7100
8457
  logger.success(`\u{1F389} All done! Generated ${totalGenerated} file(s) total (${parts.join(" + ")})`);
7101
8458
  }
7102
8459
  }
@@ -7107,18 +8464,22 @@ async function generateRules(config) {
7107
8464
  }
7108
8465
  let totalRulesOutputs = 0;
7109
8466
  logger.info("Generating rule files...");
7110
- const toolTargets = config.getGlobal() ? intersection(config.getTargets(), RulesProcessor.getToolTargetsGlobal()) : intersection(config.getTargets(), RulesProcessor.getToolTargets());
8467
+ const toolTargets = intersection(
8468
+ config.getTargets(),
8469
+ RulesProcessor.getToolTargets({ global: config.getGlobal() })
8470
+ );
7111
8471
  for (const baseDir of config.getBaseDirs()) {
7112
8472
  for (const toolTarget of toolTargets) {
7113
8473
  const processor = new RulesProcessor({
7114
8474
  baseDir,
7115
8475
  toolTarget,
7116
8476
  global: config.getGlobal(),
7117
- simulateCommands: config.getSimulatedCommands(),
7118
- simulateSubagents: config.getSimulatedSubagents()
8477
+ simulateCommands: config.getSimulateCommands(),
8478
+ simulateSubagents: config.getSimulateSubagents(),
8479
+ simulateSkills: config.getSimulateSkills()
7119
8480
  });
7120
8481
  if (config.getDelete()) {
7121
- const oldToolFiles = await processor.loadToolFilesToDelete();
8482
+ const oldToolFiles = await processor.loadToolFiles({ forDeletion: true });
7122
8483
  await processor.removeAiFiles(oldToolFiles);
7123
8484
  }
7124
8485
  let rulesyncFiles = await processor.loadRulesyncFiles();
@@ -7152,7 +8513,7 @@ async function generateIgnore(config) {
7152
8513
  toolTarget
7153
8514
  });
7154
8515
  if (config.getDelete()) {
7155
- const oldToolFiles = await processor.loadToolFilesToDelete();
8516
+ const oldToolFiles = await processor.loadToolFiles({ forDeletion: true });
7156
8517
  await processor.removeAiFiles(oldToolFiles);
7157
8518
  }
7158
8519
  const rulesyncFiles = await processor.loadRulesyncFiles();
@@ -7183,7 +8544,10 @@ async function generateMcp(config) {
7183
8544
  if (config.getModularMcp()) {
7184
8545
  logger.info("\u2139\uFE0F Modular MCP support is experimental.");
7185
8546
  }
7186
- const toolTargets = config.getGlobal() ? intersection(config.getTargets(), McpProcessor.getToolTargetsGlobal()) : intersection(config.getTargets(), McpProcessor.getToolTargets());
8547
+ const toolTargets = intersection(
8548
+ config.getTargets(),
8549
+ McpProcessor.getToolTargets({ global: config.getGlobal() })
8550
+ );
7187
8551
  for (const baseDir of config.getBaseDirs()) {
7188
8552
  for (const toolTarget of toolTargets) {
7189
8553
  const processor = new McpProcessor({
@@ -7193,7 +8557,7 @@ async function generateMcp(config) {
7193
8557
  modularMcp: config.getModularMcp()
7194
8558
  });
7195
8559
  if (config.getDelete()) {
7196
- const oldToolFiles = await processor.loadToolFilesToDelete();
8560
+ const oldToolFiles = await processor.loadToolFiles({ forDeletion: true });
7197
8561
  await processor.removeAiFiles(oldToolFiles);
7198
8562
  }
7199
8563
  const rulesyncFiles = await processor.loadRulesyncFiles();
@@ -7212,10 +8576,11 @@ async function generateCommands(config) {
7212
8576
  }
7213
8577
  let totalCommandOutputs = 0;
7214
8578
  logger.info("Generating command files...");
7215
- const toolTargets = config.getGlobal() ? intersection(config.getTargets(), CommandsProcessor.getToolTargetsGlobal()) : intersection(
8579
+ const toolTargets = intersection(
7216
8580
  config.getTargets(),
7217
8581
  CommandsProcessor.getToolTargets({
7218
- includeSimulated: config.getSimulatedCommands()
8582
+ global: config.getGlobal(),
8583
+ includeSimulated: config.getSimulateCommands()
7219
8584
  })
7220
8585
  );
7221
8586
  for (const baseDir of config.getBaseDirs()) {
@@ -7226,7 +8591,7 @@ async function generateCommands(config) {
7226
8591
  global: config.getGlobal()
7227
8592
  });
7228
8593
  if (config.getDelete()) {
7229
- const oldToolFiles = await processor.loadToolFilesToDelete();
8594
+ const oldToolFiles = await processor.loadToolFiles({ forDeletion: true });
7230
8595
  await processor.removeAiFiles(oldToolFiles);
7231
8596
  }
7232
8597
  const rulesyncFiles = await processor.loadRulesyncFiles();
@@ -7245,10 +8610,11 @@ async function generateSubagents(config) {
7245
8610
  }
7246
8611
  let totalSubagentOutputs = 0;
7247
8612
  logger.info("Generating subagent files...");
7248
- const toolTargets = config.getGlobal() ? intersection(config.getTargets(), SubagentsProcessor.getToolTargetsGlobal()) : intersection(
8613
+ const toolTargets = intersection(
7249
8614
  config.getTargets(),
7250
8615
  SubagentsProcessor.getToolTargets({
7251
- includeSimulated: config.getSimulatedSubagents()
8616
+ global: config.getGlobal(),
8617
+ includeSimulated: config.getSimulateSubagents()
7252
8618
  })
7253
8619
  );
7254
8620
  for (const baseDir of config.getBaseDirs()) {
@@ -7259,7 +8625,7 @@ async function generateSubagents(config) {
7259
8625
  global: config.getGlobal()
7260
8626
  });
7261
8627
  if (config.getDelete()) {
7262
- const oldToolFiles = await processor.loadToolFilesToDelete();
8628
+ const oldToolFiles = await processor.loadToolFiles({ forDeletion: true });
7263
8629
  await processor.removeAiFiles(oldToolFiles);
7264
8630
  }
7265
8631
  const rulesyncFiles = await processor.loadRulesyncFiles();
@@ -7271,16 +8637,51 @@ async function generateSubagents(config) {
7271
8637
  }
7272
8638
  return totalSubagentOutputs;
7273
8639
  }
8640
+ async function generateSkills(config) {
8641
+ if (!config.getFeatures().includes("skills")) {
8642
+ logger.debug("Skipping skill generation (not in --features)");
8643
+ return 0;
8644
+ }
8645
+ let totalSkillOutputs = 0;
8646
+ logger.info("Generating skill files...");
8647
+ const toolTargets = intersection(
8648
+ config.getTargets(),
8649
+ SkillsProcessor.getToolTargets({
8650
+ global: config.getGlobal(),
8651
+ includeSimulated: config.getSimulateSkills()
8652
+ })
8653
+ );
8654
+ for (const baseDir of config.getBaseDirs()) {
8655
+ for (const toolTarget of toolTargets) {
8656
+ const processor = new SkillsProcessor({
8657
+ baseDir,
8658
+ toolTarget,
8659
+ global: config.getGlobal()
8660
+ });
8661
+ if (config.getDelete()) {
8662
+ const oldToolDirs = await processor.loadToolDirsToDelete();
8663
+ await processor.removeAiDirs(oldToolDirs);
8664
+ }
8665
+ const rulesyncDirs = await processor.loadRulesyncDirs();
8666
+ const toolDirs = await processor.convertRulesyncDirsToToolDirs(rulesyncDirs);
8667
+ const writtenCount = await processor.writeAiDirs(toolDirs);
8668
+ totalSkillOutputs += writtenCount;
8669
+ logger.success(`Generated ${writtenCount} ${toolTarget} skill(s) in ${baseDir}`);
8670
+ }
8671
+ }
8672
+ return totalSkillOutputs;
8673
+ }
7274
8674
 
7275
8675
  // src/cli/commands/gitignore.ts
7276
- import { join as join65 } from "path";
8676
+ import { join as join78 } from "path";
7277
8677
  var gitignoreCommand = async () => {
7278
- const gitignorePath = join65(process.cwd(), ".gitignore");
8678
+ const gitignorePath = join78(process.cwd(), ".gitignore");
7279
8679
  const rulesFilesToIgnore = [
7280
8680
  "# Generated by rulesync - AI tool configuration files",
7281
8681
  // AGENTS.md
7282
8682
  "**/AGENTS.md",
7283
8683
  "**/.agents/",
8684
+ "**/.agents/skills/",
7284
8685
  // Amazon Q
7285
8686
  "**/.amazonq/",
7286
8687
  // Augment
@@ -7292,6 +8693,7 @@ var gitignoreCommand = async () => {
7292
8693
  "**/.claude/memories/",
7293
8694
  "**/.claude/commands/",
7294
8695
  "**/.claude/agents/",
8696
+ "**/.claude/skills/",
7295
8697
  "**/.claude/settings.local.json",
7296
8698
  "**/.mcp.json",
7297
8699
  // Cline
@@ -7301,20 +8703,25 @@ var gitignoreCommand = async () => {
7301
8703
  // Codex
7302
8704
  "**/.codexignore",
7303
8705
  "**/.codex/",
8706
+ "**/.codex/skills/",
7304
8707
  // Cursor
7305
8708
  "**/.cursor/",
7306
8709
  "**/.cursorignore",
7307
8710
  "**/.cursor/mcp.json",
8711
+ "**/.cursor/subagents/",
8712
+ "**/.cursor/skills/",
7308
8713
  // Gemini
7309
8714
  "**/GEMINI.md",
7310
8715
  "**/.gemini/memories/",
7311
8716
  "**/.gemini/commands/",
7312
8717
  "**/.gemini/subagents/",
8718
+ "**/.gemini/skills/",
7313
8719
  // GitHub Copilot
7314
8720
  "**/.github/copilot-instructions.md",
7315
8721
  "**/.github/instructions/",
7316
8722
  "**/.github/prompts/",
7317
8723
  "**/.github/subagents/",
8724
+ "**/.github/skills/",
7318
8725
  "**/.vscode/mcp.json",
7319
8726
  // Junie
7320
8727
  "**/.junie/guidelines.md",
@@ -7385,13 +8792,14 @@ async function importCommand(options) {
7385
8792
  await importMcp(config, tool);
7386
8793
  await importCommands(config, tool);
7387
8794
  await importSubagents(config, tool);
8795
+ await importSkills(config, tool);
7388
8796
  }
7389
8797
  async function importRules(config, tool) {
7390
8798
  if (!config.getFeatures().includes("rules")) {
7391
8799
  return 0;
7392
8800
  }
7393
8801
  const global = config.getGlobal();
7394
- const supportedTargets = global ? RulesProcessor.getToolTargetsGlobal() : RulesProcessor.getToolTargets();
8802
+ const supportedTargets = RulesProcessor.getToolTargets({ global });
7395
8803
  if (!supportedTargets.includes(tool)) {
7396
8804
  return 0;
7397
8805
  }
@@ -7445,7 +8853,7 @@ async function importMcp(config, tool) {
7445
8853
  return 0;
7446
8854
  }
7447
8855
  const global = config.getGlobal();
7448
- const supportedTargets = global ? McpProcessor.getToolTargetsGlobal() : McpProcessor.getToolTargets();
8856
+ const supportedTargets = McpProcessor.getToolTargets({ global });
7449
8857
  if (!supportedTargets.includes(tool)) {
7450
8858
  return 0;
7451
8859
  }
@@ -7470,7 +8878,7 @@ async function importCommands(config, tool) {
7470
8878
  return 0;
7471
8879
  }
7472
8880
  const global = config.getGlobal();
7473
- const supportedTargets = global ? CommandsProcessor.getToolTargetsGlobal() : CommandsProcessor.getToolTargets({ includeSimulated: false });
8881
+ const supportedTargets = CommandsProcessor.getToolTargets({ global, includeSimulated: false });
7474
8882
  if (!supportedTargets.includes(tool)) {
7475
8883
  return 0;
7476
8884
  }
@@ -7494,7 +8902,8 @@ async function importSubagents(config, tool) {
7494
8902
  if (!config.getFeatures().includes("subagents")) {
7495
8903
  return 0;
7496
8904
  }
7497
- const supportedTargets = SubagentsProcessor.getToolTargets({ includeSimulated: false });
8905
+ const global = config.getGlobal();
8906
+ const supportedTargets = SubagentsProcessor.getToolTargets({ global, includeSimulated: false });
7498
8907
  if (!supportedTargets.includes(tool)) {
7499
8908
  return 0;
7500
8909
  }
@@ -7514,9 +8923,34 @@ async function importSubagents(config, tool) {
7514
8923
  }
7515
8924
  return writtenCount;
7516
8925
  }
8926
+ async function importSkills(config, tool) {
8927
+ if (!config.getFeatures().includes("skills")) {
8928
+ return 0;
8929
+ }
8930
+ const global = config.getGlobal();
8931
+ const supportedTargets = SkillsProcessor.getToolTargets({ global });
8932
+ if (!supportedTargets.includes(tool)) {
8933
+ return 0;
8934
+ }
8935
+ const skillsProcessor = new SkillsProcessor({
8936
+ baseDir: config.getBaseDirs()[0] ?? ".",
8937
+ toolTarget: tool,
8938
+ global
8939
+ });
8940
+ const toolDirs = await skillsProcessor.loadToolDirs();
8941
+ if (toolDirs.length === 0) {
8942
+ return 0;
8943
+ }
8944
+ const rulesyncDirs = await skillsProcessor.convertToolDirsToRulesyncDirs(toolDirs);
8945
+ const writtenCount = await skillsProcessor.writeAiDirs(rulesyncDirs);
8946
+ if (config.getVerbose() && writtenCount > 0) {
8947
+ logger.success(`Created ${writtenCount} skill directories`);
8948
+ }
8949
+ return writtenCount;
8950
+ }
7517
8951
 
7518
8952
  // src/cli/commands/init.ts
7519
- import { join as join66 } from "path";
8953
+ import { join as join79 } from "path";
7520
8954
  async function initCommand() {
7521
8955
  logger.info("Initializing rulesync...");
7522
8956
  await ensureDir(RULESYNC_RELATIVE_DIR_PATH);
@@ -7544,8 +8978,8 @@ async function createConfigFile() {
7544
8978
  delete: true,
7545
8979
  verbose: false,
7546
8980
  global: false,
7547
- simulatedCommands: false,
7548
- simulatedSubagents: false,
8981
+ simulateCommands: false,
8982
+ simulateSubagents: false,
7549
8983
  modularMcp: false
7550
8984
  },
7551
8985
  null,
@@ -7679,14 +9113,14 @@ Attention, again, you are just the planner, so though you can read any files and
7679
9113
  await ensureDir(commandPaths.relativeDirPath);
7680
9114
  await ensureDir(subagentPaths.relativeDirPath);
7681
9115
  await ensureDir(ignorePaths.relativeDirPath);
7682
- const ruleFilepath = join66(rulePaths.recommended.relativeDirPath, sampleRuleFile.filename);
9116
+ const ruleFilepath = join79(rulePaths.recommended.relativeDirPath, sampleRuleFile.filename);
7683
9117
  if (!await fileExists(ruleFilepath)) {
7684
9118
  await writeFileContent(ruleFilepath, sampleRuleFile.content);
7685
9119
  logger.success(`Created ${ruleFilepath}`);
7686
9120
  } else {
7687
9121
  logger.info(`Skipped ${ruleFilepath} (already exists)`);
7688
9122
  }
7689
- const mcpFilepath = join66(
9123
+ const mcpFilepath = join79(
7690
9124
  mcpPaths.recommended.relativeDirPath,
7691
9125
  mcpPaths.recommended.relativeFilePath
7692
9126
  );
@@ -7696,21 +9130,21 @@ Attention, again, you are just the planner, so though you can read any files and
7696
9130
  } else {
7697
9131
  logger.info(`Skipped ${mcpFilepath} (already exists)`);
7698
9132
  }
7699
- const commandFilepath = join66(commandPaths.relativeDirPath, sampleCommandFile.filename);
9133
+ const commandFilepath = join79(commandPaths.relativeDirPath, sampleCommandFile.filename);
7700
9134
  if (!await fileExists(commandFilepath)) {
7701
9135
  await writeFileContent(commandFilepath, sampleCommandFile.content);
7702
9136
  logger.success(`Created ${commandFilepath}`);
7703
9137
  } else {
7704
9138
  logger.info(`Skipped ${commandFilepath} (already exists)`);
7705
9139
  }
7706
- const subagentFilepath = join66(subagentPaths.relativeDirPath, sampleSubagentFile.filename);
9140
+ const subagentFilepath = join79(subagentPaths.relativeDirPath, sampleSubagentFile.filename);
7707
9141
  if (!await fileExists(subagentFilepath)) {
7708
9142
  await writeFileContent(subagentFilepath, sampleSubagentFile.content);
7709
9143
  logger.success(`Created ${subagentFilepath}`);
7710
9144
  } else {
7711
9145
  logger.info(`Skipped ${subagentFilepath} (already exists)`);
7712
9146
  }
7713
- const ignoreFilepath = join66(ignorePaths.relativeDirPath, ignorePaths.relativeFilePath);
9147
+ const ignoreFilepath = join79(ignorePaths.relativeDirPath, ignorePaths.relativeFilePath);
7714
9148
  if (!await fileExists(ignoreFilepath)) {
7715
9149
  await writeFileContent(ignoreFilepath, sampleIgnoreFile.content);
7716
9150
  logger.success(`Created ${ignoreFilepath}`);
@@ -7723,12 +9157,12 @@ Attention, again, you are just the planner, so though you can read any files and
7723
9157
  import { FastMCP } from "fastmcp";
7724
9158
 
7725
9159
  // src/mcp/commands.ts
7726
- import { basename as basename18, join as join67 } from "path";
7727
- import { z as z25 } from "zod/mini";
9160
+ import { basename as basename20, join as join80 } from "path";
9161
+ import { z as z30 } from "zod/mini";
7728
9162
  var maxCommandSizeBytes = 1024 * 1024;
7729
9163
  var maxCommandsCount = 1e3;
7730
9164
  async function listCommands() {
7731
- const commandsDir = join67(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
9165
+ const commandsDir = join80(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
7732
9166
  try {
7733
9167
  const files = await listDirectoryFiles(commandsDir);
7734
9168
  const mdFiles = files.filter((file) => file.endsWith(".md"));
@@ -7740,7 +9174,7 @@ async function listCommands() {
7740
9174
  });
7741
9175
  const frontmatter = command.getFrontmatter();
7742
9176
  return {
7743
- relativePathFromCwd: join67(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, file),
9177
+ relativePathFromCwd: join80(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, file),
7744
9178
  frontmatter
7745
9179
  };
7746
9180
  } catch (error) {
@@ -7760,13 +9194,13 @@ async function getCommand({ relativePathFromCwd }) {
7760
9194
  relativePath: relativePathFromCwd,
7761
9195
  intendedRootDir: process.cwd()
7762
9196
  });
7763
- const filename = basename18(relativePathFromCwd);
9197
+ const filename = basename20(relativePathFromCwd);
7764
9198
  try {
7765
9199
  const command = await RulesyncCommand.fromFile({
7766
9200
  relativeFilePath: filename
7767
9201
  });
7768
9202
  return {
7769
- relativePathFromCwd: join67(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
9203
+ relativePathFromCwd: join80(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
7770
9204
  frontmatter: command.getFrontmatter(),
7771
9205
  body: command.getBody()
7772
9206
  };
@@ -7785,7 +9219,7 @@ async function putCommand({
7785
9219
  relativePath: relativePathFromCwd,
7786
9220
  intendedRootDir: process.cwd()
7787
9221
  });
7788
- const filename = basename18(relativePathFromCwd);
9222
+ const filename = basename20(relativePathFromCwd);
7789
9223
  const estimatedSize = JSON.stringify(frontmatter).length + body.length;
7790
9224
  if (estimatedSize > maxCommandSizeBytes) {
7791
9225
  throw new Error(
@@ -7795,7 +9229,7 @@ async function putCommand({
7795
9229
  try {
7796
9230
  const existingCommands = await listCommands();
7797
9231
  const isUpdate = existingCommands.some(
7798
- (command2) => command2.relativePathFromCwd === join67(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
9232
+ (command2) => command2.relativePathFromCwd === join80(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
7799
9233
  );
7800
9234
  if (!isUpdate && existingCommands.length >= maxCommandsCount) {
7801
9235
  throw new Error(`Maximum number of commands (${maxCommandsCount}) reached`);
@@ -7810,11 +9244,11 @@ async function putCommand({
7810
9244
  fileContent,
7811
9245
  validate: true
7812
9246
  });
7813
- const commandsDir = join67(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
9247
+ const commandsDir = join80(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
7814
9248
  await ensureDir(commandsDir);
7815
9249
  await writeFileContent(command.getFilePath(), command.getFileContent());
7816
9250
  return {
7817
- relativePathFromCwd: join67(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
9251
+ relativePathFromCwd: join80(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
7818
9252
  frontmatter: command.getFrontmatter(),
7819
9253
  body: command.getBody()
7820
9254
  };
@@ -7829,12 +9263,12 @@ async function deleteCommand({ relativePathFromCwd }) {
7829
9263
  relativePath: relativePathFromCwd,
7830
9264
  intendedRootDir: process.cwd()
7831
9265
  });
7832
- const filename = basename18(relativePathFromCwd);
7833
- const fullPath = join67(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename);
9266
+ const filename = basename20(relativePathFromCwd);
9267
+ const fullPath = join80(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename);
7834
9268
  try {
7835
9269
  await removeFile(fullPath);
7836
9270
  return {
7837
- relativePathFromCwd: join67(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
9271
+ relativePathFromCwd: join80(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
7838
9272
  };
7839
9273
  } catch (error) {
7840
9274
  throw new Error(`Failed to delete command file ${relativePathFromCwd}: ${formatError(error)}`, {
@@ -7843,23 +9277,23 @@ async function deleteCommand({ relativePathFromCwd }) {
7843
9277
  }
7844
9278
  }
7845
9279
  var commandToolSchemas = {
7846
- listCommands: z25.object({}),
7847
- getCommand: z25.object({
7848
- relativePathFromCwd: z25.string()
9280
+ listCommands: z30.object({}),
9281
+ getCommand: z30.object({
9282
+ relativePathFromCwd: z30.string()
7849
9283
  }),
7850
- putCommand: z25.object({
7851
- relativePathFromCwd: z25.string(),
9284
+ putCommand: z30.object({
9285
+ relativePathFromCwd: z30.string(),
7852
9286
  frontmatter: RulesyncCommandFrontmatterSchema,
7853
- body: z25.string()
9287
+ body: z30.string()
7854
9288
  }),
7855
- deleteCommand: z25.object({
7856
- relativePathFromCwd: z25.string()
9289
+ deleteCommand: z30.object({
9290
+ relativePathFromCwd: z30.string()
7857
9291
  })
7858
9292
  };
7859
9293
  var commandTools = {
7860
9294
  listCommands: {
7861
9295
  name: "listCommands",
7862
- description: `List all commands from ${join67(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
9296
+ description: `List all commands from ${join80(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
7863
9297
  parameters: commandToolSchemas.listCommands,
7864
9298
  execute: async () => {
7865
9299
  const commands = await listCommands();
@@ -7901,11 +9335,11 @@ var commandTools = {
7901
9335
  };
7902
9336
 
7903
9337
  // src/mcp/ignore.ts
7904
- import { join as join68 } from "path";
7905
- import { z as z26 } from "zod/mini";
9338
+ import { join as join81 } from "path";
9339
+ import { z as z31 } from "zod/mini";
7906
9340
  var maxIgnoreFileSizeBytes = 100 * 1024;
7907
9341
  async function getIgnoreFile() {
7908
- const ignoreFilePath = join68(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
9342
+ const ignoreFilePath = join81(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
7909
9343
  try {
7910
9344
  const content = await readFileContent(ignoreFilePath);
7911
9345
  return {
@@ -7919,7 +9353,7 @@ async function getIgnoreFile() {
7919
9353
  }
7920
9354
  }
7921
9355
  async function putIgnoreFile({ content }) {
7922
- const ignoreFilePath = join68(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
9356
+ const ignoreFilePath = join81(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
7923
9357
  const contentSizeBytes = Buffer.byteLength(content, "utf8");
7924
9358
  if (contentSizeBytes > maxIgnoreFileSizeBytes) {
7925
9359
  throw new Error(
@@ -7940,7 +9374,7 @@ async function putIgnoreFile({ content }) {
7940
9374
  }
7941
9375
  }
7942
9376
  async function deleteIgnoreFile() {
7943
- const ignoreFilePath = join68(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
9377
+ const ignoreFilePath = join81(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
7944
9378
  try {
7945
9379
  await removeFile(ignoreFilePath);
7946
9380
  return {
@@ -7953,11 +9387,11 @@ async function deleteIgnoreFile() {
7953
9387
  }
7954
9388
  }
7955
9389
  var ignoreToolSchemas = {
7956
- getIgnoreFile: z26.object({}),
7957
- putIgnoreFile: z26.object({
7958
- content: z26.string()
9390
+ getIgnoreFile: z31.object({}),
9391
+ putIgnoreFile: z31.object({
9392
+ content: z31.string()
7959
9393
  }),
7960
- deleteIgnoreFile: z26.object({})
9394
+ deleteIgnoreFile: z31.object({})
7961
9395
  };
7962
9396
  var ignoreTools = {
7963
9397
  getIgnoreFile: {
@@ -7990,8 +9424,8 @@ var ignoreTools = {
7990
9424
  };
7991
9425
 
7992
9426
  // src/mcp/mcp.ts
7993
- import { join as join69 } from "path";
7994
- import { z as z27 } from "zod/mini";
9427
+ import { join as join82 } from "path";
9428
+ import { z as z32 } from "zod/mini";
7995
9429
  var maxMcpSizeBytes = 1024 * 1024;
7996
9430
  async function getMcpFile() {
7997
9431
  const config = await ConfigResolver.resolve({});
@@ -8000,7 +9434,7 @@ async function getMcpFile() {
8000
9434
  validate: true,
8001
9435
  modularMcp: config.getModularMcp()
8002
9436
  });
8003
- const relativePathFromCwd = join69(
9437
+ const relativePathFromCwd = join82(
8004
9438
  rulesyncMcp.getRelativeDirPath(),
8005
9439
  rulesyncMcp.getRelativeFilePath()
8006
9440
  );
@@ -8033,7 +9467,7 @@ async function putMcpFile({ content }) {
8033
9467
  const paths = RulesyncMcp.getSettablePaths();
8034
9468
  const relativeDirPath = paths.recommended.relativeDirPath;
8035
9469
  const relativeFilePath = paths.recommended.relativeFilePath;
8036
- const fullPath = join69(baseDir, relativeDirPath, relativeFilePath);
9470
+ const fullPath = join82(baseDir, relativeDirPath, relativeFilePath);
8037
9471
  const rulesyncMcp = new RulesyncMcp({
8038
9472
  baseDir,
8039
9473
  relativeDirPath,
@@ -8042,9 +9476,9 @@ async function putMcpFile({ content }) {
8042
9476
  validate: true,
8043
9477
  modularMcp: config.getModularMcp()
8044
9478
  });
8045
- await ensureDir(join69(baseDir, relativeDirPath));
9479
+ await ensureDir(join82(baseDir, relativeDirPath));
8046
9480
  await writeFileContent(fullPath, content);
8047
- const relativePathFromCwd = join69(relativeDirPath, relativeFilePath);
9481
+ const relativePathFromCwd = join82(relativeDirPath, relativeFilePath);
8048
9482
  return {
8049
9483
  relativePathFromCwd,
8050
9484
  content: rulesyncMcp.getFileContent()
@@ -8059,15 +9493,15 @@ async function deleteMcpFile() {
8059
9493
  try {
8060
9494
  const baseDir = process.cwd();
8061
9495
  const paths = RulesyncMcp.getSettablePaths();
8062
- const recommendedPath = join69(
9496
+ const recommendedPath = join82(
8063
9497
  baseDir,
8064
9498
  paths.recommended.relativeDirPath,
8065
9499
  paths.recommended.relativeFilePath
8066
9500
  );
8067
- const legacyPath = join69(baseDir, paths.legacy.relativeDirPath, paths.legacy.relativeFilePath);
9501
+ const legacyPath = join82(baseDir, paths.legacy.relativeDirPath, paths.legacy.relativeFilePath);
8068
9502
  await removeFile(recommendedPath);
8069
9503
  await removeFile(legacyPath);
8070
- const relativePathFromCwd = join69(
9504
+ const relativePathFromCwd = join82(
8071
9505
  paths.recommended.relativeDirPath,
8072
9506
  paths.recommended.relativeFilePath
8073
9507
  );
@@ -8081,11 +9515,11 @@ async function deleteMcpFile() {
8081
9515
  }
8082
9516
  }
8083
9517
  var mcpToolSchemas = {
8084
- getMcpFile: z27.object({}),
8085
- putMcpFile: z27.object({
8086
- content: z27.string()
9518
+ getMcpFile: z32.object({}),
9519
+ putMcpFile: z32.object({
9520
+ content: z32.string()
8087
9521
  }),
8088
- deleteMcpFile: z27.object({})
9522
+ deleteMcpFile: z32.object({})
8089
9523
  };
8090
9524
  var mcpTools = {
8091
9525
  getMcpFile: {
@@ -8118,12 +9552,12 @@ var mcpTools = {
8118
9552
  };
8119
9553
 
8120
9554
  // src/mcp/rules.ts
8121
- import { basename as basename19, join as join70 } from "path";
8122
- import { z as z28 } from "zod/mini";
9555
+ import { basename as basename21, join as join83 } from "path";
9556
+ import { z as z33 } from "zod/mini";
8123
9557
  var maxRuleSizeBytes = 1024 * 1024;
8124
9558
  var maxRulesCount = 1e3;
8125
9559
  async function listRules() {
8126
- const rulesDir = join70(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
9560
+ const rulesDir = join83(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
8127
9561
  try {
8128
9562
  const files = await listDirectoryFiles(rulesDir);
8129
9563
  const mdFiles = files.filter((file) => file.endsWith(".md"));
@@ -8136,7 +9570,7 @@ async function listRules() {
8136
9570
  });
8137
9571
  const frontmatter = rule.getFrontmatter();
8138
9572
  return {
8139
- relativePathFromCwd: join70(RULESYNC_RULES_RELATIVE_DIR_PATH, file),
9573
+ relativePathFromCwd: join83(RULESYNC_RULES_RELATIVE_DIR_PATH, file),
8140
9574
  frontmatter
8141
9575
  };
8142
9576
  } catch (error) {
@@ -8156,14 +9590,14 @@ async function getRule({ relativePathFromCwd }) {
8156
9590
  relativePath: relativePathFromCwd,
8157
9591
  intendedRootDir: process.cwd()
8158
9592
  });
8159
- const filename = basename19(relativePathFromCwd);
9593
+ const filename = basename21(relativePathFromCwd);
8160
9594
  try {
8161
9595
  const rule = await RulesyncRule.fromFile({
8162
9596
  relativeFilePath: filename,
8163
9597
  validate: true
8164
9598
  });
8165
9599
  return {
8166
- relativePathFromCwd: join70(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
9600
+ relativePathFromCwd: join83(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
8167
9601
  frontmatter: rule.getFrontmatter(),
8168
9602
  body: rule.getBody()
8169
9603
  };
@@ -8182,7 +9616,7 @@ async function putRule({
8182
9616
  relativePath: relativePathFromCwd,
8183
9617
  intendedRootDir: process.cwd()
8184
9618
  });
8185
- const filename = basename19(relativePathFromCwd);
9619
+ const filename = basename21(relativePathFromCwd);
8186
9620
  const estimatedSize = JSON.stringify(frontmatter).length + body.length;
8187
9621
  if (estimatedSize > maxRuleSizeBytes) {
8188
9622
  throw new Error(
@@ -8192,7 +9626,7 @@ async function putRule({
8192
9626
  try {
8193
9627
  const existingRules = await listRules();
8194
9628
  const isUpdate = existingRules.some(
8195
- (rule2) => rule2.relativePathFromCwd === join70(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
9629
+ (rule2) => rule2.relativePathFromCwd === join83(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
8196
9630
  );
8197
9631
  if (!isUpdate && existingRules.length >= maxRulesCount) {
8198
9632
  throw new Error(`Maximum number of rules (${maxRulesCount}) reached`);
@@ -8205,11 +9639,11 @@ async function putRule({
8205
9639
  body,
8206
9640
  validate: true
8207
9641
  });
8208
- const rulesDir = join70(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
9642
+ const rulesDir = join83(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
8209
9643
  await ensureDir(rulesDir);
8210
9644
  await writeFileContent(rule.getFilePath(), rule.getFileContent());
8211
9645
  return {
8212
- relativePathFromCwd: join70(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
9646
+ relativePathFromCwd: join83(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
8213
9647
  frontmatter: rule.getFrontmatter(),
8214
9648
  body: rule.getBody()
8215
9649
  };
@@ -8224,12 +9658,12 @@ async function deleteRule({ relativePathFromCwd }) {
8224
9658
  relativePath: relativePathFromCwd,
8225
9659
  intendedRootDir: process.cwd()
8226
9660
  });
8227
- const filename = basename19(relativePathFromCwd);
8228
- const fullPath = join70(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH, filename);
9661
+ const filename = basename21(relativePathFromCwd);
9662
+ const fullPath = join83(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH, filename);
8229
9663
  try {
8230
9664
  await removeFile(fullPath);
8231
9665
  return {
8232
- relativePathFromCwd: join70(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
9666
+ relativePathFromCwd: join83(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
8233
9667
  };
8234
9668
  } catch (error) {
8235
9669
  throw new Error(`Failed to delete rule file ${relativePathFromCwd}: ${formatError(error)}`, {
@@ -8238,23 +9672,23 @@ async function deleteRule({ relativePathFromCwd }) {
8238
9672
  }
8239
9673
  }
8240
9674
  var ruleToolSchemas = {
8241
- listRules: z28.object({}),
8242
- getRule: z28.object({
8243
- relativePathFromCwd: z28.string()
9675
+ listRules: z33.object({}),
9676
+ getRule: z33.object({
9677
+ relativePathFromCwd: z33.string()
8244
9678
  }),
8245
- putRule: z28.object({
8246
- relativePathFromCwd: z28.string(),
9679
+ putRule: z33.object({
9680
+ relativePathFromCwd: z33.string(),
8247
9681
  frontmatter: RulesyncRuleFrontmatterSchema,
8248
- body: z28.string()
9682
+ body: z33.string()
8249
9683
  }),
8250
- deleteRule: z28.object({
8251
- relativePathFromCwd: z28.string()
9684
+ deleteRule: z33.object({
9685
+ relativePathFromCwd: z33.string()
8252
9686
  })
8253
9687
  };
8254
9688
  var ruleTools = {
8255
9689
  listRules: {
8256
9690
  name: "listRules",
8257
- description: `List all rules from ${join70(RULESYNC_RULES_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
9691
+ description: `List all rules from ${join83(RULESYNC_RULES_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
8258
9692
  parameters: ruleToolSchemas.listRules,
8259
9693
  execute: async () => {
8260
9694
  const rules = await listRules();
@@ -8296,12 +9730,12 @@ var ruleTools = {
8296
9730
  };
8297
9731
 
8298
9732
  // src/mcp/subagents.ts
8299
- import { basename as basename20, join as join71 } from "path";
8300
- import { z as z29 } from "zod/mini";
9733
+ import { basename as basename22, join as join84 } from "path";
9734
+ import { z as z34 } from "zod/mini";
8301
9735
  var maxSubagentSizeBytes = 1024 * 1024;
8302
9736
  var maxSubagentsCount = 1e3;
8303
9737
  async function listSubagents() {
8304
- const subagentsDir = join71(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
9738
+ const subagentsDir = join84(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
8305
9739
  try {
8306
9740
  const files = await listDirectoryFiles(subagentsDir);
8307
9741
  const mdFiles = files.filter((file) => file.endsWith(".md"));
@@ -8314,7 +9748,7 @@ async function listSubagents() {
8314
9748
  });
8315
9749
  const frontmatter = subagent.getFrontmatter();
8316
9750
  return {
8317
- relativePathFromCwd: join71(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, file),
9751
+ relativePathFromCwd: join84(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, file),
8318
9752
  frontmatter
8319
9753
  };
8320
9754
  } catch (error) {
@@ -8336,14 +9770,14 @@ async function getSubagent({ relativePathFromCwd }) {
8336
9770
  relativePath: relativePathFromCwd,
8337
9771
  intendedRootDir: process.cwd()
8338
9772
  });
8339
- const filename = basename20(relativePathFromCwd);
9773
+ const filename = basename22(relativePathFromCwd);
8340
9774
  try {
8341
9775
  const subagent = await RulesyncSubagent.fromFile({
8342
9776
  relativeFilePath: filename,
8343
9777
  validate: true
8344
9778
  });
8345
9779
  return {
8346
- relativePathFromCwd: join71(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
9780
+ relativePathFromCwd: join84(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
8347
9781
  frontmatter: subagent.getFrontmatter(),
8348
9782
  body: subagent.getBody()
8349
9783
  };
@@ -8362,7 +9796,7 @@ async function putSubagent({
8362
9796
  relativePath: relativePathFromCwd,
8363
9797
  intendedRootDir: process.cwd()
8364
9798
  });
8365
- const filename = basename20(relativePathFromCwd);
9799
+ const filename = basename22(relativePathFromCwd);
8366
9800
  const estimatedSize = JSON.stringify(frontmatter).length + body.length;
8367
9801
  if (estimatedSize > maxSubagentSizeBytes) {
8368
9802
  throw new Error(
@@ -8372,7 +9806,7 @@ async function putSubagent({
8372
9806
  try {
8373
9807
  const existingSubagents = await listSubagents();
8374
9808
  const isUpdate = existingSubagents.some(
8375
- (subagent2) => subagent2.relativePathFromCwd === join71(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
9809
+ (subagent2) => subagent2.relativePathFromCwd === join84(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
8376
9810
  );
8377
9811
  if (!isUpdate && existingSubagents.length >= maxSubagentsCount) {
8378
9812
  throw new Error(`Maximum number of subagents (${maxSubagentsCount}) reached`);
@@ -8385,11 +9819,11 @@ async function putSubagent({
8385
9819
  body,
8386
9820
  validate: true
8387
9821
  });
8388
- const subagentsDir = join71(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
9822
+ const subagentsDir = join84(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
8389
9823
  await ensureDir(subagentsDir);
8390
9824
  await writeFileContent(subagent.getFilePath(), subagent.getFileContent());
8391
9825
  return {
8392
- relativePathFromCwd: join71(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
9826
+ relativePathFromCwd: join84(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
8393
9827
  frontmatter: subagent.getFrontmatter(),
8394
9828
  body: subagent.getBody()
8395
9829
  };
@@ -8404,12 +9838,12 @@ async function deleteSubagent({ relativePathFromCwd }) {
8404
9838
  relativePath: relativePathFromCwd,
8405
9839
  intendedRootDir: process.cwd()
8406
9840
  });
8407
- const filename = basename20(relativePathFromCwd);
8408
- const fullPath = join71(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename);
9841
+ const filename = basename22(relativePathFromCwd);
9842
+ const fullPath = join84(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename);
8409
9843
  try {
8410
9844
  await removeFile(fullPath);
8411
9845
  return {
8412
- relativePathFromCwd: join71(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
9846
+ relativePathFromCwd: join84(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
8413
9847
  };
8414
9848
  } catch (error) {
8415
9849
  throw new Error(
@@ -8421,23 +9855,23 @@ async function deleteSubagent({ relativePathFromCwd }) {
8421
9855
  }
8422
9856
  }
8423
9857
  var subagentToolSchemas = {
8424
- listSubagents: z29.object({}),
8425
- getSubagent: z29.object({
8426
- relativePathFromCwd: z29.string()
9858
+ listSubagents: z34.object({}),
9859
+ getSubagent: z34.object({
9860
+ relativePathFromCwd: z34.string()
8427
9861
  }),
8428
- putSubagent: z29.object({
8429
- relativePathFromCwd: z29.string(),
9862
+ putSubagent: z34.object({
9863
+ relativePathFromCwd: z34.string(),
8430
9864
  frontmatter: RulesyncSubagentFrontmatterSchema,
8431
- body: z29.string()
9865
+ body: z34.string()
8432
9866
  }),
8433
- deleteSubagent: z29.object({
8434
- relativePathFromCwd: z29.string()
9867
+ deleteSubagent: z34.object({
9868
+ relativePathFromCwd: z34.string()
8435
9869
  })
8436
9870
  };
8437
9871
  var subagentTools = {
8438
9872
  listSubagents: {
8439
9873
  name: "listSubagents",
8440
- description: `List all subagents from ${join71(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
9874
+ description: `List all subagents from ${join84(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
8441
9875
  parameters: subagentToolSchemas.listSubagents,
8442
9876
  execute: async () => {
8443
9877
  const subagents = await listSubagents();
@@ -8511,7 +9945,7 @@ async function mcpCommand({ version }) {
8511
9945
  }
8512
9946
 
8513
9947
  // src/cli/index.ts
8514
- var getVersion = () => "3.23.6";
9948
+ var getVersion = () => "3.25.0";
8515
9949
  var main = async () => {
8516
9950
  const program = new Command();
8517
9951
  const version = getVersion();
@@ -8577,20 +10011,23 @@ var main = async () => {
8577
10011
  "-b, --base-dir <paths>",
8578
10012
  "Base directories to generate files (comma-separated for multiple paths)"
8579
10013
  ).option("-V, --verbose", "Verbose output").option("-c, --config <path>", "Path to configuration file").option("-g, --global", "Generate for global(user scope) configuration files").option(
8580
- "--simulated-commands",
10014
+ "--simulate-commands",
8581
10015
  "Generate simulated commands. This feature is only available for copilot, cursor and codexcli."
8582
10016
  ).option(
8583
- "--simulated-subagents",
10017
+ "--simulate-subagents",
8584
10018
  "Generate simulated subagents. This feature is only available for copilot, cursor and codexcli."
10019
+ ).option(
10020
+ "--simulate-skills",
10021
+ "Generate simulated skills. This feature is only available for copilot, cursor and codexcli."
8585
10022
  ).option(
8586
10023
  "--experimental-global",
8587
10024
  "Generate for global(user scope) configuration files (deprecated: use --global instead)"
8588
10025
  ).option(
8589
10026
  "--experimental-simulate-commands",
8590
- "Generate simulated commands (deprecated: use --simulated-commands instead)"
10027
+ "Generate simulated commands (deprecated: use --simulate-commands instead)"
8591
10028
  ).option(
8592
10029
  "--experimental-simulate-subagents",
8593
- "Generate simulated subagents (deprecated: use --simulated-subagents instead)"
10030
+ "Generate simulated subagents (deprecated: use --simulate-subagents instead)"
8594
10031
  ).option(
8595
10032
  "--modular-mcp",
8596
10033
  "Generate modular-mcp configuration for context compression (experimental)"
@@ -8604,8 +10041,9 @@ var main = async () => {
8604
10041
  baseDirs: options.baseDirs,
8605
10042
  configPath: options.config,
8606
10043
  global: options.global,
8607
- simulatedCommands: options.simulatedCommands,
8608
- simulatedSubagents: options.simulatedSubagents,
10044
+ simulateCommands: options.simulateCommands,
10045
+ simulateSubagents: options.simulateSubagents,
10046
+ simulateSkills: options.simulateSkills,
8609
10047
  modularMcp: options.modularMcp,
8610
10048
  experimentalGlobal: options.experimentalGlobal,
8611
10049
  experimentalSimulateCommands: options.experimentalSimulateCommands,