rulesync 3.31.0 → 3.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -229,17 +229,18 @@ var ALL_TOOL_TARGETS = [
229
229
  "antigravity",
230
230
  "augmentcode",
231
231
  "augmentcode-legacy",
232
- "copilot",
233
- "cursor",
234
- "cline",
235
232
  "claudecode",
233
+ "claudecode-legacy",
234
+ "cline",
236
235
  "codexcli",
236
+ "copilot",
237
+ "cursor",
238
+ "geminicli",
239
+ "junie",
240
+ "kiro",
237
241
  "opencode",
238
242
  "qwencode",
239
243
  "roo",
240
- "geminicli",
241
- "kiro",
242
- "junie",
243
244
  "warp",
244
245
  "windsurf"
245
246
  ];
@@ -272,6 +273,11 @@ var ConfigFileSchema = z3.object({
272
273
  ...z3.partial(ConfigParamsSchema).shape
273
274
  });
274
275
  var RequiredConfigParamsSchema = z3.required(ConfigParamsSchema);
276
+ var CONFLICTING_TARGET_PAIRS = [
277
+ ["augmentcode", "augmentcode-legacy"],
278
+ ["claudecode", "claudecode-legacy"]
279
+ ];
280
+ var LEGACY_TARGETS = ["augmentcode-legacy", "claudecode-legacy"];
275
281
  var Config = class {
276
282
  baseDirs;
277
283
  targets;
@@ -298,6 +304,7 @@ var Config = class {
298
304
  experimentalSimulateCommands,
299
305
  experimentalSimulateSubagents
300
306
  }) {
307
+ this.validateConflictingTargets(targets);
301
308
  this.baseDirs = baseDirs;
302
309
  this.targets = targets;
303
310
  this.features = features;
@@ -309,12 +316,26 @@ var Config = class {
309
316
  this.simulateSkills = simulateSkills ?? false;
310
317
  this.modularMcp = modularMcp ?? false;
311
318
  }
319
+ validateConflictingTargets(targets) {
320
+ for (const [target1, target2] of CONFLICTING_TARGET_PAIRS) {
321
+ const hasTarget1 = targets.includes(target1);
322
+ const hasTarget2 = targets.includes(target2);
323
+ if (hasTarget1 && hasTarget2) {
324
+ throw new Error(
325
+ `Conflicting targets: '${target1}' and '${target2}' cannot be used together. Please choose one.`
326
+ );
327
+ }
328
+ }
329
+ }
312
330
  getBaseDirs() {
313
331
  return this.baseDirs;
314
332
  }
315
333
  getTargets() {
316
334
  if (this.targets.includes("*")) {
317
- return [...ALL_TOOL_TARGETS];
335
+ return ALL_TOOL_TARGETS.filter(
336
+ // eslint-disable-next-line no-type-assertion/no-type-assertion
337
+ (target) => !LEGACY_TARGETS.includes(target)
338
+ );
318
339
  }
319
340
  return this.targets.filter((target) => target !== "*");
320
341
  }
@@ -4214,9 +4235,9 @@ var McpProcessor = class extends FeatureProcessor {
4214
4235
  };
4215
4236
 
4216
4237
  // src/features/rules/rules-processor.ts
4217
- import { basename as basename21, join as join81 } from "path";
4238
+ import { basename as basename21, join as join82 } from "path";
4218
4239
  import { encode } from "@toon-format/toon";
4219
- import { z as z32 } from "zod/mini";
4240
+ import { z as z33 } from "zod/mini";
4220
4241
 
4221
4242
  // src/features/skills/codexcli-skill.ts
4222
4243
  import { join as join42 } from "path";
@@ -6062,6 +6083,13 @@ var RulesyncRuleFrontmatterSchema = z28.object({
6062
6083
  subprojectPath: z28.optional(z28.string())
6063
6084
  })
6064
6085
  ),
6086
+ claudecode: z28.optional(
6087
+ z28.object({
6088
+ // Glob patterns for conditional rules (takes precedence over globs)
6089
+ // @example "src/**/*.ts, tests/**/*.test.ts"
6090
+ paths: z28.optional(z28.string())
6091
+ })
6092
+ ),
6065
6093
  cursor: z28.optional(
6066
6094
  z28.object({
6067
6095
  alwaysApply: z28.optional(z28.boolean()),
@@ -6625,9 +6653,9 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
6625
6653
  }
6626
6654
  };
6627
6655
 
6628
- // src/features/rules/claudecode-rule.ts
6656
+ // src/features/rules/claudecode-legacy-rule.ts
6629
6657
  import { join as join68 } from "path";
6630
- var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
6658
+ var ClaudecodeLegacyRule = class _ClaudecodeLegacyRule extends ToolRule {
6631
6659
  static getSettablePaths({
6632
6660
  global
6633
6661
  } = {}) {
@@ -6662,7 +6690,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
6662
6690
  const fileContent2 = await readFileContent(
6663
6691
  join68(baseDir, paths.root.relativeDirPath, relativePath2)
6664
6692
  );
6665
- return new _ClaudecodeRule({
6693
+ return new _ClaudecodeLegacyRule({
6666
6694
  baseDir,
6667
6695
  relativeDirPath: paths.root.relativeDirPath,
6668
6696
  relativeFilePath: paths.root.relativeFilePath,
@@ -6676,7 +6704,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
6676
6704
  }
6677
6705
  const relativePath = join68(paths.nonRoot.relativeDirPath, relativeFilePath);
6678
6706
  const fileContent = await readFileContent(join68(baseDir, relativePath));
6679
- return new _ClaudecodeRule({
6707
+ return new _ClaudecodeLegacyRule({
6680
6708
  baseDir,
6681
6709
  relativeDirPath: paths.nonRoot.relativeDirPath,
6682
6710
  relativeFilePath,
@@ -6692,7 +6720,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
6692
6720
  global = false
6693
6721
  }) {
6694
6722
  const paths = this.getSettablePaths({ global });
6695
- return new _ClaudecodeRule(
6723
+ return new _ClaudecodeLegacyRule(
6696
6724
  this.buildToolRuleParamsDefault({
6697
6725
  baseDir,
6698
6726
  rulesyncRule,
@@ -6711,16 +6739,208 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
6711
6739
  static isTargetedByRulesyncRule(rulesyncRule) {
6712
6740
  return this.isTargetedByRulesyncRuleDefault({
6713
6741
  rulesyncRule,
6714
- toolTarget: "claudecode"
6742
+ toolTarget: "claudecode-legacy"
6715
6743
  });
6716
6744
  }
6717
6745
  };
6718
6746
 
6719
- // src/features/rules/cline-rule.ts
6747
+ // src/features/rules/claudecode-rule.ts
6720
6748
  import { join as join69 } from "path";
6721
6749
  import { z as z29 } from "zod/mini";
6722
- var ClineRuleFrontmatterSchema = z29.object({
6723
- description: z29.string()
6750
+ var ClaudecodeRuleFrontmatterSchema = z29.object({
6751
+ paths: z29.optional(z29.string())
6752
+ });
6753
+ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
6754
+ frontmatter;
6755
+ body;
6756
+ static getSettablePaths({
6757
+ global
6758
+ } = {}) {
6759
+ if (global) {
6760
+ return {
6761
+ root: {
6762
+ relativeDirPath: ".claude",
6763
+ relativeFilePath: "CLAUDE.md"
6764
+ }
6765
+ };
6766
+ }
6767
+ return {
6768
+ root: {
6769
+ relativeDirPath: ".claude",
6770
+ relativeFilePath: "CLAUDE.md"
6771
+ },
6772
+ nonRoot: {
6773
+ relativeDirPath: join69(".claude", "rules")
6774
+ }
6775
+ };
6776
+ }
6777
+ constructor({ frontmatter, body, ...rest }) {
6778
+ if (rest.validate) {
6779
+ const result = ClaudecodeRuleFrontmatterSchema.safeParse(frontmatter);
6780
+ if (!result.success) {
6781
+ throw new Error(
6782
+ `Invalid frontmatter in ${join69(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
6783
+ );
6784
+ }
6785
+ }
6786
+ super({
6787
+ ...rest,
6788
+ // Root file: no frontmatter; Non-root file: with optional paths frontmatter
6789
+ fileContent: rest.root ? body : _ClaudecodeRule.generateFileContent(body, frontmatter)
6790
+ });
6791
+ this.frontmatter = frontmatter;
6792
+ this.body = body;
6793
+ }
6794
+ static generateFileContent(body, frontmatter) {
6795
+ if (frontmatter.paths) {
6796
+ return stringifyFrontmatter(body, { paths: frontmatter.paths });
6797
+ }
6798
+ return body;
6799
+ }
6800
+ static async fromFile({
6801
+ baseDir = process.cwd(),
6802
+ relativeFilePath,
6803
+ validate = true,
6804
+ global = false
6805
+ }) {
6806
+ const paths = this.getSettablePaths({ global });
6807
+ const isRoot = relativeFilePath === paths.root.relativeFilePath;
6808
+ if (isRoot) {
6809
+ const fileContent2 = await readFileContent(
6810
+ join69(baseDir, paths.root.relativeDirPath, paths.root.relativeFilePath)
6811
+ );
6812
+ return new _ClaudecodeRule({
6813
+ baseDir,
6814
+ relativeDirPath: paths.root.relativeDirPath,
6815
+ relativeFilePath: paths.root.relativeFilePath,
6816
+ frontmatter: {},
6817
+ body: fileContent2.trim(),
6818
+ validate,
6819
+ root: true
6820
+ });
6821
+ }
6822
+ if (!paths.nonRoot) {
6823
+ throw new Error("nonRoot path is not set");
6824
+ }
6825
+ const relativePath = join69(paths.nonRoot.relativeDirPath, relativeFilePath);
6826
+ const fileContent = await readFileContent(join69(baseDir, relativePath));
6827
+ const { frontmatter, body: content } = parseFrontmatter(fileContent);
6828
+ const result = ClaudecodeRuleFrontmatterSchema.safeParse(frontmatter);
6829
+ if (!result.success) {
6830
+ throw new Error(
6831
+ `Invalid frontmatter in ${join69(baseDir, relativePath)}: ${formatError(result.error)}`
6832
+ );
6833
+ }
6834
+ return new _ClaudecodeRule({
6835
+ baseDir,
6836
+ relativeDirPath: paths.nonRoot.relativeDirPath,
6837
+ relativeFilePath,
6838
+ frontmatter: result.data,
6839
+ body: content.trim(),
6840
+ validate,
6841
+ root: false
6842
+ });
6843
+ }
6844
+ static fromRulesyncRule({
6845
+ baseDir = process.cwd(),
6846
+ rulesyncRule,
6847
+ validate = true,
6848
+ global = false
6849
+ }) {
6850
+ const rulesyncFrontmatter = rulesyncRule.getFrontmatter();
6851
+ const root = rulesyncFrontmatter.root ?? false;
6852
+ const paths = this.getSettablePaths({ global });
6853
+ const claudecodePaths = rulesyncFrontmatter.claudecode?.paths;
6854
+ const globs = rulesyncFrontmatter.globs;
6855
+ const pathsValue = claudecodePaths ?? (globs?.length ? globs.join(", ") : void 0);
6856
+ const claudecodeFrontmatter = {
6857
+ paths: root ? void 0 : pathsValue
6858
+ };
6859
+ const body = rulesyncRule.getBody();
6860
+ if (root) {
6861
+ return new _ClaudecodeRule({
6862
+ baseDir,
6863
+ frontmatter: claudecodeFrontmatter,
6864
+ body,
6865
+ relativeDirPath: paths.root.relativeDirPath,
6866
+ relativeFilePath: paths.root.relativeFilePath,
6867
+ validate,
6868
+ root
6869
+ });
6870
+ }
6871
+ if (!paths.nonRoot) {
6872
+ throw new Error("nonRoot path is not set");
6873
+ }
6874
+ return new _ClaudecodeRule({
6875
+ baseDir,
6876
+ frontmatter: claudecodeFrontmatter,
6877
+ body,
6878
+ relativeDirPath: paths.nonRoot.relativeDirPath,
6879
+ relativeFilePath: rulesyncRule.getRelativeFilePath(),
6880
+ validate,
6881
+ root
6882
+ });
6883
+ }
6884
+ toRulesyncRule() {
6885
+ let globs;
6886
+ if (this.isRoot()) {
6887
+ globs = ["**/*"];
6888
+ } else if (this.frontmatter.paths) {
6889
+ globs = this.frontmatter.paths.split(",").map((g) => g.trim());
6890
+ }
6891
+ const rulesyncFrontmatter = {
6892
+ targets: ["*"],
6893
+ root: this.isRoot(),
6894
+ description: this.description,
6895
+ globs,
6896
+ ...this.frontmatter.paths && {
6897
+ claudecode: { paths: this.frontmatter.paths }
6898
+ }
6899
+ };
6900
+ return new RulesyncRule({
6901
+ baseDir: this.getBaseDir(),
6902
+ frontmatter: rulesyncFrontmatter,
6903
+ body: this.body,
6904
+ relativeDirPath: RULESYNC_RULES_RELATIVE_DIR_PATH,
6905
+ relativeFilePath: this.getRelativeFilePath(),
6906
+ validate: true
6907
+ });
6908
+ }
6909
+ validate() {
6910
+ if (!this.frontmatter) {
6911
+ return { success: true, error: null };
6912
+ }
6913
+ const result = ClaudecodeRuleFrontmatterSchema.safeParse(this.frontmatter);
6914
+ if (result.success) {
6915
+ return { success: true, error: null };
6916
+ } else {
6917
+ return {
6918
+ success: false,
6919
+ error: new Error(
6920
+ `Invalid frontmatter in ${join69(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
6921
+ )
6922
+ };
6923
+ }
6924
+ }
6925
+ getFrontmatter() {
6926
+ return this.frontmatter;
6927
+ }
6928
+ getBody() {
6929
+ return this.body;
6930
+ }
6931
+ static isTargetedByRulesyncRule(rulesyncRule) {
6932
+ return this.isTargetedByRulesyncRuleDefault({
6933
+ rulesyncRule,
6934
+ toolTarget: "claudecode"
6935
+ });
6936
+ }
6937
+ };
6938
+
6939
+ // src/features/rules/cline-rule.ts
6940
+ import { join as join70 } from "path";
6941
+ import { z as z30 } from "zod/mini";
6942
+ var ClineRuleFrontmatterSchema = z30.object({
6943
+ description: z30.string()
6724
6944
  });
6725
6945
  var ClineRule = class _ClineRule extends ToolRule {
6726
6946
  static getSettablePaths() {
@@ -6762,7 +6982,7 @@ var ClineRule = class _ClineRule extends ToolRule {
6762
6982
  validate = true
6763
6983
  }) {
6764
6984
  const fileContent = await readFileContent(
6765
- join69(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
6985
+ join70(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
6766
6986
  );
6767
6987
  return new _ClineRule({
6768
6988
  baseDir,
@@ -6775,7 +6995,7 @@ var ClineRule = class _ClineRule extends ToolRule {
6775
6995
  };
6776
6996
 
6777
6997
  // src/features/rules/codexcli-rule.ts
6778
- import { join as join70 } from "path";
6998
+ import { join as join71 } from "path";
6779
6999
  var CodexcliRule = class _CodexcliRule extends ToolRule {
6780
7000
  static getSettablePaths({
6781
7001
  global
@@ -6794,7 +7014,7 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
6794
7014
  relativeFilePath: "AGENTS.md"
6795
7015
  },
6796
7016
  nonRoot: {
6797
- relativeDirPath: join70(".codex", "memories")
7017
+ relativeDirPath: join71(".codex", "memories")
6798
7018
  }
6799
7019
  };
6800
7020
  }
@@ -6809,7 +7029,7 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
6809
7029
  if (isRoot) {
6810
7030
  const relativePath2 = paths.root.relativeFilePath;
6811
7031
  const fileContent2 = await readFileContent(
6812
- join70(baseDir, paths.root.relativeDirPath, relativePath2)
7032
+ join71(baseDir, paths.root.relativeDirPath, relativePath2)
6813
7033
  );
6814
7034
  return new _CodexcliRule({
6815
7035
  baseDir,
@@ -6823,8 +7043,8 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
6823
7043
  if (!paths.nonRoot) {
6824
7044
  throw new Error("nonRoot path is not set");
6825
7045
  }
6826
- const relativePath = join70(paths.nonRoot.relativeDirPath, relativeFilePath);
6827
- const fileContent = await readFileContent(join70(baseDir, relativePath));
7046
+ const relativePath = join71(paths.nonRoot.relativeDirPath, relativeFilePath);
7047
+ const fileContent = await readFileContent(join71(baseDir, relativePath));
6828
7048
  return new _CodexcliRule({
6829
7049
  baseDir,
6830
7050
  relativeDirPath: paths.nonRoot.relativeDirPath,
@@ -6866,12 +7086,12 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
6866
7086
  };
6867
7087
 
6868
7088
  // src/features/rules/copilot-rule.ts
6869
- import { join as join71 } from "path";
6870
- import { z as z30 } from "zod/mini";
6871
- var CopilotRuleFrontmatterSchema = z30.object({
6872
- description: z30.optional(z30.string()),
6873
- applyTo: z30.optional(z30.string()),
6874
- excludeAgent: z30.optional(z30.union([z30.literal("code-review"), z30.literal("coding-agent")]))
7089
+ import { join as join72 } from "path";
7090
+ import { z as z31 } from "zod/mini";
7091
+ var CopilotRuleFrontmatterSchema = z31.object({
7092
+ description: z31.optional(z31.string()),
7093
+ applyTo: z31.optional(z31.string()),
7094
+ excludeAgent: z31.optional(z31.union([z31.literal("code-review"), z31.literal("coding-agent")]))
6875
7095
  });
6876
7096
  var CopilotRule = class _CopilotRule extends ToolRule {
6877
7097
  frontmatter;
@@ -6883,7 +7103,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
6883
7103
  relativeFilePath: "copilot-instructions.md"
6884
7104
  },
6885
7105
  nonRoot: {
6886
- relativeDirPath: join71(".github", "instructions")
7106
+ relativeDirPath: join72(".github", "instructions")
6887
7107
  }
6888
7108
  };
6889
7109
  }
@@ -6892,7 +7112,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
6892
7112
  const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
6893
7113
  if (!result.success) {
6894
7114
  throw new Error(
6895
- `Invalid frontmatter in ${join71(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
7115
+ `Invalid frontmatter in ${join72(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
6896
7116
  );
6897
7117
  }
6898
7118
  }
@@ -6974,11 +7194,11 @@ var CopilotRule = class _CopilotRule extends ToolRule {
6974
7194
  validate = true
6975
7195
  }) {
6976
7196
  const isRoot = relativeFilePath === "copilot-instructions.md";
6977
- const relativePath = isRoot ? join71(
7197
+ const relativePath = isRoot ? join72(
6978
7198
  this.getSettablePaths().root.relativeDirPath,
6979
7199
  this.getSettablePaths().root.relativeFilePath
6980
- ) : join71(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
6981
- const fileContent = await readFileContent(join71(baseDir, relativePath));
7200
+ ) : join72(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
7201
+ const fileContent = await readFileContent(join72(baseDir, relativePath));
6982
7202
  if (isRoot) {
6983
7203
  return new _CopilotRule({
6984
7204
  baseDir,
@@ -6994,7 +7214,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
6994
7214
  const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
6995
7215
  if (!result.success) {
6996
7216
  throw new Error(
6997
- `Invalid frontmatter in ${join71(baseDir, relativeFilePath)}: ${formatError(result.error)}`
7217
+ `Invalid frontmatter in ${join72(baseDir, relativeFilePath)}: ${formatError(result.error)}`
6998
7218
  );
6999
7219
  }
7000
7220
  return new _CopilotRule({
@@ -7018,7 +7238,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
7018
7238
  return {
7019
7239
  success: false,
7020
7240
  error: new Error(
7021
- `Invalid frontmatter in ${join71(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
7241
+ `Invalid frontmatter in ${join72(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
7022
7242
  )
7023
7243
  };
7024
7244
  }
@@ -7038,12 +7258,12 @@ var CopilotRule = class _CopilotRule extends ToolRule {
7038
7258
  };
7039
7259
 
7040
7260
  // src/features/rules/cursor-rule.ts
7041
- import { basename as basename20, join as join72 } from "path";
7042
- import { z as z31 } from "zod/mini";
7043
- var CursorRuleFrontmatterSchema = z31.object({
7044
- description: z31.optional(z31.string()),
7045
- globs: z31.optional(z31.string()),
7046
- alwaysApply: z31.optional(z31.boolean())
7261
+ import { basename as basename20, join as join73 } from "path";
7262
+ import { z as z32 } from "zod/mini";
7263
+ var CursorRuleFrontmatterSchema = z32.object({
7264
+ description: z32.optional(z32.string()),
7265
+ globs: z32.optional(z32.string()),
7266
+ alwaysApply: z32.optional(z32.boolean())
7047
7267
  });
7048
7268
  var CursorRule = class _CursorRule extends ToolRule {
7049
7269
  frontmatter;
@@ -7051,7 +7271,7 @@ var CursorRule = class _CursorRule extends ToolRule {
7051
7271
  static getSettablePaths() {
7052
7272
  return {
7053
7273
  nonRoot: {
7054
- relativeDirPath: join72(".cursor", "rules")
7274
+ relativeDirPath: join73(".cursor", "rules")
7055
7275
  }
7056
7276
  };
7057
7277
  }
@@ -7060,7 +7280,7 @@ var CursorRule = class _CursorRule extends ToolRule {
7060
7280
  const result = CursorRuleFrontmatterSchema.safeParse(frontmatter);
7061
7281
  if (!result.success) {
7062
7282
  throw new Error(
7063
- `Invalid frontmatter in ${join72(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
7283
+ `Invalid frontmatter in ${join73(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
7064
7284
  );
7065
7285
  }
7066
7286
  }
@@ -7177,13 +7397,13 @@ var CursorRule = class _CursorRule extends ToolRule {
7177
7397
  validate = true
7178
7398
  }) {
7179
7399
  const fileContent = await readFileContent(
7180
- join72(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7400
+ join73(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7181
7401
  );
7182
7402
  const { frontmatter, body: content } = _CursorRule.parseCursorFrontmatter(fileContent);
7183
7403
  const result = CursorRuleFrontmatterSchema.safeParse(frontmatter);
7184
7404
  if (!result.success) {
7185
7405
  throw new Error(
7186
- `Invalid frontmatter in ${join72(baseDir, relativeFilePath)}: ${formatError(result.error)}`
7406
+ `Invalid frontmatter in ${join73(baseDir, relativeFilePath)}: ${formatError(result.error)}`
7187
7407
  );
7188
7408
  }
7189
7409
  return new _CursorRule({
@@ -7206,7 +7426,7 @@ var CursorRule = class _CursorRule extends ToolRule {
7206
7426
  return {
7207
7427
  success: false,
7208
7428
  error: new Error(
7209
- `Invalid frontmatter in ${join72(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
7429
+ `Invalid frontmatter in ${join73(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
7210
7430
  )
7211
7431
  };
7212
7432
  }
@@ -7226,7 +7446,7 @@ var CursorRule = class _CursorRule extends ToolRule {
7226
7446
  };
7227
7447
 
7228
7448
  // src/features/rules/geminicli-rule.ts
7229
- import { join as join73 } from "path";
7449
+ import { join as join74 } from "path";
7230
7450
  var GeminiCliRule = class _GeminiCliRule extends ToolRule {
7231
7451
  static getSettablePaths({
7232
7452
  global
@@ -7245,7 +7465,7 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
7245
7465
  relativeFilePath: "GEMINI.md"
7246
7466
  },
7247
7467
  nonRoot: {
7248
- relativeDirPath: join73(".gemini", "memories")
7468
+ relativeDirPath: join74(".gemini", "memories")
7249
7469
  }
7250
7470
  };
7251
7471
  }
@@ -7260,7 +7480,7 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
7260
7480
  if (isRoot) {
7261
7481
  const relativePath2 = paths.root.relativeFilePath;
7262
7482
  const fileContent2 = await readFileContent(
7263
- join73(baseDir, paths.root.relativeDirPath, relativePath2)
7483
+ join74(baseDir, paths.root.relativeDirPath, relativePath2)
7264
7484
  );
7265
7485
  return new _GeminiCliRule({
7266
7486
  baseDir,
@@ -7274,8 +7494,8 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
7274
7494
  if (!paths.nonRoot) {
7275
7495
  throw new Error("nonRoot path is not set");
7276
7496
  }
7277
- const relativePath = join73(paths.nonRoot.relativeDirPath, relativeFilePath);
7278
- const fileContent = await readFileContent(join73(baseDir, relativePath));
7497
+ const relativePath = join74(paths.nonRoot.relativeDirPath, relativeFilePath);
7498
+ const fileContent = await readFileContent(join74(baseDir, relativePath));
7279
7499
  return new _GeminiCliRule({
7280
7500
  baseDir,
7281
7501
  relativeDirPath: paths.nonRoot.relativeDirPath,
@@ -7317,7 +7537,7 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
7317
7537
  };
7318
7538
 
7319
7539
  // src/features/rules/junie-rule.ts
7320
- import { join as join74 } from "path";
7540
+ import { join as join75 } from "path";
7321
7541
  var JunieRule = class _JunieRule extends ToolRule {
7322
7542
  static getSettablePaths() {
7323
7543
  return {
@@ -7326,7 +7546,7 @@ var JunieRule = class _JunieRule extends ToolRule {
7326
7546
  relativeFilePath: "guidelines.md"
7327
7547
  },
7328
7548
  nonRoot: {
7329
- relativeDirPath: join74(".junie", "memories")
7549
+ relativeDirPath: join75(".junie", "memories")
7330
7550
  }
7331
7551
  };
7332
7552
  }
@@ -7336,8 +7556,8 @@ var JunieRule = class _JunieRule extends ToolRule {
7336
7556
  validate = true
7337
7557
  }) {
7338
7558
  const isRoot = relativeFilePath === "guidelines.md";
7339
- const relativePath = isRoot ? "guidelines.md" : join74(".junie", "memories", relativeFilePath);
7340
- const fileContent = await readFileContent(join74(baseDir, relativePath));
7559
+ const relativePath = isRoot ? "guidelines.md" : join75(".junie", "memories", relativeFilePath);
7560
+ const fileContent = await readFileContent(join75(baseDir, relativePath));
7341
7561
  return new _JunieRule({
7342
7562
  baseDir,
7343
7563
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -7377,12 +7597,12 @@ var JunieRule = class _JunieRule extends ToolRule {
7377
7597
  };
7378
7598
 
7379
7599
  // src/features/rules/kiro-rule.ts
7380
- import { join as join75 } from "path";
7600
+ import { join as join76 } from "path";
7381
7601
  var KiroRule = class _KiroRule extends ToolRule {
7382
7602
  static getSettablePaths() {
7383
7603
  return {
7384
7604
  nonRoot: {
7385
- relativeDirPath: join75(".kiro", "steering")
7605
+ relativeDirPath: join76(".kiro", "steering")
7386
7606
  }
7387
7607
  };
7388
7608
  }
@@ -7392,7 +7612,7 @@ var KiroRule = class _KiroRule extends ToolRule {
7392
7612
  validate = true
7393
7613
  }) {
7394
7614
  const fileContent = await readFileContent(
7395
- join75(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7615
+ join76(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7396
7616
  );
7397
7617
  return new _KiroRule({
7398
7618
  baseDir,
@@ -7432,7 +7652,7 @@ var KiroRule = class _KiroRule extends ToolRule {
7432
7652
  };
7433
7653
 
7434
7654
  // src/features/rules/opencode-rule.ts
7435
- import { join as join76 } from "path";
7655
+ import { join as join77 } from "path";
7436
7656
  var OpenCodeRule = class _OpenCodeRule extends ToolRule {
7437
7657
  static getSettablePaths() {
7438
7658
  return {
@@ -7441,7 +7661,7 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
7441
7661
  relativeFilePath: "AGENTS.md"
7442
7662
  },
7443
7663
  nonRoot: {
7444
- relativeDirPath: join76(".opencode", "memories")
7664
+ relativeDirPath: join77(".opencode", "memories")
7445
7665
  }
7446
7666
  };
7447
7667
  }
@@ -7451,8 +7671,8 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
7451
7671
  validate = true
7452
7672
  }) {
7453
7673
  const isRoot = relativeFilePath === "AGENTS.md";
7454
- const relativePath = isRoot ? "AGENTS.md" : join76(".opencode", "memories", relativeFilePath);
7455
- const fileContent = await readFileContent(join76(baseDir, relativePath));
7674
+ const relativePath = isRoot ? "AGENTS.md" : join77(".opencode", "memories", relativeFilePath);
7675
+ const fileContent = await readFileContent(join77(baseDir, relativePath));
7456
7676
  return new _OpenCodeRule({
7457
7677
  baseDir,
7458
7678
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -7492,7 +7712,7 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
7492
7712
  };
7493
7713
 
7494
7714
  // src/features/rules/qwencode-rule.ts
7495
- import { join as join77 } from "path";
7715
+ import { join as join78 } from "path";
7496
7716
  var QwencodeRule = class _QwencodeRule extends ToolRule {
7497
7717
  static getSettablePaths() {
7498
7718
  return {
@@ -7501,7 +7721,7 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
7501
7721
  relativeFilePath: "QWEN.md"
7502
7722
  },
7503
7723
  nonRoot: {
7504
- relativeDirPath: join77(".qwen", "memories")
7724
+ relativeDirPath: join78(".qwen", "memories")
7505
7725
  }
7506
7726
  };
7507
7727
  }
@@ -7511,8 +7731,8 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
7511
7731
  validate = true
7512
7732
  }) {
7513
7733
  const isRoot = relativeFilePath === "QWEN.md";
7514
- const relativePath = isRoot ? "QWEN.md" : join77(".qwen", "memories", relativeFilePath);
7515
- const fileContent = await readFileContent(join77(baseDir, relativePath));
7734
+ const relativePath = isRoot ? "QWEN.md" : join78(".qwen", "memories", relativeFilePath);
7735
+ const fileContent = await readFileContent(join78(baseDir, relativePath));
7516
7736
  return new _QwencodeRule({
7517
7737
  baseDir,
7518
7738
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
@@ -7549,12 +7769,12 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
7549
7769
  };
7550
7770
 
7551
7771
  // src/features/rules/roo-rule.ts
7552
- import { join as join78 } from "path";
7772
+ import { join as join79 } from "path";
7553
7773
  var RooRule = class _RooRule extends ToolRule {
7554
7774
  static getSettablePaths() {
7555
7775
  return {
7556
7776
  nonRoot: {
7557
- relativeDirPath: join78(".roo", "rules")
7777
+ relativeDirPath: join79(".roo", "rules")
7558
7778
  }
7559
7779
  };
7560
7780
  }
@@ -7564,7 +7784,7 @@ var RooRule = class _RooRule extends ToolRule {
7564
7784
  validate = true
7565
7785
  }) {
7566
7786
  const fileContent = await readFileContent(
7567
- join78(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7787
+ join79(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7568
7788
  );
7569
7789
  return new _RooRule({
7570
7790
  baseDir,
@@ -7619,7 +7839,7 @@ var RooRule = class _RooRule extends ToolRule {
7619
7839
  };
7620
7840
 
7621
7841
  // src/features/rules/warp-rule.ts
7622
- import { join as join79 } from "path";
7842
+ import { join as join80 } from "path";
7623
7843
  var WarpRule = class _WarpRule extends ToolRule {
7624
7844
  constructor({ fileContent, root, ...rest }) {
7625
7845
  super({
@@ -7635,7 +7855,7 @@ var WarpRule = class _WarpRule extends ToolRule {
7635
7855
  relativeFilePath: "WARP.md"
7636
7856
  },
7637
7857
  nonRoot: {
7638
- relativeDirPath: join79(".warp", "memories")
7858
+ relativeDirPath: join80(".warp", "memories")
7639
7859
  }
7640
7860
  };
7641
7861
  }
@@ -7645,8 +7865,8 @@ var WarpRule = class _WarpRule extends ToolRule {
7645
7865
  validate = true
7646
7866
  }) {
7647
7867
  const isRoot = relativeFilePath === this.getSettablePaths().root.relativeFilePath;
7648
- const relativePath = isRoot ? this.getSettablePaths().root.relativeFilePath : join79(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
7649
- const fileContent = await readFileContent(join79(baseDir, relativePath));
7868
+ const relativePath = isRoot ? this.getSettablePaths().root.relativeFilePath : join80(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
7869
+ const fileContent = await readFileContent(join80(baseDir, relativePath));
7650
7870
  return new _WarpRule({
7651
7871
  baseDir,
7652
7872
  relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : ".warp",
@@ -7686,12 +7906,12 @@ var WarpRule = class _WarpRule extends ToolRule {
7686
7906
  };
7687
7907
 
7688
7908
  // src/features/rules/windsurf-rule.ts
7689
- import { join as join80 } from "path";
7909
+ import { join as join81 } from "path";
7690
7910
  var WindsurfRule = class _WindsurfRule extends ToolRule {
7691
7911
  static getSettablePaths() {
7692
7912
  return {
7693
7913
  nonRoot: {
7694
- relativeDirPath: join80(".windsurf", "rules")
7914
+ relativeDirPath: join81(".windsurf", "rules")
7695
7915
  }
7696
7916
  };
7697
7917
  }
@@ -7701,7 +7921,7 @@ var WindsurfRule = class _WindsurfRule extends ToolRule {
7701
7921
  validate = true
7702
7922
  }) {
7703
7923
  const fileContent = await readFileContent(
7704
- join80(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7924
+ join81(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
7705
7925
  );
7706
7926
  return new _WindsurfRule({
7707
7927
  baseDir,
@@ -7747,6 +7967,7 @@ var rulesProcessorToolTargets = [
7747
7967
  "augmentcode",
7748
7968
  "augmentcode-legacy",
7749
7969
  "claudecode",
7970
+ "claudecode-legacy",
7750
7971
  "cline",
7751
7972
  "codexcli",
7752
7973
  "copilot",
@@ -7760,9 +7981,10 @@ var rulesProcessorToolTargets = [
7760
7981
  "warp",
7761
7982
  "windsurf"
7762
7983
  ];
7763
- var RulesProcessorToolTargetSchema = z32.enum(rulesProcessorToolTargets);
7984
+ var RulesProcessorToolTargetSchema = z33.enum(rulesProcessorToolTargets);
7764
7985
  var rulesProcessorToolTargetsGlobal = [
7765
7986
  "claudecode",
7987
+ "claudecode-legacy",
7766
7988
  "codexcli",
7767
7989
  "geminicli"
7768
7990
  ];
@@ -7773,6 +7995,7 @@ var toolRuleFactories = /* @__PURE__ */ new Map([
7773
7995
  ["augmentcode", { class: AugmentcodeRule, meta: { extension: "md" } }],
7774
7996
  ["augmentcode-legacy", { class: AugmentcodeLegacyRule, meta: { extension: "md" } }],
7775
7997
  ["claudecode", { class: ClaudecodeRule, meta: { extension: "md" } }],
7998
+ ["claudecode-legacy", { class: ClaudecodeLegacyRule, meta: { extension: "md" } }],
7776
7999
  ["cline", { class: ClineRule, meta: { extension: "md" } }],
7777
8000
  ["codexcli", { class: CodexcliRule, meta: { extension: "md" } }],
7778
8001
  ["copilot", { class: CopilotRule, meta: { extension: "md" } }],
@@ -7903,6 +8126,9 @@ var RulesProcessor = class extends FeatureProcessor {
7903
8126
  return toolRules;
7904
8127
  }
7905
8128
  case "claudecode": {
8129
+ return toolRules;
8130
+ }
8131
+ case "claudecode-legacy": {
7906
8132
  const rootRule = toolRules[rootRuleIndex];
7907
8133
  rootRule?.setFileContent(
7908
8134
  this.generateReferencesSection(toolRules) + rootRule.getFileContent()
@@ -7997,7 +8223,7 @@ var RulesProcessor = class extends FeatureProcessor {
7997
8223
  * Load and parse rulesync rule files from .rulesync/rules/ directory
7998
8224
  */
7999
8225
  async loadRulesyncFiles() {
8000
- const files = await findFilesByGlobs(join81(RULESYNC_RULES_RELATIVE_DIR_PATH, "*.md"));
8226
+ const files = await findFilesByGlobs(join82(RULESYNC_RULES_RELATIVE_DIR_PATH, "*.md"));
8001
8227
  logger.debug(`Found ${files.length} rulesync files`);
8002
8228
  const rulesyncRules = await Promise.all(
8003
8229
  files.map((file) => RulesyncRule.fromFile({ relativeFilePath: basename21(file) }))
@@ -8018,7 +8244,7 @@ var RulesProcessor = class extends FeatureProcessor {
8018
8244
  return rulesyncRules;
8019
8245
  }
8020
8246
  async loadRulesyncFilesLegacy() {
8021
- const legacyFiles = await findFilesByGlobs(join81(RULESYNC_RELATIVE_DIR_PATH, "*.md"));
8247
+ const legacyFiles = await findFilesByGlobs(join82(RULESYNC_RELATIVE_DIR_PATH, "*.md"));
8022
8248
  logger.debug(`Found ${legacyFiles.length} legacy rulesync files`);
8023
8249
  return Promise.all(
8024
8250
  legacyFiles.map((file) => RulesyncRule.fromFileLegacy({ relativeFilePath: basename21(file) }))
@@ -8039,7 +8265,7 @@ var RulesProcessor = class extends FeatureProcessor {
8039
8265
  return [];
8040
8266
  }
8041
8267
  const rootFilePaths = await findFilesByGlobs(
8042
- join81(
8268
+ join82(
8043
8269
  this.baseDir,
8044
8270
  settablePaths.root.relativeDirPath ?? ".",
8045
8271
  settablePaths.root.relativeFilePath
@@ -8061,7 +8287,7 @@ var RulesProcessor = class extends FeatureProcessor {
8061
8287
  return [];
8062
8288
  }
8063
8289
  const nonRootFilePaths = await findFilesByGlobs(
8064
- join81(this.baseDir, settablePaths.nonRoot.relativeDirPath, `*.${factory.meta.extension}`)
8290
+ join82(this.baseDir, settablePaths.nonRoot.relativeDirPath, `*.${factory.meta.extension}`)
8065
8291
  );
8066
8292
  return await Promise.all(
8067
8293
  nonRootFilePaths.map(
@@ -8160,21 +8386,21 @@ s/<command> [arguments]
8160
8386
  This syntax employs a double slash (\`s/\`) to prevent conflicts with built-in slash commands.
8161
8387
  The \`s\` in \`s/\` stands for *simulate*. Because custom slash commands are not built-in, this syntax provides a pseudo way to invoke them.
8162
8388
 
8163
- When users call a custom slash command, you have to look for the markdown file, \`${join81(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "{command}.md")}\`, then execute the contents of that file as the block of operations.` : "";
8389
+ When users call a custom slash command, you have to look for the markdown file, \`${join82(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "{command}.md")}\`, then execute the contents of that file as the block of operations.` : "";
8164
8390
  const subagentsSection = subagents ? `## Simulated Subagents
8165
8391
 
8166
8392
  Simulated subagents are specialized AI assistants that can be invoked to handle specific types of tasks. In this case, it can be appear something like custom slash commands simply. Simulated subagents can be called by custom slash commands.
8167
8393
 
8168
- When users call a simulated subagent, it will look for the corresponding markdown file, \`${join81(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "{subagent}.md")}\`, and execute its contents as the block of operations.
8394
+ When users call a simulated subagent, it will look for the corresponding markdown file, \`${join82(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "{subagent}.md")}\`, and execute its contents as the block of operations.
8169
8395
 
8170
- For example, if the user instructs \`Call planner subagent to plan the refactoring\`, you have to look for the markdown file, \`${join81(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "planner.md")}\`, and execute its contents as the block of operations.` : "";
8396
+ For example, if the user instructs \`Call planner subagent to plan the refactoring\`, you have to look for the markdown file, \`${join82(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "planner.md")}\`, and execute its contents as the block of operations.` : "";
8171
8397
  const skillsSection = skills ? `## Simulated Skills
8172
8398
 
8173
8399
  Simulated skills are specialized capabilities that can be invoked to handle specific types of tasks.
8174
8400
 
8175
- When users invoke a simulated skill, look for the corresponding SKILL.md file in \`${join81(RULESYNC_SKILLS_RELATIVE_DIR_PATH, "{skill}/SKILL.md")}\` and execute its contents as the block of operations.
8401
+ When users invoke a simulated skill, look for the corresponding SKILL.md file in \`${join82(RULESYNC_SKILLS_RELATIVE_DIR_PATH, "{skill}/SKILL.md")}\` and execute its contents as the block of operations.
8176
8402
 
8177
- For example, if the user instructs \`Use the skill example-skill to achieve something\`, look for \`${join81(RULESYNC_SKILLS_RELATIVE_DIR_PATH, "example-skill/SKILL.md")}\` and execute its contents.
8403
+ For example, if the user instructs \`Use the skill example-skill to achieve something\`, look for \`${join82(RULESYNC_SKILLS_RELATIVE_DIR_PATH, "example-skill/SKILL.md")}\` and execute its contents.
8178
8404
 
8179
8405
  Additionally, you should proactively consider using available skills when they would help accomplish a task more effectively, even if the user doesn't explicitly request them.` : "";
8180
8406
  const result = [
@@ -8436,102 +8662,149 @@ async function generateSkills(config) {
8436
8662
  }
8437
8663
 
8438
8664
  // src/cli/commands/gitignore.ts
8439
- import { join as join82 } from "path";
8665
+ import { join as join83 } from "path";
8666
+ var RULESYNC_HEADER = "# Generated by Rulesync";
8667
+ var LEGACY_RULESYNC_HEADER = "# Generated by rulesync - AI tool configuration files";
8668
+ var RULESYNC_IGNORE_ENTRIES = [
8669
+ // AGENTS.md
8670
+ "**/AGENTS.md",
8671
+ "**/.agents/",
8672
+ // Amazon Q
8673
+ "**/.amazonq/",
8674
+ // Augment
8675
+ "**/.augmentignore",
8676
+ "**/.augment/rules/",
8677
+ "**/.augment-guidelines",
8678
+ // Claude Code
8679
+ "**/CLAUDE.md",
8680
+ "**/.claude/CLAUDE.md",
8681
+ "**/.claude/memories/",
8682
+ "**/.claude/rules/",
8683
+ "**/.claude/commands/",
8684
+ "**/.claude/agents/",
8685
+ "**/.claude/skills/",
8686
+ "**/.claude/settings.local.json",
8687
+ "**/.mcp.json",
8688
+ // Cline
8689
+ "**/.clinerules/",
8690
+ "**/.clineignore",
8691
+ "**/.cline/mcp.json",
8692
+ // Codex
8693
+ "**/.codexignore",
8694
+ "**/.codex/",
8695
+ "**/.codex/skills/",
8696
+ // Cursor
8697
+ "**/.cursor/",
8698
+ "**/.cursorignore",
8699
+ // Gemini
8700
+ "**/GEMINI.md",
8701
+ "**/.gemini/memories/",
8702
+ "**/.gemini/commands/",
8703
+ "**/.gemini/subagents/",
8704
+ "**/.gemini/skills/",
8705
+ "**/.geminiignore",
8706
+ // GitHub Copilot
8707
+ "**/.github/copilot-instructions.md",
8708
+ "**/.github/instructions/",
8709
+ "**/.github/prompts/",
8710
+ "**/.github/subagents/",
8711
+ "**/.github/skills/",
8712
+ "**/.vscode/mcp.json",
8713
+ // Junie
8714
+ "**/.junie/guidelines.md",
8715
+ "**/.junie/mcp.json",
8716
+ // Kiro
8717
+ "**/.kiro/steering/",
8718
+ "**/.aiignore",
8719
+ // OpenCode
8720
+ "**/.opencode/memories/",
8721
+ "**/.opencode/command/",
8722
+ "**/opencode.json",
8723
+ // Qwen
8724
+ "**/QWEN.md",
8725
+ "**/.qwen/memories/",
8726
+ // Roo
8727
+ "**/.roo/rules/",
8728
+ "**/.rooignore",
8729
+ "**/.roo/mcp.json",
8730
+ "**/.roo/subagents/",
8731
+ // Warp
8732
+ "**/.warp/",
8733
+ "**/WARP.md",
8734
+ // Others
8735
+ "**/modular-mcp.json",
8736
+ "!.rulesync/.aiignore"
8737
+ ];
8738
+ var isRulesyncHeader = (line) => {
8739
+ const trimmed = line.trim();
8740
+ return trimmed === RULESYNC_HEADER || trimmed === LEGACY_RULESYNC_HEADER;
8741
+ };
8742
+ var isRulesyncEntry = (line) => {
8743
+ const trimmed = line.trim();
8744
+ if (trimmed === "" || isRulesyncHeader(line)) {
8745
+ return false;
8746
+ }
8747
+ return RULESYNC_IGNORE_ENTRIES.includes(trimmed);
8748
+ };
8749
+ var removeExistingRulesyncEntries = (content) => {
8750
+ const lines = content.split("\n");
8751
+ const filteredLines = [];
8752
+ let inRulesyncBlock = false;
8753
+ let consecutiveEmptyLines = 0;
8754
+ for (const line of lines) {
8755
+ const trimmed = line.trim();
8756
+ if (isRulesyncHeader(line)) {
8757
+ inRulesyncBlock = true;
8758
+ continue;
8759
+ }
8760
+ if (inRulesyncBlock) {
8761
+ if (trimmed === "") {
8762
+ consecutiveEmptyLines++;
8763
+ if (consecutiveEmptyLines >= 2) {
8764
+ inRulesyncBlock = false;
8765
+ consecutiveEmptyLines = 0;
8766
+ }
8767
+ continue;
8768
+ }
8769
+ if (isRulesyncEntry(line)) {
8770
+ consecutiveEmptyLines = 0;
8771
+ continue;
8772
+ }
8773
+ inRulesyncBlock = false;
8774
+ consecutiveEmptyLines = 0;
8775
+ }
8776
+ if (isRulesyncEntry(line)) {
8777
+ continue;
8778
+ }
8779
+ filteredLines.push(line);
8780
+ }
8781
+ let result = filteredLines.join("\n");
8782
+ while (result.endsWith("\n\n")) {
8783
+ result = result.slice(0, -1);
8784
+ }
8785
+ return result;
8786
+ };
8440
8787
  var gitignoreCommand = async () => {
8441
- const gitignorePath = join82(process.cwd(), ".gitignore");
8442
- const rulesFilesToIgnore = [
8443
- "# Generated by rulesync - AI tool configuration files",
8444
- // AGENTS.md
8445
- "**/AGENTS.md",
8446
- "**/.agents/",
8447
- // Amazon Q
8448
- "**/.amazonq/",
8449
- // Augment
8450
- "**/.augmentignore",
8451
- "**/.augment/rules/",
8452
- "**/.augment-guidelines",
8453
- // Claude Code
8454
- "**/CLAUDE.md",
8455
- "**/.claude/memories/",
8456
- "**/.claude/commands/",
8457
- "**/.claude/agents/",
8458
- "**/.claude/skills/",
8459
- "**/.claude/settings.local.json",
8460
- "**/.mcp.json",
8461
- // Cline
8462
- "**/.clinerules/",
8463
- "**/.clineignore",
8464
- "**/.cline/mcp.json",
8465
- // Codex
8466
- "**/.codexignore",
8467
- "**/.codex/",
8468
- "**/.codex/skills/",
8469
- // Cursor
8470
- "**/.cursor/",
8471
- "**/.cursorignore",
8472
- // Gemini
8473
- "**/GEMINI.md",
8474
- "**/.gemini/memories/",
8475
- "**/.gemini/commands/",
8476
- "**/.gemini/subagents/",
8477
- "**/.gemini/skills/",
8478
- // GitHub Copilot
8479
- "**/.github/copilot-instructions.md",
8480
- "**/.github/instructions/",
8481
- "**/.github/prompts/",
8482
- "**/.github/subagents/",
8483
- "**/.github/skills/",
8484
- "**/.vscode/mcp.json",
8485
- // Junie
8486
- "**/.junie/guidelines.md",
8487
- "**/.junie/mcp.json",
8488
- // Kiro
8489
- "**/.kiro/steering/",
8490
- "**/.aiignore",
8491
- // OpenCode
8492
- "**/.opencode/memories/",
8493
- "**/.opencode/command/",
8494
- "**/opencode.json",
8495
- // Qwen
8496
- "**/QWEN.md",
8497
- "**/.qwen/memories/",
8498
- // Roo
8499
- "**/.roo/rules/",
8500
- "**/.rooignore",
8501
- "**/.roo/mcp.json",
8502
- "**/.roo/subagents/",
8503
- // Warp
8504
- "**/.warp/",
8505
- "**/WARP.md",
8506
- // Others
8507
- "**/modular-mcp.json",
8508
- "!.rulesync/.aiignore"
8509
- ];
8788
+ const gitignorePath = join83(process.cwd(), ".gitignore");
8510
8789
  let gitignoreContent = "";
8511
8790
  if (await fileExists(gitignorePath)) {
8512
8791
  gitignoreContent = await readFileContent(gitignorePath);
8513
8792
  }
8514
- const linesToAdd = [];
8515
- for (const rule of rulesFilesToIgnore) {
8516
- if (!gitignoreContent.includes(rule)) {
8517
- linesToAdd.push(rule);
8518
- }
8519
- }
8520
- if (linesToAdd.length === 0) {
8793
+ const cleanedContent = removeExistingRulesyncEntries(gitignoreContent);
8794
+ const rulesyncBlock = [RULESYNC_HEADER, ...RULESYNC_IGNORE_ENTRIES].join("\n");
8795
+ const newContent = cleanedContent.trim() ? `${cleanedContent.trimEnd()}
8796
+
8797
+ ${rulesyncBlock}
8798
+ ` : `${rulesyncBlock}
8799
+ `;
8800
+ if (gitignoreContent === newContent) {
8521
8801
  logger.success(".gitignore is already up to date");
8522
8802
  return;
8523
8803
  }
8524
- const newContent = gitignoreContent ? `${gitignoreContent.trimEnd()}
8525
-
8526
- ${linesToAdd.join("\n")}
8527
- ` : `${linesToAdd.join("\n")}
8528
- `;
8529
8804
  await writeFileContent(gitignorePath, newContent);
8530
- logger.success(`Added ${linesToAdd.length} rules to .gitignore:`);
8531
- for (const line of linesToAdd) {
8532
- if (!line.startsWith("#")) {
8533
- logger.info(` ${line}`);
8534
- }
8805
+ logger.success("Updated .gitignore with rulesync entries:");
8806
+ for (const entry of RULESYNC_IGNORE_ENTRIES) {
8807
+ logger.info(` ${entry}`);
8535
8808
  }
8536
8809
  };
8537
8810
 
@@ -8711,7 +8984,7 @@ async function importSkills(config, tool) {
8711
8984
  }
8712
8985
 
8713
8986
  // src/cli/commands/init.ts
8714
- import { join as join83 } from "path";
8987
+ import { join as join84 } from "path";
8715
8988
  async function initCommand() {
8716
8989
  logger.info("Initializing rulesync...");
8717
8990
  await ensureDir(RULESYNC_RELATIVE_DIR_PATH);
@@ -8874,14 +9147,14 @@ Attention, again, you are just the planner, so though you can read any files and
8874
9147
  await ensureDir(commandPaths.relativeDirPath);
8875
9148
  await ensureDir(subagentPaths.relativeDirPath);
8876
9149
  await ensureDir(ignorePaths.recommended.relativeDirPath);
8877
- const ruleFilepath = join83(rulePaths.recommended.relativeDirPath, sampleRuleFile.filename);
9150
+ const ruleFilepath = join84(rulePaths.recommended.relativeDirPath, sampleRuleFile.filename);
8878
9151
  if (!await fileExists(ruleFilepath)) {
8879
9152
  await writeFileContent(ruleFilepath, sampleRuleFile.content);
8880
9153
  logger.success(`Created ${ruleFilepath}`);
8881
9154
  } else {
8882
9155
  logger.info(`Skipped ${ruleFilepath} (already exists)`);
8883
9156
  }
8884
- const mcpFilepath = join83(
9157
+ const mcpFilepath = join84(
8885
9158
  mcpPaths.recommended.relativeDirPath,
8886
9159
  mcpPaths.recommended.relativeFilePath
8887
9160
  );
@@ -8891,21 +9164,21 @@ Attention, again, you are just the planner, so though you can read any files and
8891
9164
  } else {
8892
9165
  logger.info(`Skipped ${mcpFilepath} (already exists)`);
8893
9166
  }
8894
- const commandFilepath = join83(commandPaths.relativeDirPath, sampleCommandFile.filename);
9167
+ const commandFilepath = join84(commandPaths.relativeDirPath, sampleCommandFile.filename);
8895
9168
  if (!await fileExists(commandFilepath)) {
8896
9169
  await writeFileContent(commandFilepath, sampleCommandFile.content);
8897
9170
  logger.success(`Created ${commandFilepath}`);
8898
9171
  } else {
8899
9172
  logger.info(`Skipped ${commandFilepath} (already exists)`);
8900
9173
  }
8901
- const subagentFilepath = join83(subagentPaths.relativeDirPath, sampleSubagentFile.filename);
9174
+ const subagentFilepath = join84(subagentPaths.relativeDirPath, sampleSubagentFile.filename);
8902
9175
  if (!await fileExists(subagentFilepath)) {
8903
9176
  await writeFileContent(subagentFilepath, sampleSubagentFile.content);
8904
9177
  logger.success(`Created ${subagentFilepath}`);
8905
9178
  } else {
8906
9179
  logger.info(`Skipped ${subagentFilepath} (already exists)`);
8907
9180
  }
8908
- const ignoreFilepath = join83(
9181
+ const ignoreFilepath = join84(
8909
9182
  ignorePaths.recommended.relativeDirPath,
8910
9183
  ignorePaths.recommended.relativeFilePath
8911
9184
  );
@@ -8921,12 +9194,12 @@ Attention, again, you are just the planner, so though you can read any files and
8921
9194
  import { FastMCP } from "fastmcp";
8922
9195
 
8923
9196
  // src/mcp/commands.ts
8924
- import { basename as basename22, join as join84 } from "path";
8925
- import { z as z33 } from "zod/mini";
9197
+ import { basename as basename22, join as join85 } from "path";
9198
+ import { z as z34 } from "zod/mini";
8926
9199
  var maxCommandSizeBytes = 1024 * 1024;
8927
9200
  var maxCommandsCount = 1e3;
8928
9201
  async function listCommands() {
8929
- const commandsDir = join84(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
9202
+ const commandsDir = join85(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
8930
9203
  try {
8931
9204
  const files = await listDirectoryFiles(commandsDir);
8932
9205
  const mdFiles = files.filter((file) => file.endsWith(".md"));
@@ -8938,7 +9211,7 @@ async function listCommands() {
8938
9211
  });
8939
9212
  const frontmatter = command.getFrontmatter();
8940
9213
  return {
8941
- relativePathFromCwd: join84(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, file),
9214
+ relativePathFromCwd: join85(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, file),
8942
9215
  frontmatter
8943
9216
  };
8944
9217
  } catch (error) {
@@ -8964,7 +9237,7 @@ async function getCommand({ relativePathFromCwd }) {
8964
9237
  relativeFilePath: filename
8965
9238
  });
8966
9239
  return {
8967
- relativePathFromCwd: join84(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
9240
+ relativePathFromCwd: join85(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
8968
9241
  frontmatter: command.getFrontmatter(),
8969
9242
  body: command.getBody()
8970
9243
  };
@@ -8993,7 +9266,7 @@ async function putCommand({
8993
9266
  try {
8994
9267
  const existingCommands = await listCommands();
8995
9268
  const isUpdate = existingCommands.some(
8996
- (command2) => command2.relativePathFromCwd === join84(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
9269
+ (command2) => command2.relativePathFromCwd === join85(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
8997
9270
  );
8998
9271
  if (!isUpdate && existingCommands.length >= maxCommandsCount) {
8999
9272
  throw new Error(`Maximum number of commands (${maxCommandsCount}) reached`);
@@ -9008,11 +9281,11 @@ async function putCommand({
9008
9281
  fileContent,
9009
9282
  validate: true
9010
9283
  });
9011
- const commandsDir = join84(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
9284
+ const commandsDir = join85(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
9012
9285
  await ensureDir(commandsDir);
9013
9286
  await writeFileContent(command.getFilePath(), command.getFileContent());
9014
9287
  return {
9015
- relativePathFromCwd: join84(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
9288
+ relativePathFromCwd: join85(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
9016
9289
  frontmatter: command.getFrontmatter(),
9017
9290
  body: command.getBody()
9018
9291
  };
@@ -9028,11 +9301,11 @@ async function deleteCommand({ relativePathFromCwd }) {
9028
9301
  intendedRootDir: process.cwd()
9029
9302
  });
9030
9303
  const filename = basename22(relativePathFromCwd);
9031
- const fullPath = join84(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename);
9304
+ const fullPath = join85(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename);
9032
9305
  try {
9033
9306
  await removeFile(fullPath);
9034
9307
  return {
9035
- relativePathFromCwd: join84(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
9308
+ relativePathFromCwd: join85(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
9036
9309
  };
9037
9310
  } catch (error) {
9038
9311
  throw new Error(`Failed to delete command file ${relativePathFromCwd}: ${formatError(error)}`, {
@@ -9041,23 +9314,23 @@ async function deleteCommand({ relativePathFromCwd }) {
9041
9314
  }
9042
9315
  }
9043
9316
  var commandToolSchemas = {
9044
- listCommands: z33.object({}),
9045
- getCommand: z33.object({
9046
- relativePathFromCwd: z33.string()
9317
+ listCommands: z34.object({}),
9318
+ getCommand: z34.object({
9319
+ relativePathFromCwd: z34.string()
9047
9320
  }),
9048
- putCommand: z33.object({
9049
- relativePathFromCwd: z33.string(),
9321
+ putCommand: z34.object({
9322
+ relativePathFromCwd: z34.string(),
9050
9323
  frontmatter: RulesyncCommandFrontmatterSchema,
9051
- body: z33.string()
9324
+ body: z34.string()
9052
9325
  }),
9053
- deleteCommand: z33.object({
9054
- relativePathFromCwd: z33.string()
9326
+ deleteCommand: z34.object({
9327
+ relativePathFromCwd: z34.string()
9055
9328
  })
9056
9329
  };
9057
9330
  var commandTools = {
9058
9331
  listCommands: {
9059
9332
  name: "listCommands",
9060
- description: `List all commands from ${join84(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
9333
+ description: `List all commands from ${join85(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
9061
9334
  parameters: commandToolSchemas.listCommands,
9062
9335
  execute: async () => {
9063
9336
  const commands = await listCommands();
@@ -9099,11 +9372,11 @@ var commandTools = {
9099
9372
  };
9100
9373
 
9101
9374
  // src/mcp/ignore.ts
9102
- import { join as join85 } from "path";
9103
- import { z as z34 } from "zod/mini";
9375
+ import { join as join86 } from "path";
9376
+ import { z as z35 } from "zod/mini";
9104
9377
  var maxIgnoreFileSizeBytes = 100 * 1024;
9105
9378
  async function getIgnoreFile() {
9106
- const ignoreFilePath = join85(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
9379
+ const ignoreFilePath = join86(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
9107
9380
  try {
9108
9381
  const content = await readFileContent(ignoreFilePath);
9109
9382
  return {
@@ -9117,7 +9390,7 @@ async function getIgnoreFile() {
9117
9390
  }
9118
9391
  }
9119
9392
  async function putIgnoreFile({ content }) {
9120
- const ignoreFilePath = join85(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
9393
+ const ignoreFilePath = join86(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
9121
9394
  const contentSizeBytes = Buffer.byteLength(content, "utf8");
9122
9395
  if (contentSizeBytes > maxIgnoreFileSizeBytes) {
9123
9396
  throw new Error(
@@ -9138,8 +9411,8 @@ async function putIgnoreFile({ content }) {
9138
9411
  }
9139
9412
  }
9140
9413
  async function deleteIgnoreFile() {
9141
- const aiignorePath = join85(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
9142
- const legacyIgnorePath = join85(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
9414
+ const aiignorePath = join86(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
9415
+ const legacyIgnorePath = join86(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
9143
9416
  try {
9144
9417
  await Promise.all([removeFile(aiignorePath), removeFile(legacyIgnorePath)]);
9145
9418
  return {
@@ -9157,11 +9430,11 @@ async function deleteIgnoreFile() {
9157
9430
  }
9158
9431
  }
9159
9432
  var ignoreToolSchemas = {
9160
- getIgnoreFile: z34.object({}),
9161
- putIgnoreFile: z34.object({
9162
- content: z34.string()
9433
+ getIgnoreFile: z35.object({}),
9434
+ putIgnoreFile: z35.object({
9435
+ content: z35.string()
9163
9436
  }),
9164
- deleteIgnoreFile: z34.object({})
9437
+ deleteIgnoreFile: z35.object({})
9165
9438
  };
9166
9439
  var ignoreTools = {
9167
9440
  getIgnoreFile: {
@@ -9194,8 +9467,8 @@ var ignoreTools = {
9194
9467
  };
9195
9468
 
9196
9469
  // src/mcp/mcp.ts
9197
- import { join as join86 } from "path";
9198
- import { z as z35 } from "zod/mini";
9470
+ import { join as join87 } from "path";
9471
+ import { z as z36 } from "zod/mini";
9199
9472
  var maxMcpSizeBytes = 1024 * 1024;
9200
9473
  async function getMcpFile() {
9201
9474
  const config = await ConfigResolver.resolve({});
@@ -9204,7 +9477,7 @@ async function getMcpFile() {
9204
9477
  validate: true,
9205
9478
  modularMcp: config.getModularMcp()
9206
9479
  });
9207
- const relativePathFromCwd = join86(
9480
+ const relativePathFromCwd = join87(
9208
9481
  rulesyncMcp.getRelativeDirPath(),
9209
9482
  rulesyncMcp.getRelativeFilePath()
9210
9483
  );
@@ -9237,7 +9510,7 @@ async function putMcpFile({ content }) {
9237
9510
  const paths = RulesyncMcp.getSettablePaths();
9238
9511
  const relativeDirPath = paths.recommended.relativeDirPath;
9239
9512
  const relativeFilePath = paths.recommended.relativeFilePath;
9240
- const fullPath = join86(baseDir, relativeDirPath, relativeFilePath);
9513
+ const fullPath = join87(baseDir, relativeDirPath, relativeFilePath);
9241
9514
  const rulesyncMcp = new RulesyncMcp({
9242
9515
  baseDir,
9243
9516
  relativeDirPath,
@@ -9246,9 +9519,9 @@ async function putMcpFile({ content }) {
9246
9519
  validate: true,
9247
9520
  modularMcp: config.getModularMcp()
9248
9521
  });
9249
- await ensureDir(join86(baseDir, relativeDirPath));
9522
+ await ensureDir(join87(baseDir, relativeDirPath));
9250
9523
  await writeFileContent(fullPath, content);
9251
- const relativePathFromCwd = join86(relativeDirPath, relativeFilePath);
9524
+ const relativePathFromCwd = join87(relativeDirPath, relativeFilePath);
9252
9525
  return {
9253
9526
  relativePathFromCwd,
9254
9527
  content: rulesyncMcp.getFileContent()
@@ -9263,15 +9536,15 @@ async function deleteMcpFile() {
9263
9536
  try {
9264
9537
  const baseDir = process.cwd();
9265
9538
  const paths = RulesyncMcp.getSettablePaths();
9266
- const recommendedPath = join86(
9539
+ const recommendedPath = join87(
9267
9540
  baseDir,
9268
9541
  paths.recommended.relativeDirPath,
9269
9542
  paths.recommended.relativeFilePath
9270
9543
  );
9271
- const legacyPath = join86(baseDir, paths.legacy.relativeDirPath, paths.legacy.relativeFilePath);
9544
+ const legacyPath = join87(baseDir, paths.legacy.relativeDirPath, paths.legacy.relativeFilePath);
9272
9545
  await removeFile(recommendedPath);
9273
9546
  await removeFile(legacyPath);
9274
- const relativePathFromCwd = join86(
9547
+ const relativePathFromCwd = join87(
9275
9548
  paths.recommended.relativeDirPath,
9276
9549
  paths.recommended.relativeFilePath
9277
9550
  );
@@ -9285,11 +9558,11 @@ async function deleteMcpFile() {
9285
9558
  }
9286
9559
  }
9287
9560
  var mcpToolSchemas = {
9288
- getMcpFile: z35.object({}),
9289
- putMcpFile: z35.object({
9290
- content: z35.string()
9561
+ getMcpFile: z36.object({}),
9562
+ putMcpFile: z36.object({
9563
+ content: z36.string()
9291
9564
  }),
9292
- deleteMcpFile: z35.object({})
9565
+ deleteMcpFile: z36.object({})
9293
9566
  };
9294
9567
  var mcpTools = {
9295
9568
  getMcpFile: {
@@ -9322,12 +9595,12 @@ var mcpTools = {
9322
9595
  };
9323
9596
 
9324
9597
  // src/mcp/rules.ts
9325
- import { basename as basename23, join as join87 } from "path";
9326
- import { z as z36 } from "zod/mini";
9598
+ import { basename as basename23, join as join88 } from "path";
9599
+ import { z as z37 } from "zod/mini";
9327
9600
  var maxRuleSizeBytes = 1024 * 1024;
9328
9601
  var maxRulesCount = 1e3;
9329
9602
  async function listRules() {
9330
- const rulesDir = join87(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
9603
+ const rulesDir = join88(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
9331
9604
  try {
9332
9605
  const files = await listDirectoryFiles(rulesDir);
9333
9606
  const mdFiles = files.filter((file) => file.endsWith(".md"));
@@ -9340,7 +9613,7 @@ async function listRules() {
9340
9613
  });
9341
9614
  const frontmatter = rule.getFrontmatter();
9342
9615
  return {
9343
- relativePathFromCwd: join87(RULESYNC_RULES_RELATIVE_DIR_PATH, file),
9616
+ relativePathFromCwd: join88(RULESYNC_RULES_RELATIVE_DIR_PATH, file),
9344
9617
  frontmatter
9345
9618
  };
9346
9619
  } catch (error) {
@@ -9367,7 +9640,7 @@ async function getRule({ relativePathFromCwd }) {
9367
9640
  validate: true
9368
9641
  });
9369
9642
  return {
9370
- relativePathFromCwd: join87(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
9643
+ relativePathFromCwd: join88(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
9371
9644
  frontmatter: rule.getFrontmatter(),
9372
9645
  body: rule.getBody()
9373
9646
  };
@@ -9396,7 +9669,7 @@ async function putRule({
9396
9669
  try {
9397
9670
  const existingRules = await listRules();
9398
9671
  const isUpdate = existingRules.some(
9399
- (rule2) => rule2.relativePathFromCwd === join87(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
9672
+ (rule2) => rule2.relativePathFromCwd === join88(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
9400
9673
  );
9401
9674
  if (!isUpdate && existingRules.length >= maxRulesCount) {
9402
9675
  throw new Error(`Maximum number of rules (${maxRulesCount}) reached`);
@@ -9409,11 +9682,11 @@ async function putRule({
9409
9682
  body,
9410
9683
  validate: true
9411
9684
  });
9412
- const rulesDir = join87(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
9685
+ const rulesDir = join88(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
9413
9686
  await ensureDir(rulesDir);
9414
9687
  await writeFileContent(rule.getFilePath(), rule.getFileContent());
9415
9688
  return {
9416
- relativePathFromCwd: join87(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
9689
+ relativePathFromCwd: join88(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
9417
9690
  frontmatter: rule.getFrontmatter(),
9418
9691
  body: rule.getBody()
9419
9692
  };
@@ -9429,11 +9702,11 @@ async function deleteRule({ relativePathFromCwd }) {
9429
9702
  intendedRootDir: process.cwd()
9430
9703
  });
9431
9704
  const filename = basename23(relativePathFromCwd);
9432
- const fullPath = join87(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH, filename);
9705
+ const fullPath = join88(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH, filename);
9433
9706
  try {
9434
9707
  await removeFile(fullPath);
9435
9708
  return {
9436
- relativePathFromCwd: join87(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
9709
+ relativePathFromCwd: join88(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
9437
9710
  };
9438
9711
  } catch (error) {
9439
9712
  throw new Error(`Failed to delete rule file ${relativePathFromCwd}: ${formatError(error)}`, {
@@ -9442,23 +9715,23 @@ async function deleteRule({ relativePathFromCwd }) {
9442
9715
  }
9443
9716
  }
9444
9717
  var ruleToolSchemas = {
9445
- listRules: z36.object({}),
9446
- getRule: z36.object({
9447
- relativePathFromCwd: z36.string()
9718
+ listRules: z37.object({}),
9719
+ getRule: z37.object({
9720
+ relativePathFromCwd: z37.string()
9448
9721
  }),
9449
- putRule: z36.object({
9450
- relativePathFromCwd: z36.string(),
9722
+ putRule: z37.object({
9723
+ relativePathFromCwd: z37.string(),
9451
9724
  frontmatter: RulesyncRuleFrontmatterSchema,
9452
- body: z36.string()
9725
+ body: z37.string()
9453
9726
  }),
9454
- deleteRule: z36.object({
9455
- relativePathFromCwd: z36.string()
9727
+ deleteRule: z37.object({
9728
+ relativePathFromCwd: z37.string()
9456
9729
  })
9457
9730
  };
9458
9731
  var ruleTools = {
9459
9732
  listRules: {
9460
9733
  name: "listRules",
9461
- description: `List all rules from ${join87(RULESYNC_RULES_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
9734
+ description: `List all rules from ${join88(RULESYNC_RULES_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
9462
9735
  parameters: ruleToolSchemas.listRules,
9463
9736
  execute: async () => {
9464
9737
  const rules = await listRules();
@@ -9500,8 +9773,8 @@ var ruleTools = {
9500
9773
  };
9501
9774
 
9502
9775
  // src/mcp/skills.ts
9503
- import { basename as basename24, dirname as dirname2, join as join88 } from "path";
9504
- import { z as z37 } from "zod/mini";
9776
+ import { basename as basename24, dirname as dirname2, join as join89 } from "path";
9777
+ import { z as z38 } from "zod/mini";
9505
9778
  var maxSkillSizeBytes = 1024 * 1024;
9506
9779
  var maxSkillsCount = 1e3;
9507
9780
  function aiDirFileToMcpSkillFile(file) {
@@ -9524,9 +9797,9 @@ function extractDirName(relativeDirPathFromCwd) {
9524
9797
  return dirName;
9525
9798
  }
9526
9799
  async function listSkills() {
9527
- const skillsDir = join88(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH);
9800
+ const skillsDir = join89(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH);
9528
9801
  try {
9529
- const skillDirPaths = await findFilesByGlobs(join88(skillsDir, "*"), { type: "dir" });
9802
+ const skillDirPaths = await findFilesByGlobs(join89(skillsDir, "*"), { type: "dir" });
9530
9803
  const skills = await Promise.all(
9531
9804
  skillDirPaths.map(async (dirPath) => {
9532
9805
  const dirName = basename24(dirPath);
@@ -9537,7 +9810,7 @@ async function listSkills() {
9537
9810
  });
9538
9811
  const frontmatter = skill.getFrontmatter();
9539
9812
  return {
9540
- relativeDirPathFromCwd: join88(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
9813
+ relativeDirPathFromCwd: join89(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
9541
9814
  frontmatter
9542
9815
  };
9543
9816
  } catch (error) {
@@ -9563,7 +9836,7 @@ async function getSkill({ relativeDirPathFromCwd }) {
9563
9836
  dirName
9564
9837
  });
9565
9838
  return {
9566
- relativeDirPathFromCwd: join88(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
9839
+ relativeDirPathFromCwd: join89(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
9567
9840
  frontmatter: skill.getFrontmatter(),
9568
9841
  body: skill.getBody(),
9569
9842
  otherFiles: skill.getOtherFiles().map(aiDirFileToMcpSkillFile)
@@ -9597,7 +9870,7 @@ async function putSkill({
9597
9870
  try {
9598
9871
  const existingSkills = await listSkills();
9599
9872
  const isUpdate = existingSkills.some(
9600
- (skill2) => skill2.relativeDirPathFromCwd === join88(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName)
9873
+ (skill2) => skill2.relativeDirPathFromCwd === join89(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName)
9601
9874
  );
9602
9875
  if (!isUpdate && existingSkills.length >= maxSkillsCount) {
9603
9876
  throw new Error(`Maximum number of skills (${maxSkillsCount}) reached`);
@@ -9612,9 +9885,9 @@ async function putSkill({
9612
9885
  otherFiles: aiDirFiles,
9613
9886
  validate: true
9614
9887
  });
9615
- const skillDirPath = join88(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName);
9888
+ const skillDirPath = join89(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName);
9616
9889
  await ensureDir(skillDirPath);
9617
- const skillFilePath = join88(skillDirPath, SKILL_FILE_NAME);
9890
+ const skillFilePath = join89(skillDirPath, SKILL_FILE_NAME);
9618
9891
  const skillFileContent = stringifyFrontmatter(body, frontmatter);
9619
9892
  await writeFileContent(skillFilePath, skillFileContent);
9620
9893
  for (const file of otherFiles) {
@@ -9622,15 +9895,15 @@ async function putSkill({
9622
9895
  relativePath: file.name,
9623
9896
  intendedRootDir: skillDirPath
9624
9897
  });
9625
- const filePath = join88(skillDirPath, file.name);
9626
- const fileDir = join88(skillDirPath, dirname2(file.name));
9898
+ const filePath = join89(skillDirPath, file.name);
9899
+ const fileDir = join89(skillDirPath, dirname2(file.name));
9627
9900
  if (fileDir !== skillDirPath) {
9628
9901
  await ensureDir(fileDir);
9629
9902
  }
9630
9903
  await writeFileContent(filePath, file.body);
9631
9904
  }
9632
9905
  return {
9633
- relativeDirPathFromCwd: join88(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
9906
+ relativeDirPathFromCwd: join89(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
9634
9907
  frontmatter: skill.getFrontmatter(),
9635
9908
  body: skill.getBody(),
9636
9909
  otherFiles: skill.getOtherFiles().map(aiDirFileToMcpSkillFile)
@@ -9652,13 +9925,13 @@ async function deleteSkill({
9652
9925
  intendedRootDir: process.cwd()
9653
9926
  });
9654
9927
  const dirName = extractDirName(relativeDirPathFromCwd);
9655
- const skillDirPath = join88(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName);
9928
+ const skillDirPath = join89(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName);
9656
9929
  try {
9657
9930
  if (await directoryExists(skillDirPath)) {
9658
9931
  await removeDirectory(skillDirPath);
9659
9932
  }
9660
9933
  return {
9661
- relativeDirPathFromCwd: join88(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName)
9934
+ relativeDirPathFromCwd: join89(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName)
9662
9935
  };
9663
9936
  } catch (error) {
9664
9937
  throw new Error(
@@ -9669,29 +9942,29 @@ async function deleteSkill({
9669
9942
  );
9670
9943
  }
9671
9944
  }
9672
- var McpSkillFileSchema = z37.object({
9673
- name: z37.string(),
9674
- body: z37.string()
9945
+ var McpSkillFileSchema = z38.object({
9946
+ name: z38.string(),
9947
+ body: z38.string()
9675
9948
  });
9676
9949
  var skillToolSchemas = {
9677
- listSkills: z37.object({}),
9678
- getSkill: z37.object({
9679
- relativeDirPathFromCwd: z37.string()
9950
+ listSkills: z38.object({}),
9951
+ getSkill: z38.object({
9952
+ relativeDirPathFromCwd: z38.string()
9680
9953
  }),
9681
- putSkill: z37.object({
9682
- relativeDirPathFromCwd: z37.string(),
9954
+ putSkill: z38.object({
9955
+ relativeDirPathFromCwd: z38.string(),
9683
9956
  frontmatter: RulesyncSkillFrontmatterSchema,
9684
- body: z37.string(),
9685
- otherFiles: z37.optional(z37.array(McpSkillFileSchema))
9957
+ body: z38.string(),
9958
+ otherFiles: z38.optional(z38.array(McpSkillFileSchema))
9686
9959
  }),
9687
- deleteSkill: z37.object({
9688
- relativeDirPathFromCwd: z37.string()
9960
+ deleteSkill: z38.object({
9961
+ relativeDirPathFromCwd: z38.string()
9689
9962
  })
9690
9963
  };
9691
9964
  var skillTools = {
9692
9965
  listSkills: {
9693
9966
  name: "listSkills",
9694
- description: `List all skills from ${join88(RULESYNC_SKILLS_RELATIVE_DIR_PATH, "*", SKILL_FILE_NAME)} with their frontmatter.`,
9967
+ description: `List all skills from ${join89(RULESYNC_SKILLS_RELATIVE_DIR_PATH, "*", SKILL_FILE_NAME)} with their frontmatter.`,
9695
9968
  parameters: skillToolSchemas.listSkills,
9696
9969
  execute: async () => {
9697
9970
  const skills = await listSkills();
@@ -9734,12 +10007,12 @@ var skillTools = {
9734
10007
  };
9735
10008
 
9736
10009
  // src/mcp/subagents.ts
9737
- import { basename as basename25, join as join89 } from "path";
9738
- import { z as z38 } from "zod/mini";
10010
+ import { basename as basename25, join as join90 } from "path";
10011
+ import { z as z39 } from "zod/mini";
9739
10012
  var maxSubagentSizeBytes = 1024 * 1024;
9740
10013
  var maxSubagentsCount = 1e3;
9741
10014
  async function listSubagents() {
9742
- const subagentsDir = join89(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
10015
+ const subagentsDir = join90(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
9743
10016
  try {
9744
10017
  const files = await listDirectoryFiles(subagentsDir);
9745
10018
  const mdFiles = files.filter((file) => file.endsWith(".md"));
@@ -9752,7 +10025,7 @@ async function listSubagents() {
9752
10025
  });
9753
10026
  const frontmatter = subagent.getFrontmatter();
9754
10027
  return {
9755
- relativePathFromCwd: join89(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, file),
10028
+ relativePathFromCwd: join90(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, file),
9756
10029
  frontmatter
9757
10030
  };
9758
10031
  } catch (error) {
@@ -9781,7 +10054,7 @@ async function getSubagent({ relativePathFromCwd }) {
9781
10054
  validate: true
9782
10055
  });
9783
10056
  return {
9784
- relativePathFromCwd: join89(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
10057
+ relativePathFromCwd: join90(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
9785
10058
  frontmatter: subagent.getFrontmatter(),
9786
10059
  body: subagent.getBody()
9787
10060
  };
@@ -9810,7 +10083,7 @@ async function putSubagent({
9810
10083
  try {
9811
10084
  const existingSubagents = await listSubagents();
9812
10085
  const isUpdate = existingSubagents.some(
9813
- (subagent2) => subagent2.relativePathFromCwd === join89(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
10086
+ (subagent2) => subagent2.relativePathFromCwd === join90(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
9814
10087
  );
9815
10088
  if (!isUpdate && existingSubagents.length >= maxSubagentsCount) {
9816
10089
  throw new Error(`Maximum number of subagents (${maxSubagentsCount}) reached`);
@@ -9823,11 +10096,11 @@ async function putSubagent({
9823
10096
  body,
9824
10097
  validate: true
9825
10098
  });
9826
- const subagentsDir = join89(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
10099
+ const subagentsDir = join90(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
9827
10100
  await ensureDir(subagentsDir);
9828
10101
  await writeFileContent(subagent.getFilePath(), subagent.getFileContent());
9829
10102
  return {
9830
- relativePathFromCwd: join89(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
10103
+ relativePathFromCwd: join90(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
9831
10104
  frontmatter: subagent.getFrontmatter(),
9832
10105
  body: subagent.getBody()
9833
10106
  };
@@ -9843,11 +10116,11 @@ async function deleteSubagent({ relativePathFromCwd }) {
9843
10116
  intendedRootDir: process.cwd()
9844
10117
  });
9845
10118
  const filename = basename25(relativePathFromCwd);
9846
- const fullPath = join89(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename);
10119
+ const fullPath = join90(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename);
9847
10120
  try {
9848
10121
  await removeFile(fullPath);
9849
10122
  return {
9850
- relativePathFromCwd: join89(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
10123
+ relativePathFromCwd: join90(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
9851
10124
  };
9852
10125
  } catch (error) {
9853
10126
  throw new Error(
@@ -9859,23 +10132,23 @@ async function deleteSubagent({ relativePathFromCwd }) {
9859
10132
  }
9860
10133
  }
9861
10134
  var subagentToolSchemas = {
9862
- listSubagents: z38.object({}),
9863
- getSubagent: z38.object({
9864
- relativePathFromCwd: z38.string()
10135
+ listSubagents: z39.object({}),
10136
+ getSubagent: z39.object({
10137
+ relativePathFromCwd: z39.string()
9865
10138
  }),
9866
- putSubagent: z38.object({
9867
- relativePathFromCwd: z38.string(),
10139
+ putSubagent: z39.object({
10140
+ relativePathFromCwd: z39.string(),
9868
10141
  frontmatter: RulesyncSubagentFrontmatterSchema,
9869
- body: z38.string()
10142
+ body: z39.string()
9870
10143
  }),
9871
- deleteSubagent: z38.object({
9872
- relativePathFromCwd: z38.string()
10144
+ deleteSubagent: z39.object({
10145
+ relativePathFromCwd: z39.string()
9873
10146
  })
9874
10147
  };
9875
10148
  var subagentTools = {
9876
10149
  listSubagents: {
9877
10150
  name: "listSubagents",
9878
- description: `List all subagents from ${join89(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
10151
+ description: `List all subagents from ${join90(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
9879
10152
  parameters: subagentToolSchemas.listSubagents,
9880
10153
  execute: async () => {
9881
10154
  const subagents = await listSubagents();
@@ -9953,7 +10226,7 @@ async function mcpCommand({ version }) {
9953
10226
  }
9954
10227
 
9955
10228
  // src/cli/index.ts
9956
- var getVersion = () => "3.31.0";
10229
+ var getVersion = () => "3.32.0";
9957
10230
  var main = async () => {
9958
10231
  const program = new Command();
9959
10232
  const version = getVersion();