rulesync 3.19.0 → 3.20.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 +52 -0
  2. package/dist/index.cjs +1218 -615
  3. package/dist/index.js +1060 -457
  4. package/package.json +2 -2
package/dist/index.cjs CHANGED
@@ -107,9 +107,9 @@ var logger = new Logger();
107
107
  // src/cli/commands/generate.ts
108
108
  var import_es_toolkit2 = require("es-toolkit");
109
109
 
110
- // src/commands/commands-processor.ts
111
- var import_node_path12 = require("path");
112
- var import_mini9 = require("zod/mini");
110
+ // src/config/config-resolver.ts
111
+ var import_node_path2 = require("path");
112
+ var import_jsonc_parser = require("jsonc-parser");
113
113
 
114
114
  // src/utils/file.ts
115
115
  var import_node_fs = require("fs");
@@ -132,14 +132,24 @@ async function readOrInitializeFileContent(filePath, initialContent = "") {
132
132
  return initialContent;
133
133
  }
134
134
  }
135
- function resolvePath(relativePath, baseDir) {
136
- if (!baseDir) return relativePath;
137
- const resolved = (0, import_node_path.resolve)(baseDir, relativePath);
138
- const rel = (0, import_node_path.relative)(baseDir, resolved);
135
+ function checkPathTraversal({
136
+ relativePath,
137
+ intendedRootDir
138
+ }) {
139
+ const segments = relativePath.split(/[/\\]/);
140
+ if (segments.includes("..")) {
141
+ throw new Error(`Path traversal detected: ${relativePath}`);
142
+ }
143
+ const resolved = (0, import_node_path.resolve)(intendedRootDir, relativePath);
144
+ const rel = (0, import_node_path.relative)(intendedRootDir, resolved);
139
145
  if (rel.startsWith("..") || (0, import_node_path.resolve)(resolved) !== resolved) {
140
146
  throw new Error(`Path traversal detected: ${relativePath}`);
141
147
  }
142
- return resolved;
148
+ }
149
+ function resolvePath(relativePath, baseDir) {
150
+ if (!baseDir) return relativePath;
151
+ checkPathTraversal({ relativePath, intendedRootDir: baseDir });
152
+ return (0, import_node_path.resolve)(baseDir, relativePath);
143
153
  }
144
154
  async function directoryExists(dirPath) {
145
155
  try {
@@ -202,16 +212,252 @@ function validateBaseDir(baseDir) {
202
212
  if (baseDir.trim() === "") {
203
213
  throw new Error("baseDir cannot be an empty string");
204
214
  }
205
- if (baseDir.includes("..")) {
206
- throw new Error(`baseDir cannot contain directory traversal (..): ${baseDir}`);
215
+ checkPathTraversal({ relativePath: baseDir, intendedRootDir: process.cwd() });
216
+ }
217
+
218
+ // src/config/config.ts
219
+ var import_mini3 = require("zod/mini");
220
+
221
+ // src/types/tool-targets.ts
222
+ var import_mini2 = require("zod/mini");
223
+ var ALL_TOOL_TARGETS = [
224
+ "agentsmd",
225
+ "amazonqcli",
226
+ "augmentcode",
227
+ "augmentcode-legacy",
228
+ "copilot",
229
+ "cursor",
230
+ "cline",
231
+ "claudecode",
232
+ "codexcli",
233
+ "opencode",
234
+ "qwencode",
235
+ "roo",
236
+ "geminicli",
237
+ "kiro",
238
+ "junie",
239
+ "warp",
240
+ "windsurf"
241
+ ];
242
+ var ALL_TOOL_TARGETS_WITH_WILDCARD = [...ALL_TOOL_TARGETS, "*"];
243
+ var ToolTargetSchema = import_mini2.z.enum(ALL_TOOL_TARGETS);
244
+ var ToolTargetsSchema = import_mini2.z.array(ToolTargetSchema);
245
+ var RulesyncTargetsSchema = import_mini2.z.array(import_mini2.z.enum(ALL_TOOL_TARGETS_WITH_WILDCARD));
246
+
247
+ // src/config/config.ts
248
+ var ConfigParamsSchema = import_mini3.z.object({
249
+ baseDirs: import_mini3.z.array(import_mini3.z.string()),
250
+ targets: RulesyncTargetsSchema,
251
+ features: RulesyncFeaturesSchema,
252
+ verbose: import_mini3.z.boolean(),
253
+ delete: import_mini3.z.boolean(),
254
+ // New non-experimental options
255
+ global: (0, import_mini3.optional)(import_mini3.z.boolean()),
256
+ simulatedCommands: (0, import_mini3.optional)(import_mini3.z.boolean()),
257
+ simulatedSubagents: (0, import_mini3.optional)(import_mini3.z.boolean()),
258
+ modularMcp: (0, import_mini3.optional)(import_mini3.z.boolean()),
259
+ // Deprecated experimental options (for backward compatibility)
260
+ experimentalGlobal: (0, import_mini3.optional)(import_mini3.z.boolean()),
261
+ experimentalSimulateCommands: (0, import_mini3.optional)(import_mini3.z.boolean()),
262
+ experimentalSimulateSubagents: (0, import_mini3.optional)(import_mini3.z.boolean())
263
+ });
264
+ var PartialConfigParamsSchema = import_mini3.z.partial(ConfigParamsSchema);
265
+ var RequiredConfigParamsSchema = import_mini3.z.required(ConfigParamsSchema);
266
+ var Config = class {
267
+ baseDirs;
268
+ targets;
269
+ features;
270
+ verbose;
271
+ delete;
272
+ global;
273
+ simulatedCommands;
274
+ simulatedSubagents;
275
+ modularMcp;
276
+ constructor({
277
+ baseDirs,
278
+ targets,
279
+ features,
280
+ verbose,
281
+ delete: isDelete,
282
+ global,
283
+ simulatedCommands,
284
+ simulatedSubagents,
285
+ modularMcp,
286
+ experimentalGlobal,
287
+ experimentalSimulateCommands,
288
+ experimentalSimulateSubagents
289
+ }) {
290
+ this.baseDirs = baseDirs;
291
+ this.targets = targets;
292
+ this.features = features;
293
+ this.verbose = verbose;
294
+ this.delete = isDelete;
295
+ this.global = global ?? experimentalGlobal ?? false;
296
+ this.simulatedCommands = simulatedCommands ?? experimentalSimulateCommands ?? false;
297
+ this.simulatedSubagents = simulatedSubagents ?? experimentalSimulateSubagents ?? false;
298
+ this.modularMcp = modularMcp ?? false;
299
+ }
300
+ getBaseDirs() {
301
+ return this.baseDirs;
302
+ }
303
+ getTargets() {
304
+ if (this.targets.includes("*")) {
305
+ return [...ALL_TOOL_TARGETS];
306
+ }
307
+ return this.targets.filter((target) => target !== "*");
308
+ }
309
+ getFeatures() {
310
+ if (this.features.includes("*")) {
311
+ return [...ALL_FEATURES];
312
+ }
313
+ return this.features.filter((feature) => feature !== "*");
314
+ }
315
+ getVerbose() {
316
+ return this.verbose;
317
+ }
318
+ getDelete() {
319
+ return this.delete;
320
+ }
321
+ getGlobal() {
322
+ return this.global;
323
+ }
324
+ getSimulatedCommands() {
325
+ return this.simulatedCommands;
326
+ }
327
+ getSimulatedSubagents() {
328
+ return this.simulatedSubagents;
329
+ }
330
+ getModularMcp() {
331
+ return this.modularMcp;
332
+ }
333
+ // Deprecated getters for backward compatibility
334
+ /** @deprecated Use getGlobal() instead */
335
+ getExperimentalGlobal() {
336
+ return this.global;
337
+ }
338
+ /** @deprecated Use getSimulatedCommands() instead */
339
+ getExperimentalSimulateCommands() {
340
+ return this.simulatedCommands;
341
+ }
342
+ /** @deprecated Use getSimulatedSubagents() instead */
343
+ getExperimentalSimulateSubagents() {
344
+ return this.simulatedSubagents;
345
+ }
346
+ };
347
+
348
+ // src/config/config-resolver.ts
349
+ var defaults = {
350
+ targets: ["agentsmd"],
351
+ features: ["rules"],
352
+ verbose: false,
353
+ delete: false,
354
+ baseDirs: [process.cwd()],
355
+ configPath: "rulesync.jsonc",
356
+ global: false,
357
+ simulatedCommands: false,
358
+ simulatedSubagents: false,
359
+ modularMcp: false,
360
+ experimentalGlobal: false,
361
+ experimentalSimulateCommands: false,
362
+ experimentalSimulateSubagents: false
363
+ };
364
+ var ConfigResolver = class {
365
+ static async resolve({
366
+ targets,
367
+ features,
368
+ verbose,
369
+ delete: isDelete,
370
+ baseDirs,
371
+ configPath = defaults.configPath,
372
+ global,
373
+ simulatedCommands,
374
+ simulatedSubagents,
375
+ modularMcp,
376
+ experimentalGlobal,
377
+ experimentalSimulateCommands,
378
+ experimentalSimulateSubagents
379
+ }) {
380
+ const validatedConfigPath = resolvePath(configPath, process.cwd());
381
+ let configByFile = {};
382
+ if (await fileExists(validatedConfigPath)) {
383
+ try {
384
+ const fileContent = await readFileContent(validatedConfigPath);
385
+ const jsonData = (0, import_jsonc_parser.parse)(fileContent);
386
+ configByFile = PartialConfigParamsSchema.parse(jsonData);
387
+ } catch (error) {
388
+ logger.error(`Failed to load config file: ${formatError(error)}`);
389
+ throw error;
390
+ }
391
+ }
392
+ const deprecatedGlobal = experimentalGlobal ?? configByFile.experimentalGlobal;
393
+ const deprecatedCommands = experimentalSimulateCommands ?? configByFile.experimentalSimulateCommands;
394
+ const deprecatedSubagents = experimentalSimulateSubagents ?? configByFile.experimentalSimulateSubagents;
395
+ if (deprecatedGlobal !== void 0) {
396
+ warnDeprecatedOptions({ experimentalGlobal: deprecatedGlobal });
397
+ }
398
+ if (deprecatedCommands !== void 0) {
399
+ warnDeprecatedOptions({ experimentalSimulateCommands: deprecatedCommands });
400
+ }
401
+ if (deprecatedSubagents !== void 0) {
402
+ warnDeprecatedOptions({ experimentalSimulateSubagents: deprecatedSubagents });
403
+ }
404
+ const resolvedGlobal = global ?? configByFile.global ?? experimentalGlobal ?? configByFile.experimentalGlobal ?? defaults.global;
405
+ const resolvedSimulatedCommands = simulatedCommands ?? configByFile.simulatedCommands ?? experimentalSimulateCommands ?? configByFile.experimentalSimulateCommands ?? defaults.simulatedCommands;
406
+ const resolvedSimulatedSubagents = simulatedSubagents ?? configByFile.simulatedSubagents ?? experimentalSimulateSubagents ?? configByFile.experimentalSimulateSubagents ?? defaults.simulatedSubagents;
407
+ const configParams = {
408
+ targets: targets ?? configByFile.targets ?? defaults.targets,
409
+ features: features ?? configByFile.features ?? defaults.features,
410
+ verbose: verbose ?? configByFile.verbose ?? defaults.verbose,
411
+ delete: isDelete ?? configByFile.delete ?? defaults.delete,
412
+ baseDirs: getBaseDirsInLightOfGlobal({
413
+ baseDirs: baseDirs ?? configByFile.baseDirs ?? defaults.baseDirs,
414
+ global: resolvedGlobal
415
+ }),
416
+ global: resolvedGlobal,
417
+ simulatedCommands: resolvedSimulatedCommands,
418
+ simulatedSubagents: resolvedSimulatedSubagents,
419
+ modularMcp: modularMcp ?? configByFile.modularMcp ?? defaults.modularMcp
420
+ };
421
+ return new Config(configParams);
422
+ }
423
+ };
424
+ function warnDeprecatedOptions({
425
+ experimentalGlobal,
426
+ experimentalSimulateCommands,
427
+ experimentalSimulateSubagents
428
+ }) {
429
+ if (experimentalGlobal !== void 0) {
430
+ logger.warn("'experimentalGlobal' option is deprecated. Please use 'global' instead.");
431
+ }
432
+ if (experimentalSimulateCommands !== void 0) {
433
+ logger.warn(
434
+ "'experimentalSimulateCommands' option is deprecated. Please use 'simulatedCommands' instead."
435
+ );
436
+ }
437
+ if (experimentalSimulateSubagents !== void 0) {
438
+ logger.warn(
439
+ "'experimentalSimulateSubagents' option is deprecated. Please use 'simulatedSubagents' instead."
440
+ );
207
441
  }
208
- const normalized = (0, import_node_path.resolve)(baseDir);
209
- const rel = (0, import_node_path.relative)(process.cwd(), normalized);
210
- if (rel.startsWith("..")) {
211
- throw new Error(`baseDir cannot contain directory traversal (..): ${baseDir}`);
442
+ }
443
+ function getBaseDirsInLightOfGlobal({
444
+ baseDirs,
445
+ global
446
+ }) {
447
+ if (global) {
448
+ return [getHomeDirectory()];
212
449
  }
450
+ const resolvedBaseDirs = baseDirs.map((baseDir) => (0, import_node_path2.resolve)(baseDir));
451
+ resolvedBaseDirs.forEach((baseDir) => {
452
+ validateBaseDir(baseDir);
453
+ });
454
+ return resolvedBaseDirs;
213
455
  }
214
456
 
457
+ // src/features/commands/commands-processor.ts
458
+ var import_node_path13 = require("path");
459
+ var import_mini10 = require("zod/mini");
460
+
215
461
  // src/types/feature-processor.ts
216
462
  var FeatureProcessor = class {
217
463
  baseDir;
@@ -242,8 +488,8 @@ var FeatureProcessor = class {
242
488
  }
243
489
  };
244
490
 
245
- // src/commands/agentsmd-command.ts
246
- var import_node_path4 = require("path");
491
+ // src/features/commands/agentsmd-command.ts
492
+ var import_node_path5 = require("path");
247
493
 
248
494
  // src/utils/frontmatter.ts
249
495
  var import_gray_matter = __toESM(require("gray-matter"), 1);
@@ -294,12 +540,12 @@ function parseFrontmatter(content) {
294
540
  return { frontmatter, body };
295
541
  }
296
542
 
297
- // src/commands/simulated-command.ts
298
- var import_node_path3 = require("path");
299
- var import_mini2 = require("zod/mini");
543
+ // src/features/commands/simulated-command.ts
544
+ var import_node_path4 = require("path");
545
+ var import_mini4 = require("zod/mini");
300
546
 
301
547
  // src/types/ai-file.ts
302
- var import_node_path2 = __toESM(require("path"), 1);
548
+ var import_node_path3 = __toESM(require("path"), 1);
303
549
  var AiFile = class {
304
550
  /**
305
551
  * @example "."
@@ -354,11 +600,11 @@ var AiFile = class {
354
600
  return this.relativeFilePath;
355
601
  }
356
602
  getFilePath() {
357
- const fullPath = import_node_path2.default.join(this.baseDir, this.relativeDirPath, this.relativeFilePath);
358
- const resolvedFull = (0, import_node_path2.resolve)(fullPath);
359
- const resolvedBase = (0, import_node_path2.resolve)(this.baseDir);
360
- const rel = (0, import_node_path2.relative)(resolvedBase, resolvedFull);
361
- if (rel.startsWith("..") || import_node_path2.default.isAbsolute(rel)) {
603
+ const fullPath = import_node_path3.default.join(this.baseDir, this.relativeDirPath, this.relativeFilePath);
604
+ const resolvedFull = (0, import_node_path3.resolve)(fullPath);
605
+ const resolvedBase = (0, import_node_path3.resolve)(this.baseDir);
606
+ const rel = (0, import_node_path3.relative)(resolvedBase, resolvedFull);
607
+ if (rel.startsWith("..") || import_node_path3.default.isAbsolute(rel)) {
362
608
  throw new Error(
363
609
  `Path traversal detected: Final path escapes baseDir. baseDir="${this.baseDir}", relativeDirPath="${this.relativeDirPath}", relativeFilePath="${this.relativeFilePath}"`
364
610
  );
@@ -369,14 +615,14 @@ var AiFile = class {
369
615
  return this.fileContent;
370
616
  }
371
617
  getRelativePathFromCwd() {
372
- return import_node_path2.default.join(this.relativeDirPath, this.relativeFilePath);
618
+ return import_node_path3.default.join(this.relativeDirPath, this.relativeFilePath);
373
619
  }
374
620
  setFileContent(newFileContent) {
375
621
  this.fileContent = newFileContent;
376
622
  }
377
623
  };
378
624
 
379
- // src/commands/tool-command.ts
625
+ // src/features/commands/tool-command.ts
380
626
  var ToolCommand = class extends AiFile {
381
627
  static getSettablePaths() {
382
628
  throw new Error("Please implement this method in the subclass.");
@@ -446,9 +692,9 @@ var ToolCommand = class extends AiFile {
446
692
  }
447
693
  };
448
694
 
449
- // src/commands/simulated-command.ts
450
- var SimulatedCommandFrontmatterSchema = import_mini2.z.object({
451
- description: import_mini2.z.string()
695
+ // src/features/commands/simulated-command.ts
696
+ var SimulatedCommandFrontmatterSchema = import_mini4.z.object({
697
+ description: import_mini4.z.string()
452
698
  });
453
699
  var SimulatedCommand = class _SimulatedCommand extends ToolCommand {
454
700
  frontmatter;
@@ -458,7 +704,7 @@ var SimulatedCommand = class _SimulatedCommand extends ToolCommand {
458
704
  const result = SimulatedCommandFrontmatterSchema.safeParse(frontmatter);
459
705
  if (!result.success) {
460
706
  throw new Error(
461
- `Invalid frontmatter in ${(0, import_node_path3.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
707
+ `Invalid frontmatter in ${(0, import_node_path4.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
462
708
  );
463
709
  }
464
710
  }
@@ -508,7 +754,7 @@ var SimulatedCommand = class _SimulatedCommand extends ToolCommand {
508
754
  return {
509
755
  success: false,
510
756
  error: new Error(
511
- `Invalid frontmatter in ${(0, import_node_path3.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
757
+ `Invalid frontmatter in ${(0, import_node_path4.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
512
758
  )
513
759
  };
514
760
  }
@@ -518,7 +764,7 @@ var SimulatedCommand = class _SimulatedCommand extends ToolCommand {
518
764
  relativeFilePath,
519
765
  validate = true
520
766
  }) {
521
- const filePath = (0, import_node_path3.join)(
767
+ const filePath = (0, import_node_path4.join)(
522
768
  baseDir,
523
769
  _SimulatedCommand.getSettablePaths().relativeDirPath,
524
770
  relativeFilePath
@@ -532,7 +778,7 @@ var SimulatedCommand = class _SimulatedCommand extends ToolCommand {
532
778
  return {
533
779
  baseDir,
534
780
  relativeDirPath: _SimulatedCommand.getSettablePaths().relativeDirPath,
535
- relativeFilePath: (0, import_node_path3.basename)(relativeFilePath),
781
+ relativeFilePath: (0, import_node_path4.basename)(relativeFilePath),
536
782
  frontmatter: result.data,
537
783
  body: content.trim(),
538
784
  validate
@@ -540,11 +786,11 @@ var SimulatedCommand = class _SimulatedCommand extends ToolCommand {
540
786
  }
541
787
  };
542
788
 
543
- // src/commands/agentsmd-command.ts
789
+ // src/features/commands/agentsmd-command.ts
544
790
  var AgentsmdCommand = class _AgentsmdCommand extends SimulatedCommand {
545
791
  static getSettablePaths() {
546
792
  return {
547
- relativeDirPath: (0, import_node_path4.join)(".agents", "commands")
793
+ relativeDirPath: (0, import_node_path5.join)(".agents", "commands")
548
794
  };
549
795
  }
550
796
  static fromRulesyncCommand({
@@ -561,7 +807,7 @@ var AgentsmdCommand = class _AgentsmdCommand extends SimulatedCommand {
561
807
  relativeFilePath,
562
808
  validate = true
563
809
  }) {
564
- const filePath = (0, import_node_path4.join)(
810
+ const filePath = (0, import_node_path5.join)(
565
811
  baseDir,
566
812
  _AgentsmdCommand.getSettablePaths().relativeDirPath,
567
813
  relativeFilePath
@@ -575,7 +821,7 @@ var AgentsmdCommand = class _AgentsmdCommand extends SimulatedCommand {
575
821
  return new _AgentsmdCommand({
576
822
  baseDir,
577
823
  relativeDirPath: _AgentsmdCommand.getSettablePaths().relativeDirPath,
578
- relativeFilePath: (0, import_node_path4.basename)(relativeFilePath),
824
+ relativeFilePath: (0, import_node_path5.basename)(relativeFilePath),
579
825
  frontmatter: result.data,
580
826
  body: content.trim(),
581
827
  validate
@@ -589,14 +835,14 @@ var AgentsmdCommand = class _AgentsmdCommand extends SimulatedCommand {
589
835
  }
590
836
  };
591
837
 
592
- // src/commands/claudecode-command.ts
838
+ // src/features/commands/claudecode-command.ts
839
+ var import_node_path7 = require("path");
840
+ var import_mini6 = require("zod/mini");
841
+
842
+ // src/features/commands/rulesync-command.ts
593
843
  var import_node_path6 = require("path");
594
844
  var import_mini5 = require("zod/mini");
595
845
 
596
- // src/commands/rulesync-command.ts
597
- var import_node_path5 = require("path");
598
- var import_mini4 = require("zod/mini");
599
-
600
846
  // src/types/rulesync-file.ts
601
847
  var RulesyncFile = class extends AiFile {
602
848
  static async fromFile(_params) {
@@ -607,36 +853,10 @@ var RulesyncFile = class extends AiFile {
607
853
  }
608
854
  };
609
855
 
610
- // src/types/tool-targets.ts
611
- var import_mini3 = require("zod/mini");
612
- var ALL_TOOL_TARGETS = [
613
- "agentsmd",
614
- "amazonqcli",
615
- "augmentcode",
616
- "augmentcode-legacy",
617
- "copilot",
618
- "cursor",
619
- "cline",
620
- "claudecode",
621
- "codexcli",
622
- "opencode",
623
- "qwencode",
624
- "roo",
625
- "geminicli",
626
- "kiro",
627
- "junie",
628
- "warp",
629
- "windsurf"
630
- ];
631
- var ALL_TOOL_TARGETS_WITH_WILDCARD = [...ALL_TOOL_TARGETS, "*"];
632
- var ToolTargetSchema = import_mini3.z.enum(ALL_TOOL_TARGETS);
633
- var ToolTargetsSchema = import_mini3.z.array(ToolTargetSchema);
634
- var RulesyncTargetsSchema = import_mini3.z.array(import_mini3.z.enum(ALL_TOOL_TARGETS_WITH_WILDCARD));
635
-
636
- // src/commands/rulesync-command.ts
637
- var RulesyncCommandFrontmatterSchema = import_mini4.z.object({
856
+ // src/features/commands/rulesync-command.ts
857
+ var RulesyncCommandFrontmatterSchema = import_mini5.z.object({
638
858
  targets: RulesyncTargetsSchema,
639
- description: import_mini4.z.string()
859
+ description: import_mini5.z.string()
640
860
  });
641
861
  var RulesyncCommand = class _RulesyncCommand extends RulesyncFile {
642
862
  frontmatter;
@@ -646,7 +866,7 @@ var RulesyncCommand = class _RulesyncCommand extends RulesyncFile {
646
866
  const result = RulesyncCommandFrontmatterSchema.safeParse(frontmatter);
647
867
  if (!result.success) {
648
868
  throw new Error(
649
- `Invalid frontmatter in ${(0, import_node_path5.join)(rest.baseDir ?? process.cwd(), rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
869
+ `Invalid frontmatter in ${(0, import_node_path6.join)(rest.baseDir ?? process.cwd(), rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
650
870
  );
651
871
  }
652
872
  }
@@ -659,7 +879,7 @@ var RulesyncCommand = class _RulesyncCommand extends RulesyncFile {
659
879
  }
660
880
  static getSettablePaths() {
661
881
  return {
662
- relativeDirPath: (0, import_node_path5.join)(".rulesync", "commands")
882
+ relativeDirPath: (0, import_node_path6.join)(".rulesync", "commands")
663
883
  };
664
884
  }
665
885
  getFrontmatter() {
@@ -679,7 +899,7 @@ var RulesyncCommand = class _RulesyncCommand extends RulesyncFile {
679
899
  return {
680
900
  success: false,
681
901
  error: new Error(
682
- `Invalid frontmatter in ${(0, import_node_path5.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
902
+ `Invalid frontmatter in ${(0, import_node_path6.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
683
903
  )
684
904
  };
685
905
  }
@@ -687,15 +907,18 @@ var RulesyncCommand = class _RulesyncCommand extends RulesyncFile {
687
907
  static async fromFile({
688
908
  relativeFilePath
689
909
  }) {
690
- const fileContent = await readFileContent(
691
- (0, import_node_path5.join)(_RulesyncCommand.getSettablePaths().relativeDirPath, relativeFilePath)
910
+ const filePath = (0, import_node_path6.join)(
911
+ process.cwd(),
912
+ _RulesyncCommand.getSettablePaths().relativeDirPath,
913
+ relativeFilePath
692
914
  );
915
+ const fileContent = await readFileContent(filePath);
693
916
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
694
917
  const result = RulesyncCommandFrontmatterSchema.safeParse(frontmatter);
695
918
  if (!result.success) {
696
919
  throw new Error(`Invalid frontmatter in ${relativeFilePath}: ${formatError(result.error)}`);
697
920
  }
698
- const filename = (0, import_node_path5.basename)(relativeFilePath);
921
+ const filename = (0, import_node_path6.basename)(relativeFilePath);
699
922
  return new _RulesyncCommand({
700
923
  baseDir: process.cwd(),
701
924
  relativeDirPath: _RulesyncCommand.getSettablePaths().relativeDirPath,
@@ -707,9 +930,9 @@ var RulesyncCommand = class _RulesyncCommand extends RulesyncFile {
707
930
  }
708
931
  };
709
932
 
710
- // src/commands/claudecode-command.ts
711
- var ClaudecodeCommandFrontmatterSchema = import_mini5.z.object({
712
- description: import_mini5.z.string()
933
+ // src/features/commands/claudecode-command.ts
934
+ var ClaudecodeCommandFrontmatterSchema = import_mini6.z.object({
935
+ description: import_mini6.z.string()
713
936
  });
714
937
  var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
715
938
  frontmatter;
@@ -719,7 +942,7 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
719
942
  const result = ClaudecodeCommandFrontmatterSchema.safeParse(frontmatter);
720
943
  if (!result.success) {
721
944
  throw new Error(
722
- `Invalid frontmatter in ${(0, import_node_path6.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
945
+ `Invalid frontmatter in ${(0, import_node_path7.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
723
946
  );
724
947
  }
725
948
  }
@@ -732,7 +955,7 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
732
955
  }
733
956
  static getSettablePaths(_options = {}) {
734
957
  return {
735
- relativeDirPath: (0, import_node_path6.join)(".claude", "commands")
958
+ relativeDirPath: (0, import_node_path7.join)(".claude", "commands")
736
959
  };
737
960
  }
738
961
  getBody() {
@@ -790,7 +1013,7 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
790
1013
  return {
791
1014
  success: false,
792
1015
  error: new Error(
793
- `Invalid frontmatter in ${(0, import_node_path6.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
1016
+ `Invalid frontmatter in ${(0, import_node_path7.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
794
1017
  )
795
1018
  };
796
1019
  }
@@ -808,7 +1031,7 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
808
1031
  global = false
809
1032
  }) {
810
1033
  const paths = this.getSettablePaths({ global });
811
- const filePath = (0, import_node_path6.join)(baseDir, paths.relativeDirPath, relativeFilePath);
1034
+ const filePath = (0, import_node_path7.join)(baseDir, paths.relativeDirPath, relativeFilePath);
812
1035
  const fileContent = await readFileContent(filePath);
813
1036
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
814
1037
  const result = ClaudecodeCommandFrontmatterSchema.safeParse(frontmatter);
@@ -818,7 +1041,7 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
818
1041
  return new _ClaudecodeCommand({
819
1042
  baseDir,
820
1043
  relativeDirPath: paths.relativeDirPath,
821
- relativeFilePath: (0, import_node_path6.basename)(relativeFilePath),
1044
+ relativeFilePath: (0, import_node_path7.basename)(relativeFilePath),
822
1045
  frontmatter: result.data,
823
1046
  body: content.trim(),
824
1047
  validate
@@ -826,15 +1049,15 @@ var ClaudecodeCommand = class _ClaudecodeCommand extends ToolCommand {
826
1049
  }
827
1050
  };
828
1051
 
829
- // src/commands/codexcli-command.ts
830
- var import_node_path7 = require("path");
1052
+ // src/features/commands/codexcli-command.ts
1053
+ var import_node_path8 = require("path");
831
1054
  var CodexcliCommand = class _CodexcliCommand extends ToolCommand {
832
1055
  static getSettablePaths({ global } = {}) {
833
1056
  if (!global) {
834
1057
  throw new Error("CodexcliCommand only supports global mode. Please pass { global: true }.");
835
1058
  }
836
1059
  return {
837
- relativeDirPath: (0, import_node_path7.join)(".codex", "prompts")
1060
+ relativeDirPath: (0, import_node_path8.join)(".codex", "prompts")
838
1061
  };
839
1062
  }
840
1063
  toRulesyncCommand() {
@@ -887,25 +1110,25 @@ var CodexcliCommand = class _CodexcliCommand extends ToolCommand {
887
1110
  global = false
888
1111
  }) {
889
1112
  const paths = this.getSettablePaths({ global });
890
- const filePath = (0, import_node_path7.join)(baseDir, paths.relativeDirPath, relativeFilePath);
1113
+ const filePath = (0, import_node_path8.join)(baseDir, paths.relativeDirPath, relativeFilePath);
891
1114
  const fileContent = await readFileContent(filePath);
892
1115
  const { body: content } = parseFrontmatter(fileContent);
893
1116
  return new _CodexcliCommand({
894
1117
  baseDir,
895
1118
  relativeDirPath: paths.relativeDirPath,
896
- relativeFilePath: (0, import_node_path7.basename)(relativeFilePath),
1119
+ relativeFilePath: (0, import_node_path8.basename)(relativeFilePath),
897
1120
  fileContent: content.trim(),
898
1121
  validate
899
1122
  });
900
1123
  }
901
1124
  };
902
1125
 
903
- // src/commands/copilot-command.ts
904
- var import_node_path8 = require("path");
905
- var import_mini6 = require("zod/mini");
906
- var CopilotCommandFrontmatterSchema = import_mini6.z.object({
907
- mode: import_mini6.z.literal("agent"),
908
- description: import_mini6.z.string()
1126
+ // src/features/commands/copilot-command.ts
1127
+ var import_node_path9 = require("path");
1128
+ var import_mini7 = require("zod/mini");
1129
+ var CopilotCommandFrontmatterSchema = import_mini7.z.object({
1130
+ mode: import_mini7.z.literal("agent"),
1131
+ description: import_mini7.z.string()
909
1132
  });
910
1133
  var CopilotCommand = class _CopilotCommand extends ToolCommand {
911
1134
  frontmatter;
@@ -915,7 +1138,7 @@ var CopilotCommand = class _CopilotCommand extends ToolCommand {
915
1138
  const result = CopilotCommandFrontmatterSchema.safeParse(frontmatter);
916
1139
  if (!result.success) {
917
1140
  throw new Error(
918
- `Invalid frontmatter in ${(0, import_node_path8.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
1141
+ `Invalid frontmatter in ${(0, import_node_path9.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
919
1142
  );
920
1143
  }
921
1144
  }
@@ -928,7 +1151,7 @@ var CopilotCommand = class _CopilotCommand extends ToolCommand {
928
1151
  }
929
1152
  static getSettablePaths() {
930
1153
  return {
931
- relativeDirPath: (0, import_node_path8.join)(".github", "prompts")
1154
+ relativeDirPath: (0, import_node_path9.join)(".github", "prompts")
932
1155
  };
933
1156
  }
934
1157
  getBody() {
@@ -965,7 +1188,7 @@ var CopilotCommand = class _CopilotCommand extends ToolCommand {
965
1188
  return {
966
1189
  success: false,
967
1190
  error: new Error(
968
- `Invalid frontmatter in ${(0, import_node_path8.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
1191
+ `Invalid frontmatter in ${(0, import_node_path9.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
969
1192
  )
970
1193
  };
971
1194
  }
@@ -999,7 +1222,7 @@ var CopilotCommand = class _CopilotCommand extends ToolCommand {
999
1222
  validate = true
1000
1223
  }) {
1001
1224
  const paths = this.getSettablePaths();
1002
- const filePath = (0, import_node_path8.join)(baseDir, paths.relativeDirPath, relativeFilePath);
1225
+ const filePath = (0, import_node_path9.join)(baseDir, paths.relativeDirPath, relativeFilePath);
1003
1226
  const fileContent = await readFileContent(filePath);
1004
1227
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
1005
1228
  const result = CopilotCommandFrontmatterSchema.safeParse(frontmatter);
@@ -1009,7 +1232,7 @@ var CopilotCommand = class _CopilotCommand extends ToolCommand {
1009
1232
  return new _CopilotCommand({
1010
1233
  baseDir,
1011
1234
  relativeDirPath: paths.relativeDirPath,
1012
- relativeFilePath: (0, import_node_path8.basename)(relativeFilePath),
1235
+ relativeFilePath: (0, import_node_path9.basename)(relativeFilePath),
1013
1236
  frontmatter: result.data,
1014
1237
  body: content.trim(),
1015
1238
  validate
@@ -1023,12 +1246,12 @@ var CopilotCommand = class _CopilotCommand extends ToolCommand {
1023
1246
  }
1024
1247
  };
1025
1248
 
1026
- // src/commands/cursor-command.ts
1027
- var import_node_path9 = require("path");
1249
+ // src/features/commands/cursor-command.ts
1250
+ var import_node_path10 = require("path");
1028
1251
  var CursorCommand = class _CursorCommand extends ToolCommand {
1029
1252
  static getSettablePaths(_options = {}) {
1030
1253
  return {
1031
- relativeDirPath: (0, import_node_path9.join)(".cursor", "commands")
1254
+ relativeDirPath: (0, import_node_path10.join)(".cursor", "commands")
1032
1255
  };
1033
1256
  }
1034
1257
  toRulesyncCommand() {
@@ -1081,26 +1304,26 @@ var CursorCommand = class _CursorCommand extends ToolCommand {
1081
1304
  global = false
1082
1305
  }) {
1083
1306
  const paths = this.getSettablePaths({ global });
1084
- const filePath = (0, import_node_path9.join)(baseDir, paths.relativeDirPath, relativeFilePath);
1307
+ const filePath = (0, import_node_path10.join)(baseDir, paths.relativeDirPath, relativeFilePath);
1085
1308
  const fileContent = await readFileContent(filePath);
1086
1309
  const { body: content } = parseFrontmatter(fileContent);
1087
1310
  return new _CursorCommand({
1088
1311
  baseDir,
1089
1312
  relativeDirPath: paths.relativeDirPath,
1090
- relativeFilePath: (0, import_node_path9.basename)(relativeFilePath),
1313
+ relativeFilePath: (0, import_node_path10.basename)(relativeFilePath),
1091
1314
  fileContent: content.trim(),
1092
1315
  validate
1093
1316
  });
1094
1317
  }
1095
1318
  };
1096
1319
 
1097
- // src/commands/geminicli-command.ts
1098
- var import_node_path10 = require("path");
1320
+ // src/features/commands/geminicli-command.ts
1321
+ var import_node_path11 = require("path");
1099
1322
  var import_smol_toml = require("smol-toml");
1100
- var import_mini7 = require("zod/mini");
1101
- var GeminiCliCommandFrontmatterSchema = import_mini7.z.object({
1102
- description: import_mini7.z.optional(import_mini7.z.string()),
1103
- prompt: import_mini7.z.string()
1323
+ var import_mini8 = require("zod/mini");
1324
+ var GeminiCliCommandFrontmatterSchema = import_mini8.z.object({
1325
+ description: import_mini8.z.optional(import_mini8.z.string()),
1326
+ prompt: import_mini8.z.string()
1104
1327
  });
1105
1328
  var GeminiCliCommand = class _GeminiCliCommand extends ToolCommand {
1106
1329
  frontmatter;
@@ -1113,7 +1336,7 @@ var GeminiCliCommand = class _GeminiCliCommand extends ToolCommand {
1113
1336
  }
1114
1337
  static getSettablePaths(_options = {}) {
1115
1338
  return {
1116
- relativeDirPath: (0, import_node_path10.join)(".gemini", "commands")
1339
+ relativeDirPath: (0, import_node_path11.join)(".gemini", "commands")
1117
1340
  };
1118
1341
  }
1119
1342
  parseTomlContent(content) {
@@ -1190,12 +1413,12 @@ ${geminiFrontmatter.prompt}
1190
1413
  global = false
1191
1414
  }) {
1192
1415
  const paths = this.getSettablePaths({ global });
1193
- const filePath = (0, import_node_path10.join)(baseDir, paths.relativeDirPath, relativeFilePath);
1416
+ const filePath = (0, import_node_path11.join)(baseDir, paths.relativeDirPath, relativeFilePath);
1194
1417
  const fileContent = await readFileContent(filePath);
1195
1418
  return new _GeminiCliCommand({
1196
1419
  baseDir,
1197
1420
  relativeDirPath: paths.relativeDirPath,
1198
- relativeFilePath: (0, import_node_path10.basename)(relativeFilePath),
1421
+ relativeFilePath: (0, import_node_path11.basename)(relativeFilePath),
1199
1422
  fileContent,
1200
1423
  validate
1201
1424
  });
@@ -1216,19 +1439,19 @@ ${geminiFrontmatter.prompt}
1216
1439
  }
1217
1440
  };
1218
1441
 
1219
- // src/commands/roo-command.ts
1220
- var import_node_path11 = require("path");
1221
- var import_mini8 = require("zod/mini");
1222
- var RooCommandFrontmatterSchema = import_mini8.z.object({
1223
- description: import_mini8.z.string(),
1224
- "argument-hint": (0, import_mini8.optional)(import_mini8.z.string())
1442
+ // src/features/commands/roo-command.ts
1443
+ var import_node_path12 = require("path");
1444
+ var import_mini9 = require("zod/mini");
1445
+ var RooCommandFrontmatterSchema = import_mini9.z.object({
1446
+ description: import_mini9.z.string(),
1447
+ "argument-hint": (0, import_mini9.optional)(import_mini9.z.string())
1225
1448
  });
1226
1449
  var RooCommand = class _RooCommand extends ToolCommand {
1227
1450
  frontmatter;
1228
1451
  body;
1229
1452
  static getSettablePaths() {
1230
1453
  return {
1231
- relativeDirPath: (0, import_node_path11.join)(".roo", "commands")
1454
+ relativeDirPath: (0, import_node_path12.join)(".roo", "commands")
1232
1455
  };
1233
1456
  }
1234
1457
  constructor({ frontmatter, body, ...rest }) {
@@ -1236,7 +1459,7 @@ var RooCommand = class _RooCommand extends ToolCommand {
1236
1459
  const result = RooCommandFrontmatterSchema.safeParse(frontmatter);
1237
1460
  if (!result.success) {
1238
1461
  throw new Error(
1239
- `Invalid frontmatter in ${(0, import_node_path11.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
1462
+ `Invalid frontmatter in ${(0, import_node_path12.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
1240
1463
  );
1241
1464
  }
1242
1465
  }
@@ -1302,7 +1525,7 @@ var RooCommand = class _RooCommand extends ToolCommand {
1302
1525
  return {
1303
1526
  success: false,
1304
1527
  error: new Error(
1305
- `Invalid frontmatter in ${(0, import_node_path11.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
1528
+ `Invalid frontmatter in ${(0, import_node_path12.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
1306
1529
  )
1307
1530
  };
1308
1531
  }
@@ -1318,7 +1541,7 @@ var RooCommand = class _RooCommand extends ToolCommand {
1318
1541
  relativeFilePath,
1319
1542
  validate = true
1320
1543
  }) {
1321
- const filePath = (0, import_node_path11.join)(baseDir, _RooCommand.getSettablePaths().relativeDirPath, relativeFilePath);
1544
+ const filePath = (0, import_node_path12.join)(baseDir, _RooCommand.getSettablePaths().relativeDirPath, relativeFilePath);
1322
1545
  const fileContent = await readFileContent(filePath);
1323
1546
  const { frontmatter, body: content } = parseFrontmatter(fileContent);
1324
1547
  const result = RooCommandFrontmatterSchema.safeParse(frontmatter);
@@ -1328,7 +1551,7 @@ var RooCommand = class _RooCommand extends ToolCommand {
1328
1551
  return new _RooCommand({
1329
1552
  baseDir,
1330
1553
  relativeDirPath: _RooCommand.getSettablePaths().relativeDirPath,
1331
- relativeFilePath: (0, import_node_path11.basename)(relativeFilePath),
1554
+ relativeFilePath: (0, import_node_path12.basename)(relativeFilePath),
1332
1555
  frontmatter: result.data,
1333
1556
  body: content.trim(),
1334
1557
  fileContent,
@@ -1337,7 +1560,7 @@ var RooCommand = class _RooCommand extends ToolCommand {
1337
1560
  }
1338
1561
  };
1339
1562
 
1340
- // src/commands/commands-processor.ts
1563
+ // src/features/commands/commands-processor.ts
1341
1564
  var commandsProcessorToolTargets = [
1342
1565
  "agentsmd",
1343
1566
  "claudecode",
@@ -1346,7 +1569,7 @@ var commandsProcessorToolTargets = [
1346
1569
  "copilot",
1347
1570
  "cursor"
1348
1571
  ];
1349
- var CommandsProcessorToolTargetSchema = import_mini9.z.enum(
1572
+ var CommandsProcessorToolTargetSchema = import_mini10.z.enum(
1350
1573
  // 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
1351
1574
  commandsProcessorToolTargets.concat("codexcli")
1352
1575
  );
@@ -1464,11 +1687,11 @@ var CommandsProcessor = class extends FeatureProcessor {
1464
1687
  */
1465
1688
  async loadRulesyncFiles() {
1466
1689
  const rulesyncCommandPaths = await findFilesByGlobs(
1467
- (0, import_node_path12.join)(RulesyncCommand.getSettablePaths().relativeDirPath, "*.md")
1690
+ (0, import_node_path13.join)(RulesyncCommand.getSettablePaths().relativeDirPath, "*.md")
1468
1691
  );
1469
1692
  const rulesyncCommands = (await Promise.allSettled(
1470
1693
  rulesyncCommandPaths.map(
1471
- (path2) => RulesyncCommand.fromFile({ relativeFilePath: (0, import_node_path12.basename)(path2) })
1694
+ (path2) => RulesyncCommand.fromFile({ relativeFilePath: (0, import_node_path13.basename)(path2) })
1472
1695
  )
1473
1696
  )).filter((result) => result.status === "fulfilled").map((result) => result.value);
1474
1697
  logger.info(`Successfully loaded ${rulesyncCommands.length} rulesync commands`);
@@ -1507,7 +1730,7 @@ var CommandsProcessor = class extends FeatureProcessor {
1507
1730
  extension
1508
1731
  }) {
1509
1732
  const commandFilePaths = await findFilesByGlobs(
1510
- (0, import_node_path12.join)(this.baseDir, relativeDirPath, `*.${extension}`)
1733
+ (0, import_node_path13.join)(this.baseDir, relativeDirPath, `*.${extension}`)
1511
1734
  );
1512
1735
  const toolCommands = (await Promise.allSettled(
1513
1736
  commandFilePaths.map((path2) => {
@@ -1515,40 +1738,40 @@ var CommandsProcessor = class extends FeatureProcessor {
1515
1738
  case "agentsmd":
1516
1739
  return AgentsmdCommand.fromFile({
1517
1740
  baseDir: this.baseDir,
1518
- relativeFilePath: (0, import_node_path12.basename)(path2)
1741
+ relativeFilePath: (0, import_node_path13.basename)(path2)
1519
1742
  });
1520
1743
  case "claudecode":
1521
1744
  return ClaudecodeCommand.fromFile({
1522
1745
  baseDir: this.baseDir,
1523
- relativeFilePath: (0, import_node_path12.basename)(path2),
1746
+ relativeFilePath: (0, import_node_path13.basename)(path2),
1524
1747
  global: this.global
1525
1748
  });
1526
1749
  case "geminicli":
1527
1750
  return GeminiCliCommand.fromFile({
1528
1751
  baseDir: this.baseDir,
1529
- relativeFilePath: (0, import_node_path12.basename)(path2),
1752
+ relativeFilePath: (0, import_node_path13.basename)(path2),
1530
1753
  global: this.global
1531
1754
  });
1532
1755
  case "roo":
1533
1756
  return RooCommand.fromFile({
1534
1757
  baseDir: this.baseDir,
1535
- relativeFilePath: (0, import_node_path12.basename)(path2)
1758
+ relativeFilePath: (0, import_node_path13.basename)(path2)
1536
1759
  });
1537
1760
  case "copilot":
1538
1761
  return CopilotCommand.fromFile({
1539
1762
  baseDir: this.baseDir,
1540
- relativeFilePath: (0, import_node_path12.basename)(path2)
1763
+ relativeFilePath: (0, import_node_path13.basename)(path2)
1541
1764
  });
1542
1765
  case "cursor":
1543
1766
  return CursorCommand.fromFile({
1544
1767
  baseDir: this.baseDir,
1545
- relativeFilePath: (0, import_node_path12.basename)(path2),
1768
+ relativeFilePath: (0, import_node_path13.basename)(path2),
1546
1769
  global: this.global
1547
1770
  });
1548
1771
  case "codexcli":
1549
1772
  return CodexcliCommand.fromFile({
1550
1773
  baseDir: this.baseDir,
1551
- relativeFilePath: (0, import_node_path12.basename)(path2),
1774
+ relativeFilePath: (0, import_node_path13.basename)(path2),
1552
1775
  global: this.global
1553
1776
  });
1554
1777
  default:
@@ -1655,353 +1878,138 @@ var CommandsProcessor = class extends FeatureProcessor {
1655
1878
  }
1656
1879
  };
1657
1880
 
1658
- // src/config/config-resolver.ts
1659
- var import_node_path13 = require("path");
1660
- var import_jsonc_parser = require("jsonc-parser");
1881
+ // src/features/ignore/ignore-processor.ts
1882
+ var import_mini11 = require("zod/mini");
1661
1883
 
1662
- // src/config/config.ts
1663
- var import_mini10 = require("zod/mini");
1664
- var ConfigParamsSchema = import_mini10.z.object({
1665
- baseDirs: import_mini10.z.array(import_mini10.z.string()),
1666
- targets: RulesyncTargetsSchema,
1667
- features: RulesyncFeaturesSchema,
1668
- verbose: import_mini10.z.boolean(),
1669
- delete: import_mini10.z.boolean(),
1670
- // New non-experimental options
1671
- global: (0, import_mini10.optional)(import_mini10.z.boolean()),
1672
- simulatedCommands: (0, import_mini10.optional)(import_mini10.z.boolean()),
1673
- simulatedSubagents: (0, import_mini10.optional)(import_mini10.z.boolean()),
1674
- modularMcp: (0, import_mini10.optional)(import_mini10.z.boolean()),
1675
- // Deprecated experimental options (for backward compatibility)
1676
- experimentalGlobal: (0, import_mini10.optional)(import_mini10.z.boolean()),
1677
- experimentalSimulateCommands: (0, import_mini10.optional)(import_mini10.z.boolean()),
1678
- experimentalSimulateSubagents: (0, import_mini10.optional)(import_mini10.z.boolean())
1679
- });
1680
- var PartialConfigParamsSchema = import_mini10.z.partial(ConfigParamsSchema);
1681
- var RequiredConfigParamsSchema = import_mini10.z.required(ConfigParamsSchema);
1682
- var Config = class {
1683
- baseDirs;
1684
- targets;
1685
- features;
1686
- verbose;
1687
- delete;
1688
- global;
1689
- simulatedCommands;
1690
- simulatedSubagents;
1691
- modularMcp;
1692
- constructor({
1693
- baseDirs,
1694
- targets,
1695
- features,
1696
- verbose,
1697
- delete: isDelete,
1698
- global,
1699
- simulatedCommands,
1700
- simulatedSubagents,
1701
- modularMcp,
1702
- experimentalGlobal,
1703
- experimentalSimulateCommands,
1704
- experimentalSimulateSubagents
1705
- }) {
1706
- this.baseDirs = baseDirs;
1707
- this.targets = targets;
1708
- this.features = features;
1709
- this.verbose = verbose;
1710
- this.delete = isDelete;
1711
- this.global = global ?? experimentalGlobal ?? false;
1712
- this.simulatedCommands = simulatedCommands ?? experimentalSimulateCommands ?? false;
1713
- this.simulatedSubagents = simulatedSubagents ?? experimentalSimulateSubagents ?? false;
1714
- this.modularMcp = modularMcp ?? false;
1884
+ // src/features/ignore/amazonqcli-ignore.ts
1885
+ var import_node_path15 = require("path");
1886
+
1887
+ // src/types/tool-file.ts
1888
+ var ToolFile = class extends AiFile {
1889
+ };
1890
+
1891
+ // src/features/ignore/rulesync-ignore.ts
1892
+ var import_node_path14 = require("path");
1893
+ var RulesyncIgnore = class _RulesyncIgnore extends RulesyncFile {
1894
+ validate() {
1895
+ return { success: true, error: null };
1715
1896
  }
1716
- getBaseDirs() {
1717
- return this.baseDirs;
1897
+ static getSettablePaths() {
1898
+ return {
1899
+ relativeDirPath: ".",
1900
+ relativeFilePath: ".rulesyncignore"
1901
+ };
1718
1902
  }
1719
- getTargets() {
1720
- if (this.targets.includes("*")) {
1721
- return [...ALL_TOOL_TARGETS];
1722
- }
1723
- return this.targets.filter((target) => target !== "*");
1903
+ static async fromFile() {
1904
+ const baseDir = process.cwd();
1905
+ const filePath = (0, import_node_path14.join)(baseDir, this.getSettablePaths().relativeFilePath);
1906
+ const fileContent = await readFileContent(filePath);
1907
+ return new _RulesyncIgnore({
1908
+ baseDir,
1909
+ relativeDirPath: this.getSettablePaths().relativeDirPath,
1910
+ relativeFilePath: this.getSettablePaths().relativeFilePath,
1911
+ fileContent
1912
+ });
1724
1913
  }
1725
- getFeatures() {
1726
- if (this.features.includes("*")) {
1727
- return [...ALL_FEATURES];
1914
+ };
1915
+
1916
+ // src/features/ignore/tool-ignore.ts
1917
+ var ToolIgnore = class extends ToolFile {
1918
+ patterns;
1919
+ constructor(params) {
1920
+ super({
1921
+ ...params,
1922
+ validate: true
1923
+ });
1924
+ this.patterns = this.fileContent.split(/\r?\n|\r/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
1925
+ if (params.validate) {
1926
+ const result = this.validate();
1927
+ if (!result.success) {
1928
+ throw result.error;
1929
+ }
1728
1930
  }
1729
- return this.features.filter((feature) => feature !== "*");
1730
1931
  }
1731
- getVerbose() {
1732
- return this.verbose;
1932
+ static getSettablePaths() {
1933
+ throw new Error("Please implement this method in the subclass.");
1733
1934
  }
1734
- getDelete() {
1735
- return this.delete;
1935
+ getPatterns() {
1936
+ return this.patterns;
1736
1937
  }
1737
- getGlobal() {
1738
- return this.global;
1938
+ validate() {
1939
+ return { success: true, error: null };
1739
1940
  }
1740
- getSimulatedCommands() {
1741
- return this.simulatedCommands;
1941
+ static fromRulesyncIgnore(_params) {
1942
+ throw new Error("Please implement this method in the subclass.");
1742
1943
  }
1743
- getSimulatedSubagents() {
1744
- return this.simulatedSubagents;
1944
+ toRulesyncIgnoreDefault() {
1945
+ return new RulesyncIgnore({
1946
+ baseDir: ".",
1947
+ relativeDirPath: ".",
1948
+ relativeFilePath: ".rulesyncignore",
1949
+ fileContent: this.fileContent
1950
+ });
1745
1951
  }
1746
- getModularMcp() {
1747
- return this.modularMcp;
1952
+ static async fromFile(_params) {
1953
+ throw new Error("Please implement this method in the subclass.");
1748
1954
  }
1749
- // Deprecated getters for backward compatibility
1750
- /** @deprecated Use getGlobal() instead */
1751
- getExperimentalGlobal() {
1752
- return this.global;
1955
+ };
1956
+
1957
+ // src/features/ignore/amazonqcli-ignore.ts
1958
+ var AmazonqcliIgnore = class _AmazonqcliIgnore extends ToolIgnore {
1959
+ static getSettablePaths() {
1960
+ return {
1961
+ relativeDirPath: ".",
1962
+ relativeFilePath: ".amazonqignore"
1963
+ };
1753
1964
  }
1754
- /** @deprecated Use getSimulatedCommands() instead */
1755
- getExperimentalSimulateCommands() {
1756
- return this.simulatedCommands;
1965
+ /**
1966
+ * Convert to RulesyncIgnore format
1967
+ */
1968
+ toRulesyncIgnore() {
1969
+ return this.toRulesyncIgnoreDefault();
1757
1970
  }
1758
- /** @deprecated Use getSimulatedSubagents() instead */
1759
- getExperimentalSimulateSubagents() {
1760
- return this.simulatedSubagents;
1971
+ /**
1972
+ * Create AmazonqcliIgnore from RulesyncIgnore
1973
+ * Supports conversion from unified rulesync format to Amazon Q CLI specific format
1974
+ */
1975
+ static fromRulesyncIgnore({
1976
+ baseDir = process.cwd(),
1977
+ rulesyncIgnore
1978
+ }) {
1979
+ const body = rulesyncIgnore.getFileContent();
1980
+ return new _AmazonqcliIgnore({
1981
+ baseDir,
1982
+ relativeDirPath: this.getSettablePaths().relativeDirPath,
1983
+ relativeFilePath: this.getSettablePaths().relativeFilePath,
1984
+ fileContent: body
1985
+ });
1986
+ }
1987
+ /**
1988
+ * Create AmazonqcliIgnore from file path
1989
+ * Supports both proposed .q-ignore and .amazonqignore formats
1990
+ */
1991
+ static async fromFile({
1992
+ baseDir = process.cwd(),
1993
+ validate = true
1994
+ }) {
1995
+ const fileContent = await readFileContent(
1996
+ (0, import_node_path15.join)(
1997
+ baseDir,
1998
+ this.getSettablePaths().relativeDirPath,
1999
+ this.getSettablePaths().relativeFilePath
2000
+ )
2001
+ );
2002
+ return new _AmazonqcliIgnore({
2003
+ baseDir,
2004
+ relativeDirPath: this.getSettablePaths().relativeDirPath,
2005
+ relativeFilePath: this.getSettablePaths().relativeFilePath,
2006
+ fileContent,
2007
+ validate
2008
+ });
1761
2009
  }
1762
2010
  };
1763
2011
 
1764
- // src/config/config-resolver.ts
1765
- var defaults = {
1766
- targets: ["agentsmd"],
1767
- features: ["rules"],
1768
- verbose: false,
1769
- delete: false,
1770
- baseDirs: [process.cwd()],
1771
- configPath: "rulesync.jsonc",
1772
- global: false,
1773
- simulatedCommands: false,
1774
- simulatedSubagents: false,
1775
- modularMcp: false,
1776
- experimentalGlobal: false,
1777
- experimentalSimulateCommands: false,
1778
- experimentalSimulateSubagents: false
1779
- };
1780
- var ConfigResolver = class {
1781
- static async resolve({
1782
- targets,
1783
- features,
1784
- verbose,
1785
- delete: isDelete,
1786
- baseDirs,
1787
- configPath = defaults.configPath,
1788
- global,
1789
- simulatedCommands,
1790
- simulatedSubagents,
1791
- modularMcp,
1792
- experimentalGlobal,
1793
- experimentalSimulateCommands,
1794
- experimentalSimulateSubagents
1795
- }) {
1796
- const validatedConfigPath = resolvePath(configPath, process.cwd());
1797
- let configByFile = {};
1798
- if (await fileExists(validatedConfigPath)) {
1799
- try {
1800
- const fileContent = await readFileContent(validatedConfigPath);
1801
- const jsonData = (0, import_jsonc_parser.parse)(fileContent);
1802
- configByFile = PartialConfigParamsSchema.parse(jsonData);
1803
- } catch (error) {
1804
- logger.error(`Failed to load config file: ${formatError(error)}`);
1805
- throw error;
1806
- }
1807
- }
1808
- const deprecatedGlobal = experimentalGlobal ?? configByFile.experimentalGlobal;
1809
- const deprecatedCommands = experimentalSimulateCommands ?? configByFile.experimentalSimulateCommands;
1810
- const deprecatedSubagents = experimentalSimulateSubagents ?? configByFile.experimentalSimulateSubagents;
1811
- if (deprecatedGlobal !== void 0) {
1812
- warnDeprecatedOptions({ experimentalGlobal: deprecatedGlobal });
1813
- }
1814
- if (deprecatedCommands !== void 0) {
1815
- warnDeprecatedOptions({ experimentalSimulateCommands: deprecatedCommands });
1816
- }
1817
- if (deprecatedSubagents !== void 0) {
1818
- warnDeprecatedOptions({ experimentalSimulateSubagents: deprecatedSubagents });
1819
- }
1820
- const resolvedGlobal = global ?? configByFile.global ?? experimentalGlobal ?? configByFile.experimentalGlobal ?? defaults.global;
1821
- const resolvedSimulatedCommands = simulatedCommands ?? configByFile.simulatedCommands ?? experimentalSimulateCommands ?? configByFile.experimentalSimulateCommands ?? defaults.simulatedCommands;
1822
- const resolvedSimulatedSubagents = simulatedSubagents ?? configByFile.simulatedSubagents ?? experimentalSimulateSubagents ?? configByFile.experimentalSimulateSubagents ?? defaults.simulatedSubagents;
1823
- const configParams = {
1824
- targets: targets ?? configByFile.targets ?? defaults.targets,
1825
- features: features ?? configByFile.features ?? defaults.features,
1826
- verbose: verbose ?? configByFile.verbose ?? defaults.verbose,
1827
- delete: isDelete ?? configByFile.delete ?? defaults.delete,
1828
- baseDirs: getBaseDirsInLightOfGlobal({
1829
- baseDirs: baseDirs ?? configByFile.baseDirs ?? defaults.baseDirs,
1830
- global: resolvedGlobal
1831
- }),
1832
- global: resolvedGlobal,
1833
- simulatedCommands: resolvedSimulatedCommands,
1834
- simulatedSubagents: resolvedSimulatedSubagents,
1835
- modularMcp: modularMcp ?? configByFile.modularMcp ?? defaults.modularMcp
1836
- };
1837
- return new Config(configParams);
1838
- }
1839
- };
1840
- function warnDeprecatedOptions({
1841
- experimentalGlobal,
1842
- experimentalSimulateCommands,
1843
- experimentalSimulateSubagents
1844
- }) {
1845
- if (experimentalGlobal !== void 0) {
1846
- logger.warn("'experimentalGlobal' option is deprecated. Please use 'global' instead.");
1847
- }
1848
- if (experimentalSimulateCommands !== void 0) {
1849
- logger.warn(
1850
- "'experimentalSimulateCommands' option is deprecated. Please use 'simulatedCommands' instead."
1851
- );
1852
- }
1853
- if (experimentalSimulateSubagents !== void 0) {
1854
- logger.warn(
1855
- "'experimentalSimulateSubagents' option is deprecated. Please use 'simulatedSubagents' instead."
1856
- );
1857
- }
1858
- }
1859
- function getBaseDirsInLightOfGlobal({
1860
- baseDirs,
1861
- global
1862
- }) {
1863
- if (global) {
1864
- return [getHomeDirectory()];
1865
- }
1866
- const resolvedBaseDirs = baseDirs.map((baseDir) => (0, import_node_path13.resolve)(baseDir));
1867
- resolvedBaseDirs.forEach((baseDir) => {
1868
- validateBaseDir(baseDir);
1869
- });
1870
- return resolvedBaseDirs;
1871
- }
1872
-
1873
- // src/ignore/ignore-processor.ts
1874
- var import_mini11 = require("zod/mini");
1875
-
1876
- // src/ignore/amazonqcli-ignore.ts
1877
- var import_node_path15 = require("path");
1878
-
1879
- // src/types/tool-file.ts
1880
- var ToolFile = class extends AiFile {
1881
- };
1882
-
1883
- // src/ignore/rulesync-ignore.ts
1884
- var import_node_path14 = require("path");
1885
- var RulesyncIgnore = class _RulesyncIgnore extends RulesyncFile {
1886
- validate() {
1887
- return { success: true, error: null };
1888
- }
1889
- static getSettablePaths() {
1890
- return {
1891
- relativeDirPath: ".",
1892
- relativeFilePath: ".rulesyncignore"
1893
- };
1894
- }
1895
- static async fromFile() {
1896
- const baseDir = process.cwd();
1897
- const filePath = (0, import_node_path14.join)(baseDir, this.getSettablePaths().relativeFilePath);
1898
- const fileContent = await readFileContent(filePath);
1899
- return new _RulesyncIgnore({
1900
- baseDir,
1901
- relativeDirPath: this.getSettablePaths().relativeDirPath,
1902
- relativeFilePath: this.getSettablePaths().relativeFilePath,
1903
- fileContent
1904
- });
1905
- }
1906
- };
1907
-
1908
- // src/ignore/tool-ignore.ts
1909
- var ToolIgnore = class extends ToolFile {
1910
- patterns;
1911
- constructor(params) {
1912
- super({
1913
- ...params,
1914
- validate: true
1915
- });
1916
- this.patterns = this.fileContent.split(/\r?\n|\r/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
1917
- if (params.validate) {
1918
- const result = this.validate();
1919
- if (!result.success) {
1920
- throw result.error;
1921
- }
1922
- }
1923
- }
1924
- static getSettablePaths() {
1925
- throw new Error("Please implement this method in the subclass.");
1926
- }
1927
- getPatterns() {
1928
- return this.patterns;
1929
- }
1930
- validate() {
1931
- return { success: true, error: null };
1932
- }
1933
- static fromRulesyncIgnore(_params) {
1934
- throw new Error("Please implement this method in the subclass.");
1935
- }
1936
- toRulesyncIgnoreDefault() {
1937
- return new RulesyncIgnore({
1938
- baseDir: ".",
1939
- relativeDirPath: ".",
1940
- relativeFilePath: ".rulesyncignore",
1941
- fileContent: this.fileContent
1942
- });
1943
- }
1944
- static async fromFile(_params) {
1945
- throw new Error("Please implement this method in the subclass.");
1946
- }
1947
- };
1948
-
1949
- // src/ignore/amazonqcli-ignore.ts
1950
- var AmazonqcliIgnore = class _AmazonqcliIgnore extends ToolIgnore {
1951
- static getSettablePaths() {
1952
- return {
1953
- relativeDirPath: ".",
1954
- relativeFilePath: ".amazonqignore"
1955
- };
1956
- }
1957
- /**
1958
- * Convert to RulesyncIgnore format
1959
- */
1960
- toRulesyncIgnore() {
1961
- return this.toRulesyncIgnoreDefault();
1962
- }
1963
- /**
1964
- * Create AmazonqcliIgnore from RulesyncIgnore
1965
- * Supports conversion from unified rulesync format to Amazon Q CLI specific format
1966
- */
1967
- static fromRulesyncIgnore({
1968
- baseDir = process.cwd(),
1969
- rulesyncIgnore
1970
- }) {
1971
- const body = rulesyncIgnore.getFileContent();
1972
- return new _AmazonqcliIgnore({
1973
- baseDir,
1974
- relativeDirPath: this.getSettablePaths().relativeDirPath,
1975
- relativeFilePath: this.getSettablePaths().relativeFilePath,
1976
- fileContent: body
1977
- });
1978
- }
1979
- /**
1980
- * Create AmazonqcliIgnore from file path
1981
- * Supports both proposed .q-ignore and .amazonqignore formats
1982
- */
1983
- static async fromFile({
1984
- baseDir = process.cwd(),
1985
- validate = true
1986
- }) {
1987
- const fileContent = await readFileContent(
1988
- (0, import_node_path15.join)(
1989
- baseDir,
1990
- this.getSettablePaths().relativeDirPath,
1991
- this.getSettablePaths().relativeFilePath
1992
- )
1993
- );
1994
- return new _AmazonqcliIgnore({
1995
- baseDir,
1996
- relativeDirPath: this.getSettablePaths().relativeDirPath,
1997
- relativeFilePath: this.getSettablePaths().relativeFilePath,
1998
- fileContent,
1999
- validate
2000
- });
2001
- }
2002
- };
2003
-
2004
- // src/ignore/augmentcode-ignore.ts
2012
+ // src/features/ignore/augmentcode-ignore.ts
2005
2013
  var import_node_path16 = require("path");
2006
2014
  var AugmentcodeIgnore = class _AugmentcodeIgnore extends ToolIgnore {
2007
2015
  static getSettablePaths() {
@@ -2056,7 +2064,7 @@ var AugmentcodeIgnore = class _AugmentcodeIgnore extends ToolIgnore {
2056
2064
  }
2057
2065
  };
2058
2066
 
2059
- // src/ignore/claudecode-ignore.ts
2067
+ // src/features/ignore/claudecode-ignore.ts
2060
2068
  var import_node_path17 = require("path");
2061
2069
  var import_es_toolkit = require("es-toolkit");
2062
2070
  var ClaudecodeIgnore = class _ClaudecodeIgnore extends ToolIgnore {
@@ -2137,7 +2145,7 @@ var ClaudecodeIgnore = class _ClaudecodeIgnore extends ToolIgnore {
2137
2145
  }
2138
2146
  };
2139
2147
 
2140
- // src/ignore/cline-ignore.ts
2148
+ // src/features/ignore/cline-ignore.ts
2141
2149
  var import_node_path18 = require("path");
2142
2150
  var ClineIgnore = class _ClineIgnore extends ToolIgnore {
2143
2151
  static getSettablePaths() {
@@ -2191,7 +2199,7 @@ var ClineIgnore = class _ClineIgnore extends ToolIgnore {
2191
2199
  }
2192
2200
  };
2193
2201
 
2194
- // src/ignore/cursor-ignore.ts
2202
+ // src/features/ignore/cursor-ignore.ts
2195
2203
  var import_node_path19 = require("path");
2196
2204
  var CursorIgnore = class _CursorIgnore extends ToolIgnore {
2197
2205
  static getSettablePaths() {
@@ -2241,7 +2249,7 @@ var CursorIgnore = class _CursorIgnore extends ToolIgnore {
2241
2249
  }
2242
2250
  };
2243
2251
 
2244
- // src/ignore/geminicli-ignore.ts
2252
+ // src/features/ignore/geminicli-ignore.ts
2245
2253
  var import_node_path20 = require("path");
2246
2254
  var GeminiCliIgnore = class _GeminiCliIgnore extends ToolIgnore {
2247
2255
  static getSettablePaths() {
@@ -2285,7 +2293,7 @@ var GeminiCliIgnore = class _GeminiCliIgnore extends ToolIgnore {
2285
2293
  }
2286
2294
  };
2287
2295
 
2288
- // src/ignore/junie-ignore.ts
2296
+ // src/features/ignore/junie-ignore.ts
2289
2297
  var import_node_path21 = require("path");
2290
2298
  var JunieIgnore = class _JunieIgnore extends ToolIgnore {
2291
2299
  static getSettablePaths() {
@@ -2329,7 +2337,7 @@ var JunieIgnore = class _JunieIgnore extends ToolIgnore {
2329
2337
  }
2330
2338
  };
2331
2339
 
2332
- // src/ignore/kiro-ignore.ts
2340
+ // src/features/ignore/kiro-ignore.ts
2333
2341
  var import_node_path22 = require("path");
2334
2342
  var KiroIgnore = class _KiroIgnore extends ToolIgnore {
2335
2343
  static getSettablePaths() {
@@ -2373,7 +2381,7 @@ var KiroIgnore = class _KiroIgnore extends ToolIgnore {
2373
2381
  }
2374
2382
  };
2375
2383
 
2376
- // src/ignore/qwencode-ignore.ts
2384
+ // src/features/ignore/qwencode-ignore.ts
2377
2385
  var import_node_path23 = require("path");
2378
2386
  var QwencodeIgnore = class _QwencodeIgnore extends ToolIgnore {
2379
2387
  static getSettablePaths() {
@@ -2417,7 +2425,7 @@ var QwencodeIgnore = class _QwencodeIgnore extends ToolIgnore {
2417
2425
  }
2418
2426
  };
2419
2427
 
2420
- // src/ignore/roo-ignore.ts
2428
+ // src/features/ignore/roo-ignore.ts
2421
2429
  var import_node_path24 = require("path");
2422
2430
  var RooIgnore = class _RooIgnore extends ToolIgnore {
2423
2431
  static getSettablePaths() {
@@ -2461,7 +2469,7 @@ var RooIgnore = class _RooIgnore extends ToolIgnore {
2461
2469
  }
2462
2470
  };
2463
2471
 
2464
- // src/ignore/windsurf-ignore.ts
2472
+ // src/features/ignore/windsurf-ignore.ts
2465
2473
  var import_node_path25 = require("path");
2466
2474
  var WindsurfIgnore = class _WindsurfIgnore extends ToolIgnore {
2467
2475
  static getSettablePaths() {
@@ -2505,7 +2513,7 @@ var WindsurfIgnore = class _WindsurfIgnore extends ToolIgnore {
2505
2513
  }
2506
2514
  };
2507
2515
 
2508
- // src/ignore/ignore-processor.ts
2516
+ // src/features/ignore/ignore-processor.ts
2509
2517
  var ignoreProcessorToolTargets = [
2510
2518
  "amazonqcli",
2511
2519
  "augmentcode",
@@ -2693,13 +2701,13 @@ var IgnoreProcessor = class extends FeatureProcessor {
2693
2701
  }
2694
2702
  };
2695
2703
 
2696
- // src/mcp/mcp-processor.ts
2704
+ // src/features/mcp/mcp-processor.ts
2697
2705
  var import_mini13 = require("zod/mini");
2698
2706
 
2699
- // src/mcp/amazonqcli-mcp.ts
2707
+ // src/features/mcp/amazonqcli-mcp.ts
2700
2708
  var import_node_path27 = require("path");
2701
2709
 
2702
- // src/mcp/rulesync-mcp.ts
2710
+ // src/features/mcp/rulesync-mcp.ts
2703
2711
  var import_node_path26 = require("path");
2704
2712
  var import_object = require("es-toolkit/object");
2705
2713
  var import_mini12 = require("zod/mini");
@@ -2844,7 +2852,7 @@ var RulesyncMcp = class _RulesyncMcp extends RulesyncFile {
2844
2852
  }
2845
2853
  };
2846
2854
 
2847
- // src/mcp/tool-mcp.ts
2855
+ // src/features/mcp/tool-mcp.ts
2848
2856
  var ToolMcp = class extends ToolFile {
2849
2857
  constructor({ ...rest }) {
2850
2858
  super({
@@ -2883,7 +2891,7 @@ var ToolMcp = class extends ToolFile {
2883
2891
  }
2884
2892
  };
2885
2893
 
2886
- // src/mcp/amazonqcli-mcp.ts
2894
+ // src/features/mcp/amazonqcli-mcp.ts
2887
2895
  var AmazonqcliMcp = class _AmazonqcliMcp extends ToolMcp {
2888
2896
  json;
2889
2897
  constructor(params) {
@@ -2939,10 +2947,10 @@ var AmazonqcliMcp = class _AmazonqcliMcp extends ToolMcp {
2939
2947
  }
2940
2948
  };
2941
2949
 
2942
- // src/mcp/claudecode-mcp.ts
2950
+ // src/features/mcp/claudecode-mcp.ts
2943
2951
  var import_node_path29 = require("path");
2944
2952
 
2945
- // src/mcp/modular-mcp.ts
2953
+ // src/features/mcp/modular-mcp.ts
2946
2954
  var import_node_path28 = require("path");
2947
2955
  var ModularMcp = class _ModularMcp extends AiFile {
2948
2956
  json;
@@ -3030,7 +3038,7 @@ var ModularMcp = class _ModularMcp extends AiFile {
3030
3038
  }
3031
3039
  };
3032
3040
 
3033
- // src/mcp/claudecode-mcp.ts
3041
+ // src/features/mcp/claudecode-mcp.ts
3034
3042
  var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
3035
3043
  json;
3036
3044
  constructor(params) {
@@ -3111,7 +3119,7 @@ var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
3111
3119
  }
3112
3120
  };
3113
3121
 
3114
- // src/mcp/cline-mcp.ts
3122
+ // src/features/mcp/cline-mcp.ts
3115
3123
  var import_node_path30 = require("path");
3116
3124
  var ClineMcp = class _ClineMcp extends ToolMcp {
3117
3125
  json;
@@ -3168,7 +3176,7 @@ var ClineMcp = class _ClineMcp extends ToolMcp {
3168
3176
  }
3169
3177
  };
3170
3178
 
3171
- // src/mcp/codexcli-mcp.ts
3179
+ // src/features/mcp/codexcli-mcp.ts
3172
3180
  var import_node_path31 = require("path");
3173
3181
  var smolToml = __toESM(require("smol-toml"), 1);
3174
3182
  var CodexcliMcp = class _CodexcliMcp extends ToolMcp {
@@ -3262,7 +3270,7 @@ var CodexcliMcp = class _CodexcliMcp extends ToolMcp {
3262
3270
  }
3263
3271
  };
3264
3272
 
3265
- // src/mcp/copilot-mcp.ts
3273
+ // src/features/mcp/copilot-mcp.ts
3266
3274
  var import_node_path32 = require("path");
3267
3275
  var CopilotMcp = class _CopilotMcp extends ToolMcp {
3268
3276
  json;
@@ -3319,7 +3327,7 @@ var CopilotMcp = class _CopilotMcp extends ToolMcp {
3319
3327
  }
3320
3328
  };
3321
3329
 
3322
- // src/mcp/cursor-mcp.ts
3330
+ // src/features/mcp/cursor-mcp.ts
3323
3331
  var import_node_path33 = require("path");
3324
3332
  var CursorMcp = class _CursorMcp extends ToolMcp {
3325
3333
  json;
@@ -3387,7 +3395,7 @@ var CursorMcp = class _CursorMcp extends ToolMcp {
3387
3395
  }
3388
3396
  };
3389
3397
 
3390
- // src/mcp/geminicli-mcp.ts
3398
+ // src/features/mcp/geminicli-mcp.ts
3391
3399
  var import_node_path34 = require("path");
3392
3400
  var GeminiCliMcp = class _GeminiCliMcp extends ToolMcp {
3393
3401
  json;
@@ -3461,7 +3469,7 @@ var GeminiCliMcp = class _GeminiCliMcp extends ToolMcp {
3461
3469
  }
3462
3470
  };
3463
3471
 
3464
- // src/mcp/roo-mcp.ts
3472
+ // src/features/mcp/roo-mcp.ts
3465
3473
  var import_node_path35 = require("path");
3466
3474
  var RooMcp = class _RooMcp extends ToolMcp {
3467
3475
  json;
@@ -3519,7 +3527,7 @@ var RooMcp = class _RooMcp extends ToolMcp {
3519
3527
  }
3520
3528
  };
3521
3529
 
3522
- // src/mcp/mcp-processor.ts
3530
+ // src/features/mcp/mcp-processor.ts
3523
3531
  var mcpProcessorToolTargets = [
3524
3532
  "amazonqcli",
3525
3533
  "claudecode",
@@ -3765,19 +3773,19 @@ var McpProcessor = class extends FeatureProcessor {
3765
3773
  }
3766
3774
  };
3767
3775
 
3768
- // src/rules/rules-processor.ts
3776
+ // src/features/rules/rules-processor.ts
3769
3777
  var import_node_path65 = require("path");
3770
3778
  var import_fast_xml_parser = require("fast-xml-parser");
3771
3779
  var import_mini22 = require("zod/mini");
3772
3780
 
3773
- // src/subagents/agentsmd-subagent.ts
3781
+ // src/features/subagents/agentsmd-subagent.ts
3774
3782
  var import_node_path37 = require("path");
3775
3783
 
3776
- // src/subagents/simulated-subagent.ts
3784
+ // src/features/subagents/simulated-subagent.ts
3777
3785
  var import_node_path36 = require("path");
3778
3786
  var import_mini14 = require("zod/mini");
3779
3787
 
3780
- // src/subagents/tool-subagent.ts
3788
+ // src/features/subagents/tool-subagent.ts
3781
3789
  var ToolSubagent = class extends ToolFile {
3782
3790
  static getSettablePaths() {
3783
3791
  throw new Error("Please implement this method in the subclass.");
@@ -3809,7 +3817,7 @@ var ToolSubagent = class extends ToolFile {
3809
3817
  }
3810
3818
  };
3811
3819
 
3812
- // src/subagents/simulated-subagent.ts
3820
+ // src/features/subagents/simulated-subagent.ts
3813
3821
  var SimulatedSubagentFrontmatterSchema = import_mini14.z.object({
3814
3822
  name: import_mini14.z.string(),
3815
3823
  description: import_mini14.z.string()
@@ -3901,7 +3909,7 @@ var SimulatedSubagent = class extends ToolSubagent {
3901
3909
  }
3902
3910
  };
3903
3911
 
3904
- // src/subagents/agentsmd-subagent.ts
3912
+ // src/features/subagents/agentsmd-subagent.ts
3905
3913
  var AgentsmdSubagent = class _AgentsmdSubagent extends SimulatedSubagent {
3906
3914
  static getSettablePaths() {
3907
3915
  return {
@@ -3924,7 +3932,7 @@ var AgentsmdSubagent = class _AgentsmdSubagent extends SimulatedSubagent {
3924
3932
  }
3925
3933
  };
3926
3934
 
3927
- // src/subagents/codexcli-subagent.ts
3935
+ // src/features/subagents/codexcli-subagent.ts
3928
3936
  var import_node_path38 = require("path");
3929
3937
  var CodexCliSubagent = class _CodexCliSubagent extends SimulatedSubagent {
3930
3938
  static getSettablePaths() {
@@ -3948,7 +3956,7 @@ var CodexCliSubagent = class _CodexCliSubagent extends SimulatedSubagent {
3948
3956
  }
3949
3957
  };
3950
3958
 
3951
- // src/subagents/copilot-subagent.ts
3959
+ // src/features/subagents/copilot-subagent.ts
3952
3960
  var import_node_path39 = require("path");
3953
3961
  var CopilotSubagent = class _CopilotSubagent extends SimulatedSubagent {
3954
3962
  static getSettablePaths() {
@@ -3972,7 +3980,7 @@ var CopilotSubagent = class _CopilotSubagent extends SimulatedSubagent {
3972
3980
  }
3973
3981
  };
3974
3982
 
3975
- // src/subagents/cursor-subagent.ts
3983
+ // src/features/subagents/cursor-subagent.ts
3976
3984
  var import_node_path40 = require("path");
3977
3985
  var CursorSubagent = class _CursorSubagent extends SimulatedSubagent {
3978
3986
  static getSettablePaths() {
@@ -3996,7 +4004,7 @@ var CursorSubagent = class _CursorSubagent extends SimulatedSubagent {
3996
4004
  }
3997
4005
  };
3998
4006
 
3999
- // src/subagents/geminicli-subagent.ts
4007
+ // src/features/subagents/geminicli-subagent.ts
4000
4008
  var import_node_path41 = require("path");
4001
4009
  var GeminiCliSubagent = class _GeminiCliSubagent extends SimulatedSubagent {
4002
4010
  static getSettablePaths() {
@@ -4020,7 +4028,7 @@ var GeminiCliSubagent = class _GeminiCliSubagent extends SimulatedSubagent {
4020
4028
  }
4021
4029
  };
4022
4030
 
4023
- // src/subagents/roo-subagent.ts
4031
+ // src/features/subagents/roo-subagent.ts
4024
4032
  var import_node_path42 = require("path");
4025
4033
  var RooSubagent = class _RooSubagent extends SimulatedSubagent {
4026
4034
  static getSettablePaths() {
@@ -4044,15 +4052,15 @@ var RooSubagent = class _RooSubagent extends SimulatedSubagent {
4044
4052
  }
4045
4053
  };
4046
4054
 
4047
- // src/subagents/subagents-processor.ts
4055
+ // src/features/subagents/subagents-processor.ts
4048
4056
  var import_node_path45 = require("path");
4049
4057
  var import_mini17 = require("zod/mini");
4050
4058
 
4051
- // src/subagents/claudecode-subagent.ts
4059
+ // src/features/subagents/claudecode-subagent.ts
4052
4060
  var import_node_path44 = require("path");
4053
4061
  var import_mini16 = require("zod/mini");
4054
4062
 
4055
- // src/subagents/rulesync-subagent.ts
4063
+ // src/features/subagents/rulesync-subagent.ts
4056
4064
  var import_node_path43 = require("path");
4057
4065
  var import_mini15 = require("zod/mini");
4058
4066
  var RulesyncSubagentModelSchema = import_mini15.z.enum(["opus", "sonnet", "haiku", "inherit"]);
@@ -4079,7 +4087,8 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
4079
4087
  }
4080
4088
  }
4081
4089
  super({
4082
- ...rest
4090
+ ...rest,
4091
+ fileContent: stringifyFrontmatter(body, frontmatter)
4083
4092
  });
4084
4093
  this.frontmatter = frontmatter;
4085
4094
  this.body = body;
@@ -4128,13 +4137,12 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
4128
4137
  relativeDirPath: this.getSettablePaths().relativeDirPath,
4129
4138
  relativeFilePath: filename,
4130
4139
  frontmatter: result.data,
4131
- body: content.trim(),
4132
- fileContent
4140
+ body: content.trim()
4133
4141
  });
4134
4142
  }
4135
4143
  };
4136
4144
 
4137
- // src/subagents/claudecode-subagent.ts
4145
+ // src/features/subagents/claudecode-subagent.ts
4138
4146
  var ClaudecodeSubagentFrontmatterSchema = import_mini16.z.object({
4139
4147
  name: import_mini16.z.string(),
4140
4148
  description: import_mini16.z.string(),
@@ -4180,7 +4188,6 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4180
4188
  }
4181
4189
  }
4182
4190
  };
4183
- const fileContent = stringifyFrontmatter(this.body, rulesyncFrontmatter);
4184
4191
  return new RulesyncSubagent({
4185
4192
  baseDir: ".",
4186
4193
  // RulesyncCommand baseDir is always the project root directory
@@ -4188,7 +4195,6 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4188
4195
  body: this.body,
4189
4196
  relativeDirPath: (0, import_node_path44.join)(".rulesync", "subagents"),
4190
4197
  relativeFilePath: this.getRelativeFilePath(),
4191
- fileContent,
4192
4198
  validate: true
4193
4199
  });
4194
4200
  }
@@ -4265,7 +4271,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
4265
4271
  }
4266
4272
  };
4267
4273
 
4268
- // src/subagents/subagents-processor.ts
4274
+ // src/features/subagents/subagents-processor.ts
4269
4275
  var subagentsProcessorToolTargets = [
4270
4276
  "agentsmd",
4271
4277
  "claudecode",
@@ -4561,13 +4567,13 @@ var SubagentsProcessor = class extends FeatureProcessor {
4561
4567
  }
4562
4568
  };
4563
4569
 
4564
- // src/rules/agentsmd-rule.ts
4570
+ // src/features/rules/agentsmd-rule.ts
4565
4571
  var import_node_path48 = require("path");
4566
4572
 
4567
- // src/rules/tool-rule.ts
4573
+ // src/features/rules/tool-rule.ts
4568
4574
  var import_node_path47 = require("path");
4569
4575
 
4570
- // src/rules/rulesync-rule.ts
4576
+ // src/features/rules/rulesync-rule.ts
4571
4577
  var import_node_path46 = require("path");
4572
4578
  var import_mini18 = require("zod/mini");
4573
4579
  var RulesyncRuleFrontmatterSchema = import_mini18.z.object({
@@ -4713,7 +4719,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
4713
4719
  }
4714
4720
  };
4715
4721
 
4716
- // src/rules/tool-rule.ts
4722
+ // src/features/rules/tool-rule.ts
4717
4723
  var ToolRule = class extends ToolFile {
4718
4724
  root;
4719
4725
  description;
@@ -4834,7 +4840,7 @@ var ToolRule = class extends ToolFile {
4834
4840
  }
4835
4841
  };
4836
4842
 
4837
- // src/rules/agentsmd-rule.ts
4843
+ // src/features/rules/agentsmd-rule.ts
4838
4844
  var AgentsMdRule = class _AgentsMdRule extends ToolRule {
4839
4845
  constructor({ fileContent, root, ...rest }) {
4840
4846
  super({
@@ -4900,7 +4906,7 @@ var AgentsMdRule = class _AgentsMdRule extends ToolRule {
4900
4906
  }
4901
4907
  };
4902
4908
 
4903
- // src/rules/amazonqcli-rule.ts
4909
+ // src/features/rules/amazonqcli-rule.ts
4904
4910
  var import_node_path49 = require("path");
4905
4911
  var AmazonQCliRule = class _AmazonQCliRule extends ToolRule {
4906
4912
  static getSettablePaths() {
@@ -4955,7 +4961,7 @@ var AmazonQCliRule = class _AmazonQCliRule extends ToolRule {
4955
4961
  }
4956
4962
  };
4957
4963
 
4958
- // src/rules/augmentcode-legacy-rule.ts
4964
+ // src/features/rules/augmentcode-legacy-rule.ts
4959
4965
  var import_node_path50 = require("path");
4960
4966
  var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
4961
4967
  toRulesyncRule() {
@@ -5030,7 +5036,7 @@ var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
5030
5036
  }
5031
5037
  };
5032
5038
 
5033
- // src/rules/augmentcode-rule.ts
5039
+ // src/features/rules/augmentcode-rule.ts
5034
5040
  var import_node_path51 = require("path");
5035
5041
  var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
5036
5042
  toRulesyncRule() {
@@ -5085,7 +5091,7 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
5085
5091
  }
5086
5092
  };
5087
5093
 
5088
- // src/rules/claudecode-rule.ts
5094
+ // src/features/rules/claudecode-rule.ts
5089
5095
  var import_node_path52 = require("path");
5090
5096
  var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
5091
5097
  static getSettablePaths({
@@ -5176,7 +5182,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
5176
5182
  }
5177
5183
  };
5178
5184
 
5179
- // src/rules/cline-rule.ts
5185
+ // src/features/rules/cline-rule.ts
5180
5186
  var import_node_path53 = require("path");
5181
5187
  var import_mini19 = require("zod/mini");
5182
5188
  var ClineRuleFrontmatterSchema = import_mini19.z.object({
@@ -5234,7 +5240,7 @@ var ClineRule = class _ClineRule extends ToolRule {
5234
5240
  }
5235
5241
  };
5236
5242
 
5237
- // src/rules/codexcli-rule.ts
5243
+ // src/features/rules/codexcli-rule.ts
5238
5244
  var import_node_path54 = require("path");
5239
5245
  var CodexcliRule = class _CodexcliRule extends ToolRule {
5240
5246
  static getSettablePaths({
@@ -5325,7 +5331,7 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
5325
5331
  }
5326
5332
  };
5327
5333
 
5328
- // src/rules/copilot-rule.ts
5334
+ // src/features/rules/copilot-rule.ts
5329
5335
  var import_node_path55 = require("path");
5330
5336
  var import_mini20 = require("zod/mini");
5331
5337
  var CopilotRuleFrontmatterSchema = import_mini20.z.object({
@@ -5495,7 +5501,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
5495
5501
  }
5496
5502
  };
5497
5503
 
5498
- // src/rules/cursor-rule.ts
5504
+ // src/features/rules/cursor-rule.ts
5499
5505
  var import_node_path56 = require("path");
5500
5506
  var import_mini21 = require("zod/mini");
5501
5507
  var CursorRuleFrontmatterSchema = import_mini21.z.object({
@@ -5683,7 +5689,7 @@ var CursorRule = class _CursorRule extends ToolRule {
5683
5689
  }
5684
5690
  };
5685
5691
 
5686
- // src/rules/geminicli-rule.ts
5692
+ // src/features/rules/geminicli-rule.ts
5687
5693
  var import_node_path57 = require("path");
5688
5694
  var GeminiCliRule = class _GeminiCliRule extends ToolRule {
5689
5695
  static getSettablePaths({
@@ -5774,7 +5780,7 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
5774
5780
  }
5775
5781
  };
5776
5782
 
5777
- // src/rules/junie-rule.ts
5783
+ // src/features/rules/junie-rule.ts
5778
5784
  var import_node_path58 = require("path");
5779
5785
  var JunieRule = class _JunieRule extends ToolRule {
5780
5786
  static getSettablePaths() {
@@ -5834,7 +5840,7 @@ var JunieRule = class _JunieRule extends ToolRule {
5834
5840
  }
5835
5841
  };
5836
5842
 
5837
- // src/rules/kiro-rule.ts
5843
+ // src/features/rules/kiro-rule.ts
5838
5844
  var import_node_path59 = require("path");
5839
5845
  var KiroRule = class _KiroRule extends ToolRule {
5840
5846
  static getSettablePaths() {
@@ -5889,7 +5895,7 @@ var KiroRule = class _KiroRule extends ToolRule {
5889
5895
  }
5890
5896
  };
5891
5897
 
5892
- // src/rules/opencode-rule.ts
5898
+ // src/features/rules/opencode-rule.ts
5893
5899
  var import_node_path60 = require("path");
5894
5900
  var OpenCodeRule = class _OpenCodeRule extends ToolRule {
5895
5901
  static getSettablePaths() {
@@ -5949,7 +5955,7 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
5949
5955
  }
5950
5956
  };
5951
5957
 
5952
- // src/rules/qwencode-rule.ts
5958
+ // src/features/rules/qwencode-rule.ts
5953
5959
  var import_node_path61 = require("path");
5954
5960
  var QwencodeRule = class _QwencodeRule extends ToolRule {
5955
5961
  static getSettablePaths() {
@@ -6006,7 +6012,7 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
6006
6012
  }
6007
6013
  };
6008
6014
 
6009
- // src/rules/roo-rule.ts
6015
+ // src/features/rules/roo-rule.ts
6010
6016
  var import_node_path62 = require("path");
6011
6017
  var RooRule = class _RooRule extends ToolRule {
6012
6018
  static getSettablePaths() {
@@ -6076,7 +6082,7 @@ var RooRule = class _RooRule extends ToolRule {
6076
6082
  }
6077
6083
  };
6078
6084
 
6079
- // src/rules/warp-rule.ts
6085
+ // src/features/rules/warp-rule.ts
6080
6086
  var import_node_path63 = require("path");
6081
6087
  var WarpRule = class _WarpRule extends ToolRule {
6082
6088
  constructor({ fileContent, root, ...rest }) {
@@ -6143,7 +6149,7 @@ var WarpRule = class _WarpRule extends ToolRule {
6143
6149
  }
6144
6150
  };
6145
6151
 
6146
- // src/rules/windsurf-rule.ts
6152
+ // src/features/rules/windsurf-rule.ts
6147
6153
  var import_node_path64 = require("path");
6148
6154
  var WindsurfRule = class _WindsurfRule extends ToolRule {
6149
6155
  static getSettablePaths() {
@@ -6197,7 +6203,7 @@ var WindsurfRule = class _WindsurfRule extends ToolRule {
6197
6203
  }
6198
6204
  };
6199
6205
 
6200
- // src/rules/rules-processor.ts
6206
+ // src/features/rules/rules-processor.ts
6201
6207
  var rulesProcessorToolTargets = [
6202
6208
  "agentsmd",
6203
6209
  "amazonqcli",
@@ -7707,68 +7713,448 @@ Attention, again, you are just the planner, so though you can read any files and
7707
7713
  }
7708
7714
 
7709
7715
  // src/cli/commands/mcp.ts
7710
- var import_node_path68 = require("path");
7711
7716
  var import_fastmcp = require("fastmcp");
7717
+
7718
+ // src/mcp/commands.ts
7719
+ var import_node_path68 = require("path");
7712
7720
  var import_mini23 = require("zod/mini");
7713
- var MAX_RULE_SIZE_BYTES = 1024 * 1024;
7714
- var MAX_RULES_COUNT = 1e3;
7715
- var RULES_DIR_PREFIX = ".rulesync/rules";
7716
- function validateRulePath(relativePathFromCwd) {
7717
- const normalizedPath = relativePathFromCwd.replace(/\\/g, "/");
7718
- if (!normalizedPath.startsWith(`${RULES_DIR_PREFIX}/`)) {
7719
- throw new Error(`Invalid rule path: must be within ${RULES_DIR_PREFIX}/ directory`);
7720
- }
7721
- try {
7722
- resolvePath(normalizedPath, process.cwd());
7723
- } catch (error) {
7724
- throw new Error(`Path validation failed: ${formatError(error)}`, { cause: error });
7725
- }
7726
- const filename = (0, import_node_path68.basename)(normalizedPath);
7727
- if (!/^[a-zA-Z0-9_-]+\.md$/.test(filename)) {
7728
- throw new Error(
7729
- `Invalid filename: ${filename}. Must match pattern [a-zA-Z0-9_-]+.md (alphanumeric, hyphens, underscores only)`
7730
- );
7731
- }
7732
- }
7733
- async function listRules() {
7734
- const rulesDir = (0, import_node_path68.join)(process.cwd(), ".rulesync", "rules");
7721
+ var maxCommandSizeBytes = 1024 * 1024;
7722
+ var maxCommandsCount = 1e3;
7723
+ async function listCommands() {
7724
+ const commandsDir = (0, import_node_path68.join)(process.cwd(), ".rulesync", "commands");
7735
7725
  try {
7736
- const files = await listDirectoryFiles(rulesDir);
7726
+ const files = await listDirectoryFiles(commandsDir);
7737
7727
  const mdFiles = files.filter((file) => file.endsWith(".md"));
7738
- const rules = await Promise.all(
7728
+ const commands = await Promise.all(
7739
7729
  mdFiles.map(async (file) => {
7740
7730
  try {
7741
- const rule = await RulesyncRule.fromFile({
7742
- relativeFilePath: file,
7743
- validate: true
7731
+ const command = await RulesyncCommand.fromFile({
7732
+ relativeFilePath: file
7744
7733
  });
7745
- const frontmatter = rule.getFrontmatter();
7734
+ const frontmatter = command.getFrontmatter();
7746
7735
  return {
7747
- relativePathFromCwd: (0, import_node_path68.join)(".rulesync", "rules", file),
7736
+ relativePathFromCwd: (0, import_node_path68.join)(".rulesync", "commands", file),
7748
7737
  frontmatter
7749
7738
  };
7750
7739
  } catch (error) {
7751
- logger.error(`Failed to read rule file ${file}: ${formatError(error)}`);
7740
+ logger.error(`Failed to read command file ${file}: ${formatError(error)}`);
7752
7741
  return null;
7753
7742
  }
7754
7743
  })
7755
7744
  );
7756
- return rules.filter((rule) => rule !== null);
7745
+ return commands.filter((command) => command !== null);
7757
7746
  } catch (error) {
7758
- logger.error(`Failed to read rules directory: ${formatError(error)}`);
7747
+ logger.error(`Failed to read commands directory: ${formatError(error)}`);
7759
7748
  return [];
7760
7749
  }
7761
7750
  }
7762
- async function getRule({ relativePathFromCwd }) {
7763
- validateRulePath(relativePathFromCwd);
7751
+ async function getCommand({ relativePathFromCwd }) {
7752
+ checkPathTraversal({
7753
+ relativePath: relativePathFromCwd,
7754
+ intendedRootDir: process.cwd()
7755
+ });
7764
7756
  const filename = (0, import_node_path68.basename)(relativePathFromCwd);
7757
+ try {
7758
+ const command = await RulesyncCommand.fromFile({
7759
+ relativeFilePath: filename
7760
+ });
7761
+ return {
7762
+ relativePathFromCwd: (0, import_node_path68.join)(".rulesync", "commands", filename),
7763
+ frontmatter: command.getFrontmatter(),
7764
+ body: command.getBody()
7765
+ };
7766
+ } catch (error) {
7767
+ throw new Error(`Failed to read command file ${relativePathFromCwd}: ${formatError(error)}`, {
7768
+ cause: error
7769
+ });
7770
+ }
7771
+ }
7772
+ async function putCommand({
7773
+ relativePathFromCwd,
7774
+ frontmatter,
7775
+ body
7776
+ }) {
7777
+ checkPathTraversal({
7778
+ relativePath: relativePathFromCwd,
7779
+ intendedRootDir: process.cwd()
7780
+ });
7781
+ const filename = (0, import_node_path68.basename)(relativePathFromCwd);
7782
+ const estimatedSize = JSON.stringify(frontmatter).length + body.length;
7783
+ if (estimatedSize > maxCommandSizeBytes) {
7784
+ throw new Error(
7785
+ `Command size ${estimatedSize} bytes exceeds maximum ${maxCommandSizeBytes} bytes (1MB)`
7786
+ );
7787
+ }
7788
+ try {
7789
+ const existingCommands = await listCommands();
7790
+ const isUpdate = existingCommands.some(
7791
+ (command2) => command2.relativePathFromCwd === (0, import_node_path68.join)(".rulesync", "commands", filename)
7792
+ );
7793
+ if (!isUpdate && existingCommands.length >= maxCommandsCount) {
7794
+ throw new Error(`Maximum number of commands (${maxCommandsCount}) reached`);
7795
+ }
7796
+ const fileContent = stringifyFrontmatter(body, frontmatter);
7797
+ const command = new RulesyncCommand({
7798
+ baseDir: process.cwd(),
7799
+ relativeDirPath: (0, import_node_path68.join)(".rulesync", "commands"),
7800
+ relativeFilePath: filename,
7801
+ frontmatter,
7802
+ body,
7803
+ fileContent,
7804
+ validate: true
7805
+ });
7806
+ const commandsDir = (0, import_node_path68.join)(process.cwd(), ".rulesync", "commands");
7807
+ await ensureDir(commandsDir);
7808
+ await writeFileContent(command.getFilePath(), command.getFileContent());
7809
+ return {
7810
+ relativePathFromCwd: (0, import_node_path68.join)(".rulesync", "commands", filename),
7811
+ frontmatter: command.getFrontmatter(),
7812
+ body: command.getBody()
7813
+ };
7814
+ } catch (error) {
7815
+ throw new Error(`Failed to write command file ${relativePathFromCwd}: ${formatError(error)}`, {
7816
+ cause: error
7817
+ });
7818
+ }
7819
+ }
7820
+ async function deleteCommand({ relativePathFromCwd }) {
7821
+ checkPathTraversal({
7822
+ relativePath: relativePathFromCwd,
7823
+ intendedRootDir: process.cwd()
7824
+ });
7825
+ const filename = (0, import_node_path68.basename)(relativePathFromCwd);
7826
+ const fullPath = (0, import_node_path68.join)(process.cwd(), ".rulesync", "commands", filename);
7827
+ try {
7828
+ await removeFile(fullPath);
7829
+ return {
7830
+ relativePathFromCwd: (0, import_node_path68.join)(".rulesync", "commands", filename)
7831
+ };
7832
+ } catch (error) {
7833
+ throw new Error(`Failed to delete command file ${relativePathFromCwd}: ${formatError(error)}`, {
7834
+ cause: error
7835
+ });
7836
+ }
7837
+ }
7838
+ var commandToolSchemas = {
7839
+ listCommands: import_mini23.z.object({}),
7840
+ getCommand: import_mini23.z.object({
7841
+ relativePathFromCwd: import_mini23.z.string()
7842
+ }),
7843
+ putCommand: import_mini23.z.object({
7844
+ relativePathFromCwd: import_mini23.z.string(),
7845
+ frontmatter: RulesyncCommandFrontmatterSchema,
7846
+ body: import_mini23.z.string()
7847
+ }),
7848
+ deleteCommand: import_mini23.z.object({
7849
+ relativePathFromCwd: import_mini23.z.string()
7850
+ })
7851
+ };
7852
+ var commandTools = {
7853
+ listCommands: {
7854
+ name: "listCommands",
7855
+ description: `List all commands from ${(0, import_node_path68.join)(".rulesync", "commands", "*.md")} with their frontmatter.`,
7856
+ parameters: commandToolSchemas.listCommands,
7857
+ execute: async () => {
7858
+ const commands = await listCommands();
7859
+ const output = { commands };
7860
+ return JSON.stringify(output, null, 2);
7861
+ }
7862
+ },
7863
+ getCommand: {
7864
+ name: "getCommand",
7865
+ description: "Get detailed information about a specific command. relativePathFromCwd parameter is required.",
7866
+ parameters: commandToolSchemas.getCommand,
7867
+ execute: async (args) => {
7868
+ const result = await getCommand({ relativePathFromCwd: args.relativePathFromCwd });
7869
+ return JSON.stringify(result, null, 2);
7870
+ }
7871
+ },
7872
+ putCommand: {
7873
+ name: "putCommand",
7874
+ description: "Create or update a command (upsert operation). relativePathFromCwd, frontmatter, and body parameters are required.",
7875
+ parameters: commandToolSchemas.putCommand,
7876
+ execute: async (args) => {
7877
+ const result = await putCommand({
7878
+ relativePathFromCwd: args.relativePathFromCwd,
7879
+ frontmatter: args.frontmatter,
7880
+ body: args.body
7881
+ });
7882
+ return JSON.stringify(result, null, 2);
7883
+ }
7884
+ },
7885
+ deleteCommand: {
7886
+ name: "deleteCommand",
7887
+ description: "Delete a command file. relativePathFromCwd parameter is required.",
7888
+ parameters: commandToolSchemas.deleteCommand,
7889
+ execute: async (args) => {
7890
+ const result = await deleteCommand({ relativePathFromCwd: args.relativePathFromCwd });
7891
+ return JSON.stringify(result, null, 2);
7892
+ }
7893
+ }
7894
+ };
7895
+
7896
+ // src/mcp/ignore.ts
7897
+ var import_node_path69 = require("path");
7898
+ var import_mini24 = require("zod/mini");
7899
+ var maxIgnoreFileSizeBytes = 100 * 1024;
7900
+ async function getIgnoreFile() {
7901
+ const ignoreFilePath = (0, import_node_path69.join)(process.cwd(), ".rulesyncignore");
7902
+ try {
7903
+ const content = await readFileContent(ignoreFilePath);
7904
+ return {
7905
+ relativePathFromCwd: ".rulesyncignore",
7906
+ content
7907
+ };
7908
+ } catch (error) {
7909
+ throw new Error(`Failed to read .rulesyncignore file: ${formatError(error)}`, {
7910
+ cause: error
7911
+ });
7912
+ }
7913
+ }
7914
+ async function putIgnoreFile({ content }) {
7915
+ const ignoreFilePath = (0, import_node_path69.join)(process.cwd(), ".rulesyncignore");
7916
+ const contentSizeBytes = Buffer.byteLength(content, "utf8");
7917
+ if (contentSizeBytes > maxIgnoreFileSizeBytes) {
7918
+ throw new Error(
7919
+ `Ignore file size ${contentSizeBytes} bytes exceeds maximum ${maxIgnoreFileSizeBytes} bytes (100KB)`
7920
+ );
7921
+ }
7922
+ try {
7923
+ await ensureDir(process.cwd());
7924
+ await writeFileContent(ignoreFilePath, content);
7925
+ return {
7926
+ relativePathFromCwd: ".rulesyncignore",
7927
+ content
7928
+ };
7929
+ } catch (error) {
7930
+ throw new Error(`Failed to write .rulesyncignore file: ${formatError(error)}`, {
7931
+ cause: error
7932
+ });
7933
+ }
7934
+ }
7935
+ async function deleteIgnoreFile() {
7936
+ const ignoreFilePath = (0, import_node_path69.join)(process.cwd(), ".rulesyncignore");
7937
+ try {
7938
+ await removeFile(ignoreFilePath);
7939
+ return {
7940
+ relativePathFromCwd: ".rulesyncignore"
7941
+ };
7942
+ } catch (error) {
7943
+ throw new Error(`Failed to delete .rulesyncignore file: ${formatError(error)}`, {
7944
+ cause: error
7945
+ });
7946
+ }
7947
+ }
7948
+ var ignoreToolSchemas = {
7949
+ getIgnoreFile: import_mini24.z.object({}),
7950
+ putIgnoreFile: import_mini24.z.object({
7951
+ content: import_mini24.z.string()
7952
+ }),
7953
+ deleteIgnoreFile: import_mini24.z.object({})
7954
+ };
7955
+ var ignoreTools = {
7956
+ getIgnoreFile: {
7957
+ name: "getIgnoreFile",
7958
+ description: "Get the content of the .rulesyncignore file from the project root.",
7959
+ parameters: ignoreToolSchemas.getIgnoreFile,
7960
+ execute: async () => {
7961
+ const result = await getIgnoreFile();
7962
+ return JSON.stringify(result, null, 2);
7963
+ }
7964
+ },
7965
+ putIgnoreFile: {
7966
+ name: "putIgnoreFile",
7967
+ description: "Create or update the .rulesyncignore file (upsert operation). content parameter is required.",
7968
+ parameters: ignoreToolSchemas.putIgnoreFile,
7969
+ execute: async (args) => {
7970
+ const result = await putIgnoreFile({ content: args.content });
7971
+ return JSON.stringify(result, null, 2);
7972
+ }
7973
+ },
7974
+ deleteIgnoreFile: {
7975
+ name: "deleteIgnoreFile",
7976
+ description: "Delete the .rulesyncignore file from the project root.",
7977
+ parameters: ignoreToolSchemas.deleteIgnoreFile,
7978
+ execute: async () => {
7979
+ const result = await deleteIgnoreFile();
7980
+ return JSON.stringify(result, null, 2);
7981
+ }
7982
+ }
7983
+ };
7984
+
7985
+ // src/mcp/mcp.ts
7986
+ var import_node_path70 = require("path");
7987
+ var import_mini25 = require("zod/mini");
7988
+ var maxMcpSizeBytes = 1024 * 1024;
7989
+ async function getMcpFile() {
7990
+ try {
7991
+ const rulesyncMcp = await RulesyncMcp.fromFile({
7992
+ validate: true,
7993
+ modularMcp: false
7994
+ });
7995
+ const relativePathFromCwd = (0, import_node_path70.join)(
7996
+ rulesyncMcp.getRelativeDirPath(),
7997
+ rulesyncMcp.getRelativeFilePath()
7998
+ );
7999
+ return {
8000
+ relativePathFromCwd,
8001
+ content: rulesyncMcp.getFileContent()
8002
+ };
8003
+ } catch (error) {
8004
+ throw new Error(`Failed to read MCP file: ${formatError(error)}`, {
8005
+ cause: error
8006
+ });
8007
+ }
8008
+ }
8009
+ async function putMcpFile({ content }) {
8010
+ if (content.length > maxMcpSizeBytes) {
8011
+ throw new Error(
8012
+ `MCP file size ${content.length} bytes exceeds maximum ${maxMcpSizeBytes} bytes (1MB)`
8013
+ );
8014
+ }
8015
+ try {
8016
+ JSON.parse(content);
8017
+ } catch (error) {
8018
+ throw new Error(`Invalid JSON format in MCP file: ${formatError(error)}`, {
8019
+ cause: error
8020
+ });
8021
+ }
8022
+ try {
8023
+ const baseDir = process.cwd();
8024
+ const paths = RulesyncMcp.getSettablePaths();
8025
+ const relativeDirPath = paths.recommended.relativeDirPath;
8026
+ const relativeFilePath = paths.recommended.relativeFilePath;
8027
+ const fullPath = (0, import_node_path70.join)(baseDir, relativeDirPath, relativeFilePath);
8028
+ const rulesyncMcp = new RulesyncMcp({
8029
+ baseDir,
8030
+ relativeDirPath,
8031
+ relativeFilePath,
8032
+ fileContent: content,
8033
+ validate: true,
8034
+ modularMcp: false
8035
+ });
8036
+ await ensureDir((0, import_node_path70.join)(baseDir, relativeDirPath));
8037
+ await writeFileContent(fullPath, content);
8038
+ const relativePathFromCwd = (0, import_node_path70.join)(relativeDirPath, relativeFilePath);
8039
+ return {
8040
+ relativePathFromCwd,
8041
+ content: rulesyncMcp.getFileContent()
8042
+ };
8043
+ } catch (error) {
8044
+ throw new Error(`Failed to write MCP file: ${formatError(error)}`, {
8045
+ cause: error
8046
+ });
8047
+ }
8048
+ }
8049
+ async function deleteMcpFile() {
8050
+ try {
8051
+ const baseDir = process.cwd();
8052
+ const paths = RulesyncMcp.getSettablePaths();
8053
+ const recommendedPath = (0, import_node_path70.join)(
8054
+ baseDir,
8055
+ paths.recommended.relativeDirPath,
8056
+ paths.recommended.relativeFilePath
8057
+ );
8058
+ const legacyPath = (0, import_node_path70.join)(baseDir, paths.legacy.relativeDirPath, paths.legacy.relativeFilePath);
8059
+ await removeFile(recommendedPath);
8060
+ await removeFile(legacyPath);
8061
+ const relativePathFromCwd = (0, import_node_path70.join)(
8062
+ paths.recommended.relativeDirPath,
8063
+ paths.recommended.relativeFilePath
8064
+ );
8065
+ return {
8066
+ relativePathFromCwd
8067
+ };
8068
+ } catch (error) {
8069
+ throw new Error(`Failed to delete MCP file: ${formatError(error)}`, {
8070
+ cause: error
8071
+ });
8072
+ }
8073
+ }
8074
+ var mcpToolSchemas = {
8075
+ getMcpFile: import_mini25.z.object({}),
8076
+ putMcpFile: import_mini25.z.object({
8077
+ content: import_mini25.z.string()
8078
+ }),
8079
+ deleteMcpFile: import_mini25.z.object({})
8080
+ };
8081
+ var mcpTools = {
8082
+ getMcpFile: {
8083
+ name: "getMcpFile",
8084
+ description: `Get the MCP configuration file (${(0, import_node_path70.join)(".rulesync", "mcp.json")}).`,
8085
+ parameters: mcpToolSchemas.getMcpFile,
8086
+ execute: async () => {
8087
+ const result = await getMcpFile();
8088
+ return JSON.stringify(result, null, 2);
8089
+ }
8090
+ },
8091
+ putMcpFile: {
8092
+ name: "putMcpFile",
8093
+ description: "Create or update the MCP configuration file (upsert operation). content parameter is required and must be valid JSON.",
8094
+ parameters: mcpToolSchemas.putMcpFile,
8095
+ execute: async (args) => {
8096
+ const result = await putMcpFile({ content: args.content });
8097
+ return JSON.stringify(result, null, 2);
8098
+ }
8099
+ },
8100
+ deleteMcpFile: {
8101
+ name: "deleteMcpFile",
8102
+ description: "Delete the MCP configuration file.",
8103
+ parameters: mcpToolSchemas.deleteMcpFile,
8104
+ execute: async () => {
8105
+ const result = await deleteMcpFile();
8106
+ return JSON.stringify(result, null, 2);
8107
+ }
8108
+ }
8109
+ };
8110
+
8111
+ // src/mcp/rules.ts
8112
+ var import_node_path71 = require("path");
8113
+ var import_mini26 = require("zod/mini");
8114
+ var maxRuleSizeBytes = 1024 * 1024;
8115
+ var maxRulesCount = 1e3;
8116
+ async function listRules() {
8117
+ const rulesDir = (0, import_node_path71.join)(process.cwd(), ".rulesync", "rules");
8118
+ try {
8119
+ const files = await listDirectoryFiles(rulesDir);
8120
+ const mdFiles = files.filter((file) => file.endsWith(".md"));
8121
+ const rules = await Promise.all(
8122
+ mdFiles.map(async (file) => {
8123
+ try {
8124
+ const rule = await RulesyncRule.fromFile({
8125
+ relativeFilePath: file,
8126
+ validate: true
8127
+ });
8128
+ const frontmatter = rule.getFrontmatter();
8129
+ return {
8130
+ relativePathFromCwd: (0, import_node_path71.join)(".rulesync", "rules", file),
8131
+ frontmatter
8132
+ };
8133
+ } catch (error) {
8134
+ logger.error(`Failed to read rule file ${file}: ${formatError(error)}`);
8135
+ return null;
8136
+ }
8137
+ })
8138
+ );
8139
+ return rules.filter((rule) => rule !== null);
8140
+ } catch (error) {
8141
+ logger.error(`Failed to read rules directory: ${formatError(error)}`);
8142
+ return [];
8143
+ }
8144
+ }
8145
+ async function getRule({ relativePathFromCwd }) {
8146
+ checkPathTraversal({
8147
+ relativePath: relativePathFromCwd,
8148
+ intendedRootDir: process.cwd()
8149
+ });
8150
+ const filename = (0, import_node_path71.basename)(relativePathFromCwd);
7765
8151
  try {
7766
8152
  const rule = await RulesyncRule.fromFile({
7767
8153
  relativeFilePath: filename,
7768
8154
  validate: true
7769
8155
  });
7770
8156
  return {
7771
- relativePathFromCwd: (0, import_node_path68.join)(".rulesync", "rules", filename),
8157
+ relativePathFromCwd: (0, import_node_path71.join)(".rulesync", "rules", filename),
7772
8158
  frontmatter: rule.getFrontmatter(),
7773
8159
  body: rule.getBody()
7774
8160
  };
@@ -7783,35 +8169,38 @@ async function putRule({
7783
8169
  frontmatter,
7784
8170
  body
7785
8171
  }) {
7786
- validateRulePath(relativePathFromCwd);
7787
- const filename = (0, import_node_path68.basename)(relativePathFromCwd);
8172
+ checkPathTraversal({
8173
+ relativePath: relativePathFromCwd,
8174
+ intendedRootDir: process.cwd()
8175
+ });
8176
+ const filename = (0, import_node_path71.basename)(relativePathFromCwd);
7788
8177
  const estimatedSize = JSON.stringify(frontmatter).length + body.length;
7789
- if (estimatedSize > MAX_RULE_SIZE_BYTES) {
8178
+ if (estimatedSize > maxRuleSizeBytes) {
7790
8179
  throw new Error(
7791
- `Rule size ${estimatedSize} bytes exceeds maximum ${MAX_RULE_SIZE_BYTES} bytes (1MB)`
8180
+ `Rule size ${estimatedSize} bytes exceeds maximum ${maxRuleSizeBytes} bytes (1MB)`
7792
8181
  );
7793
8182
  }
7794
8183
  try {
7795
8184
  const existingRules = await listRules();
7796
8185
  const isUpdate = existingRules.some(
7797
- (rule2) => rule2.relativePathFromCwd === (0, import_node_path68.join)(".rulesync", "rules", filename)
8186
+ (rule2) => rule2.relativePathFromCwd === (0, import_node_path71.join)(".rulesync", "rules", filename)
7798
8187
  );
7799
- if (!isUpdate && existingRules.length >= MAX_RULES_COUNT) {
7800
- throw new Error(`Maximum number of rules (${MAX_RULES_COUNT}) reached`);
8188
+ if (!isUpdate && existingRules.length >= maxRulesCount) {
8189
+ throw new Error(`Maximum number of rules (${maxRulesCount}) reached`);
7801
8190
  }
7802
8191
  const rule = new RulesyncRule({
7803
8192
  baseDir: process.cwd(),
7804
- relativeDirPath: ".rulesync/rules",
8193
+ relativeDirPath: (0, import_node_path71.join)(".rulesync", "rules"),
7805
8194
  relativeFilePath: filename,
7806
8195
  frontmatter,
7807
8196
  body,
7808
8197
  validate: true
7809
8198
  });
7810
- const rulesDir = (0, import_node_path68.join)(process.cwd(), ".rulesync", "rules");
8199
+ const rulesDir = (0, import_node_path71.join)(process.cwd(), ".rulesync", "rules");
7811
8200
  await ensureDir(rulesDir);
7812
8201
  await writeFileContent(rule.getFilePath(), rule.getFileContent());
7813
8202
  return {
7814
- relativePathFromCwd: (0, import_node_path68.join)(".rulesync", "rules", filename),
8203
+ relativePathFromCwd: (0, import_node_path71.join)(".rulesync", "rules", filename),
7815
8204
  frontmatter: rule.getFrontmatter(),
7816
8205
  body: rule.getBody()
7817
8206
  };
@@ -7822,13 +8211,16 @@ async function putRule({
7822
8211
  }
7823
8212
  }
7824
8213
  async function deleteRule({ relativePathFromCwd }) {
7825
- validateRulePath(relativePathFromCwd);
7826
- const filename = (0, import_node_path68.basename)(relativePathFromCwd);
7827
- const fullPath = (0, import_node_path68.join)(process.cwd(), ".rulesync", "rules", filename);
8214
+ checkPathTraversal({
8215
+ relativePath: relativePathFromCwd,
8216
+ intendedRootDir: process.cwd()
8217
+ });
8218
+ const filename = (0, import_node_path71.basename)(relativePathFromCwd);
8219
+ const fullPath = (0, import_node_path71.join)(process.cwd(), ".rulesync", "rules", filename);
7828
8220
  try {
7829
8221
  await removeFile(fullPath);
7830
8222
  return {
7831
- relativePathFromCwd: (0, import_node_path68.join)(".rulesync", "rules", filename)
8223
+ relativePathFromCwd: (0, import_node_path71.join)(".rulesync", "rules", filename)
7832
8224
  };
7833
8225
  } catch (error) {
7834
8226
  throw new Error(`Failed to delete rule file ${relativePathFromCwd}: ${formatError(error)}`, {
@@ -7836,42 +8228,44 @@ async function deleteRule({ relativePathFromCwd }) {
7836
8228
  });
7837
8229
  }
7838
8230
  }
7839
- async function mcpCommand({ version }) {
7840
- const server = new import_fastmcp.FastMCP({
7841
- name: "rulesync-mcp-server",
7842
- // Type assertion is safe here because version comes from package.json which follows semver
7843
- // eslint-disable-next-line no-type-assertion/no-type-assertion
7844
- version
7845
- });
7846
- server.addTool({
8231
+ var ruleToolSchemas = {
8232
+ listRules: import_mini26.z.object({}),
8233
+ getRule: import_mini26.z.object({
8234
+ relativePathFromCwd: import_mini26.z.string()
8235
+ }),
8236
+ putRule: import_mini26.z.object({
8237
+ relativePathFromCwd: import_mini26.z.string(),
8238
+ frontmatter: RulesyncRuleFrontmatterSchema,
8239
+ body: import_mini26.z.string()
8240
+ }),
8241
+ deleteRule: import_mini26.z.object({
8242
+ relativePathFromCwd: import_mini26.z.string()
8243
+ })
8244
+ };
8245
+ var ruleTools = {
8246
+ listRules: {
7847
8247
  name: "listRules",
7848
- description: "List all rules from .rulesync/rules/*.md with their frontmatter",
7849
- parameters: import_mini23.z.object({}),
8248
+ description: `List all rules from ${(0, import_node_path71.join)(".rulesync", "rules", "*.md")} with their frontmatter.`,
8249
+ parameters: ruleToolSchemas.listRules,
7850
8250
  execute: async () => {
7851
8251
  const rules = await listRules();
7852
8252
  const output = { rules };
7853
8253
  return JSON.stringify(output, null, 2);
7854
8254
  }
7855
- });
7856
- server.addTool({
8255
+ },
8256
+ getRule: {
7857
8257
  name: "getRule",
7858
8258
  description: "Get detailed information about a specific rule. relativePathFromCwd parameter is required.",
7859
- parameters: import_mini23.z.object({
7860
- relativePathFromCwd: import_mini23.z.string()
7861
- }),
8259
+ parameters: ruleToolSchemas.getRule,
7862
8260
  execute: async (args) => {
7863
8261
  const result = await getRule({ relativePathFromCwd: args.relativePathFromCwd });
7864
8262
  return JSON.stringify(result, null, 2);
7865
8263
  }
7866
- });
7867
- server.addTool({
8264
+ },
8265
+ putRule: {
7868
8266
  name: "putRule",
7869
8267
  description: "Create or update a rule (upsert operation). relativePathFromCwd, frontmatter, and body parameters are required.",
7870
- parameters: import_mini23.z.object({
7871
- relativePathFromCwd: import_mini23.z.string(),
7872
- frontmatter: RulesyncRuleFrontmatterSchema,
7873
- body: import_mini23.z.string()
7874
- }),
8268
+ parameters: ruleToolSchemas.putRule,
7875
8269
  execute: async (args) => {
7876
8270
  const result = await putRule({
7877
8271
  relativePathFromCwd: args.relativePathFromCwd,
@@ -7880,18 +8274,227 @@ async function mcpCommand({ version }) {
7880
8274
  });
7881
8275
  return JSON.stringify(result, null, 2);
7882
8276
  }
7883
- });
7884
- server.addTool({
8277
+ },
8278
+ deleteRule: {
7885
8279
  name: "deleteRule",
7886
8280
  description: "Delete a rule file. relativePathFromCwd parameter is required.",
7887
- parameters: import_mini23.z.object({
7888
- relativePathFromCwd: import_mini23.z.string()
7889
- }),
8281
+ parameters: ruleToolSchemas.deleteRule,
7890
8282
  execute: async (args) => {
7891
8283
  const result = await deleteRule({ relativePathFromCwd: args.relativePathFromCwd });
7892
8284
  return JSON.stringify(result, null, 2);
7893
8285
  }
8286
+ }
8287
+ };
8288
+
8289
+ // src/mcp/subagents.ts
8290
+ var import_node_path72 = require("path");
8291
+ var import_mini27 = require("zod/mini");
8292
+ var maxSubagentSizeBytes = 1024 * 1024;
8293
+ var maxSubagentsCount = 1e3;
8294
+ async function listSubagents() {
8295
+ const subagentsDir = (0, import_node_path72.join)(process.cwd(), ".rulesync", "subagents");
8296
+ try {
8297
+ const files = await listDirectoryFiles(subagentsDir);
8298
+ const mdFiles = files.filter((file) => file.endsWith(".md"));
8299
+ const subagents = await Promise.all(
8300
+ mdFiles.map(async (file) => {
8301
+ try {
8302
+ const subagent = await RulesyncSubagent.fromFile({
8303
+ relativeFilePath: file,
8304
+ validate: true
8305
+ });
8306
+ const frontmatter = subagent.getFrontmatter();
8307
+ return {
8308
+ relativePathFromCwd: (0, import_node_path72.join)(".rulesync", "subagents", file),
8309
+ frontmatter
8310
+ };
8311
+ } catch (error) {
8312
+ logger.error(`Failed to read subagent file ${file}: ${formatError(error)}`);
8313
+ return null;
8314
+ }
8315
+ })
8316
+ );
8317
+ return subagents.filter(
8318
+ (subagent) => subagent !== null
8319
+ );
8320
+ } catch (error) {
8321
+ logger.error(`Failed to read subagents directory: ${formatError(error)}`);
8322
+ return [];
8323
+ }
8324
+ }
8325
+ async function getSubagent({ relativePathFromCwd }) {
8326
+ checkPathTraversal({
8327
+ relativePath: relativePathFromCwd,
8328
+ intendedRootDir: process.cwd()
8329
+ });
8330
+ const filename = (0, import_node_path72.basename)(relativePathFromCwd);
8331
+ try {
8332
+ const subagent = await RulesyncSubagent.fromFile({
8333
+ relativeFilePath: filename,
8334
+ validate: true
8335
+ });
8336
+ return {
8337
+ relativePathFromCwd: (0, import_node_path72.join)(".rulesync", "subagents", filename),
8338
+ frontmatter: subagent.getFrontmatter(),
8339
+ body: subagent.getBody()
8340
+ };
8341
+ } catch (error) {
8342
+ throw new Error(`Failed to read subagent file ${relativePathFromCwd}: ${formatError(error)}`, {
8343
+ cause: error
8344
+ });
8345
+ }
8346
+ }
8347
+ async function putSubagent({
8348
+ relativePathFromCwd,
8349
+ frontmatter,
8350
+ body
8351
+ }) {
8352
+ checkPathTraversal({
8353
+ relativePath: relativePathFromCwd,
8354
+ intendedRootDir: process.cwd()
8355
+ });
8356
+ const filename = (0, import_node_path72.basename)(relativePathFromCwd);
8357
+ const estimatedSize = JSON.stringify(frontmatter).length + body.length;
8358
+ if (estimatedSize > maxSubagentSizeBytes) {
8359
+ throw new Error(
8360
+ `Subagent size ${estimatedSize} bytes exceeds maximum ${maxSubagentSizeBytes} bytes (1MB)`
8361
+ );
8362
+ }
8363
+ try {
8364
+ const existingSubagents = await listSubagents();
8365
+ const isUpdate = existingSubagents.some(
8366
+ (subagent2) => subagent2.relativePathFromCwd === (0, import_node_path72.join)(".rulesync", "subagents", filename)
8367
+ );
8368
+ if (!isUpdate && existingSubagents.length >= maxSubagentsCount) {
8369
+ throw new Error(`Maximum number of subagents (${maxSubagentsCount}) reached`);
8370
+ }
8371
+ const subagent = new RulesyncSubagent({
8372
+ baseDir: process.cwd(),
8373
+ relativeDirPath: (0, import_node_path72.join)(".rulesync", "subagents"),
8374
+ relativeFilePath: filename,
8375
+ frontmatter,
8376
+ body,
8377
+ validate: true
8378
+ });
8379
+ const subagentsDir = (0, import_node_path72.join)(process.cwd(), ".rulesync", "subagents");
8380
+ await ensureDir(subagentsDir);
8381
+ await writeFileContent(subagent.getFilePath(), subagent.getFileContent());
8382
+ return {
8383
+ relativePathFromCwd: (0, import_node_path72.join)(".rulesync", "subagents", filename),
8384
+ frontmatter: subagent.getFrontmatter(),
8385
+ body: subagent.getBody()
8386
+ };
8387
+ } catch (error) {
8388
+ throw new Error(`Failed to write subagent file ${relativePathFromCwd}: ${formatError(error)}`, {
8389
+ cause: error
8390
+ });
8391
+ }
8392
+ }
8393
+ async function deleteSubagent({ relativePathFromCwd }) {
8394
+ checkPathTraversal({
8395
+ relativePath: relativePathFromCwd,
8396
+ intendedRootDir: process.cwd()
8397
+ });
8398
+ const filename = (0, import_node_path72.basename)(relativePathFromCwd);
8399
+ const fullPath = (0, import_node_path72.join)(process.cwd(), ".rulesync", "subagents", filename);
8400
+ try {
8401
+ await removeFile(fullPath);
8402
+ return {
8403
+ relativePathFromCwd: (0, import_node_path72.join)(".rulesync", "subagents", filename)
8404
+ };
8405
+ } catch (error) {
8406
+ throw new Error(
8407
+ `Failed to delete subagent file ${relativePathFromCwd}: ${formatError(error)}`,
8408
+ {
8409
+ cause: error
8410
+ }
8411
+ );
8412
+ }
8413
+ }
8414
+ var subagentToolSchemas = {
8415
+ listSubagents: import_mini27.z.object({}),
8416
+ getSubagent: import_mini27.z.object({
8417
+ relativePathFromCwd: import_mini27.z.string()
8418
+ }),
8419
+ putSubagent: import_mini27.z.object({
8420
+ relativePathFromCwd: import_mini27.z.string(),
8421
+ frontmatter: RulesyncSubagentFrontmatterSchema,
8422
+ body: import_mini27.z.string()
8423
+ }),
8424
+ deleteSubagent: import_mini27.z.object({
8425
+ relativePathFromCwd: import_mini27.z.string()
8426
+ })
8427
+ };
8428
+ var subagentTools = {
8429
+ listSubagents: {
8430
+ name: "listSubagents",
8431
+ description: `List all subagents from ${(0, import_node_path72.join)(".rulesync", "subagents", "*.md")} with their frontmatter.`,
8432
+ parameters: subagentToolSchemas.listSubagents,
8433
+ execute: async () => {
8434
+ const subagents = await listSubagents();
8435
+ const output = { subagents };
8436
+ return JSON.stringify(output, null, 2);
8437
+ }
8438
+ },
8439
+ getSubagent: {
8440
+ name: "getSubagent",
8441
+ description: "Get detailed information about a specific subagent. relativePathFromCwd parameter is required.",
8442
+ parameters: subagentToolSchemas.getSubagent,
8443
+ execute: async (args) => {
8444
+ const result = await getSubagent({ relativePathFromCwd: args.relativePathFromCwd });
8445
+ return JSON.stringify(result, null, 2);
8446
+ }
8447
+ },
8448
+ putSubagent: {
8449
+ name: "putSubagent",
8450
+ description: "Create or update a subagent (upsert operation). relativePathFromCwd, frontmatter, and body parameters are required.",
8451
+ parameters: subagentToolSchemas.putSubagent,
8452
+ execute: async (args) => {
8453
+ const result = await putSubagent({
8454
+ relativePathFromCwd: args.relativePathFromCwd,
8455
+ frontmatter: args.frontmatter,
8456
+ body: args.body
8457
+ });
8458
+ return JSON.stringify(result, null, 2);
8459
+ }
8460
+ },
8461
+ deleteSubagent: {
8462
+ name: "deleteSubagent",
8463
+ description: "Delete a subagent file. relativePathFromCwd parameter is required.",
8464
+ parameters: subagentToolSchemas.deleteSubagent,
8465
+ execute: async (args) => {
8466
+ const result = await deleteSubagent({ relativePathFromCwd: args.relativePathFromCwd });
8467
+ return JSON.stringify(result, null, 2);
8468
+ }
8469
+ }
8470
+ };
8471
+
8472
+ // src/cli/commands/mcp.ts
8473
+ async function mcpCommand({ version }) {
8474
+ const server = new import_fastmcp.FastMCP({
8475
+ name: "Rulesync MCP Server",
8476
+ // eslint-disable-next-line no-type-assertion/no-type-assertion
8477
+ version,
8478
+ instructions: "This server handles Rulesync files including rules, commands, MCP, ignore files, and subagents for any AI agents. It should be used when you need those files."
7894
8479
  });
8480
+ server.addTool(ruleTools.listRules);
8481
+ server.addTool(ruleTools.getRule);
8482
+ server.addTool(ruleTools.putRule);
8483
+ server.addTool(ruleTools.deleteRule);
8484
+ server.addTool(commandTools.listCommands);
8485
+ server.addTool(commandTools.getCommand);
8486
+ server.addTool(commandTools.putCommand);
8487
+ server.addTool(commandTools.deleteCommand);
8488
+ server.addTool(subagentTools.listSubagents);
8489
+ server.addTool(subagentTools.getSubagent);
8490
+ server.addTool(subagentTools.putSubagent);
8491
+ server.addTool(subagentTools.deleteSubagent);
8492
+ server.addTool(ignoreTools.getIgnoreFile);
8493
+ server.addTool(ignoreTools.putIgnoreFile);
8494
+ server.addTool(ignoreTools.deleteIgnoreFile);
8495
+ server.addTool(mcpTools.getMcpFile);
8496
+ server.addTool(mcpTools.putMcpFile);
8497
+ server.addTool(mcpTools.deleteMcpFile);
7895
8498
  logger.info("Rulesync MCP server started via stdio");
7896
8499
  void server.start({
7897
8500
  transportType: "stdio"
@@ -7899,7 +8502,7 @@ async function mcpCommand({ version }) {
7899
8502
  }
7900
8503
 
7901
8504
  // src/cli/index.ts
7902
- var getVersion = () => "3.19.0";
8505
+ var getVersion = () => "3.20.0";
7903
8506
  var main = async () => {
7904
8507
  const program = new import_commander.Command();
7905
8508
  const version = getVersion();