rulesync 0.42.0 → 0.43.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
@@ -1,30 +1,30 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  generateClaudeMcp
4
- } from "./chunk-HMMPZV7X.js";
4
+ } from "./chunk-B3627VQY.js";
5
5
  import {
6
6
  generateClineMcp
7
- } from "./chunk-X3FEMISQ.js";
7
+ } from "./chunk-XHRBWFGI.js";
8
8
  import {
9
9
  generateCopilotMcp
10
- } from "./chunk-SXEFNT27.js";
10
+ } from "./chunk-2FR4Z37J.js";
11
11
  import {
12
12
  generateCursorMcp
13
- } from "./chunk-D3YGI36J.js";
13
+ } from "./chunk-ZMAL5LIX.js";
14
14
  import {
15
15
  generateGeminiCliMcp
16
- } from "./chunk-2SPL7QTK.js";
16
+ } from "./chunk-TCK42GOL.js";
17
17
  import {
18
18
  generateRooMcp
19
- } from "./chunk-3NRSCDLQ.js";
20
- import "./chunk-6YNGMPAL.js";
19
+ } from "./chunk-RL3TE3EZ.js";
20
+ import "./chunk-THWXK5Z2.js";
21
21
 
22
22
  // src/cli/index.ts
23
23
  import { Command } from "commander";
24
24
 
25
25
  // src/cli/commands/add.ts
26
26
  import { mkdir, writeFile } from "fs/promises";
27
- import path from "path";
27
+ import * as path from "path";
28
28
 
29
29
  // src/utils/config.ts
30
30
  function getDefaultConfig() {
@@ -35,12 +35,11 @@ function getDefaultConfig() {
35
35
  cursor: ".cursor/rules",
36
36
  cline: ".clinerules",
37
37
  claudecode: ".",
38
- claude: ".",
39
38
  roo: ".roo/rules",
40
39
  geminicli: ".gemini/memories"
41
40
  },
42
41
  watchEnabled: false,
43
- defaultTargets: ["copilot", "cursor", "cline", "claudecode", "claude", "roo", "geminicli"]
42
+ defaultTargets: ["copilot", "cursor", "cline", "claudecode", "roo", "geminicli"]
44
43
  };
45
44
  }
46
45
  function resolveTargets(targets, config) {
@@ -87,11 +86,19 @@ async function addCommand(filename) {
87
86
  }
88
87
 
89
88
  // src/generators/rules/claudecode.ts
90
- import { join as join3 } from "path";
89
+ import { join as join4 } from "path";
90
+
91
+ // src/types/claudecode.ts
92
+ import { z } from "zod/v4";
93
+ var ClaudeSettingsSchema = z.looseObject({
94
+ permissions: z.looseObject({
95
+ deny: z.array(z.string()).default([])
96
+ }).default({ deny: [] })
97
+ });
91
98
 
92
99
  // src/utils/file.ts
93
100
  import { readdir, rm } from "fs/promises";
94
- import { join as join2 } from "path";
101
+ import { join as join3 } from "path";
95
102
 
96
103
  // src/utils/file-ops.ts
97
104
  import { mkdir as mkdir2, readFile, stat, writeFile as writeFile2 } from "fs/promises";
@@ -120,14 +127,14 @@ async function fileExists(filepath) {
120
127
  }
121
128
 
122
129
  // src/utils/ignore.ts
123
- import { join } from "path";
130
+ import { join as join2 } from "path";
124
131
  import micromatch from "micromatch";
125
132
  var cachedIgnorePatterns = null;
126
133
  async function loadIgnorePatterns(baseDir = process.cwd()) {
127
134
  if (cachedIgnorePatterns) {
128
135
  return cachedIgnorePatterns;
129
136
  }
130
- const ignorePath = join(baseDir, ".rulesyncignore");
137
+ const ignorePath = join2(baseDir, ".rulesyncignore");
131
138
  if (!await fileExists(ignorePath)) {
132
139
  cachedIgnorePatterns = { patterns: [] };
133
140
  return cachedIgnorePatterns;
@@ -174,7 +181,7 @@ function filterIgnoredFiles(files, ignorePatterns) {
174
181
  async function findFiles(dir, extension = ".md", ignorePatterns) {
175
182
  try {
176
183
  const files = await readdir(dir);
177
- const filtered = files.filter((file) => file.endsWith(extension)).map((file) => join2(dir, file));
184
+ const filtered = files.filter((file) => file.endsWith(extension)).map((file) => join3(dir, file));
178
185
  if (ignorePatterns && ignorePatterns.length > 0) {
179
186
  return filterIgnoredFiles(filtered, ignorePatterns);
180
187
  }
@@ -223,23 +230,23 @@ async function generateClaudecodeConfig(rules, config, baseDir) {
223
230
  const rootRules = rules.filter((r) => r.frontmatter.root === true);
224
231
  const detailRules = rules.filter((r) => r.frontmatter.root === false);
225
232
  const claudeMdContent = generateClaudeMarkdown(rootRules, detailRules);
226
- const claudeOutputDir = baseDir ? join3(baseDir, config.outputPaths.claudecode) : config.outputPaths.claudecode;
233
+ const claudeOutputDir = baseDir ? join4(baseDir, config.outputPaths.claudecode) : config.outputPaths.claudecode;
227
234
  outputs.push({
228
235
  tool: "claudecode",
229
- filepath: join3(claudeOutputDir, "CLAUDE.md"),
236
+ filepath: join4(claudeOutputDir, "CLAUDE.md"),
230
237
  content: claudeMdContent
231
238
  });
232
239
  for (const rule of detailRules) {
233
240
  const memoryContent = generateMemoryFile(rule);
234
241
  outputs.push({
235
242
  tool: "claudecode",
236
- filepath: join3(claudeOutputDir, ".claude", "memories", `${rule.filename}.md`),
243
+ filepath: join4(claudeOutputDir, ".claude", "memories", `${rule.filename}.md`),
237
244
  content: memoryContent
238
245
  });
239
246
  }
240
247
  const ignorePatterns = await loadIgnorePatterns(baseDir);
241
248
  if (ignorePatterns.patterns.length > 0) {
242
- const settingsPath = baseDir ? join3(baseDir, ".claude", "settings.json") : join3(".claude", "settings.json");
249
+ const settingsPath = baseDir ? join4(baseDir, ".claude", "settings.json") : join4(".claude", "settings.json");
243
250
  await updateClaudeSettings(settingsPath, ignorePatterns.patterns);
244
251
  }
245
252
  return outputs;
@@ -271,51 +278,46 @@ function generateMemoryFile(rule) {
271
278
  return rule.content.trim();
272
279
  }
273
280
  async function updateClaudeSettings(settingsPath, ignorePatterns) {
274
- let settings = {};
281
+ let rawSettings = {};
275
282
  if (await fileExists(settingsPath)) {
276
283
  try {
277
284
  const content = await readFileContent(settingsPath);
278
- settings = JSON.parse(content);
285
+ rawSettings = JSON.parse(content);
279
286
  } catch {
280
287
  console.warn(`Failed to parse existing ${settingsPath}, creating new settings`);
281
- settings = {};
288
+ rawSettings = {};
282
289
  }
283
290
  }
284
- if (typeof settings !== "object" || settings === null) {
285
- settings = {};
286
- }
287
- const settingsObj = settings;
288
- if (!settingsObj.permissions || typeof settingsObj.permissions !== "object" || settingsObj.permissions === null) {
289
- settingsObj.permissions = {};
291
+ const parseResult = ClaudeSettingsSchema.safeParse(rawSettings);
292
+ const settings = parseResult.success ? parseResult.data : ClaudeSettingsSchema.parse({});
293
+ const readDenyRules = ignorePatterns.map((pattern) => `Read(${pattern})`);
294
+ if (!settings.permissions) {
295
+ settings.permissions = { deny: [] };
290
296
  }
291
- const permissions = settingsObj.permissions;
292
- if (!Array.isArray(permissions.deny)) {
293
- permissions.deny = [];
297
+ if (!Array.isArray(settings.permissions.deny)) {
298
+ settings.permissions.deny = [];
294
299
  }
295
- const readDenyRules = ignorePatterns.map((pattern) => `Read(${pattern})`);
296
- const denyArray = permissions.deny;
297
- const filteredDeny = denyArray.filter((rule) => {
298
- if (typeof rule !== "string") return false;
300
+ const filteredDeny = settings.permissions.deny.filter((rule) => {
299
301
  if (!rule.startsWith("Read(")) return true;
300
302
  const match = rule.match(/^Read\((.*)\)$/);
301
303
  if (!match) return true;
302
304
  return !ignorePatterns.includes(match[1] ?? "");
303
305
  });
304
306
  filteredDeny.push(...readDenyRules);
305
- permissions.deny = [...new Set(filteredDeny)];
306
- const jsonContent = JSON.stringify(settingsObj, null, 2);
307
+ settings.permissions.deny = Array.from(new Set(filteredDeny));
308
+ const jsonContent = JSON.stringify(settings, null, 2);
307
309
  await writeFileContent(settingsPath, jsonContent);
308
310
  console.log(`\u2705 Updated Claude Code settings: ${settingsPath}`);
309
311
  }
310
312
 
311
313
  // src/generators/rules/cline.ts
312
- import { join as join4 } from "path";
314
+ import { join as join5 } from "path";
313
315
  async function generateClineConfig(rules, config, baseDir) {
314
316
  const outputs = [];
315
317
  for (const rule of rules) {
316
318
  const content = generateClineMarkdown(rule);
317
- const outputDir = baseDir ? join4(baseDir, config.outputPaths.cline) : config.outputPaths.cline;
318
- const filepath = join4(outputDir, `${rule.filename}.md`);
319
+ const outputDir = baseDir ? join5(baseDir, config.outputPaths.cline) : config.outputPaths.cline;
320
+ const filepath = join5(outputDir, `${rule.filename}.md`);
319
321
  outputs.push({
320
322
  tool: "cline",
321
323
  filepath,
@@ -324,7 +326,7 @@ async function generateClineConfig(rules, config, baseDir) {
324
326
  }
325
327
  const ignorePatterns = await loadIgnorePatterns(baseDir);
326
328
  if (ignorePatterns.patterns.length > 0) {
327
- const clineIgnorePath = baseDir ? join4(baseDir, ".clineignore") : ".clineignore";
329
+ const clineIgnorePath = baseDir ? join5(baseDir, ".clineignore") : ".clineignore";
328
330
  const clineIgnoreContent = generateClineIgnore(ignorePatterns.patterns);
329
331
  outputs.push({
330
332
  tool: "cline",
@@ -348,14 +350,14 @@ function generateClineIgnore(patterns) {
348
350
  }
349
351
 
350
352
  // src/generators/rules/copilot.ts
351
- import { join as join5 } from "path";
353
+ import { join as join6 } from "path";
352
354
  async function generateCopilotConfig(rules, config, baseDir) {
353
355
  const outputs = [];
354
356
  for (const rule of rules) {
355
357
  const content = generateCopilotMarkdown(rule);
356
358
  const baseFilename = rule.filename.replace(/\.md$/, "");
357
- const outputDir = baseDir ? join5(baseDir, config.outputPaths.copilot) : config.outputPaths.copilot;
358
- const filepath = join5(outputDir, `${baseFilename}.instructions.md`);
359
+ const outputDir = baseDir ? join6(baseDir, config.outputPaths.copilot) : config.outputPaths.copilot;
360
+ const filepath = join6(outputDir, `${baseFilename}.instructions.md`);
359
361
  outputs.push({
360
362
  tool: "copilot",
361
363
  filepath,
@@ -364,7 +366,7 @@ async function generateCopilotConfig(rules, config, baseDir) {
364
366
  }
365
367
  const ignorePatterns = await loadIgnorePatterns(baseDir);
366
368
  if (ignorePatterns.patterns.length > 0) {
367
- const copilotIgnorePath = baseDir ? join5(baseDir, ".copilotignore") : ".copilotignore";
369
+ const copilotIgnorePath = baseDir ? join6(baseDir, ".copilotignore") : ".copilotignore";
368
370
  const copilotIgnoreContent = generateCopilotIgnore(ignorePatterns.patterns);
369
371
  outputs.push({
370
372
  tool: "copilot",
@@ -400,13 +402,13 @@ function generateCopilotIgnore(patterns) {
400
402
  }
401
403
 
402
404
  // src/generators/rules/cursor.ts
403
- import { join as join6 } from "path";
405
+ import { join as join7 } from "path";
404
406
  async function generateCursorConfig(rules, config, baseDir) {
405
407
  const outputs = [];
406
408
  for (const rule of rules) {
407
409
  const content = generateCursorMarkdown(rule);
408
- const outputDir = baseDir ? join6(baseDir, config.outputPaths.cursor) : config.outputPaths.cursor;
409
- const filepath = join6(outputDir, `${rule.filename}.mdc`);
410
+ const outputDir = baseDir ? join7(baseDir, config.outputPaths.cursor) : config.outputPaths.cursor;
411
+ const filepath = join7(outputDir, `${rule.filename}.mdc`);
410
412
  outputs.push({
411
413
  tool: "cursor",
412
414
  filepath,
@@ -415,7 +417,7 @@ async function generateCursorConfig(rules, config, baseDir) {
415
417
  }
416
418
  const ignorePatterns = await loadIgnorePatterns(baseDir);
417
419
  if (ignorePatterns.patterns.length > 0) {
418
- const cursorIgnorePath = baseDir ? join6(baseDir, ".cursorignore") : ".cursorignore";
420
+ const cursorIgnorePath = baseDir ? join7(baseDir, ".cursorignore") : ".cursorignore";
419
421
  const cursorIgnoreContent = generateCursorIgnore(ignorePatterns.patterns);
420
422
  outputs.push({
421
423
  tool: "cursor",
@@ -488,15 +490,15 @@ function generateCursorIgnore(patterns) {
488
490
  }
489
491
 
490
492
  // src/generators/rules/geminicli.ts
491
- import { join as join7 } from "path";
493
+ import { join as join8 } from "path";
492
494
  async function generateGeminiConfig(rules, config, baseDir) {
493
495
  const outputs = [];
494
496
  const rootRule = rules.find((rule) => rule.frontmatter.root === true);
495
497
  const memoryRules = rules.filter((rule) => rule.frontmatter.root === false);
496
498
  for (const rule of memoryRules) {
497
499
  const content = generateGeminiMemoryMarkdown(rule);
498
- const outputDir = baseDir ? join7(baseDir, config.outputPaths.geminicli) : config.outputPaths.geminicli;
499
- const filepath = join7(outputDir, `${rule.filename}.md`);
500
+ const outputDir = baseDir ? join8(baseDir, config.outputPaths.geminicli) : config.outputPaths.geminicli;
501
+ const filepath = join8(outputDir, `${rule.filename}.md`);
500
502
  outputs.push({
501
503
  tool: "geminicli",
502
504
  filepath,
@@ -504,7 +506,7 @@ async function generateGeminiConfig(rules, config, baseDir) {
504
506
  });
505
507
  }
506
508
  const rootContent = generateGeminiRootMarkdown(rootRule, memoryRules, baseDir);
507
- const rootFilepath = baseDir ? join7(baseDir, "GEMINI.md") : "GEMINI.md";
509
+ const rootFilepath = baseDir ? join8(baseDir, "GEMINI.md") : "GEMINI.md";
508
510
  outputs.push({
509
511
  tool: "geminicli",
510
512
  filepath: rootFilepath,
@@ -512,7 +514,7 @@ async function generateGeminiConfig(rules, config, baseDir) {
512
514
  });
513
515
  const ignorePatterns = await loadIgnorePatterns(baseDir);
514
516
  if (ignorePatterns.patterns.length > 0) {
515
- const aiexcludePath = baseDir ? join7(baseDir, ".aiexclude") : ".aiexclude";
517
+ const aiexcludePath = baseDir ? join8(baseDir, ".aiexclude") : ".aiexclude";
516
518
  const aiexcludeContent = generateAiexclude(ignorePatterns.patterns);
517
519
  outputs.push({
518
520
  tool: "geminicli",
@@ -560,13 +562,13 @@ function generateAiexclude(patterns) {
560
562
  }
561
563
 
562
564
  // src/generators/rules/roo.ts
563
- import { join as join8 } from "path";
565
+ import { join as join9 } from "path";
564
566
  async function generateRooConfig(rules, config, baseDir) {
565
567
  const outputs = [];
566
568
  for (const rule of rules) {
567
569
  const content = generateRooMarkdown(rule);
568
- const outputDir = baseDir ? join8(baseDir, config.outputPaths.roo) : config.outputPaths.roo;
569
- const filepath = join8(outputDir, `${rule.filename}.md`);
570
+ const outputDir = baseDir ? join9(baseDir, config.outputPaths.roo) : config.outputPaths.roo;
571
+ const filepath = join9(outputDir, `${rule.filename}.md`);
570
572
  outputs.push({
571
573
  tool: "roo",
572
574
  filepath,
@@ -575,7 +577,7 @@ async function generateRooConfig(rules, config, baseDir) {
575
577
  }
576
578
  const ignorePatterns = await loadIgnorePatterns(baseDir);
577
579
  if (ignorePatterns.patterns.length > 0) {
578
- const rooIgnorePath = baseDir ? join8(baseDir, ".rooignore") : ".rooignore";
580
+ const rooIgnorePath = baseDir ? join9(baseDir, ".rooignore") : ".rooignore";
579
581
  const rooIgnoreContent = generateRooIgnore(ignorePatterns.patterns);
580
582
  outputs.push({
581
583
  tool: "roo",
@@ -814,11 +816,11 @@ async function validateRule(rule) {
814
816
  }
815
817
 
816
818
  // src/core/mcp-generator.ts
817
- import path3 from "path";
819
+ import * as path3 from "path";
818
820
 
819
821
  // src/core/mcp-parser.ts
820
- import fs from "fs";
821
- import path2 from "path";
822
+ import * as fs from "fs";
823
+ import * as path2 from "path";
822
824
  function parseMcpConfig(projectRoot) {
823
825
  const mcpPath = path2.join(projectRoot, ".rulesync", ".mcp.json");
824
826
  if (!fs.existsSync(mcpPath)) {
@@ -1038,10 +1040,10 @@ Generating configurations for base directory: ${baseDir}`);
1038
1040
  }
1039
1041
 
1040
1042
  // src/cli/commands/gitignore.ts
1041
- import { existsSync, readFileSync, writeFileSync } from "fs";
1042
- import { join as join9 } from "path";
1043
+ import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
1044
+ import { join as join12 } from "path";
1043
1045
  var gitignoreCommand = async () => {
1044
- const gitignorePath = join9(process.cwd(), ".gitignore");
1046
+ const gitignorePath = join12(process.cwd(), ".gitignore");
1045
1047
  const rulesFilesToIgnore = [
1046
1048
  "# Generated by rulesync - AI tool configuration files",
1047
1049
  "**/.github/copilot-instructions.md",
@@ -1067,8 +1069,8 @@ var gitignoreCommand = async () => {
1067
1069
  "**/.roo/mcp.json"
1068
1070
  ];
1069
1071
  let gitignoreContent = "";
1070
- if (existsSync(gitignorePath)) {
1071
- gitignoreContent = readFileSync(gitignorePath, "utf-8");
1072
+ if (existsSync2(gitignorePath)) {
1073
+ gitignoreContent = readFileSync2(gitignorePath, "utf-8");
1072
1074
  }
1073
1075
  const linesToAdd = [];
1074
1076
  for (const rule of rulesFilesToIgnore) {
@@ -1095,17 +1097,17 @@ ${linesToAdd.join("\n")}
1095
1097
  };
1096
1098
 
1097
1099
  // src/core/importer.ts
1098
- import { join as join16 } from "path";
1100
+ import { join as join19 } from "path";
1099
1101
  import matter4 from "gray-matter";
1100
1102
 
1101
1103
  // src/parsers/claudecode.ts
1102
- import { basename as basename2, join as join10 } from "path";
1104
+ import { basename as basename2, join as join13 } from "path";
1103
1105
  async function parseClaudeConfiguration(baseDir = process.cwd()) {
1104
1106
  const errors = [];
1105
1107
  const rules = [];
1106
1108
  let ignorePatterns;
1107
1109
  let mcpServers;
1108
- const claudeFilePath = join10(baseDir, "CLAUDE.md");
1110
+ const claudeFilePath = join13(baseDir, "CLAUDE.md");
1109
1111
  if (!await fileExists(claudeFilePath)) {
1110
1112
  errors.push("CLAUDE.md file not found");
1111
1113
  return { rules, errors };
@@ -1116,12 +1118,12 @@ async function parseClaudeConfiguration(baseDir = process.cwd()) {
1116
1118
  if (mainRule) {
1117
1119
  rules.push(mainRule);
1118
1120
  }
1119
- const memoryDir = join10(baseDir, ".claude", "memories");
1121
+ const memoryDir = join13(baseDir, ".claude", "memories");
1120
1122
  if (await fileExists(memoryDir)) {
1121
1123
  const memoryRules = await parseClaudeMemoryFiles(memoryDir);
1122
1124
  rules.push(...memoryRules);
1123
1125
  }
1124
- const settingsPath = join10(baseDir, ".claude", "settings.json");
1126
+ const settingsPath = join13(baseDir, ".claude", "settings.json");
1125
1127
  if (await fileExists(settingsPath)) {
1126
1128
  const settingsResult = await parseClaudeSettings(settingsPath);
1127
1129
  if (settingsResult.ignorePatterns) {
@@ -1178,7 +1180,7 @@ async function parseClaudeMemoryFiles(memoryDir) {
1178
1180
  const files = await readdir2(memoryDir);
1179
1181
  for (const file of files) {
1180
1182
  if (file.endsWith(".md")) {
1181
- const filePath = join10(memoryDir, file);
1183
+ const filePath = join13(memoryDir, file);
1182
1184
  const content = await readFileContent(filePath);
1183
1185
  if (content.trim()) {
1184
1186
  const filename = basename2(file, ".md");
@@ -1240,11 +1242,11 @@ async function parseClaudeSettings(settingsPath) {
1240
1242
  }
1241
1243
 
1242
1244
  // src/parsers/cline.ts
1243
- import { join as join11 } from "path";
1245
+ import { join as join14 } from "path";
1244
1246
  async function parseClineConfiguration(baseDir = process.cwd()) {
1245
1247
  const errors = [];
1246
1248
  const rules = [];
1247
- const clineFilePath = join11(baseDir, ".cline", "instructions.md");
1249
+ const clineFilePath = join14(baseDir, ".cline", "instructions.md");
1248
1250
  if (await fileExists(clineFilePath)) {
1249
1251
  try {
1250
1252
  const content = await readFileContent(clineFilePath);
@@ -1267,14 +1269,14 @@ async function parseClineConfiguration(baseDir = process.cwd()) {
1267
1269
  errors.push(`Failed to parse .cline/instructions.md: ${errorMessage}`);
1268
1270
  }
1269
1271
  }
1270
- const clinerulesDirPath = join11(baseDir, ".clinerules");
1272
+ const clinerulesDirPath = join14(baseDir, ".clinerules");
1271
1273
  if (await fileExists(clinerulesDirPath)) {
1272
1274
  try {
1273
1275
  const { readdir: readdir2 } = await import("fs/promises");
1274
1276
  const files = await readdir2(clinerulesDirPath);
1275
1277
  for (const file of files) {
1276
1278
  if (file.endsWith(".md")) {
1277
- const filePath = join11(clinerulesDirPath, file);
1279
+ const filePath = join14(clinerulesDirPath, file);
1278
1280
  try {
1279
1281
  const content = await readFileContent(filePath);
1280
1282
  if (content.trim()) {
@@ -1310,12 +1312,12 @@ async function parseClineConfiguration(baseDir = process.cwd()) {
1310
1312
  }
1311
1313
 
1312
1314
  // src/parsers/copilot.ts
1313
- import { basename as basename3, join as join12 } from "path";
1315
+ import { basename as basename3, join as join15 } from "path";
1314
1316
  import matter2 from "gray-matter";
1315
1317
  async function parseCopilotConfiguration(baseDir = process.cwd()) {
1316
1318
  const errors = [];
1317
1319
  const rules = [];
1318
- const copilotFilePath = join12(baseDir, ".github", "copilot-instructions.md");
1320
+ const copilotFilePath = join15(baseDir, ".github", "copilot-instructions.md");
1319
1321
  if (await fileExists(copilotFilePath)) {
1320
1322
  try {
1321
1323
  const rawContent = await readFileContent(copilotFilePath);
@@ -1340,14 +1342,14 @@ async function parseCopilotConfiguration(baseDir = process.cwd()) {
1340
1342
  errors.push(`Failed to parse copilot-instructions.md: ${errorMessage}`);
1341
1343
  }
1342
1344
  }
1343
- const instructionsDir = join12(baseDir, ".github", "instructions");
1345
+ const instructionsDir = join15(baseDir, ".github", "instructions");
1344
1346
  if (await fileExists(instructionsDir)) {
1345
1347
  try {
1346
1348
  const { readdir: readdir2 } = await import("fs/promises");
1347
1349
  const files = await readdir2(instructionsDir);
1348
1350
  for (const file of files) {
1349
1351
  if (file.endsWith(".instructions.md")) {
1350
- const filePath = join12(instructionsDir, file);
1352
+ const filePath = join15(instructionsDir, file);
1351
1353
  const rawContent = await readFileContent(filePath);
1352
1354
  const parsed = matter2(rawContent);
1353
1355
  const content = parsed.content.trim();
@@ -1382,7 +1384,7 @@ async function parseCopilotConfiguration(baseDir = process.cwd()) {
1382
1384
  }
1383
1385
 
1384
1386
  // src/parsers/cursor.ts
1385
- import { basename as basename4, join as join13 } from "path";
1387
+ import { basename as basename4, join as join16 } from "path";
1386
1388
  import matter3 from "gray-matter";
1387
1389
  import { DEFAULT_SCHEMA, FAILSAFE_SCHEMA, load } from "js-yaml";
1388
1390
  var customMatterOptions = {
@@ -1487,7 +1489,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
1487
1489
  const rules = [];
1488
1490
  let ignorePatterns;
1489
1491
  let mcpServers;
1490
- const cursorFilePath = join13(baseDir, ".cursorrules");
1492
+ const cursorFilePath = join16(baseDir, ".cursorrules");
1491
1493
  if (await fileExists(cursorFilePath)) {
1492
1494
  try {
1493
1495
  const rawContent = await readFileContent(cursorFilePath);
@@ -1508,14 +1510,14 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
1508
1510
  errors.push(`Failed to parse .cursorrules file: ${errorMessage}`);
1509
1511
  }
1510
1512
  }
1511
- const cursorRulesDir = join13(baseDir, ".cursor", "rules");
1513
+ const cursorRulesDir = join16(baseDir, ".cursor", "rules");
1512
1514
  if (await fileExists(cursorRulesDir)) {
1513
1515
  try {
1514
1516
  const { readdir: readdir2 } = await import("fs/promises");
1515
1517
  const files = await readdir2(cursorRulesDir);
1516
1518
  for (const file of files) {
1517
1519
  if (file.endsWith(".mdc")) {
1518
- const filePath = join13(cursorRulesDir, file);
1520
+ const filePath = join16(cursorRulesDir, file);
1519
1521
  try {
1520
1522
  const rawContent = await readFileContent(filePath);
1521
1523
  const parsed = matter3(rawContent, customMatterOptions);
@@ -1544,7 +1546,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
1544
1546
  if (rules.length === 0) {
1545
1547
  errors.push("No Cursor configuration files found (.cursorrules or .cursor/rules/*.mdc)");
1546
1548
  }
1547
- const cursorIgnorePath = join13(baseDir, ".cursorignore");
1549
+ const cursorIgnorePath = join16(baseDir, ".cursorignore");
1548
1550
  if (await fileExists(cursorIgnorePath)) {
1549
1551
  try {
1550
1552
  const content = await readFileContent(cursorIgnorePath);
@@ -1557,7 +1559,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
1557
1559
  errors.push(`Failed to parse .cursorignore: ${errorMessage}`);
1558
1560
  }
1559
1561
  }
1560
- const cursorMcpPath = join13(baseDir, ".cursor", "mcp.json");
1562
+ const cursorMcpPath = join16(baseDir, ".cursor", "mcp.json");
1561
1563
  if (await fileExists(cursorMcpPath)) {
1562
1564
  try {
1563
1565
  const content = await readFileContent(cursorMcpPath);
@@ -1579,13 +1581,13 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
1579
1581
  }
1580
1582
 
1581
1583
  // src/parsers/geminicli.ts
1582
- import { basename as basename5, join as join14 } from "path";
1584
+ import { basename as basename5, join as join17 } from "path";
1583
1585
  async function parseGeminiConfiguration(baseDir = process.cwd()) {
1584
1586
  const errors = [];
1585
1587
  const rules = [];
1586
1588
  let ignorePatterns;
1587
1589
  let mcpServers;
1588
- const geminiFilePath = join14(baseDir, "GEMINI.md");
1590
+ const geminiFilePath = join17(baseDir, "GEMINI.md");
1589
1591
  if (!await fileExists(geminiFilePath)) {
1590
1592
  errors.push("GEMINI.md file not found");
1591
1593
  return { rules, errors };
@@ -1596,12 +1598,12 @@ async function parseGeminiConfiguration(baseDir = process.cwd()) {
1596
1598
  if (mainRule) {
1597
1599
  rules.push(mainRule);
1598
1600
  }
1599
- const memoryDir = join14(baseDir, ".gemini", "memories");
1601
+ const memoryDir = join17(baseDir, ".gemini", "memories");
1600
1602
  if (await fileExists(memoryDir)) {
1601
1603
  const memoryRules = await parseGeminiMemoryFiles(memoryDir);
1602
1604
  rules.push(...memoryRules);
1603
1605
  }
1604
- const settingsPath = join14(baseDir, ".gemini", "settings.json");
1606
+ const settingsPath = join17(baseDir, ".gemini", "settings.json");
1605
1607
  if (await fileExists(settingsPath)) {
1606
1608
  const settingsResult = await parseGeminiSettings(settingsPath);
1607
1609
  if (settingsResult.ignorePatterns) {
@@ -1612,7 +1614,7 @@ async function parseGeminiConfiguration(baseDir = process.cwd()) {
1612
1614
  }
1613
1615
  errors.push(...settingsResult.errors);
1614
1616
  }
1615
- const aiexcludePath = join14(baseDir, ".aiexclude");
1617
+ const aiexcludePath = join17(baseDir, ".aiexclude");
1616
1618
  if (await fileExists(aiexcludePath)) {
1617
1619
  const aiexcludePatterns = await parseAiexclude(aiexcludePath);
1618
1620
  if (aiexcludePatterns.length > 0) {
@@ -1665,7 +1667,7 @@ async function parseGeminiMemoryFiles(memoryDir) {
1665
1667
  const files = await readdir2(memoryDir);
1666
1668
  for (const file of files) {
1667
1669
  if (file.endsWith(".md")) {
1668
- const filePath = join14(memoryDir, file);
1670
+ const filePath = join17(memoryDir, file);
1669
1671
  const content = await readFileContent(filePath);
1670
1672
  if (content.trim()) {
1671
1673
  const filename = basename5(file, ".md");
@@ -1717,11 +1719,11 @@ async function parseAiexclude(aiexcludePath) {
1717
1719
  }
1718
1720
 
1719
1721
  // src/parsers/roo.ts
1720
- import { join as join15 } from "path";
1722
+ import { join as join18 } from "path";
1721
1723
  async function parseRooConfiguration(baseDir = process.cwd()) {
1722
1724
  const errors = [];
1723
1725
  const rules = [];
1724
- const rooFilePath = join15(baseDir, ".roo", "instructions.md");
1726
+ const rooFilePath = join18(baseDir, ".roo", "instructions.md");
1725
1727
  if (await fileExists(rooFilePath)) {
1726
1728
  try {
1727
1729
  const content = await readFileContent(rooFilePath);
@@ -1744,14 +1746,14 @@ async function parseRooConfiguration(baseDir = process.cwd()) {
1744
1746
  errors.push(`Failed to parse .roo/instructions.md: ${errorMessage}`);
1745
1747
  }
1746
1748
  }
1747
- const rooRulesDir = join15(baseDir, ".roo", "rules");
1749
+ const rooRulesDir = join18(baseDir, ".roo", "rules");
1748
1750
  if (await fileExists(rooRulesDir)) {
1749
1751
  try {
1750
1752
  const { readdir: readdir2 } = await import("fs/promises");
1751
1753
  const files = await readdir2(rooRulesDir);
1752
1754
  for (const file of files) {
1753
1755
  if (file.endsWith(".md")) {
1754
- const filePath = join15(rooRulesDir, file);
1756
+ const filePath = join18(rooRulesDir, file);
1755
1757
  try {
1756
1758
  const content = await readFileContent(filePath);
1757
1759
  if (content.trim()) {
@@ -1852,7 +1854,7 @@ async function importConfiguration(options) {
1852
1854
  if (rules.length === 0 && !ignorePatterns && !mcpServers) {
1853
1855
  return { success: false, rulesCreated: 0, errors };
1854
1856
  }
1855
- const rulesDirPath = join16(baseDir, rulesDir);
1857
+ const rulesDirPath = join19(baseDir, rulesDir);
1856
1858
  try {
1857
1859
  const { mkdir: mkdir3 } = await import("fs/promises");
1858
1860
  await mkdir3(rulesDirPath, { recursive: true });
@@ -1866,7 +1868,7 @@ async function importConfiguration(options) {
1866
1868
  try {
1867
1869
  const baseFilename = `${tool}__${rule.filename}`;
1868
1870
  const filename = await generateUniqueFilename(rulesDirPath, baseFilename);
1869
- const filePath = join16(rulesDirPath, `${filename}.md`);
1871
+ const filePath = join19(rulesDirPath, `${filename}.md`);
1870
1872
  const content = generateRuleFileContent(rule);
1871
1873
  await writeFileContent(filePath, content);
1872
1874
  rulesCreated++;
@@ -1881,7 +1883,7 @@ async function importConfiguration(options) {
1881
1883
  let ignoreFileCreated = false;
1882
1884
  if (ignorePatterns && ignorePatterns.length > 0) {
1883
1885
  try {
1884
- const rulesyncignorePath = join16(baseDir, ".rulesyncignore");
1886
+ const rulesyncignorePath = join19(baseDir, ".rulesyncignore");
1885
1887
  const ignoreContent = `${ignorePatterns.join("\n")}
1886
1888
  `;
1887
1889
  await writeFileContent(rulesyncignorePath, ignoreContent);
@@ -1897,7 +1899,7 @@ async function importConfiguration(options) {
1897
1899
  let mcpFileCreated = false;
1898
1900
  if (mcpServers && Object.keys(mcpServers).length > 0) {
1899
1901
  try {
1900
- const mcpPath = join16(baseDir, rulesDir, ".mcp.json");
1902
+ const mcpPath = join19(baseDir, rulesDir, ".mcp.json");
1901
1903
  const mcpContent = `${JSON.stringify({ mcpServers }, null, 2)}
1902
1904
  `;
1903
1905
  await writeFileContent(mcpPath, mcpContent);
@@ -1925,7 +1927,7 @@ function generateRuleFileContent(rule) {
1925
1927
  async function generateUniqueFilename(rulesDir, baseFilename) {
1926
1928
  let filename = baseFilename;
1927
1929
  let counter = 1;
1928
- while (await fileExists(join16(rulesDir, `${filename}.md`))) {
1930
+ while (await fileExists(join19(rulesDir, `${filename}.md`))) {
1929
1931
  filename = `${baseFilename}-${counter}`;
1930
1932
  counter++;
1931
1933
  }
@@ -1990,7 +1992,7 @@ async function importCommand(options = {}) {
1990
1992
  }
1991
1993
 
1992
1994
  // src/cli/commands/init.ts
1993
- import { join as join17 } from "path";
1995
+ import { join as join20 } from "path";
1994
1996
  async function initCommand() {
1995
1997
  const aiRulesDir = ".rulesync";
1996
1998
  console.log("Initializing rulesync...");
@@ -2120,7 +2122,7 @@ globs: ["src/api/**/*.ts", "src/services/**/*.ts", "src/models/**/*.ts"]
2120
2122
  }
2121
2123
  ];
2122
2124
  for (const file of sampleFiles) {
2123
- const filepath = join17(aiRulesDir, file.filename);
2125
+ const filepath = join20(aiRulesDir, file.filename);
2124
2126
  if (!await fileExists(filepath)) {
2125
2127
  await writeFileContent(filepath, file.content);
2126
2128
  console.log(`Created ${filepath}`);
@@ -2263,7 +2265,7 @@ async function watchCommand() {
2263
2265
 
2264
2266
  // src/cli/index.ts
2265
2267
  var program = new Command();
2266
- program.name("rulesync").description("Unified AI rules management CLI tool").version("0.42.0");
2268
+ program.name("rulesync").description("Unified AI rules management CLI tool").version("0.43.0");
2267
2269
  program.command("init").description("Initialize rulesync in current directory").action(initCommand);
2268
2270
  program.command("add <filename>").description("Add a new rule file").action(addCommand);
2269
2271
  program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  generateRooMcp,
3
3
  generateRooMcpConfiguration
4
- } from "./chunk-3NRSCDLQ.js";
5
- import "./chunk-6YNGMPAL.js";
4
+ } from "./chunk-RL3TE3EZ.js";
5
+ import "./chunk-THWXK5Z2.js";
6
6
  export {
7
7
  generateRooMcp,
8
8
  generateRooMcpConfiguration